mpiutil.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /* mpiutil.ac - Utility functions for MPI
  2. * Copyright (C) 1998, 2000, 2001, 2002, 2003,
  3. * 2007 Free Software Foundation, Inc.
  4. *
  5. * This file is part of Libgcrypt.
  6. *
  7. * Libgcrypt is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * Libgcrypt is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <config.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include "g10lib.h"
  25. #include "mpi-internal.h"
  26. #include "mod-source-info.h"
  27. const char *
  28. _gcry_mpi_get_hw_config (void)
  29. {
  30. return mod_source_info + 1;
  31. }
  32. /****************
  33. * Note: It was a bad idea to use the number of limbs to allocate
  34. * because on a alpha the limbs are large but we normally need
  35. * integers of n bits - So we should change this to bits (or bytes).
  36. *
  37. * But mpi_alloc is used in a lot of places :-(. New code
  38. * should use mpi_new.
  39. */
  40. gcry_mpi_t
  41. _gcry_mpi_alloc( unsigned nlimbs )
  42. {
  43. gcry_mpi_t a;
  44. a = gcry_xmalloc( sizeof *a );
  45. a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL;
  46. a->alloced = nlimbs;
  47. a->nlimbs = 0;
  48. a->sign = 0;
  49. a->flags = 0;
  50. return a;
  51. }
  52. void
  53. _gcry_mpi_m_check( gcry_mpi_t a )
  54. {
  55. _gcry_check_heap(a);
  56. _gcry_check_heap(a->d);
  57. }
  58. gcry_mpi_t
  59. _gcry_mpi_alloc_secure( unsigned nlimbs )
  60. {
  61. gcry_mpi_t a;
  62. a = gcry_xmalloc( sizeof *a );
  63. a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL;
  64. a->alloced = nlimbs;
  65. a->flags = 1;
  66. a->nlimbs = 0;
  67. a->sign = 0;
  68. return a;
  69. }
  70. mpi_ptr_t
  71. _gcry_mpi_alloc_limb_space( unsigned int nlimbs, int secure )
  72. {
  73. mpi_ptr_t p;
  74. size_t len;
  75. len = (nlimbs ? nlimbs : 1) * sizeof (mpi_limb_t);
  76. p = secure ? gcry_xmalloc_secure (len) : gcry_xmalloc (len);
  77. if (! nlimbs)
  78. *p = 0;
  79. return p;
  80. }
  81. void
  82. _gcry_mpi_free_limb_space( mpi_ptr_t a, unsigned int nlimbs)
  83. {
  84. if (a)
  85. {
  86. size_t len = nlimbs * sizeof(mpi_limb_t);
  87. /* If we have information on the number of allocated limbs, we
  88. better wipe that space out. This is a failsafe feature if
  89. secure memory has been disabled or was not properly
  90. implemented in user provided allocation functions. */
  91. if (len)
  92. wipememory (a, len);
  93. gcry_free(a);
  94. }
  95. }
  96. void
  97. _gcry_mpi_assign_limb_space( gcry_mpi_t a, mpi_ptr_t ap, unsigned int nlimbs )
  98. {
  99. _gcry_mpi_free_limb_space (a->d, a->alloced);
  100. a->d = ap;
  101. a->alloced = nlimbs;
  102. }
  103. /****************
  104. * Resize the array of A to NLIMBS. The additional space is cleared
  105. * (set to 0).
  106. */
  107. void
  108. _gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs)
  109. {
  110. size_t i;
  111. if (nlimbs <= a->alloced)
  112. {
  113. /* We only need to clear the new space (this is a nop if the
  114. limb space is already of the correct size. */
  115. for (i=a->nlimbs; i < a->alloced; i++)
  116. a->d[i] = 0;
  117. return;
  118. }
  119. /* Actually resize the limb space. */
  120. if (a->d)
  121. {
  122. a->d = gcry_xrealloc (a->d, nlimbs * sizeof (mpi_limb_t));
  123. for (i=a->alloced; i < nlimbs; i++)
  124. a->d[i] = 0;
  125. }
  126. else
  127. {
  128. if (a->flags & 1)
  129. /* Secure memory is wanted. */
  130. a->d = gcry_xcalloc_secure (nlimbs , sizeof (mpi_limb_t));
  131. else
  132. /* Standard memory. */
  133. a->d = gcry_xcalloc (nlimbs , sizeof (mpi_limb_t));
  134. }
  135. a->alloced = nlimbs;
  136. }
  137. void
  138. _gcry_mpi_clear( gcry_mpi_t a )
  139. {
  140. a->nlimbs = 0;
  141. a->flags = 0;
  142. }
  143. void
  144. _gcry_mpi_free( gcry_mpi_t a )
  145. {
  146. if (!a )
  147. return;
  148. if ((a->flags & 4))
  149. gcry_free( a->d );
  150. else
  151. {
  152. _gcry_mpi_free_limb_space(a->d, a->alloced);
  153. }
  154. if ((a->flags & ~7))
  155. log_bug("invalid flag value in mpi\n");
  156. gcry_free(a);
  157. }
  158. static void
  159. mpi_set_secure( gcry_mpi_t a )
  160. {
  161. mpi_ptr_t ap, bp;
  162. if ( (a->flags & 1) )
  163. return;
  164. a->flags |= 1;
  165. ap = a->d;
  166. if (!a->nlimbs)
  167. {
  168. gcry_assert (!ap);
  169. return;
  170. }
  171. bp = mpi_alloc_limb_space (a->nlimbs, 1);
  172. MPN_COPY( bp, ap, a->nlimbs );
  173. a->d = bp;
  174. _gcry_mpi_free_limb_space (ap, a->alloced);
  175. }
  176. gcry_mpi_t
  177. gcry_mpi_set_opaque( gcry_mpi_t a, void *p, unsigned int nbits )
  178. {
  179. if (!a)
  180. a = mpi_alloc(0);
  181. if( a->flags & 4 )
  182. gcry_free( a->d );
  183. else
  184. _gcry_mpi_free_limb_space (a->d, a->alloced);
  185. a->d = p;
  186. a->alloced = 0;
  187. a->nlimbs = 0;
  188. a->sign = nbits;
  189. a->flags = 4;
  190. return a;
  191. }
  192. void *
  193. gcry_mpi_get_opaque( gcry_mpi_t a, unsigned int *nbits )
  194. {
  195. if( !(a->flags & 4) )
  196. log_bug("mpi_get_opaque on normal mpi\n");
  197. if( nbits )
  198. *nbits = a->sign;
  199. return a->d;
  200. }
  201. /****************
  202. * Note: This copy function should not interpret the MPI
  203. * but copy it transparently.
  204. */
  205. gcry_mpi_t
  206. gcry_mpi_copy( gcry_mpi_t a )
  207. {
  208. int i;
  209. gcry_mpi_t b;
  210. if( a && (a->flags & 4) ) {
  211. void *p = gcry_is_secure(a->d)? gcry_xmalloc_secure( (a->sign+7)/8 )
  212. : gcry_xmalloc( (a->sign+7)/8 );
  213. memcpy( p, a->d, (a->sign+7)/8 );
  214. b = gcry_mpi_set_opaque( NULL, p, a->sign );
  215. }
  216. else if( a ) {
  217. b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
  218. : mpi_alloc( a->nlimbs );
  219. b->nlimbs = a->nlimbs;
  220. b->sign = a->sign;
  221. b->flags = a->flags;
  222. for(i=0; i < b->nlimbs; i++ )
  223. b->d[i] = a->d[i];
  224. }
  225. else
  226. b = NULL;
  227. return b;
  228. }
  229. /****************
  230. * This function allocates an MPI which is optimized to hold
  231. * a value as large as the one given in the argument and allocates it
  232. * with the same flags as A.
  233. */
  234. gcry_mpi_t
  235. _gcry_mpi_alloc_like( gcry_mpi_t a )
  236. {
  237. gcry_mpi_t b;
  238. if( a && (a->flags & 4) ) {
  239. int n = (a->sign+7)/8;
  240. void *p = gcry_is_secure(a->d)? gcry_malloc_secure( n )
  241. : gcry_malloc( n );
  242. memcpy( p, a->d, n );
  243. b = gcry_mpi_set_opaque( NULL, p, a->sign );
  244. }
  245. else if( a ) {
  246. b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
  247. : mpi_alloc( a->nlimbs );
  248. b->nlimbs = 0;
  249. b->sign = 0;
  250. b->flags = a->flags;
  251. }
  252. else
  253. b = NULL;
  254. return b;
  255. }
  256. gcry_mpi_t
  257. gcry_mpi_set( gcry_mpi_t w, gcry_mpi_t u)
  258. {
  259. mpi_ptr_t wp, up;
  260. mpi_size_t usize = u->nlimbs;
  261. int usign = u->sign;
  262. if (!w)
  263. w = _gcry_mpi_alloc( mpi_get_nlimbs(u) );
  264. RESIZE_IF_NEEDED(w, usize);
  265. wp = w->d;
  266. up = u->d;
  267. MPN_COPY( wp, up, usize );
  268. w->nlimbs = usize;
  269. w->flags = u->flags;
  270. w->sign = usign;
  271. return w;
  272. }
  273. gcry_mpi_t
  274. gcry_mpi_set_ui( gcry_mpi_t w, unsigned long u)
  275. {
  276. if (!w)
  277. w = _gcry_mpi_alloc (1);
  278. /* FIXME: If U is 0 we have no need to resize and thus possible
  279. allocating the the limbs. */
  280. RESIZE_IF_NEEDED(w, 1);
  281. w->d[0] = u;
  282. w->nlimbs = u? 1:0;
  283. w->sign = 0;
  284. w->flags = 0;
  285. return w;
  286. }
  287. gcry_err_code_t
  288. _gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
  289. {
  290. gcry_err_code_t err = GPG_ERR_NO_ERROR;
  291. unsigned long x = 0;
  292. if (w->nlimbs > 1)
  293. err = GPG_ERR_TOO_LARGE;
  294. else if (w->nlimbs == 1)
  295. x = w->d[0];
  296. else
  297. x = 0;
  298. if (! err)
  299. *u = x;
  300. return err;
  301. }
  302. gcry_error_t
  303. gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
  304. {
  305. gcry_err_code_t err = GPG_ERR_NO_ERROR;
  306. err = _gcry_mpi_get_ui (w, u);
  307. return gcry_error (err);
  308. }
  309. gcry_mpi_t
  310. _gcry_mpi_alloc_set_ui( unsigned long u)
  311. {
  312. gcry_mpi_t w = mpi_alloc(1);
  313. w->d[0] = u;
  314. w->nlimbs = u? 1:0;
  315. w->sign = 0;
  316. return w;
  317. }
  318. void
  319. gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b)
  320. {
  321. struct gcry_mpi tmp;
  322. tmp = *a; *a = *b; *b = tmp;
  323. }
  324. gcry_mpi_t
  325. gcry_mpi_new( unsigned int nbits )
  326. {
  327. return _gcry_mpi_alloc ( (nbits+BITS_PER_MPI_LIMB-1)
  328. / BITS_PER_MPI_LIMB );
  329. }
  330. gcry_mpi_t
  331. gcry_mpi_snew( unsigned int nbits )
  332. {
  333. return _gcry_mpi_alloc_secure ( (nbits+BITS_PER_MPI_LIMB-1)
  334. / BITS_PER_MPI_LIMB );
  335. }
  336. void
  337. gcry_mpi_release( gcry_mpi_t a )
  338. {
  339. _gcry_mpi_free( a );
  340. }
  341. void
  342. gcry_mpi_randomize( gcry_mpi_t w,
  343. unsigned int nbits, enum gcry_random_level level )
  344. {
  345. unsigned char *p;
  346. size_t nbytes = (nbits+7)/8;
  347. if (level == GCRY_WEAK_RANDOM)
  348. {
  349. p = mpi_is_secure(w) ? gcry_xmalloc_secure (nbytes)
  350. : gcry_xmalloc (nbytes);
  351. gcry_create_nonce (p, nbytes);
  352. }
  353. else
  354. {
  355. p = mpi_is_secure(w) ? gcry_random_bytes_secure (nbytes, level)
  356. : gcry_random_bytes (nbytes, level);
  357. }
  358. _gcry_mpi_set_buffer( w, p, nbytes, 0 );
  359. gcry_free (p);
  360. }
  361. void
  362. gcry_mpi_set_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
  363. {
  364. switch( flag ) {
  365. case GCRYMPI_FLAG_SECURE: mpi_set_secure(a); break;
  366. case GCRYMPI_FLAG_OPAQUE:
  367. default: log_bug("invalid flag value\n");
  368. }
  369. }
  370. void
  371. gcry_mpi_clear_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
  372. {
  373. (void)a; /* Not yet used. */
  374. switch (flag)
  375. {
  376. case GCRYMPI_FLAG_SECURE:
  377. case GCRYMPI_FLAG_OPAQUE:
  378. default: log_bug("invalid flag value\n");
  379. }
  380. }
  381. int
  382. gcry_mpi_get_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
  383. {
  384. switch (flag)
  385. {
  386. case GCRYMPI_FLAG_SECURE: return (a->flags & 1);
  387. case GCRYMPI_FLAG_OPAQUE: return (a->flags & 4);
  388. default: log_bug("invalid flag value\n");
  389. }
  390. /*NOTREACHED*/
  391. return 0;
  392. }