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