bn_mp_prime_rand.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include "tommath_private.h"
  2. #ifdef BN_MP_PRIME_RAND_C
  3. /* LibTomMath, multiple-precision integer library -- Tom St Denis */
  4. /* SPDX-License-Identifier: Unlicense */
  5. /* makes a truly random prime of a given size (bits),
  6. *
  7. * Flags are as follows:
  8. *
  9. * MP_PRIME_BBS - make prime congruent to 3 mod 4
  10. * MP_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies MP_PRIME_BBS)
  11. * MP_PRIME_2MSB_ON - make the 2nd highest bit one
  12. *
  13. * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
  14. * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
  15. * so it can be NULL
  16. *
  17. */
  18. /* This is possibly the mother of all prime generation functions, muahahahahaha! */
  19. mp_err s_mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_prime_callback cb, void *dat)
  20. {
  21. unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
  22. int bsize, maskOR_msb_offset;
  23. mp_bool res;
  24. mp_err err;
  25. /* sanity check the input */
  26. if ((size <= 1) || (t <= 0)) {
  27. return MP_VAL;
  28. }
  29. /* MP_PRIME_SAFE implies MP_PRIME_BBS */
  30. if ((flags & MP_PRIME_SAFE) != 0) {
  31. flags |= MP_PRIME_BBS;
  32. }
  33. /* calc the byte size */
  34. bsize = (size>>3) + ((size&7)?1:0);
  35. /* we need a buffer of bsize bytes */
  36. tmp = (unsigned char *) MP_MALLOC((size_t)bsize);
  37. if (tmp == NULL) {
  38. return MP_MEM;
  39. }
  40. /* calc the maskAND value for the MSbyte*/
  41. maskAND = ((size&7) == 0) ? 0xFFu : (unsigned char)(0xFFu >> (8 - (size & 7)));
  42. /* calc the maskOR_msb */
  43. maskOR_msb = 0;
  44. maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0;
  45. if ((flags & MP_PRIME_2MSB_ON) != 0) {
  46. maskOR_msb |= (unsigned char)(0x80 >> ((9 - size) & 7));
  47. }
  48. /* get the maskOR_lsb */
  49. maskOR_lsb = 1u;
  50. if ((flags & MP_PRIME_BBS) != 0) {
  51. maskOR_lsb |= 3u;
  52. }
  53. do {
  54. /* read the bytes */
  55. if (cb(tmp, bsize, dat) != bsize) {
  56. err = MP_VAL;
  57. goto error;
  58. }
  59. /* work over the MSbyte */
  60. tmp[0] &= maskAND;
  61. tmp[0] |= (unsigned char)(1 << ((size - 1) & 7));
  62. /* mix in the maskORs */
  63. tmp[maskOR_msb_offset] |= maskOR_msb;
  64. tmp[bsize-1] |= maskOR_lsb;
  65. /* read it in */
  66. /* TODO: casting only for now until all lengths have been changed to the type "size_t"*/
  67. if ((err = mp_from_ubin(a, tmp, (size_t)bsize)) != MP_OKAY) {
  68. goto error;
  69. }
  70. /* is it prime? */
  71. if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) {
  72. goto error;
  73. }
  74. if (res == MP_NO) {
  75. continue;
  76. }
  77. if ((flags & MP_PRIME_SAFE) != 0) {
  78. /* see if (a-1)/2 is prime */
  79. if ((err = mp_sub_d(a, 1uL, a)) != MP_OKAY) {
  80. goto error;
  81. }
  82. if ((err = mp_div_2(a, a)) != MP_OKAY) {
  83. goto error;
  84. }
  85. /* is it prime? */
  86. if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) {
  87. goto error;
  88. }
  89. }
  90. } while (res == MP_NO);
  91. if ((flags & MP_PRIME_SAFE) != 0) {
  92. /* restore a to the original value */
  93. if ((err = mp_mul_2(a, a)) != MP_OKAY) {
  94. goto error;
  95. }
  96. if ((err = mp_add_d(a, 1uL, a)) != MP_OKAY) {
  97. goto error;
  98. }
  99. }
  100. err = MP_OKAY;
  101. error:
  102. MP_FREE_BUFFER(tmp, (size_t)bsize);
  103. return err;
  104. }
  105. static int s_mp_rand_cb(unsigned char *dst, int len, void *dat)
  106. {
  107. (void)dat;
  108. if (len <= 0) {
  109. return len;
  110. }
  111. if (s_mp_rand_source(dst, (size_t)len) != MP_OKAY) {
  112. return 0;
  113. }
  114. return len;
  115. }
  116. mp_err mp_prime_rand(mp_int *a, int t, int size, int flags)
  117. {
  118. return s_mp_prime_random_ex(a, t, size, flags, s_mp_rand_cb, NULL);
  119. }
  120. #endif