xref: /freebsd/crypto/openssl/providers/implementations/rands/fips_crng_test.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1*e7be843bSPierre Pronchery /*
2*e7be843bSPierre Pronchery  * Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
3*e7be843bSPierre Pronchery  *
4*e7be843bSPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*e7be843bSPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6*e7be843bSPierre Pronchery  * in the file LICENSE in the source distribution or at
7*e7be843bSPierre Pronchery  * https://www.openssl.org/source/license.html
8*e7be843bSPierre Pronchery  */
9*e7be843bSPierre Pronchery 
10*e7be843bSPierre Pronchery /*
11*e7be843bSPierre Pronchery  * Implementation of SP 800-90B section 4.4 Approved Continuous Health Tests.
12*e7be843bSPierre Pronchery  */
13*e7be843bSPierre Pronchery 
14*e7be843bSPierre Pronchery #include <string.h>
15*e7be843bSPierre Pronchery #include <openssl/evp.h>
16*e7be843bSPierre Pronchery #include <openssl/core_dispatch.h>
17*e7be843bSPierre Pronchery #include <openssl/params.h>
18*e7be843bSPierre Pronchery #include <openssl/self_test.h>
19*e7be843bSPierre Pronchery #include <openssl/proverr.h>
20*e7be843bSPierre Pronchery #include "prov/providercommon.h"
21*e7be843bSPierre Pronchery #include "prov/provider_ctx.h"
22*e7be843bSPierre Pronchery #include "prov/implementations.h"
23*e7be843bSPierre Pronchery #include "internal/cryptlib.h"
24*e7be843bSPierre Pronchery #include "crypto/rand_pool.h"
25*e7be843bSPierre Pronchery #include "drbg_local.h"
26*e7be843bSPierre Pronchery #include "prov/seeding.h"
27*e7be843bSPierre Pronchery #include "crypto/context.h"
28*e7be843bSPierre Pronchery 
29*e7be843bSPierre Pronchery static OSSL_FUNC_rand_newctx_fn crng_test_new;
30*e7be843bSPierre Pronchery static OSSL_FUNC_rand_freectx_fn crng_test_free;
31*e7be843bSPierre Pronchery static OSSL_FUNC_rand_instantiate_fn crng_test_instantiate;
32*e7be843bSPierre Pronchery static OSSL_FUNC_rand_uninstantiate_fn crng_test_uninstantiate;
33*e7be843bSPierre Pronchery static OSSL_FUNC_rand_generate_fn crng_test_generate;
34*e7be843bSPierre Pronchery static OSSL_FUNC_rand_reseed_fn crng_test_reseed;
35*e7be843bSPierre Pronchery static OSSL_FUNC_rand_gettable_ctx_params_fn crng_test_gettable_ctx_params;
36*e7be843bSPierre Pronchery static OSSL_FUNC_rand_get_ctx_params_fn crng_test_get_ctx_params;
37*e7be843bSPierre Pronchery static OSSL_FUNC_rand_verify_zeroization_fn crng_test_verify_zeroization;
38*e7be843bSPierre Pronchery static OSSL_FUNC_rand_enable_locking_fn crng_test_enable_locking;
39*e7be843bSPierre Pronchery static OSSL_FUNC_rand_lock_fn crng_test_lock;
40*e7be843bSPierre Pronchery static OSSL_FUNC_rand_unlock_fn crng_test_unlock;
41*e7be843bSPierre Pronchery static OSSL_FUNC_rand_get_seed_fn crng_test_get_seed;
42*e7be843bSPierre Pronchery static OSSL_FUNC_rand_clear_seed_fn crng_test_clear_seed;
43*e7be843bSPierre Pronchery 
44*e7be843bSPierre Pronchery #ifndef ENTROPY_H
45*e7be843bSPierre Pronchery # define ENTROPY_H 6    /* default to six bits per byte of entropy */
46*e7be843bSPierre Pronchery #endif
47*e7be843bSPierre Pronchery #ifndef ENTROPY_APT_W
48*e7be843bSPierre Pronchery # define ENTROPY_APT_W 512
49*e7be843bSPierre Pronchery #endif
50*e7be843bSPierre Pronchery 
51*e7be843bSPierre Pronchery typedef struct crng_testal_st {
52*e7be843bSPierre Pronchery     void *provctx;
53*e7be843bSPierre Pronchery     CRYPTO_RWLOCK *lock;
54*e7be843bSPierre Pronchery     int state;
55*e7be843bSPierre Pronchery 
56*e7be843bSPierre Pronchery     /* State for SP 800-90B 4.4.1 Repetition Count Test */
57*e7be843bSPierre Pronchery     struct {
58*e7be843bSPierre Pronchery         unsigned int b;
59*e7be843bSPierre Pronchery         uint8_t a;
60*e7be843bSPierre Pronchery     } rct;
61*e7be843bSPierre Pronchery 
62*e7be843bSPierre Pronchery     /* State for SP 800-90B 4.4.2 Adaptive Proportion Test */
63*e7be843bSPierre Pronchery     struct {
64*e7be843bSPierre Pronchery         unsigned int b;
65*e7be843bSPierre Pronchery         unsigned int i;
66*e7be843bSPierre Pronchery         uint8_t a;
67*e7be843bSPierre Pronchery     } apt;
68*e7be843bSPierre Pronchery 
69*e7be843bSPierre Pronchery     /* Parent PROV_RAND and its dispatch table functions */
70*e7be843bSPierre Pronchery     void *parent;
71*e7be843bSPierre Pronchery     OSSL_FUNC_rand_enable_locking_fn *parent_enable_locking;
72*e7be843bSPierre Pronchery     OSSL_FUNC_rand_lock_fn *parent_lock;
73*e7be843bSPierre Pronchery     OSSL_FUNC_rand_unlock_fn *parent_unlock;
74*e7be843bSPierre Pronchery     OSSL_FUNC_rand_get_ctx_params_fn *parent_get_ctx_params;
75*e7be843bSPierre Pronchery     OSSL_FUNC_rand_gettable_ctx_params_fn *parent_gettable_ctx_params;
76*e7be843bSPierre Pronchery     OSSL_FUNC_rand_get_seed_fn *parent_get_seed;
77*e7be843bSPierre Pronchery     OSSL_FUNC_rand_clear_seed_fn *parent_clear_seed;
78*e7be843bSPierre Pronchery } CRNG_TEST;
79*e7be843bSPierre Pronchery 
80*e7be843bSPierre Pronchery /*
81*e7be843bSPierre Pronchery  * Some helper functions
82*e7be843bSPierre Pronchery  */
lock_parent(CRNG_TEST * crngt)83*e7be843bSPierre Pronchery static int lock_parent(CRNG_TEST *crngt)
84*e7be843bSPierre Pronchery {
85*e7be843bSPierre Pronchery     void *parent = crngt->parent;
86*e7be843bSPierre Pronchery 
87*e7be843bSPierre Pronchery     if (parent != NULL
88*e7be843bSPierre Pronchery             && crngt->parent_lock != NULL
89*e7be843bSPierre Pronchery             && !crngt->parent_lock(parent)) {
90*e7be843bSPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_LOCKING_NOT_ENABLED);
91*e7be843bSPierre Pronchery         return 0;
92*e7be843bSPierre Pronchery     }
93*e7be843bSPierre Pronchery     return 1;
94*e7be843bSPierre Pronchery }
95*e7be843bSPierre Pronchery 
unlock_parent(CRNG_TEST * crngt)96*e7be843bSPierre Pronchery static void unlock_parent(CRNG_TEST *crngt)
97*e7be843bSPierre Pronchery {
98*e7be843bSPierre Pronchery     void *parent = crngt->parent;
99*e7be843bSPierre Pronchery 
100*e7be843bSPierre Pronchery     if (parent != NULL && crngt->parent_unlock != NULL)
101*e7be843bSPierre Pronchery         crngt->parent_unlock(parent);
102*e7be843bSPierre Pronchery }
103*e7be843bSPierre Pronchery 
104*e7be843bSPierre Pronchery /*
105*e7be843bSPierre Pronchery  * Implementation of SP 800-90B section 4.4.1: Repetition Count Test
106*e7be843bSPierre Pronchery  */
RCT_test(CRNG_TEST * crngt,uint8_t next)107*e7be843bSPierre Pronchery static int RCT_test(CRNG_TEST *crngt, uint8_t next)
108*e7be843bSPierre Pronchery {
109*e7be843bSPierre Pronchery     /*
110*e7be843bSPierre Pronchery      * Critical values for this test are computed using:
111*e7be843bSPierre Pronchery      *
112*e7be843bSPierre Pronchery      *      C = 1 + \left\lceil\frac{-log_2 \alpha}H\right\rceil
113*e7be843bSPierre Pronchery      *
114*e7be843bSPierre Pronchery      * where alpha = 2^-20 and H is the expected entropy per sample.
115*e7be843bSPierre Pronchery      */
116*e7be843bSPierre Pronchery     static const unsigned int rct_c[9] = {
117*e7be843bSPierre Pronchery         41,                                 /* H = 0.5 */
118*e7be843bSPierre Pronchery         21, 11, 8, 6, 5, 5, 4, 4            /* H = 1, ..., 8 */
119*e7be843bSPierre Pronchery     };
120*e7be843bSPierre Pronchery 
121*e7be843bSPierre Pronchery     if (ossl_likely(crngt->rct.b != 0)
122*e7be843bSPierre Pronchery             && ossl_unlikely(next == crngt->rct.a))
123*e7be843bSPierre Pronchery         return ossl_likely(++crngt->rct.b < rct_c[ENTROPY_H]);
124*e7be843bSPierre Pronchery     crngt->rct.a = next;
125*e7be843bSPierre Pronchery     crngt->rct.b = 1;
126*e7be843bSPierre Pronchery     return 1;
127*e7be843bSPierre Pronchery }
128*e7be843bSPierre Pronchery 
129*e7be843bSPierre Pronchery /*
130*e7be843bSPierre Pronchery  * Implementation of SP 800-90B section 4.4.2: Adaptive Proportion Test
131*e7be843bSPierre Pronchery  */
APT_test(CRNG_TEST * crngt,uint8_t next)132*e7be843bSPierre Pronchery static int APT_test(CRNG_TEST *crngt, uint8_t next)
133*e7be843bSPierre Pronchery {
134*e7be843bSPierre Pronchery     /*
135*e7be843bSPierre Pronchery      * Critical values for this test are drawn from a binomial
136*e7be843bSPierre Pronchery      * distribution with n = 512, p = 2^-H at a critical threshold of
137*e7be843bSPierre Pronchery      * 2^-20.  H being the expected entropy per sample.  Refer SP 800-90B
138*e7be843bSPierre Pronchery      * section 4.4.2, table 2.
139*e7be843bSPierre Pronchery      */
140*e7be843bSPierre Pronchery     static const unsigned int apt_c[9] = {
141*e7be843bSPierre Pronchery         410,                                /* H = 0.5 */
142*e7be843bSPierre Pronchery         311, 177, 103, 62, 39, 25, 18, 13   /* H = 1, ..., 8 */
143*e7be843bSPierre Pronchery     };
144*e7be843bSPierre Pronchery 
145*e7be843bSPierre Pronchery     if (ossl_likely(crngt->apt.b != 0)) {
146*e7be843bSPierre Pronchery         if (ossl_unlikely(crngt->apt.a == next)
147*e7be843bSPierre Pronchery                 && ossl_unlikely(++crngt->apt.b >= apt_c[ENTROPY_H])) {
148*e7be843bSPierre Pronchery             crngt->apt.b = 0;
149*e7be843bSPierre Pronchery             return 0;
150*e7be843bSPierre Pronchery         }
151*e7be843bSPierre Pronchery         if (ossl_unlikely(++crngt->apt.i >= ENTROPY_APT_W))
152*e7be843bSPierre Pronchery             crngt->apt.b = 0;
153*e7be843bSPierre Pronchery         return 1;
154*e7be843bSPierre Pronchery     }
155*e7be843bSPierre Pronchery     crngt->apt.a = next;
156*e7be843bSPierre Pronchery     crngt->apt.b = 1;
157*e7be843bSPierre Pronchery     crngt->apt.i = 1;
158*e7be843bSPierre Pronchery     return 1;
159*e7be843bSPierre Pronchery }
160*e7be843bSPierre Pronchery 
crng_test(CRNG_TEST * crngt,const unsigned char * buf,size_t n)161*e7be843bSPierre Pronchery static int crng_test(CRNG_TEST *crngt, const unsigned char *buf, size_t n)
162*e7be843bSPierre Pronchery {
163*e7be843bSPierre Pronchery     size_t i;
164*e7be843bSPierre Pronchery 
165*e7be843bSPierre Pronchery     for (i = 0; i < n; i++)
166*e7be843bSPierre Pronchery         if (!RCT_test(crngt, buf[i]) || !APT_test(crngt, buf[i])) {
167*e7be843bSPierre Pronchery             crngt->state = EVP_RAND_STATE_ERROR;
168*e7be843bSPierre Pronchery             ERR_raise(ERR_LIB_PROV,
169*e7be843bSPierre Pronchery                       PROV_R_ENTROPY_SOURCE_FAILED_CONTINUOUS_TESTS);
170*e7be843bSPierre Pronchery             return 0;
171*e7be843bSPierre Pronchery         }
172*e7be843bSPierre Pronchery     return 1;
173*e7be843bSPierre Pronchery }
174*e7be843bSPierre Pronchery 
find_call(const OSSL_DISPATCH * dispatch,int function)175*e7be843bSPierre Pronchery static const OSSL_DISPATCH *find_call(const OSSL_DISPATCH *dispatch,
176*e7be843bSPierre Pronchery                                       int function)
177*e7be843bSPierre Pronchery {
178*e7be843bSPierre Pronchery     if (dispatch != NULL)
179*e7be843bSPierre Pronchery         while (dispatch->function_id != 0) {
180*e7be843bSPierre Pronchery             if (dispatch->function_id == function)
181*e7be843bSPierre Pronchery                 return dispatch;
182*e7be843bSPierre Pronchery             dispatch++;
183*e7be843bSPierre Pronchery         }
184*e7be843bSPierre Pronchery     return NULL;
185*e7be843bSPierre Pronchery }
186*e7be843bSPierre Pronchery 
crng_test_new(void * provctx,void * parent,const OSSL_DISPATCH * p_dispatch)187*e7be843bSPierre Pronchery static void *crng_test_new(void *provctx, void *parent,
188*e7be843bSPierre Pronchery                            const OSSL_DISPATCH *p_dispatch)
189*e7be843bSPierre Pronchery {
190*e7be843bSPierre Pronchery     CRNG_TEST *crngt = OPENSSL_zalloc(sizeof(*crngt));
191*e7be843bSPierre Pronchery     const OSSL_DISPATCH *pfunc;
192*e7be843bSPierre Pronchery 
193*e7be843bSPierre Pronchery     if (crngt == NULL)
194*e7be843bSPierre Pronchery         return NULL;
195*e7be843bSPierre Pronchery 
196*e7be843bSPierre Pronchery     crngt->provctx = provctx;
197*e7be843bSPierre Pronchery     crngt->state = EVP_RAND_STATE_UNINITIALISED;
198*e7be843bSPierre Pronchery 
199*e7be843bSPierre Pronchery     /* Extract parent's functions */
200*e7be843bSPierre Pronchery     if (parent != NULL) {
201*e7be843bSPierre Pronchery         crngt->parent = parent;
202*e7be843bSPierre Pronchery         if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_ENABLE_LOCKING)) != NULL)
203*e7be843bSPierre Pronchery             crngt->parent_enable_locking = OSSL_FUNC_rand_enable_locking(pfunc);
204*e7be843bSPierre Pronchery         if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_LOCK)) != NULL)
205*e7be843bSPierre Pronchery             crngt->parent_lock = OSSL_FUNC_rand_lock(pfunc);
206*e7be843bSPierre Pronchery         if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_UNLOCK)) != NULL)
207*e7be843bSPierre Pronchery             crngt->parent_unlock = OSSL_FUNC_rand_unlock(pfunc);
208*e7be843bSPierre Pronchery         if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS)) != NULL)
209*e7be843bSPierre Pronchery             crngt->parent_gettable_ctx_params = OSSL_FUNC_rand_gettable_ctx_params(pfunc);
210*e7be843bSPierre Pronchery         if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GET_CTX_PARAMS)) != NULL)
211*e7be843bSPierre Pronchery             crngt->parent_get_ctx_params = OSSL_FUNC_rand_get_ctx_params(pfunc);
212*e7be843bSPierre Pronchery         if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GET_SEED)) != NULL)
213*e7be843bSPierre Pronchery             crngt->parent_get_seed = OSSL_FUNC_rand_get_seed(pfunc);
214*e7be843bSPierre Pronchery         if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_CLEAR_SEED)) != NULL)
215*e7be843bSPierre Pronchery             crngt->parent_clear_seed = OSSL_FUNC_rand_clear_seed(pfunc);
216*e7be843bSPierre Pronchery     }
217*e7be843bSPierre Pronchery 
218*e7be843bSPierre Pronchery     return crngt;
219*e7be843bSPierre Pronchery }
220*e7be843bSPierre Pronchery 
crng_test_free(void * vcrngt)221*e7be843bSPierre Pronchery static void crng_test_free(void *vcrngt)
222*e7be843bSPierre Pronchery {
223*e7be843bSPierre Pronchery     CRNG_TEST *crngt = (CRNG_TEST *)vcrngt;
224*e7be843bSPierre Pronchery 
225*e7be843bSPierre Pronchery     if (crngt != NULL) {
226*e7be843bSPierre Pronchery         CRYPTO_THREAD_lock_free(crngt->lock);
227*e7be843bSPierre Pronchery         OPENSSL_free(crngt);
228*e7be843bSPierre Pronchery     }
229*e7be843bSPierre Pronchery }
230*e7be843bSPierre Pronchery 
crng_test_instantiate(void * vcrngt,unsigned int strength,int prediction_resistance,const unsigned char * pstr,size_t pstr_len,ossl_unused const OSSL_PARAM params[])231*e7be843bSPierre Pronchery static int crng_test_instantiate(void *vcrngt, unsigned int strength,
232*e7be843bSPierre Pronchery                                  int prediction_resistance,
233*e7be843bSPierre Pronchery                                  const unsigned char *pstr,
234*e7be843bSPierre Pronchery                                  size_t pstr_len,
235*e7be843bSPierre Pronchery                                  ossl_unused const OSSL_PARAM params[])
236*e7be843bSPierre Pronchery {
237*e7be843bSPierre Pronchery     CRNG_TEST *crngt = (CRNG_TEST *)vcrngt;
238*e7be843bSPierre Pronchery 
239*e7be843bSPierre Pronchery     /* Start up health tests should go here */
240*e7be843bSPierre Pronchery     crngt->state = EVP_RAND_STATE_READY;
241*e7be843bSPierre Pronchery     return 1;
242*e7be843bSPierre Pronchery }
243*e7be843bSPierre Pronchery 
crng_test_uninstantiate(void * vcrngt)244*e7be843bSPierre Pronchery static int crng_test_uninstantiate(void *vcrngt)
245*e7be843bSPierre Pronchery {
246*e7be843bSPierre Pronchery     CRNG_TEST *crngt = (CRNG_TEST *)vcrngt;
247*e7be843bSPierre Pronchery 
248*e7be843bSPierre Pronchery     crngt->state = EVP_RAND_STATE_UNINITIALISED;
249*e7be843bSPierre Pronchery     return 1;
250*e7be843bSPierre Pronchery }
251*e7be843bSPierre Pronchery 
crng_test_generate(void * vcrngt,unsigned char * out,size_t outlen,unsigned int strength,int prediction_resistance,const unsigned char * adin,size_t adin_len)252*e7be843bSPierre Pronchery static int crng_test_generate(void *vcrngt, unsigned char *out, size_t outlen,
253*e7be843bSPierre Pronchery                               unsigned int strength, int prediction_resistance,
254*e7be843bSPierre Pronchery                               const unsigned char *adin, size_t adin_len)
255*e7be843bSPierre Pronchery {
256*e7be843bSPierre Pronchery     unsigned char *p;
257*e7be843bSPierre Pronchery     CRNG_TEST *crngt = (CRNG_TEST *)vcrngt;
258*e7be843bSPierre Pronchery 
259*e7be843bSPierre Pronchery     if (!crng_test_get_seed(crngt, &p, 0, outlen, outlen, prediction_resistance,
260*e7be843bSPierre Pronchery                             adin, adin_len))
261*e7be843bSPierre Pronchery         return 0;
262*e7be843bSPierre Pronchery     memcpy(out, p, outlen);
263*e7be843bSPierre Pronchery     crng_test_clear_seed(crngt, p, outlen);
264*e7be843bSPierre Pronchery     return 1;
265*e7be843bSPierre Pronchery }
266*e7be843bSPierre Pronchery 
crng_test_reseed(ossl_unused void * vcrngt,ossl_unused int prediction_resistance,ossl_unused const unsigned char * ent,ossl_unused size_t ent_len,ossl_unused const unsigned char * adin,ossl_unused size_t adin_len)267*e7be843bSPierre Pronchery static int crng_test_reseed(ossl_unused void *vcrngt,
268*e7be843bSPierre Pronchery                             ossl_unused int prediction_resistance,
269*e7be843bSPierre Pronchery                             ossl_unused const unsigned char *ent,
270*e7be843bSPierre Pronchery                             ossl_unused size_t ent_len,
271*e7be843bSPierre Pronchery                             ossl_unused const unsigned char *adin,
272*e7be843bSPierre Pronchery                             ossl_unused size_t adin_len)
273*e7be843bSPierre Pronchery {
274*e7be843bSPierre Pronchery     return 1;
275*e7be843bSPierre Pronchery }
276*e7be843bSPierre Pronchery 
crng_test_verify_zeroization(ossl_unused void * vcrngt)277*e7be843bSPierre Pronchery static int crng_test_verify_zeroization(ossl_unused void *vcrngt)
278*e7be843bSPierre Pronchery {
279*e7be843bSPierre Pronchery     return 1;
280*e7be843bSPierre Pronchery }
281*e7be843bSPierre Pronchery 
crng_test_get_seed(void * vcrngt,unsigned char ** pout,int entropy,size_t min_len,size_t max_len,int prediction_resistance,const unsigned char * adin,size_t adin_len)282*e7be843bSPierre Pronchery static size_t crng_test_get_seed(void *vcrngt, unsigned char **pout,
283*e7be843bSPierre Pronchery                                  int entropy, size_t min_len,
284*e7be843bSPierre Pronchery                                  size_t max_len,
285*e7be843bSPierre Pronchery                                  int prediction_resistance,
286*e7be843bSPierre Pronchery                                  const unsigned char *adin,
287*e7be843bSPierre Pronchery                                  size_t adin_len)
288*e7be843bSPierre Pronchery {
289*e7be843bSPierre Pronchery     CRNG_TEST *crngt = (CRNG_TEST *)vcrngt;
290*e7be843bSPierre Pronchery     size_t n;
291*e7be843bSPierre Pronchery     int r = 0;
292*e7be843bSPierre Pronchery 
293*e7be843bSPierre Pronchery     /* Without a parent, we rely on the up calls */
294*e7be843bSPierre Pronchery     if (crngt->parent == NULL
295*e7be843bSPierre Pronchery             || crngt->parent_get_seed == NULL) {
296*e7be843bSPierre Pronchery         n = ossl_prov_get_entropy(crngt->provctx, pout, entropy,
297*e7be843bSPierre Pronchery                                   min_len, max_len);
298*e7be843bSPierre Pronchery         if (n == 0)
299*e7be843bSPierre Pronchery             return 0;
300*e7be843bSPierre Pronchery         r = crng_test(crngt, *pout, n);
301*e7be843bSPierre Pronchery         return r > 0 ? n : 0;
302*e7be843bSPierre Pronchery     }
303*e7be843bSPierre Pronchery 
304*e7be843bSPierre Pronchery     /* Grab seed from our parent */
305*e7be843bSPierre Pronchery     if (!lock_parent(crngt))
306*e7be843bSPierre Pronchery         return 0;
307*e7be843bSPierre Pronchery 
308*e7be843bSPierre Pronchery     n = crngt->parent_get_seed(crngt->parent, pout, entropy,
309*e7be843bSPierre Pronchery                                min_len, max_len, prediction_resistance,
310*e7be843bSPierre Pronchery                                adin, adin_len);
311*e7be843bSPierre Pronchery     if (n > 0 && crng_test(crngt, *pout, n) > 0)
312*e7be843bSPierre Pronchery         r = n;
313*e7be843bSPierre Pronchery     else if (crngt->parent_clear_seed != NULL)
314*e7be843bSPierre Pronchery         crngt->parent_clear_seed(crngt->parent, *pout, n);
315*e7be843bSPierre Pronchery     unlock_parent(crngt);
316*e7be843bSPierre Pronchery     return r;
317*e7be843bSPierre Pronchery }
318*e7be843bSPierre Pronchery 
crng_test_clear_seed(void * vcrngt,unsigned char * out,size_t outlen)319*e7be843bSPierre Pronchery static void crng_test_clear_seed(void *vcrngt,
320*e7be843bSPierre Pronchery                                  unsigned char *out, size_t outlen)
321*e7be843bSPierre Pronchery {
322*e7be843bSPierre Pronchery     CRNG_TEST *crngt = (CRNG_TEST *)vcrngt;
323*e7be843bSPierre Pronchery 
324*e7be843bSPierre Pronchery     if (crngt->parent == NULL || crngt->parent_get_seed == NULL)
325*e7be843bSPierre Pronchery         ossl_prov_cleanup_entropy(crngt->provctx, out, outlen);
326*e7be843bSPierre Pronchery     else if (crngt->parent_clear_seed != NULL)
327*e7be843bSPierre Pronchery         crngt->parent_clear_seed(crngt->parent, out, outlen);
328*e7be843bSPierre Pronchery }
329*e7be843bSPierre Pronchery 
crng_test_enable_locking(void * vcrngt)330*e7be843bSPierre Pronchery static int crng_test_enable_locking(void *vcrngt)
331*e7be843bSPierre Pronchery {
332*e7be843bSPierre Pronchery     CRNG_TEST *crngt = (CRNG_TEST *)vcrngt;
333*e7be843bSPierre Pronchery 
334*e7be843bSPierre Pronchery     if (crngt != NULL && crngt->lock == NULL) {
335*e7be843bSPierre Pronchery         if (crngt->parent_enable_locking != NULL)
336*e7be843bSPierre Pronchery             if (!crngt->parent_enable_locking(crngt->parent)) {
337*e7be843bSPierre Pronchery                 ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_LOCKING_NOT_ENABLED);
338*e7be843bSPierre Pronchery                 return 0;
339*e7be843bSPierre Pronchery             }
340*e7be843bSPierre Pronchery         crngt->lock = CRYPTO_THREAD_lock_new();
341*e7be843bSPierre Pronchery         if (crngt->lock == NULL) {
342*e7be843bSPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_CREATE_LOCK);
343*e7be843bSPierre Pronchery             return 0;
344*e7be843bSPierre Pronchery         }
345*e7be843bSPierre Pronchery     }
346*e7be843bSPierre Pronchery     return 1;
347*e7be843bSPierre Pronchery }
348*e7be843bSPierre Pronchery 
crng_test_lock(ossl_unused void * vcrngt)349*e7be843bSPierre Pronchery static int crng_test_lock(ossl_unused void *vcrngt)
350*e7be843bSPierre Pronchery {
351*e7be843bSPierre Pronchery     CRNG_TEST *crngt = (CRNG_TEST *)vcrngt;
352*e7be843bSPierre Pronchery 
353*e7be843bSPierre Pronchery     return crngt->lock == NULL || CRYPTO_THREAD_write_lock(crngt->lock);
354*e7be843bSPierre Pronchery }
355*e7be843bSPierre Pronchery 
crng_test_unlock(ossl_unused void * vcrngt)356*e7be843bSPierre Pronchery static void crng_test_unlock(ossl_unused void *vcrngt)
357*e7be843bSPierre Pronchery {
358*e7be843bSPierre Pronchery     CRNG_TEST *crngt = (CRNG_TEST *)vcrngt;
359*e7be843bSPierre Pronchery 
360*e7be843bSPierre Pronchery     if (crngt->lock != NULL)
361*e7be843bSPierre Pronchery         CRYPTO_THREAD_unlock(crngt->lock);
362*e7be843bSPierre Pronchery }
363*e7be843bSPierre Pronchery 
crng_test_get_ctx_params(void * vcrngt,OSSL_PARAM params[])364*e7be843bSPierre Pronchery static int crng_test_get_ctx_params(void *vcrngt, OSSL_PARAM params[])
365*e7be843bSPierre Pronchery {
366*e7be843bSPierre Pronchery     CRNG_TEST *crngt = (CRNG_TEST *)vcrngt;
367*e7be843bSPierre Pronchery     OSSL_PARAM *p;
368*e7be843bSPierre Pronchery 
369*e7be843bSPierre Pronchery     if (crngt->parent != NULL && crngt->parent_get_ctx_params != NULL)
370*e7be843bSPierre Pronchery         return crngt->parent_get_ctx_params(crngt->parent, params);
371*e7be843bSPierre Pronchery 
372*e7be843bSPierre Pronchery     /* No parent means we are using call backs for entropy */
373*e7be843bSPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE);
374*e7be843bSPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_int(p, crngt->state))
375*e7be843bSPierre Pronchery         return 0;
376*e7be843bSPierre Pronchery 
377*e7be843bSPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH);
378*e7be843bSPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_int(p, 1024))
379*e7be843bSPierre Pronchery         return 0;
380*e7be843bSPierre Pronchery 
381*e7be843bSPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
382*e7be843bSPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_size_t(p, 128))
383*e7be843bSPierre Pronchery         return 0;
384*e7be843bSPierre Pronchery 
385*e7be843bSPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_FIPS_APPROVED_INDICATOR);
386*e7be843bSPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_int(p, 0))
387*e7be843bSPierre Pronchery         return 0;
388*e7be843bSPierre Pronchery     return 1;
389*e7be843bSPierre Pronchery }
390*e7be843bSPierre Pronchery 
crng_test_gettable_ctx_params(void * vcrngt,void * provctx)391*e7be843bSPierre Pronchery static const OSSL_PARAM *crng_test_gettable_ctx_params(void *vcrngt,
392*e7be843bSPierre Pronchery                                                        void *provctx)
393*e7be843bSPierre Pronchery {
394*e7be843bSPierre Pronchery     CRNG_TEST *crngt = (CRNG_TEST *)vcrngt;
395*e7be843bSPierre Pronchery     static const OSSL_PARAM known_gettable_ctx_params[] = {
396*e7be843bSPierre Pronchery         OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL),
397*e7be843bSPierre Pronchery         OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL),
398*e7be843bSPierre Pronchery         OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL),
399*e7be843bSPierre Pronchery         OSSL_PARAM_int(OSSL_RAND_PARAM_FIPS_APPROVED_INDICATOR, NULL),
400*e7be843bSPierre Pronchery         OSSL_PARAM_END
401*e7be843bSPierre Pronchery     };
402*e7be843bSPierre Pronchery 
403*e7be843bSPierre Pronchery     if (crngt->parent != NULL && crngt->parent_gettable_ctx_params != NULL)
404*e7be843bSPierre Pronchery         return crngt->parent_gettable_ctx_params(crngt->parent, provctx);
405*e7be843bSPierre Pronchery     return known_gettable_ctx_params;
406*e7be843bSPierre Pronchery }
407*e7be843bSPierre Pronchery 
408*e7be843bSPierre Pronchery const OSSL_DISPATCH ossl_crng_test_functions[] = {
409*e7be843bSPierre Pronchery     { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))crng_test_new },
410*e7be843bSPierre Pronchery     { OSSL_FUNC_RAND_FREECTX, (void(*)(void))crng_test_free },
411*e7be843bSPierre Pronchery     { OSSL_FUNC_RAND_INSTANTIATE,
412*e7be843bSPierre Pronchery       (void(*)(void))crng_test_instantiate },
413*e7be843bSPierre Pronchery     { OSSL_FUNC_RAND_UNINSTANTIATE,
414*e7be843bSPierre Pronchery       (void(*)(void))crng_test_uninstantiate },
415*e7be843bSPierre Pronchery     { OSSL_FUNC_RAND_GENERATE, (void(*)(void))crng_test_generate },
416*e7be843bSPierre Pronchery     { OSSL_FUNC_RAND_RESEED, (void(*)(void))crng_test_reseed },
417*e7be843bSPierre Pronchery     { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))crng_test_enable_locking },
418*e7be843bSPierre Pronchery     { OSSL_FUNC_RAND_LOCK, (void(*)(void))crng_test_lock },
419*e7be843bSPierre Pronchery     { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))crng_test_unlock },
420*e7be843bSPierre Pronchery     { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
421*e7be843bSPierre Pronchery       (void(*)(void))crng_test_gettable_ctx_params },
422*e7be843bSPierre Pronchery     { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))crng_test_get_ctx_params },
423*e7be843bSPierre Pronchery     { OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
424*e7be843bSPierre Pronchery       (void(*)(void))crng_test_verify_zeroization },
425*e7be843bSPierre Pronchery     { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))crng_test_get_seed },
426*e7be843bSPierre Pronchery     { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))crng_test_clear_seed },
427*e7be843bSPierre Pronchery     OSSL_DISPATCH_END
428*e7be843bSPierre Pronchery };
429