1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 #if defined(LTC_MDSA) || defined(LTC_MECC)
6 /**
7   Generate a random number N with given bitlength (note: MSB can be 0)
8 */
9 
rand_bn_bits(void * N,int bits,prng_state * prng,int wprng)10 int rand_bn_bits(void *N, int bits, prng_state *prng, int wprng)
11 {
12    int res, bytes;
13    unsigned char *buf, mask;
14 
15    LTC_ARGCHK(N != NULL);
16    LTC_ARGCHK(bits > 1);
17 
18    /* check PRNG */
19    if ((res = prng_is_valid(wprng)) != CRYPT_OK) return res;
20 
21    bytes = (bits+7) >> 3;
22    mask = 0xff >> (bits % 8 == 0 ? 0 : 8 - bits % 8);
23 
24    /* allocate buffer */
25    if ((buf = XCALLOC(1, bytes)) == NULL) return CRYPT_MEM;
26 
27    /* generate random bytes */
28    if (prng_descriptor[wprng]->read(buf, bytes, prng) != (unsigned long)bytes) {
29       res = CRYPT_ERROR_READPRNG;
30       goto cleanup;
31    }
32    /* mask bits */
33    buf[0] &= mask;
34    /* load value */
35    if ((res = mp_read_unsigned_bin(N, buf, bytes)) != CRYPT_OK) goto cleanup;
36 
37    res = CRYPT_OK;
38 
39 cleanup:
40 #ifdef LTC_CLEAN_STACK
41    zeromem(buf, bytes);
42 #endif
43    XFREE(buf);
44    return res;
45 }
46 
47 /**
48   Generate a random number N in a range: 1 <= N < limit
49 */
rand_bn_upto(void * N,void * limit,prng_state * prng,int wprng)50 int rand_bn_upto(void *N, void *limit, prng_state *prng, int wprng)
51 {
52    int res, bits;
53 
54    LTC_ARGCHK(N != NULL);
55    LTC_ARGCHK(limit != NULL);
56 
57    bits = mp_count_bits(limit);
58    do {
59      res = rand_bn_bits(N, bits, prng, wprng);
60      if (res != CRYPT_OK) return res;
61    } while (mp_cmp_d(N, 0) != LTC_MP_GT || mp_cmp(N, limit) != LTC_MP_LT);
62 
63    return CRYPT_OK;
64 }
65 #endif
66