1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4
5 #if defined(LTC_MRSA) || (!defined(LTC_NO_MATH) && !defined(LTC_NO_PRNGS))
6
7 /**
8 @file rand_prime.c
9 Generate a random prime, Tom St Denis
10 */
11
12 #define USE_BBS 1
13
rand_prime(void * N,long len,prng_state * prng,int wprng)14 int rand_prime(void *N, long len, prng_state *prng, int wprng)
15 {
16 int err, res, type;
17 unsigned char *buf;
18
19 LTC_ARGCHK(N != NULL);
20
21 /* get type */
22 if (len < 0) {
23 type = USE_BBS;
24 len = -len;
25 } else {
26 type = 0;
27 }
28
29 /* allow sizes between 2 and 512 bytes for a prime size */
30 if (len < 2 || len > 512) {
31 return CRYPT_INVALID_PRIME_SIZE;
32 }
33
34 /* valid PRNG? Better be! */
35 if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
36 return err;
37 }
38
39 /* allocate buffer to work with */
40 buf = XCALLOC(1, len);
41 if (buf == NULL) {
42 return CRYPT_MEM;
43 }
44
45 do {
46 /* generate value */
47 if (prng_descriptor[wprng]->read(buf, len, prng) != (unsigned long)len) {
48 XFREE(buf);
49 return CRYPT_ERROR_READPRNG;
50 }
51
52 /* munge bits */
53 buf[0] |= 0x80 | 0x40;
54 buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
55
56 /* load value */
57 if ((err = mp_read_unsigned_bin(N, buf, len)) != CRYPT_OK) {
58 XFREE(buf);
59 return err;
60 }
61
62 /* test */
63 if ((err = mp_prime_is_prime(N, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) {
64 XFREE(buf);
65 return err;
66 }
67 } while (res == LTC_MP_NO);
68
69 #ifdef LTC_CLEAN_STACK
70 zeromem(buf, len);
71 #endif
72
73 XFREE(buf);
74 return CRYPT_OK;
75 }
76
77 #endif /* LTC_NO_MATH */
78
79