xref: /optee_os/core/lib/libtomcrypt/src/prngs/rng_make_prng.c (revision 8411e6ad673d20c4742ed30c785e3f5cdea54dfa)
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 #ifdef LTC_RNG_MAKE_PRNG
6 /**
7   @file rng_make_prng.c
8   portable way to get secure random bits to feed a PRNG  (Tom St Denis)
9 */
10 
11 /**
12   Create a PRNG from a RNG
13 
14      In case you pass bits as '-1' the PRNG will be setup
15      as if the export/import functionality has been used,
16      but the imported data comes directly from the RNG.
17 
18   @param bits     Number of bits of entropy desired (-1 or 64 ... 1024)
19   @param wprng    Index of which PRNG to setup
20   @param prng     [out] PRNG state to initialize
21   @param callback A pointer to a void function for when the RNG is slow, this can be NULL
22   @return CRYPT_OK if successful
23 */
rng_make_prng(int bits,int wprng,prng_state * prng,void (* callback)(void))24 int rng_make_prng(int bits, int wprng, prng_state *prng,
25                   void (*callback)(void))
26 {
27    unsigned char* buf;
28    unsigned long bytes;
29    int err;
30 
31    LTC_ARGCHK(prng != NULL);
32 
33    /* check parameter */
34    if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
35       return err;
36    }
37 
38    if (bits == -1) {
39       bytes = prng_descriptor[wprng]->export_size;
40    } else if (bits < 64 || bits > 1024) {
41       return CRYPT_INVALID_PRNGSIZE;
42    } else {
43       bytes = (unsigned long)((bits+7)/8) * 2;
44    }
45 
46    if ((err = prng_descriptor[wprng]->start(prng)) != CRYPT_OK) {
47       return err;
48    }
49 
50    buf = XMALLOC(bytes);
51    if (buf == NULL) {
52       return CRYPT_MEM;
53    }
54 
55    if (rng_get_bytes(buf, bytes, callback) != bytes) {
56       err = CRYPT_ERROR_READPRNG;
57       goto LBL_ERR;
58    }
59 
60    if (bits == -1) {
61       if ((err = prng_descriptor[wprng]->pimport(buf, bytes, prng)) != CRYPT_OK) {
62          goto LBL_ERR;
63       }
64    } else {
65       if ((err = prng_descriptor[wprng]->add_entropy(buf, bytes, prng)) != CRYPT_OK) {
66          goto LBL_ERR;
67       }
68    }
69    if ((err = prng_descriptor[wprng]->ready(prng)) != CRYPT_OK) {
70       goto LBL_ERR;
71    }
72 
73 LBL_ERR:
74    #ifdef LTC_CLEAN_STACK
75    zeromem(buf, bytes);
76    #endif
77    XFREE(buf);
78    return err;
79 }
80 #endif /* #ifdef LTC_RNG_MAKE_PRNG */
81 
82