bn_mp_prime_random_ex.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include <tommath.h>
  2. #ifdef BN_MP_PRIME_RANDOM_EX_C
  3. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4. *
  5. * LibTomMath is a library that provides multiple-precision
  6. * integer arithmetic as well as number theoretic functionality.
  7. *
  8. * The library was designed directly after the MPI library by
  9. * Michael Fromberger but has been written from scratch with
  10. * additional optimizations in place.
  11. *
  12. * The library is free for all purposes without any express
  13. * guarantee it works.
  14. *
  15. * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
  16. */
  17. /* makes a truly random prime of a given size (bits),
  18. *
  19. * Flags are as follows:
  20. *
  21. * LTM_PRIME_BBS - make prime congruent to 3 mod 4
  22. * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
  23. * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
  24. * LTM_PRIME_2MSB_ON - make the 2nd highest bit one
  25. *
  26. * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
  27. * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
  28. * so it can be NULL
  29. *
  30. */
  31. /* This is possibly the mother of all prime generation functions, muahahahahaha! */
  32. int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat)
  33. {
  34. unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
  35. int res, err, bsize, maskOR_msb_offset;
  36. /* sanity check the input */
  37. if (size <= 1 || t <= 0) {
  38. return MP_VAL;
  39. }
  40. /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */
  41. if (flags & LTM_PRIME_SAFE) {
  42. flags |= LTM_PRIME_BBS;
  43. }
  44. /* calc the byte size */
  45. bsize = (size>>3) + ((size&7)?1:0);
  46. /* we need a buffer of bsize bytes */
  47. tmp = OPT_CAST(unsigned char) XMALLOC(bsize);
  48. if (tmp == NULL) {
  49. return MP_MEM;
  50. }
  51. /* calc the maskAND value for the MSbyte*/
  52. maskAND = ((size&7) == 0) ? 0xFF : (0xFF >> (8 - (size & 7)));
  53. /* calc the maskOR_msb */
  54. maskOR_msb = 0;
  55. maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0;
  56. if (flags & LTM_PRIME_2MSB_ON) {
  57. maskOR_msb |= 0x80 >> ((9 - size) & 7);
  58. }
  59. /* get the maskOR_lsb */
  60. maskOR_lsb = 1;
  61. if (flags & LTM_PRIME_BBS) {
  62. maskOR_lsb |= 3;
  63. }
  64. do {
  65. /* read the bytes */
  66. if (cb(tmp, bsize, dat) != bsize) {
  67. err = MP_VAL;
  68. goto error;
  69. }
  70. /* work over the MSbyte */
  71. tmp[0] &= maskAND;
  72. tmp[0] |= 1 << ((size - 1) & 7);
  73. /* mix in the maskORs */
  74. tmp[maskOR_msb_offset] |= maskOR_msb;
  75. tmp[bsize-1] |= maskOR_lsb;
  76. /* read it in */
  77. if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY) { goto error; }
  78. /* is it prime? */
  79. if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; }
  80. if (res == MP_NO) {
  81. continue;
  82. }
  83. if (flags & LTM_PRIME_SAFE) {
  84. /* see if (a-1)/2 is prime */
  85. if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) { goto error; }
  86. if ((err = mp_div_2(a, a)) != MP_OKAY) { goto error; }
  87. /* is it prime? */
  88. if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; }
  89. }
  90. } while (res == MP_NO);
  91. if (flags & LTM_PRIME_SAFE) {
  92. /* restore a to the original value */
  93. if ((err = mp_mul_2(a, a)) != MP_OKAY) { goto error; }
  94. if ((err = mp_add_d(a, 1, a)) != MP_OKAY) { goto error; }
  95. }
  96. err = MP_OKAY;
  97. error:
  98. XFREE(tmp);
  99. return err;
  100. }
  101. #endif
  102. /* $Source: /cvs/libtom/libtommath/bn_mp_prime_random_ex.c,v $ */
  103. /* $Revision: 1.4 $ */
  104. /* $Date: 2006/03/31 14:18:44 $ */