xref: /freebsd/crypto/openssl/providers/implementations/rands/drbg_hmac.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1 /*
2  * Copyright 2011-2025 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <stdlib.h>
11 #include <string.h>
12 #include <openssl/crypto.h>
13 #include <openssl/err.h>
14 #include <openssl/rand.h>
15 #include <openssl/proverr.h>
16 #include "internal/thread_once.h"
17 #include "prov/providercommon.h"
18 #include "prov/implementations.h"
19 #include "prov/provider_ctx.h"
20 #include "prov/hmac_drbg.h"
21 #include "drbg_local.h"
22 #include "crypto/evp.h"
23 #include "crypto/evp/evp_local.h"
24 #include "internal/provider.h"
25 
26 static OSSL_FUNC_rand_newctx_fn drbg_hmac_new_wrapper;
27 static OSSL_FUNC_rand_freectx_fn drbg_hmac_free;
28 static OSSL_FUNC_rand_instantiate_fn drbg_hmac_instantiate_wrapper;
29 static OSSL_FUNC_rand_uninstantiate_fn drbg_hmac_uninstantiate_wrapper;
30 static OSSL_FUNC_rand_generate_fn drbg_hmac_generate_wrapper;
31 static OSSL_FUNC_rand_reseed_fn drbg_hmac_reseed_wrapper;
32 static OSSL_FUNC_rand_settable_ctx_params_fn drbg_hmac_settable_ctx_params;
33 static OSSL_FUNC_rand_set_ctx_params_fn drbg_hmac_set_ctx_params;
34 static OSSL_FUNC_rand_gettable_ctx_params_fn drbg_hmac_gettable_ctx_params;
35 static OSSL_FUNC_rand_get_ctx_params_fn drbg_hmac_get_ctx_params;
36 static OSSL_FUNC_rand_verify_zeroization_fn drbg_hmac_verify_zeroization;
37 
38 static int drbg_hmac_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[]);
39 
40 /*
41  * Called twice by SP800-90Ar1 10.1.2.2 HMAC_DRBG_Update_Process.
42  *
43  * hmac is an object that holds the input/output Key and Value (K and V).
44  * inbyte is 0x00 on the first call and 0x01 on the second call.
45  * in1, in2, in3 are optional inputs that can be NULL.
46  * in1len, in2len, in3len are the lengths of the input buffers.
47  *
48  * The returned K,V is:
49  *   hmac->K = HMAC(hmac->K, hmac->V || inbyte || [in1] || [in2] || [in3])
50  *   hmac->V = HMAC(hmac->K, hmac->V)
51  *
52  * Returns zero if an error occurs otherwise it returns 1.
53  */
do_hmac(PROV_DRBG_HMAC * hmac,unsigned char inbyte,const unsigned char * in1,size_t in1len,const unsigned char * in2,size_t in2len,const unsigned char * in3,size_t in3len)54 static int do_hmac(PROV_DRBG_HMAC *hmac, unsigned char inbyte,
55                    const unsigned char *in1, size_t in1len,
56                    const unsigned char *in2, size_t in2len,
57                    const unsigned char *in3, size_t in3len)
58 {
59     EVP_MAC_CTX *ctx = hmac->ctx;
60 
61     if (!EVP_MAC_init(ctx, hmac->K, hmac->blocklen, NULL)
62             /* K = HMAC(K, V || inbyte || [in1] || [in2] || [in3]) */
63             || !EVP_MAC_update(ctx, hmac->V, hmac->blocklen)
64             || !EVP_MAC_update(ctx, &inbyte, 1)
65             || !(in1 == NULL || in1len == 0 || EVP_MAC_update(ctx, in1, in1len))
66             || !(in2 == NULL || in2len == 0 || EVP_MAC_update(ctx, in2, in2len))
67             || !(in3 == NULL || in3len == 0 || EVP_MAC_update(ctx, in3, in3len))
68             || !EVP_MAC_final(ctx, hmac->K, NULL, sizeof(hmac->K)))
69         return 0;
70 
71    /* V = HMAC(K, V) */
72     return EVP_MAC_init(ctx, hmac->K, hmac->blocklen, NULL)
73            && EVP_MAC_update(ctx, hmac->V, hmac->blocklen)
74            && EVP_MAC_final(ctx, hmac->V, NULL, sizeof(hmac->V));
75 }
76 
77 /*
78  * SP800-90Ar1 10.1.2.2 HMAC_DRBG_Update_Process
79  *
80  *
81  * Updates the drbg objects Key(K) and Value(V) using the following algorithm:
82  *   K,V = do_hmac(hmac, 0, in1, in2, in3)
83  *   if (any input is not NULL)
84  *     K,V = do_hmac(hmac, 1, in1, in2, in3)
85  *
86  * where in1, in2, in3 are optional input buffers that can be NULL.
87  *       in1len, in2len, in3len are the lengths of the input buffers.
88  *
89  * Returns zero if an error occurs otherwise it returns 1.
90  */
drbg_hmac_update(PROV_DRBG_HMAC * hmac,const unsigned char * in1,size_t in1len,const unsigned char * in2,size_t in2len,const unsigned char * in3,size_t in3len)91 static int drbg_hmac_update(PROV_DRBG_HMAC *hmac,
92                             const unsigned char *in1, size_t in1len,
93                             const unsigned char *in2, size_t in2len,
94                             const unsigned char *in3, size_t in3len)
95 {
96     /* (Steps 1-2) K = HMAC(K, V||0x00||provided_data). V = HMAC(K,V) */
97     if (!do_hmac(hmac, 0x00, in1, in1len, in2, in2len, in3, in3len))
98         return 0;
99     /* (Step 3) If provided_data == NULL then return (K,V) */
100     if (in1len == 0 && in2len == 0 && in3len == 0)
101         return 1;
102     /* (Steps 4-5) K = HMAC(K, V||0x01||provided_data). V = HMAC(K,V) */
103     return do_hmac(hmac, 0x01, in1, in1len, in2, in2len, in3, in3len);
104 }
105 
106 /*
107  * SP800-90Ar1 10.1.2.3 HMAC_DRBG_Instantiate_Process:
108  *
109  * This sets the drbg Key (K) to all zeros, and Value (V) to all 1's.
110  * and then calls (K,V) = drbg_hmac_update() with input parameters:
111  *   ent = entropy data (Can be NULL) of length ent_len.
112  *   nonce = nonce data (Can be NULL) of length nonce_len.
113  *   pstr = personalization data (Can be NULL) of length pstr_len.
114  *
115  * Returns zero if an error occurs otherwise it returns 1.
116  */
ossl_drbg_hmac_init(PROV_DRBG_HMAC * hmac,const unsigned char * ent,size_t ent_len,const unsigned char * nonce,size_t nonce_len,const unsigned char * pstr,size_t pstr_len)117 int ossl_drbg_hmac_init(PROV_DRBG_HMAC *hmac,
118                         const unsigned char *ent, size_t ent_len,
119                         const unsigned char *nonce, size_t nonce_len,
120                         const unsigned char *pstr, size_t pstr_len)
121 {
122     if (hmac->ctx == NULL) {
123         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MAC);
124         return 0;
125     }
126 
127     /* (Step 2) Key = 0x00 00...00 */
128     memset(hmac->K, 0x00, hmac->blocklen);
129     /* (Step 3) V = 0x01 01...01 */
130     memset(hmac->V, 0x01, hmac->blocklen);
131     /* (Step 4) (K,V) = HMAC_DRBG_Update(entropy||nonce||pers string, K, V) */
132     return drbg_hmac_update(hmac, ent, ent_len, nonce, nonce_len, pstr,
133                             pstr_len);
134 }
drbg_hmac_instantiate(PROV_DRBG * drbg,const unsigned char * ent,size_t ent_len,const unsigned char * nonce,size_t nonce_len,const unsigned char * pstr,size_t pstr_len)135 static int drbg_hmac_instantiate(PROV_DRBG *drbg,
136                                  const unsigned char *ent, size_t ent_len,
137                                  const unsigned char *nonce, size_t nonce_len,
138                                  const unsigned char *pstr, size_t pstr_len)
139 {
140     return ossl_drbg_hmac_init((PROV_DRBG_HMAC *)drbg->data, ent, ent_len,
141                                nonce, nonce_len, pstr, pstr_len);
142 }
143 
drbg_hmac_instantiate_wrapper(void * vdrbg,unsigned int strength,int prediction_resistance,const unsigned char * pstr,size_t pstr_len,const OSSL_PARAM params[])144 static int drbg_hmac_instantiate_wrapper(void *vdrbg, unsigned int strength,
145                                          int prediction_resistance,
146                                          const unsigned char *pstr,
147                                          size_t pstr_len,
148                                          const OSSL_PARAM params[])
149 {
150     PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
151     int ret = 0;
152 
153     if (drbg->lock != NULL && !CRYPTO_THREAD_write_lock(drbg->lock))
154         return 0;
155 
156     if (!ossl_prov_is_running()
157             || !drbg_hmac_set_ctx_params_locked(drbg, params))
158         goto err;
159     ret = ossl_prov_drbg_instantiate(drbg, strength, prediction_resistance,
160                                      pstr, pstr_len);
161  err:
162     if (drbg->lock != NULL)
163         CRYPTO_THREAD_unlock(drbg->lock);
164     return ret;
165 }
166 
167 
168 /*
169  * SP800-90Ar1 10.1.2.4 HMAC_DRBG_Reseed_Process:
170  *
171  * Reseeds the drbg's Key (K) and Value (V) by calling
172  * (K,V) = drbg_hmac_update() with the following input parameters:
173  *   ent = entropy input data (Can be NULL) of length ent_len.
174  *   adin = additional input data (Can be NULL) of length adin_len.
175  *
176  * Returns zero if an error occurs otherwise it returns 1.
177  */
drbg_hmac_reseed(PROV_DRBG * drbg,const unsigned char * ent,size_t ent_len,const unsigned char * adin,size_t adin_len)178 static int drbg_hmac_reseed(PROV_DRBG *drbg,
179                             const unsigned char *ent, size_t ent_len,
180                             const unsigned char *adin, size_t adin_len)
181 {
182     PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
183 
184     /* (Step 2) (K,V) = HMAC_DRBG_Update(entropy||additional_input, K, V) */
185     return drbg_hmac_update(hmac, ent, ent_len, adin, adin_len, NULL, 0);
186 }
187 
drbg_hmac_reseed_wrapper(void * vdrbg,int prediction_resistance,const unsigned char * ent,size_t ent_len,const unsigned char * adin,size_t adin_len)188 static int drbg_hmac_reseed_wrapper(void *vdrbg, int prediction_resistance,
189                                     const unsigned char *ent, size_t ent_len,
190                                     const unsigned char *adin, size_t adin_len)
191 {
192     PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
193 
194     return ossl_prov_drbg_reseed(drbg, prediction_resistance, ent, ent_len,
195                                  adin, adin_len);
196 }
197 
198 /*
199  * SP800-90Ar1 10.1.2.5 HMAC_DRBG_Generate_Process:
200  *
201  * Generates pseudo random bytes and updates the internal K,V for the drbg.
202  * out is a buffer to fill with outlen bytes of pseudo random data.
203  * adin is an additional_input string of size adin_len that may be NULL.
204  *
205  * Returns zero if an error occurs otherwise it returns 1.
206  */
ossl_drbg_hmac_generate(PROV_DRBG_HMAC * hmac,unsigned char * out,size_t outlen,const unsigned char * adin,size_t adin_len)207 int ossl_drbg_hmac_generate(PROV_DRBG_HMAC *hmac,
208                             unsigned char *out, size_t outlen,
209                             const unsigned char *adin, size_t adin_len)
210 {
211     EVP_MAC_CTX *ctx = hmac->ctx;
212     const unsigned char *temp = hmac->V;
213 
214     /* (Step 2) if adin != NULL then (K,V) = HMAC_DRBG_Update(adin, K, V) */
215     if (adin != NULL
216             && adin_len > 0
217             && !drbg_hmac_update(hmac, adin, adin_len, NULL, 0, NULL, 0))
218         return 0;
219 
220     /*
221      * (Steps 3-5) temp = NULL
222      *             while (len(temp) < outlen) {
223      *                 V = HMAC(K, V)
224      *                 temp = temp || V
225      *             }
226      */
227     for (;;) {
228         if (!EVP_MAC_init(ctx, hmac->K, hmac->blocklen, NULL)
229             || !EVP_MAC_update(ctx, temp, hmac->blocklen))
230             return 0;
231 
232         if (outlen > hmac->blocklen) {
233             if (!EVP_MAC_final(ctx, out, NULL, outlen))
234                 return 0;
235             temp = out;
236         } else {
237             if (!EVP_MAC_final(ctx, hmac->V, NULL, sizeof(hmac->V)))
238                 return 0;
239             memcpy(out, hmac->V, outlen);
240             break;
241         }
242         out += hmac->blocklen;
243         outlen -= hmac->blocklen;
244     }
245     /* (Step 6) (K,V) = HMAC_DRBG_Update(adin, K, V) */
246     if (!drbg_hmac_update(hmac, adin, adin_len, NULL, 0, NULL, 0))
247         return 0;
248 
249     return 1;
250 }
251 
drbg_hmac_generate(PROV_DRBG * drbg,unsigned char * out,size_t outlen,const unsigned char * adin,size_t adin_len)252 static int drbg_hmac_generate(PROV_DRBG *drbg,
253                               unsigned char *out, size_t outlen,
254                               const unsigned char *adin, size_t adin_len)
255 {
256     return ossl_drbg_hmac_generate((PROV_DRBG_HMAC *)drbg->data, out, outlen,
257                                     adin, adin_len);
258 }
259 
drbg_hmac_generate_wrapper(void * vdrbg,unsigned char * out,size_t outlen,unsigned int strength,int prediction_resistance,const unsigned char * adin,size_t adin_len)260 static int drbg_hmac_generate_wrapper(void *vdrbg,
261      unsigned char *out, size_t outlen, unsigned int strength,
262      int prediction_resistance, const unsigned char *adin, size_t adin_len)
263 {
264     PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
265 
266     return ossl_prov_drbg_generate(drbg, out, outlen, strength,
267                                    prediction_resistance, adin, adin_len);
268 }
269 
drbg_hmac_uninstantiate(PROV_DRBG * drbg)270 static int drbg_hmac_uninstantiate(PROV_DRBG *drbg)
271 {
272     PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
273 
274     OPENSSL_cleanse(hmac->K, sizeof(hmac->K));
275     OPENSSL_cleanse(hmac->V, sizeof(hmac->V));
276     return ossl_prov_drbg_uninstantiate(drbg);
277 }
278 
drbg_hmac_uninstantiate_wrapper(void * vdrbg)279 static int drbg_hmac_uninstantiate_wrapper(void *vdrbg)
280 {
281     PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
282     int ret;
283 
284     if (drbg->lock != NULL && !CRYPTO_THREAD_write_lock(drbg->lock))
285         return 0;
286 
287     ret = drbg_hmac_uninstantiate(drbg);
288 
289     if (drbg->lock != NULL)
290         CRYPTO_THREAD_unlock(drbg->lock);
291 
292     return ret;
293 }
294 
drbg_hmac_verify_zeroization(void * vdrbg)295 static int drbg_hmac_verify_zeroization(void *vdrbg)
296 {
297     PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
298     PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
299     int ret = 0;
300 
301     if (drbg->lock != NULL && !CRYPTO_THREAD_read_lock(drbg->lock))
302         return 0;
303 
304     PROV_DRBG_VERIFY_ZEROIZATION(hmac->K);
305     PROV_DRBG_VERIFY_ZEROIZATION(hmac->V);
306 
307     ret = 1;
308  err:
309     if (drbg->lock != NULL)
310         CRYPTO_THREAD_unlock(drbg->lock);
311     return ret;
312 }
313 
drbg_hmac_new(PROV_DRBG * drbg)314 static int drbg_hmac_new(PROV_DRBG *drbg)
315 {
316     PROV_DRBG_HMAC *hmac;
317 
318     hmac = OPENSSL_secure_zalloc(sizeof(*hmac));
319     if (hmac == NULL)
320         return 0;
321 
322     OSSL_FIPS_IND_INIT(drbg)
323 
324     drbg->data = hmac;
325     /* See SP800-57 Part1 Rev4 5.6.1 Table 3 */
326     drbg->max_entropylen = DRBG_MAX_LENGTH;
327     drbg->max_noncelen = DRBG_MAX_LENGTH;
328     drbg->max_perslen = DRBG_MAX_LENGTH;
329     drbg->max_adinlen = DRBG_MAX_LENGTH;
330 
331     /* Maximum number of bits per request = 2^19  = 2^16 bytes */
332     drbg->max_request = 1 << 16;
333     return 1;
334 }
335 
drbg_hmac_new_wrapper(void * provctx,void * parent,const OSSL_DISPATCH * parent_dispatch)336 static void *drbg_hmac_new_wrapper(void *provctx, void *parent,
337                                    const OSSL_DISPATCH *parent_dispatch)
338 {
339     return ossl_rand_drbg_new(provctx, parent, parent_dispatch,
340                               &drbg_hmac_new, &drbg_hmac_free,
341                               &drbg_hmac_instantiate, &drbg_hmac_uninstantiate,
342                               &drbg_hmac_reseed, &drbg_hmac_generate);
343 }
344 
drbg_hmac_free(void * vdrbg)345 static void drbg_hmac_free(void *vdrbg)
346 {
347     PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
348     PROV_DRBG_HMAC *hmac;
349 
350     if (drbg != NULL && (hmac = (PROV_DRBG_HMAC *)drbg->data) != NULL) {
351         EVP_MAC_CTX_free(hmac->ctx);
352         ossl_prov_digest_reset(&hmac->digest);
353         OPENSSL_secure_clear_free(hmac, sizeof(*hmac));
354     }
355     ossl_rand_drbg_free(drbg);
356 }
357 
drbg_hmac_get_ctx_params(void * vdrbg,OSSL_PARAM params[])358 static int drbg_hmac_get_ctx_params(void *vdrbg, OSSL_PARAM params[])
359 {
360     PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
361     PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
362     const char *name;
363     const EVP_MD *md;
364     OSSL_PARAM *p;
365     int ret = 0, complete = 0;
366 
367     if (!ossl_drbg_get_ctx_params_no_lock(drbg, params, &complete))
368         return 0;
369 
370     if (complete)
371         return 1;
372 
373     if (drbg->lock != NULL && !CRYPTO_THREAD_read_lock(drbg->lock))
374         return 0;
375 
376     p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAC);
377     if (p != NULL) {
378         if (hmac->ctx == NULL)
379             goto err;
380         name = EVP_MAC_get0_name(EVP_MAC_CTX_get0_mac(hmac->ctx));
381         if (!OSSL_PARAM_set_utf8_string(p, name))
382             goto err;
383     }
384 
385     p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_DIGEST);
386     if (p != NULL) {
387         md = ossl_prov_digest_md(&hmac->digest);
388         if (md == NULL || !OSSL_PARAM_set_utf8_string(p, EVP_MD_get0_name(md)))
389             goto err;
390     }
391 
392     ret = ossl_drbg_get_ctx_params(drbg, params);
393  err:
394     if (drbg->lock != NULL)
395         CRYPTO_THREAD_unlock(drbg->lock);
396 
397     return ret;
398 }
399 
drbg_hmac_gettable_ctx_params(ossl_unused void * vctx,ossl_unused void * p_ctx)400 static const OSSL_PARAM *drbg_hmac_gettable_ctx_params(ossl_unused void *vctx,
401                                                        ossl_unused void *p_ctx)
402 {
403     static const OSSL_PARAM known_gettable_ctx_params[] = {
404         OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_MAC, NULL, 0),
405         OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_DIGEST, NULL, 0),
406         OSSL_PARAM_DRBG_GETTABLE_CTX_COMMON,
407         OSSL_FIPS_IND_GETTABLE_CTX_PARAM()
408         OSSL_PARAM_END
409     };
410     return known_gettable_ctx_params;
411 }
412 
drbg_fetch_algs_from_prov(const OSSL_PARAM params[],OSSL_LIB_CTX * libctx,EVP_MAC_CTX ** macctx,EVP_MD ** digest)413 static int drbg_fetch_algs_from_prov(const OSSL_PARAM params[],
414                                      OSSL_LIB_CTX *libctx,
415                                      EVP_MAC_CTX **macctx,
416                                      EVP_MD **digest)
417 {
418     OSSL_PROVIDER *prov = NULL;
419     const OSSL_PARAM *p;
420     EVP_MD *md = NULL;
421     EVP_MAC *mac = NULL;
422     int ret = 0;
423 
424     if (macctx == NULL || digest == NULL)
425         return 0;
426 
427     if ((p = OSSL_PARAM_locate_const(params,
428                                      OSSL_PROV_PARAM_CORE_PROV_NAME)) == NULL)
429         return 0;
430     if (p->data_type != OSSL_PARAM_UTF8_STRING)
431         return 0;
432     if ((prov = ossl_provider_find(libctx, (const char *)p->data, 1)) == NULL)
433         return 0;
434 
435     p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST);
436     if (p) {
437         if (p->data_type != OSSL_PARAM_UTF8_STRING)
438             goto done;
439 
440         md = evp_digest_fetch_from_prov(prov, (const char *)p->data, NULL);
441         if (md) {
442             EVP_MD_free(*digest);
443             *digest = md;
444         } else {
445             goto done;
446         }
447     }
448 
449     p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_MAC);
450     if (p == NULL) {
451         ret = 1;
452         goto done;
453     }
454 
455     if (p->data_type != OSSL_PARAM_UTF8_STRING)
456         goto done;
457 
458     EVP_MAC_CTX_free(*macctx);
459     *macctx = NULL;
460 
461     mac = evp_mac_fetch_from_prov(prov, (const char *)p->data, NULL);
462     if (mac) {
463         *macctx = EVP_MAC_CTX_new(mac);
464         /* The context holds on to the MAC */
465         EVP_MAC_free(mac);
466         ret = 1;
467     }
468 
469 done:
470     ossl_provider_free(prov);
471     return ret;
472 }
473 
drbg_hmac_set_ctx_params_locked(void * vctx,const OSSL_PARAM params[])474 static int drbg_hmac_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[])
475 {
476     PROV_DRBG *ctx = (PROV_DRBG *)vctx;
477     PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)ctx->data;
478     OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
479     EVP_MD *prov_md = NULL;
480     const EVP_MD *md;
481     int md_size;
482 
483     if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE0, params,
484                                      OSSL_DRBG_PARAM_FIPS_DIGEST_CHECK))
485         return 0;
486 
487     /* try to fetch mac and digest from provider */
488     (void)ERR_set_mark();
489     if (!drbg_fetch_algs_from_prov(params, libctx, &hmac->ctx, &prov_md)) {
490         (void)ERR_pop_to_mark();
491         /* fall back to full implementation search */
492         if (!ossl_prov_digest_load_from_params(&hmac->digest, params, libctx))
493             return 0;
494 
495         if (!ossl_prov_macctx_load_from_params(&hmac->ctx, params,
496                                                NULL, NULL, NULL, libctx))
497             return 0;
498     } else {
499         (void)ERR_clear_last_mark();
500         if (prov_md)
501             ossl_prov_digest_set_md(&hmac->digest, prov_md);
502     }
503 
504     md = ossl_prov_digest_md(&hmac->digest);
505     if (md != NULL && !ossl_drbg_verify_digest(ctx, libctx, md))
506         return 0;   /* Error already raised for us */
507 
508     if (md != NULL && hmac->ctx != NULL) {
509         /* These are taken from SP 800-90 10.1 Table 2 */
510         md_size = EVP_MD_get_size(md);
511         if (md_size <= 0)
512             return 0;
513         hmac->blocklen = (size_t)md_size;
514         /* See SP800-57 Part1 Rev4 5.6.1 Table 3 */
515         ctx->strength = 64 * (int)(hmac->blocklen >> 3);
516         if (ctx->strength > 256)
517             ctx->strength = 256;
518         ctx->seedlen = hmac->blocklen;
519         ctx->min_entropylen = ctx->strength / 8;
520         ctx->min_noncelen = ctx->min_entropylen / 2;
521     }
522 
523     return ossl_drbg_set_ctx_params(ctx, params);
524 }
525 
drbg_hmac_set_ctx_params(void * vctx,const OSSL_PARAM params[])526 static int drbg_hmac_set_ctx_params(void *vctx, const OSSL_PARAM params[])
527 {
528     PROV_DRBG *drbg = (PROV_DRBG *)vctx;
529     int ret;
530 
531     if (drbg->lock != NULL && !CRYPTO_THREAD_write_lock(drbg->lock))
532         return 0;
533 
534     ret = drbg_hmac_set_ctx_params_locked(vctx, params);
535 
536     if (drbg->lock != NULL)
537         CRYPTO_THREAD_unlock(drbg->lock);
538 
539     return ret;
540 }
541 
drbg_hmac_settable_ctx_params(ossl_unused void * vctx,ossl_unused void * p_ctx)542 static const OSSL_PARAM *drbg_hmac_settable_ctx_params(ossl_unused void *vctx,
543                                                        ossl_unused void *p_ctx)
544 {
545     static const OSSL_PARAM known_settable_ctx_params[] = {
546         OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_PROPERTIES, NULL, 0),
547         OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_DIGEST, NULL, 0),
548         OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_MAC, NULL, 0),
549         OSSL_PARAM_DRBG_SETTABLE_CTX_COMMON,
550         OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_DRBG_PARAM_FIPS_DIGEST_CHECK)
551         OSSL_PARAM_END
552     };
553     return known_settable_ctx_params;
554 }
555 
556 const OSSL_DISPATCH ossl_drbg_ossl_hmac_functions[] = {
557     { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))drbg_hmac_new_wrapper },
558     { OSSL_FUNC_RAND_FREECTX, (void(*)(void))drbg_hmac_free },
559     { OSSL_FUNC_RAND_INSTANTIATE,
560       (void(*)(void))drbg_hmac_instantiate_wrapper },
561     { OSSL_FUNC_RAND_UNINSTANTIATE,
562       (void(*)(void))drbg_hmac_uninstantiate_wrapper },
563     { OSSL_FUNC_RAND_GENERATE, (void(*)(void))drbg_hmac_generate_wrapper },
564     { OSSL_FUNC_RAND_RESEED, (void(*)(void))drbg_hmac_reseed_wrapper },
565     { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))ossl_drbg_enable_locking },
566     { OSSL_FUNC_RAND_LOCK, (void(*)(void))ossl_drbg_lock },
567     { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))ossl_drbg_unlock },
568     { OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS,
569       (void(*)(void))drbg_hmac_settable_ctx_params },
570     { OSSL_FUNC_RAND_SET_CTX_PARAMS, (void(*)(void))drbg_hmac_set_ctx_params },
571     { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
572       (void(*)(void))drbg_hmac_gettable_ctx_params },
573     { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))drbg_hmac_get_ctx_params },
574     { OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
575       (void(*)(void))drbg_hmac_verify_zeroization },
576     { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))ossl_drbg_get_seed },
577     { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))ossl_drbg_clear_seed },
578     OSSL_DISPATCH_END
579 };
580