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