xref: /aosp_15_r20/external/mbedtls/library/hmac_drbg.c (revision 62c56f9862f102b96d72393aff6076c951fb8148)
1*62c56f98SSadaf Ebrahimi /*
2*62c56f98SSadaf Ebrahimi  *  HMAC_DRBG implementation (NIST SP 800-90)
3*62c56f98SSadaf Ebrahimi  *
4*62c56f98SSadaf Ebrahimi  *  Copyright The Mbed TLS Contributors
5*62c56f98SSadaf Ebrahimi  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6*62c56f98SSadaf Ebrahimi  */
7*62c56f98SSadaf Ebrahimi 
8*62c56f98SSadaf Ebrahimi /*
9*62c56f98SSadaf Ebrahimi  *  The NIST SP 800-90A DRBGs are described in the following publication.
10*62c56f98SSadaf Ebrahimi  *  http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
11*62c56f98SSadaf Ebrahimi  *  References below are based on rev. 1 (January 2012).
12*62c56f98SSadaf Ebrahimi  */
13*62c56f98SSadaf Ebrahimi 
14*62c56f98SSadaf Ebrahimi #include "common.h"
15*62c56f98SSadaf Ebrahimi 
16*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_HMAC_DRBG_C)
17*62c56f98SSadaf Ebrahimi 
18*62c56f98SSadaf Ebrahimi #include "mbedtls/hmac_drbg.h"
19*62c56f98SSadaf Ebrahimi #include "mbedtls/platform_util.h"
20*62c56f98SSadaf Ebrahimi #include "mbedtls/error.h"
21*62c56f98SSadaf Ebrahimi 
22*62c56f98SSadaf Ebrahimi #include <string.h>
23*62c56f98SSadaf Ebrahimi 
24*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_FS_IO)
25*62c56f98SSadaf Ebrahimi #include <stdio.h>
26*62c56f98SSadaf Ebrahimi #endif
27*62c56f98SSadaf Ebrahimi 
28*62c56f98SSadaf Ebrahimi #include "mbedtls/platform.h"
29*62c56f98SSadaf Ebrahimi 
30*62c56f98SSadaf Ebrahimi /*
31*62c56f98SSadaf Ebrahimi  * HMAC_DRBG context initialization
32*62c56f98SSadaf Ebrahimi  */
mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context * ctx)33*62c56f98SSadaf Ebrahimi void mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context *ctx)
34*62c56f98SSadaf Ebrahimi {
35*62c56f98SSadaf Ebrahimi     memset(ctx, 0, sizeof(mbedtls_hmac_drbg_context));
36*62c56f98SSadaf Ebrahimi 
37*62c56f98SSadaf Ebrahimi     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
38*62c56f98SSadaf Ebrahimi }
39*62c56f98SSadaf Ebrahimi 
40*62c56f98SSadaf Ebrahimi /*
41*62c56f98SSadaf Ebrahimi  * HMAC_DRBG update, using optional additional data (10.1.2.2)
42*62c56f98SSadaf Ebrahimi  */
mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t add_len)43*62c56f98SSadaf Ebrahimi int mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx,
44*62c56f98SSadaf Ebrahimi                              const unsigned char *additional,
45*62c56f98SSadaf Ebrahimi                              size_t add_len)
46*62c56f98SSadaf Ebrahimi {
47*62c56f98SSadaf Ebrahimi     size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info);
48*62c56f98SSadaf Ebrahimi     unsigned char rounds = (additional != NULL && add_len != 0) ? 2 : 1;
49*62c56f98SSadaf Ebrahimi     unsigned char sep[1];
50*62c56f98SSadaf Ebrahimi     unsigned char K[MBEDTLS_MD_MAX_SIZE];
51*62c56f98SSadaf Ebrahimi     int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
52*62c56f98SSadaf Ebrahimi 
53*62c56f98SSadaf Ebrahimi     for (sep[0] = 0; sep[0] < rounds; sep[0]++) {
54*62c56f98SSadaf Ebrahimi         /* Step 1 or 4 */
55*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) {
56*62c56f98SSadaf Ebrahimi             goto exit;
57*62c56f98SSadaf Ebrahimi         }
58*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
59*62c56f98SSadaf Ebrahimi                                           ctx->V, md_len)) != 0) {
60*62c56f98SSadaf Ebrahimi             goto exit;
61*62c56f98SSadaf Ebrahimi         }
62*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
63*62c56f98SSadaf Ebrahimi                                           sep, 1)) != 0) {
64*62c56f98SSadaf Ebrahimi             goto exit;
65*62c56f98SSadaf Ebrahimi         }
66*62c56f98SSadaf Ebrahimi         if (rounds == 2) {
67*62c56f98SSadaf Ebrahimi             if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
68*62c56f98SSadaf Ebrahimi                                               additional, add_len)) != 0) {
69*62c56f98SSadaf Ebrahimi                 goto exit;
70*62c56f98SSadaf Ebrahimi             }
71*62c56f98SSadaf Ebrahimi         }
72*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, K)) != 0) {
73*62c56f98SSadaf Ebrahimi             goto exit;
74*62c56f98SSadaf Ebrahimi         }
75*62c56f98SSadaf Ebrahimi 
76*62c56f98SSadaf Ebrahimi         /* Step 2 or 5 */
77*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, K, md_len)) != 0) {
78*62c56f98SSadaf Ebrahimi             goto exit;
79*62c56f98SSadaf Ebrahimi         }
80*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
81*62c56f98SSadaf Ebrahimi                                           ctx->V, md_len)) != 0) {
82*62c56f98SSadaf Ebrahimi             goto exit;
83*62c56f98SSadaf Ebrahimi         }
84*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) {
85*62c56f98SSadaf Ebrahimi             goto exit;
86*62c56f98SSadaf Ebrahimi         }
87*62c56f98SSadaf Ebrahimi     }
88*62c56f98SSadaf Ebrahimi 
89*62c56f98SSadaf Ebrahimi exit:
90*62c56f98SSadaf Ebrahimi     mbedtls_platform_zeroize(K, sizeof(K));
91*62c56f98SSadaf Ebrahimi     return ret;
92*62c56f98SSadaf Ebrahimi }
93*62c56f98SSadaf Ebrahimi 
94*62c56f98SSadaf Ebrahimi /*
95*62c56f98SSadaf Ebrahimi  * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
96*62c56f98SSadaf Ebrahimi  */
mbedtls_hmac_drbg_seed_buf(mbedtls_hmac_drbg_context * ctx,const mbedtls_md_info_t * md_info,const unsigned char * data,size_t data_len)97*62c56f98SSadaf Ebrahimi int mbedtls_hmac_drbg_seed_buf(mbedtls_hmac_drbg_context *ctx,
98*62c56f98SSadaf Ebrahimi                                const mbedtls_md_info_t *md_info,
99*62c56f98SSadaf Ebrahimi                                const unsigned char *data, size_t data_len)
100*62c56f98SSadaf Ebrahimi {
101*62c56f98SSadaf Ebrahimi     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
102*62c56f98SSadaf Ebrahimi 
103*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {
104*62c56f98SSadaf Ebrahimi         return ret;
105*62c56f98SSadaf Ebrahimi     }
106*62c56f98SSadaf Ebrahimi 
107*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
108*62c56f98SSadaf Ebrahimi     mbedtls_mutex_init(&ctx->mutex);
109*62c56f98SSadaf Ebrahimi #endif
110*62c56f98SSadaf Ebrahimi 
111*62c56f98SSadaf Ebrahimi     /*
112*62c56f98SSadaf Ebrahimi      * Set initial working state.
113*62c56f98SSadaf Ebrahimi      * Use the V memory location, which is currently all 0, to initialize the
114*62c56f98SSadaf Ebrahimi      * MD context with an all-zero key. Then set V to its initial value.
115*62c56f98SSadaf Ebrahimi      */
116*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V,
117*62c56f98SSadaf Ebrahimi                                       mbedtls_md_get_size(md_info))) != 0) {
118*62c56f98SSadaf Ebrahimi         return ret;
119*62c56f98SSadaf Ebrahimi     }
120*62c56f98SSadaf Ebrahimi     memset(ctx->V, 0x01, mbedtls_md_get_size(md_info));
121*62c56f98SSadaf Ebrahimi 
122*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_hmac_drbg_update(ctx, data, data_len)) != 0) {
123*62c56f98SSadaf Ebrahimi         return ret;
124*62c56f98SSadaf Ebrahimi     }
125*62c56f98SSadaf Ebrahimi 
126*62c56f98SSadaf Ebrahimi     return 0;
127*62c56f98SSadaf Ebrahimi }
128*62c56f98SSadaf Ebrahimi 
129*62c56f98SSadaf Ebrahimi /*
130*62c56f98SSadaf Ebrahimi  * Internal function used both for seeding and reseeding the DRBG.
131*62c56f98SSadaf Ebrahimi  * Comments starting with arabic numbers refer to section 10.1.2.4
132*62c56f98SSadaf Ebrahimi  * of SP800-90A, while roman numbers refer to section 9.2.
133*62c56f98SSadaf Ebrahimi  */
hmac_drbg_reseed_core(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t len,int use_nonce)134*62c56f98SSadaf Ebrahimi static int hmac_drbg_reseed_core(mbedtls_hmac_drbg_context *ctx,
135*62c56f98SSadaf Ebrahimi                                  const unsigned char *additional, size_t len,
136*62c56f98SSadaf Ebrahimi                                  int use_nonce)
137*62c56f98SSadaf Ebrahimi {
138*62c56f98SSadaf Ebrahimi     unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
139*62c56f98SSadaf Ebrahimi     size_t seedlen = 0;
140*62c56f98SSadaf Ebrahimi     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
141*62c56f98SSadaf Ebrahimi 
142*62c56f98SSadaf Ebrahimi     {
143*62c56f98SSadaf Ebrahimi         size_t total_entropy_len;
144*62c56f98SSadaf Ebrahimi 
145*62c56f98SSadaf Ebrahimi         if (use_nonce == 0) {
146*62c56f98SSadaf Ebrahimi             total_entropy_len = ctx->entropy_len;
147*62c56f98SSadaf Ebrahimi         } else {
148*62c56f98SSadaf Ebrahimi             total_entropy_len = ctx->entropy_len * 3 / 2;
149*62c56f98SSadaf Ebrahimi         }
150*62c56f98SSadaf Ebrahimi 
151*62c56f98SSadaf Ebrahimi         /* III. Check input length */
152*62c56f98SSadaf Ebrahimi         if (len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
153*62c56f98SSadaf Ebrahimi             total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) {
154*62c56f98SSadaf Ebrahimi             return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
155*62c56f98SSadaf Ebrahimi         }
156*62c56f98SSadaf Ebrahimi     }
157*62c56f98SSadaf Ebrahimi 
158*62c56f98SSadaf Ebrahimi     memset(seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT);
159*62c56f98SSadaf Ebrahimi 
160*62c56f98SSadaf Ebrahimi     /* IV. Gather entropy_len bytes of entropy for the seed */
161*62c56f98SSadaf Ebrahimi     if ((ret = ctx->f_entropy(ctx->p_entropy,
162*62c56f98SSadaf Ebrahimi                               seed, ctx->entropy_len)) != 0) {
163*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;
164*62c56f98SSadaf Ebrahimi     }
165*62c56f98SSadaf Ebrahimi     seedlen += ctx->entropy_len;
166*62c56f98SSadaf Ebrahimi 
167*62c56f98SSadaf Ebrahimi     /* For initial seeding, allow adding of nonce generated
168*62c56f98SSadaf Ebrahimi      * from the entropy source. See Sect 8.6.7 in SP800-90A. */
169*62c56f98SSadaf Ebrahimi     if (use_nonce) {
170*62c56f98SSadaf Ebrahimi         /* Note: We don't merge the two calls to f_entropy() in order
171*62c56f98SSadaf Ebrahimi          *       to avoid requesting too much entropy from f_entropy()
172*62c56f98SSadaf Ebrahimi          *       at once. Specifically, if the underlying digest is not
173*62c56f98SSadaf Ebrahimi          *       SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which
174*62c56f98SSadaf Ebrahimi          *       is larger than the maximum of 32 Bytes that our own
175*62c56f98SSadaf Ebrahimi          *       entropy source implementation can emit in a single
176*62c56f98SSadaf Ebrahimi          *       call in configurations disabling SHA-512. */
177*62c56f98SSadaf Ebrahimi         if ((ret = ctx->f_entropy(ctx->p_entropy,
178*62c56f98SSadaf Ebrahimi                                   seed + seedlen,
179*62c56f98SSadaf Ebrahimi                                   ctx->entropy_len / 2)) != 0) {
180*62c56f98SSadaf Ebrahimi             return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;
181*62c56f98SSadaf Ebrahimi         }
182*62c56f98SSadaf Ebrahimi 
183*62c56f98SSadaf Ebrahimi         seedlen += ctx->entropy_len / 2;
184*62c56f98SSadaf Ebrahimi     }
185*62c56f98SSadaf Ebrahimi 
186*62c56f98SSadaf Ebrahimi 
187*62c56f98SSadaf Ebrahimi     /* 1. Concatenate entropy and additional data if any */
188*62c56f98SSadaf Ebrahimi     if (additional != NULL && len != 0) {
189*62c56f98SSadaf Ebrahimi         memcpy(seed + seedlen, additional, len);
190*62c56f98SSadaf Ebrahimi         seedlen += len;
191*62c56f98SSadaf Ebrahimi     }
192*62c56f98SSadaf Ebrahimi 
193*62c56f98SSadaf Ebrahimi     /* 2. Update state */
194*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_hmac_drbg_update(ctx, seed, seedlen)) != 0) {
195*62c56f98SSadaf Ebrahimi         goto exit;
196*62c56f98SSadaf Ebrahimi     }
197*62c56f98SSadaf Ebrahimi 
198*62c56f98SSadaf Ebrahimi     /* 3. Reset reseed_counter */
199*62c56f98SSadaf Ebrahimi     ctx->reseed_counter = 1;
200*62c56f98SSadaf Ebrahimi 
201*62c56f98SSadaf Ebrahimi exit:
202*62c56f98SSadaf Ebrahimi     /* 4. Done */
203*62c56f98SSadaf Ebrahimi     mbedtls_platform_zeroize(seed, seedlen);
204*62c56f98SSadaf Ebrahimi     return ret;
205*62c56f98SSadaf Ebrahimi }
206*62c56f98SSadaf Ebrahimi 
207*62c56f98SSadaf Ebrahimi /*
208*62c56f98SSadaf Ebrahimi  * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
209*62c56f98SSadaf Ebrahimi  */
mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context * ctx,const unsigned char * additional,size_t len)210*62c56f98SSadaf Ebrahimi int mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context *ctx,
211*62c56f98SSadaf Ebrahimi                              const unsigned char *additional, size_t len)
212*62c56f98SSadaf Ebrahimi {
213*62c56f98SSadaf Ebrahimi     return hmac_drbg_reseed_core(ctx, additional, len, 0);
214*62c56f98SSadaf Ebrahimi }
215*62c56f98SSadaf Ebrahimi 
216*62c56f98SSadaf Ebrahimi /*
217*62c56f98SSadaf Ebrahimi  * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
218*62c56f98SSadaf Ebrahimi  *
219*62c56f98SSadaf Ebrahimi  * The nonce is not passed as a separate parameter but extracted
220*62c56f98SSadaf Ebrahimi  * from the entropy source as suggested in 8.6.7.
221*62c56f98SSadaf Ebrahimi  */
mbedtls_hmac_drbg_seed(mbedtls_hmac_drbg_context * ctx,const mbedtls_md_info_t * md_info,int (* f_entropy)(void *,unsigned char *,size_t),void * p_entropy,const unsigned char * custom,size_t len)222*62c56f98SSadaf Ebrahimi int mbedtls_hmac_drbg_seed(mbedtls_hmac_drbg_context *ctx,
223*62c56f98SSadaf Ebrahimi                            const mbedtls_md_info_t *md_info,
224*62c56f98SSadaf Ebrahimi                            int (*f_entropy)(void *, unsigned char *, size_t),
225*62c56f98SSadaf Ebrahimi                            void *p_entropy,
226*62c56f98SSadaf Ebrahimi                            const unsigned char *custom,
227*62c56f98SSadaf Ebrahimi                            size_t len)
228*62c56f98SSadaf Ebrahimi {
229*62c56f98SSadaf Ebrahimi     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
230*62c56f98SSadaf Ebrahimi     size_t md_size;
231*62c56f98SSadaf Ebrahimi 
232*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {
233*62c56f98SSadaf Ebrahimi         return ret;
234*62c56f98SSadaf Ebrahimi     }
235*62c56f98SSadaf Ebrahimi 
236*62c56f98SSadaf Ebrahimi     /* The mutex is initialized iff the md context is set up. */
237*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
238*62c56f98SSadaf Ebrahimi     mbedtls_mutex_init(&ctx->mutex);
239*62c56f98SSadaf Ebrahimi #endif
240*62c56f98SSadaf Ebrahimi 
241*62c56f98SSadaf Ebrahimi     md_size = mbedtls_md_get_size(md_info);
242*62c56f98SSadaf Ebrahimi 
243*62c56f98SSadaf Ebrahimi     /*
244*62c56f98SSadaf Ebrahimi      * Set initial working state.
245*62c56f98SSadaf Ebrahimi      * Use the V memory location, which is currently all 0, to initialize the
246*62c56f98SSadaf Ebrahimi      * MD context with an all-zero key. Then set V to its initial value.
247*62c56f98SSadaf Ebrahimi      */
248*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V, md_size)) != 0) {
249*62c56f98SSadaf Ebrahimi         return ret;
250*62c56f98SSadaf Ebrahimi     }
251*62c56f98SSadaf Ebrahimi     memset(ctx->V, 0x01, md_size);
252*62c56f98SSadaf Ebrahimi 
253*62c56f98SSadaf Ebrahimi     ctx->f_entropy = f_entropy;
254*62c56f98SSadaf Ebrahimi     ctx->p_entropy = p_entropy;
255*62c56f98SSadaf Ebrahimi 
256*62c56f98SSadaf Ebrahimi     if (ctx->entropy_len == 0) {
257*62c56f98SSadaf Ebrahimi         /*
258*62c56f98SSadaf Ebrahimi          * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
259*62c56f98SSadaf Ebrahimi          * each hash function, then according to SP800-90A rev1 10.1 table 2,
260*62c56f98SSadaf Ebrahimi          * min_entropy_len (in bits) is security_strength.
261*62c56f98SSadaf Ebrahimi          *
262*62c56f98SSadaf Ebrahimi          * (This also matches the sizes used in the NIST test vectors.)
263*62c56f98SSadaf Ebrahimi          */
264*62c56f98SSadaf Ebrahimi         ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
265*62c56f98SSadaf Ebrahimi                            md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
266*62c56f98SSadaf Ebrahimi                            32;  /* better (256+) -> 256 bits */
267*62c56f98SSadaf Ebrahimi     }
268*62c56f98SSadaf Ebrahimi 
269*62c56f98SSadaf Ebrahimi     if ((ret = hmac_drbg_reseed_core(ctx, custom, len,
270*62c56f98SSadaf Ebrahimi                                      1 /* add nonce */)) != 0) {
271*62c56f98SSadaf Ebrahimi         return ret;
272*62c56f98SSadaf Ebrahimi     }
273*62c56f98SSadaf Ebrahimi 
274*62c56f98SSadaf Ebrahimi     return 0;
275*62c56f98SSadaf Ebrahimi }
276*62c56f98SSadaf Ebrahimi 
277*62c56f98SSadaf Ebrahimi /*
278*62c56f98SSadaf Ebrahimi  * Set prediction resistance
279*62c56f98SSadaf Ebrahimi  */
mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context * ctx,int resistance)280*62c56f98SSadaf Ebrahimi void mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context *ctx,
281*62c56f98SSadaf Ebrahimi                                                  int resistance)
282*62c56f98SSadaf Ebrahimi {
283*62c56f98SSadaf Ebrahimi     ctx->prediction_resistance = resistance;
284*62c56f98SSadaf Ebrahimi }
285*62c56f98SSadaf Ebrahimi 
286*62c56f98SSadaf Ebrahimi /*
287*62c56f98SSadaf Ebrahimi  * Set entropy length grabbed for seeding
288*62c56f98SSadaf Ebrahimi  */
mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context * ctx,size_t len)289*62c56f98SSadaf Ebrahimi void mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context *ctx, size_t len)
290*62c56f98SSadaf Ebrahimi {
291*62c56f98SSadaf Ebrahimi     ctx->entropy_len = len;
292*62c56f98SSadaf Ebrahimi }
293*62c56f98SSadaf Ebrahimi 
294*62c56f98SSadaf Ebrahimi /*
295*62c56f98SSadaf Ebrahimi  * Set reseed interval
296*62c56f98SSadaf Ebrahimi  */
mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context * ctx,int interval)297*62c56f98SSadaf Ebrahimi void mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context *ctx, int interval)
298*62c56f98SSadaf Ebrahimi {
299*62c56f98SSadaf Ebrahimi     ctx->reseed_interval = interval;
300*62c56f98SSadaf Ebrahimi }
301*62c56f98SSadaf Ebrahimi 
302*62c56f98SSadaf Ebrahimi /*
303*62c56f98SSadaf Ebrahimi  * HMAC_DRBG random function with optional additional data:
304*62c56f98SSadaf Ebrahimi  * 10.1.2.5 (arabic) + 9.3 (Roman)
305*62c56f98SSadaf Ebrahimi  */
mbedtls_hmac_drbg_random_with_add(void * p_rng,unsigned char * output,size_t out_len,const unsigned char * additional,size_t add_len)306*62c56f98SSadaf Ebrahimi int mbedtls_hmac_drbg_random_with_add(void *p_rng,
307*62c56f98SSadaf Ebrahimi                                       unsigned char *output, size_t out_len,
308*62c56f98SSadaf Ebrahimi                                       const unsigned char *additional, size_t add_len)
309*62c56f98SSadaf Ebrahimi {
310*62c56f98SSadaf Ebrahimi     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
311*62c56f98SSadaf Ebrahimi     mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
312*62c56f98SSadaf Ebrahimi     size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info);
313*62c56f98SSadaf Ebrahimi     size_t left = out_len;
314*62c56f98SSadaf Ebrahimi     unsigned char *out = output;
315*62c56f98SSadaf Ebrahimi 
316*62c56f98SSadaf Ebrahimi     /* II. Check request length */
317*62c56f98SSadaf Ebrahimi     if (out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST) {
318*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG;
319*62c56f98SSadaf Ebrahimi     }
320*62c56f98SSadaf Ebrahimi 
321*62c56f98SSadaf Ebrahimi     /* III. Check input length */
322*62c56f98SSadaf Ebrahimi     if (add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT) {
323*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
324*62c56f98SSadaf Ebrahimi     }
325*62c56f98SSadaf Ebrahimi 
326*62c56f98SSadaf Ebrahimi     /* 1. (aka VII and IX) Check reseed counter and PR */
327*62c56f98SSadaf Ebrahimi     if (ctx->f_entropy != NULL && /* For no-reseeding instances */
328*62c56f98SSadaf Ebrahimi         (ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
329*62c56f98SSadaf Ebrahimi          ctx->reseed_counter > ctx->reseed_interval)) {
330*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_hmac_drbg_reseed(ctx, additional, add_len)) != 0) {
331*62c56f98SSadaf Ebrahimi             return ret;
332*62c56f98SSadaf Ebrahimi         }
333*62c56f98SSadaf Ebrahimi 
334*62c56f98SSadaf Ebrahimi         add_len = 0; /* VII.4 */
335*62c56f98SSadaf Ebrahimi     }
336*62c56f98SSadaf Ebrahimi 
337*62c56f98SSadaf Ebrahimi     /* 2. Use additional data if any */
338*62c56f98SSadaf Ebrahimi     if (additional != NULL && add_len != 0) {
339*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_hmac_drbg_update(ctx,
340*62c56f98SSadaf Ebrahimi                                             additional, add_len)) != 0) {
341*62c56f98SSadaf Ebrahimi             goto exit;
342*62c56f98SSadaf Ebrahimi         }
343*62c56f98SSadaf Ebrahimi     }
344*62c56f98SSadaf Ebrahimi 
345*62c56f98SSadaf Ebrahimi     /* 3, 4, 5. Generate bytes */
346*62c56f98SSadaf Ebrahimi     while (left != 0) {
347*62c56f98SSadaf Ebrahimi         size_t use_len = left > md_len ? md_len : left;
348*62c56f98SSadaf Ebrahimi 
349*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) {
350*62c56f98SSadaf Ebrahimi             goto exit;
351*62c56f98SSadaf Ebrahimi         }
352*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
353*62c56f98SSadaf Ebrahimi                                           ctx->V, md_len)) != 0) {
354*62c56f98SSadaf Ebrahimi             goto exit;
355*62c56f98SSadaf Ebrahimi         }
356*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) {
357*62c56f98SSadaf Ebrahimi             goto exit;
358*62c56f98SSadaf Ebrahimi         }
359*62c56f98SSadaf Ebrahimi 
360*62c56f98SSadaf Ebrahimi         memcpy(out, ctx->V, use_len);
361*62c56f98SSadaf Ebrahimi         out += use_len;
362*62c56f98SSadaf Ebrahimi         left -= use_len;
363*62c56f98SSadaf Ebrahimi     }
364*62c56f98SSadaf Ebrahimi 
365*62c56f98SSadaf Ebrahimi     /* 6. Update */
366*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_hmac_drbg_update(ctx,
367*62c56f98SSadaf Ebrahimi                                         additional, add_len)) != 0) {
368*62c56f98SSadaf Ebrahimi         goto exit;
369*62c56f98SSadaf Ebrahimi     }
370*62c56f98SSadaf Ebrahimi 
371*62c56f98SSadaf Ebrahimi     /* 7. Update reseed counter */
372*62c56f98SSadaf Ebrahimi     ctx->reseed_counter++;
373*62c56f98SSadaf Ebrahimi 
374*62c56f98SSadaf Ebrahimi exit:
375*62c56f98SSadaf Ebrahimi     /* 8. Done */
376*62c56f98SSadaf Ebrahimi     return ret;
377*62c56f98SSadaf Ebrahimi }
378*62c56f98SSadaf Ebrahimi 
379*62c56f98SSadaf Ebrahimi /*
380*62c56f98SSadaf Ebrahimi  * HMAC_DRBG random function
381*62c56f98SSadaf Ebrahimi  */
mbedtls_hmac_drbg_random(void * p_rng,unsigned char * output,size_t out_len)382*62c56f98SSadaf Ebrahimi int mbedtls_hmac_drbg_random(void *p_rng, unsigned char *output, size_t out_len)
383*62c56f98SSadaf Ebrahimi {
384*62c56f98SSadaf Ebrahimi     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
385*62c56f98SSadaf Ebrahimi     mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
386*62c56f98SSadaf Ebrahimi 
387*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
388*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
389*62c56f98SSadaf Ebrahimi         return ret;
390*62c56f98SSadaf Ebrahimi     }
391*62c56f98SSadaf Ebrahimi #endif
392*62c56f98SSadaf Ebrahimi 
393*62c56f98SSadaf Ebrahimi     ret = mbedtls_hmac_drbg_random_with_add(ctx, output, out_len, NULL, 0);
394*62c56f98SSadaf Ebrahimi 
395*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
396*62c56f98SSadaf Ebrahimi     if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
397*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
398*62c56f98SSadaf Ebrahimi     }
399*62c56f98SSadaf Ebrahimi #endif
400*62c56f98SSadaf Ebrahimi 
401*62c56f98SSadaf Ebrahimi     return ret;
402*62c56f98SSadaf Ebrahimi }
403*62c56f98SSadaf Ebrahimi 
404*62c56f98SSadaf Ebrahimi /*
405*62c56f98SSadaf Ebrahimi  *  This function resets HMAC_DRBG context to the state immediately
406*62c56f98SSadaf Ebrahimi  *  after initial call of mbedtls_hmac_drbg_init().
407*62c56f98SSadaf Ebrahimi  */
mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context * ctx)408*62c56f98SSadaf Ebrahimi void mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context *ctx)
409*62c56f98SSadaf Ebrahimi {
410*62c56f98SSadaf Ebrahimi     if (ctx == NULL) {
411*62c56f98SSadaf Ebrahimi         return;
412*62c56f98SSadaf Ebrahimi     }
413*62c56f98SSadaf Ebrahimi 
414*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
415*62c56f98SSadaf Ebrahimi     /* The mutex is initialized iff the md context is set up. */
416*62c56f98SSadaf Ebrahimi     if (ctx->md_ctx.md_info != NULL) {
417*62c56f98SSadaf Ebrahimi         mbedtls_mutex_free(&ctx->mutex);
418*62c56f98SSadaf Ebrahimi     }
419*62c56f98SSadaf Ebrahimi #endif
420*62c56f98SSadaf Ebrahimi     mbedtls_md_free(&ctx->md_ctx);
421*62c56f98SSadaf Ebrahimi     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_hmac_drbg_context));
422*62c56f98SSadaf Ebrahimi     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
423*62c56f98SSadaf Ebrahimi }
424*62c56f98SSadaf Ebrahimi 
425*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_FS_IO)
mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context * ctx,const char * path)426*62c56f98SSadaf Ebrahimi int mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)
427*62c56f98SSadaf Ebrahimi {
428*62c56f98SSadaf Ebrahimi     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
429*62c56f98SSadaf Ebrahimi     FILE *f;
430*62c56f98SSadaf Ebrahimi     unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];
431*62c56f98SSadaf Ebrahimi 
432*62c56f98SSadaf Ebrahimi     if ((f = fopen(path, "wb")) == NULL) {
433*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
434*62c56f98SSadaf Ebrahimi     }
435*62c56f98SSadaf Ebrahimi 
436*62c56f98SSadaf Ebrahimi     /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
437*62c56f98SSadaf Ebrahimi     mbedtls_setbuf(f, NULL);
438*62c56f98SSadaf Ebrahimi 
439*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_hmac_drbg_random(ctx, buf, sizeof(buf))) != 0) {
440*62c56f98SSadaf Ebrahimi         goto exit;
441*62c56f98SSadaf Ebrahimi     }
442*62c56f98SSadaf Ebrahimi 
443*62c56f98SSadaf Ebrahimi     if (fwrite(buf, 1, sizeof(buf), f) != sizeof(buf)) {
444*62c56f98SSadaf Ebrahimi         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
445*62c56f98SSadaf Ebrahimi         goto exit;
446*62c56f98SSadaf Ebrahimi     }
447*62c56f98SSadaf Ebrahimi 
448*62c56f98SSadaf Ebrahimi     ret = 0;
449*62c56f98SSadaf Ebrahimi 
450*62c56f98SSadaf Ebrahimi exit:
451*62c56f98SSadaf Ebrahimi     fclose(f);
452*62c56f98SSadaf Ebrahimi     mbedtls_platform_zeroize(buf, sizeof(buf));
453*62c56f98SSadaf Ebrahimi 
454*62c56f98SSadaf Ebrahimi     return ret;
455*62c56f98SSadaf Ebrahimi }
456*62c56f98SSadaf Ebrahimi 
mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context * ctx,const char * path)457*62c56f98SSadaf Ebrahimi int mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)
458*62c56f98SSadaf Ebrahimi {
459*62c56f98SSadaf Ebrahimi     int ret = 0;
460*62c56f98SSadaf Ebrahimi     FILE *f = NULL;
461*62c56f98SSadaf Ebrahimi     size_t n;
462*62c56f98SSadaf Ebrahimi     unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];
463*62c56f98SSadaf Ebrahimi     unsigned char c;
464*62c56f98SSadaf Ebrahimi 
465*62c56f98SSadaf Ebrahimi     if ((f = fopen(path, "rb")) == NULL) {
466*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
467*62c56f98SSadaf Ebrahimi     }
468*62c56f98SSadaf Ebrahimi 
469*62c56f98SSadaf Ebrahimi     /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
470*62c56f98SSadaf Ebrahimi     mbedtls_setbuf(f, NULL);
471*62c56f98SSadaf Ebrahimi 
472*62c56f98SSadaf Ebrahimi     n = fread(buf, 1, sizeof(buf), f);
473*62c56f98SSadaf Ebrahimi     if (fread(&c, 1, 1, f) != 0) {
474*62c56f98SSadaf Ebrahimi         ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
475*62c56f98SSadaf Ebrahimi         goto exit;
476*62c56f98SSadaf Ebrahimi     }
477*62c56f98SSadaf Ebrahimi     if (n == 0 || ferror(f)) {
478*62c56f98SSadaf Ebrahimi         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
479*62c56f98SSadaf Ebrahimi         goto exit;
480*62c56f98SSadaf Ebrahimi     }
481*62c56f98SSadaf Ebrahimi     fclose(f);
482*62c56f98SSadaf Ebrahimi     f = NULL;
483*62c56f98SSadaf Ebrahimi 
484*62c56f98SSadaf Ebrahimi     ret = mbedtls_hmac_drbg_update(ctx, buf, n);
485*62c56f98SSadaf Ebrahimi 
486*62c56f98SSadaf Ebrahimi exit:
487*62c56f98SSadaf Ebrahimi     mbedtls_platform_zeroize(buf, sizeof(buf));
488*62c56f98SSadaf Ebrahimi     if (f != NULL) {
489*62c56f98SSadaf Ebrahimi         fclose(f);
490*62c56f98SSadaf Ebrahimi     }
491*62c56f98SSadaf Ebrahimi     if (ret != 0) {
492*62c56f98SSadaf Ebrahimi         return ret;
493*62c56f98SSadaf Ebrahimi     }
494*62c56f98SSadaf Ebrahimi     return mbedtls_hmac_drbg_write_seed_file(ctx, path);
495*62c56f98SSadaf Ebrahimi }
496*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_FS_IO */
497*62c56f98SSadaf Ebrahimi 
498*62c56f98SSadaf Ebrahimi 
499*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_SELF_TEST)
500*62c56f98SSadaf Ebrahimi 
501*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_MD_CAN_SHA1)
502*62c56f98SSadaf Ebrahimi /* Dummy checkup routine */
mbedtls_hmac_drbg_self_test(int verbose)503*62c56f98SSadaf Ebrahimi int mbedtls_hmac_drbg_self_test(int verbose)
504*62c56f98SSadaf Ebrahimi {
505*62c56f98SSadaf Ebrahimi     (void) verbose;
506*62c56f98SSadaf Ebrahimi     return 0;
507*62c56f98SSadaf Ebrahimi }
508*62c56f98SSadaf Ebrahimi #else
509*62c56f98SSadaf Ebrahimi 
510*62c56f98SSadaf Ebrahimi #define OUTPUT_LEN  80
511*62c56f98SSadaf Ebrahimi 
512*62c56f98SSadaf Ebrahimi /* From a NIST PR=true test vector */
513*62c56f98SSadaf Ebrahimi static const unsigned char entropy_pr[] = {
514*62c56f98SSadaf Ebrahimi     0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
515*62c56f98SSadaf Ebrahimi     0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
516*62c56f98SSadaf Ebrahimi     0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
517*62c56f98SSadaf Ebrahimi     0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
518*62c56f98SSadaf Ebrahimi     0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4
519*62c56f98SSadaf Ebrahimi };
520*62c56f98SSadaf Ebrahimi static const unsigned char result_pr[OUTPUT_LEN] = {
521*62c56f98SSadaf Ebrahimi     0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
522*62c56f98SSadaf Ebrahimi     0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
523*62c56f98SSadaf Ebrahimi     0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
524*62c56f98SSadaf Ebrahimi     0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
525*62c56f98SSadaf Ebrahimi     0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
526*62c56f98SSadaf Ebrahimi     0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
527*62c56f98SSadaf Ebrahimi     0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44
528*62c56f98SSadaf Ebrahimi };
529*62c56f98SSadaf Ebrahimi 
530*62c56f98SSadaf Ebrahimi /* From a NIST PR=false test vector */
531*62c56f98SSadaf Ebrahimi static const unsigned char entropy_nopr[] = {
532*62c56f98SSadaf Ebrahimi     0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
533*62c56f98SSadaf Ebrahimi     0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
534*62c56f98SSadaf Ebrahimi     0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
535*62c56f98SSadaf Ebrahimi     0xe9, 0x9d, 0xfe, 0xdf
536*62c56f98SSadaf Ebrahimi };
537*62c56f98SSadaf Ebrahimi static const unsigned char result_nopr[OUTPUT_LEN] = {
538*62c56f98SSadaf Ebrahimi     0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
539*62c56f98SSadaf Ebrahimi     0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
540*62c56f98SSadaf Ebrahimi     0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
541*62c56f98SSadaf Ebrahimi     0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
542*62c56f98SSadaf Ebrahimi     0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
543*62c56f98SSadaf Ebrahimi     0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
544*62c56f98SSadaf Ebrahimi     0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7
545*62c56f98SSadaf Ebrahimi };
546*62c56f98SSadaf Ebrahimi 
547*62c56f98SSadaf Ebrahimi /* "Entropy" from buffer */
548*62c56f98SSadaf Ebrahimi static size_t test_offset;
hmac_drbg_self_test_entropy(void * data,unsigned char * buf,size_t len)549*62c56f98SSadaf Ebrahimi static int hmac_drbg_self_test_entropy(void *data,
550*62c56f98SSadaf Ebrahimi                                        unsigned char *buf, size_t len)
551*62c56f98SSadaf Ebrahimi {
552*62c56f98SSadaf Ebrahimi     const unsigned char *p = data;
553*62c56f98SSadaf Ebrahimi     memcpy(buf, p + test_offset, len);
554*62c56f98SSadaf Ebrahimi     test_offset += len;
555*62c56f98SSadaf Ebrahimi     return 0;
556*62c56f98SSadaf Ebrahimi }
557*62c56f98SSadaf Ebrahimi 
558*62c56f98SSadaf Ebrahimi #define CHK(c)    if ((c) != 0)                          \
559*62c56f98SSadaf Ebrahimi     {                                       \
560*62c56f98SSadaf Ebrahimi         if (verbose != 0)                  \
561*62c56f98SSadaf Ebrahimi         mbedtls_printf("failed\n");  \
562*62c56f98SSadaf Ebrahimi         return 1;                        \
563*62c56f98SSadaf Ebrahimi     }
564*62c56f98SSadaf Ebrahimi 
565*62c56f98SSadaf Ebrahimi /*
566*62c56f98SSadaf Ebrahimi  * Checkup routine for HMAC_DRBG with SHA-1
567*62c56f98SSadaf Ebrahimi  */
mbedtls_hmac_drbg_self_test(int verbose)568*62c56f98SSadaf Ebrahimi int mbedtls_hmac_drbg_self_test(int verbose)
569*62c56f98SSadaf Ebrahimi {
570*62c56f98SSadaf Ebrahimi     mbedtls_hmac_drbg_context ctx;
571*62c56f98SSadaf Ebrahimi     unsigned char buf[OUTPUT_LEN];
572*62c56f98SSadaf Ebrahimi     const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
573*62c56f98SSadaf Ebrahimi 
574*62c56f98SSadaf Ebrahimi     mbedtls_hmac_drbg_init(&ctx);
575*62c56f98SSadaf Ebrahimi 
576*62c56f98SSadaf Ebrahimi     /*
577*62c56f98SSadaf Ebrahimi      * PR = True
578*62c56f98SSadaf Ebrahimi      */
579*62c56f98SSadaf Ebrahimi     if (verbose != 0) {
580*62c56f98SSadaf Ebrahimi         mbedtls_printf("  HMAC_DRBG (PR = True) : ");
581*62c56f98SSadaf Ebrahimi     }
582*62c56f98SSadaf Ebrahimi 
583*62c56f98SSadaf Ebrahimi     test_offset = 0;
584*62c56f98SSadaf Ebrahimi     CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,
585*62c56f98SSadaf Ebrahimi                                hmac_drbg_self_test_entropy, (void *) entropy_pr,
586*62c56f98SSadaf Ebrahimi                                NULL, 0));
587*62c56f98SSadaf Ebrahimi     mbedtls_hmac_drbg_set_prediction_resistance(&ctx, MBEDTLS_HMAC_DRBG_PR_ON);
588*62c56f98SSadaf Ebrahimi     CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
589*62c56f98SSadaf Ebrahimi     CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
590*62c56f98SSadaf Ebrahimi     CHK(memcmp(buf, result_pr, OUTPUT_LEN));
591*62c56f98SSadaf Ebrahimi     mbedtls_hmac_drbg_free(&ctx);
592*62c56f98SSadaf Ebrahimi 
593*62c56f98SSadaf Ebrahimi     mbedtls_hmac_drbg_free(&ctx);
594*62c56f98SSadaf Ebrahimi 
595*62c56f98SSadaf Ebrahimi     if (verbose != 0) {
596*62c56f98SSadaf Ebrahimi         mbedtls_printf("passed\n");
597*62c56f98SSadaf Ebrahimi     }
598*62c56f98SSadaf Ebrahimi 
599*62c56f98SSadaf Ebrahimi     /*
600*62c56f98SSadaf Ebrahimi      * PR = False
601*62c56f98SSadaf Ebrahimi      */
602*62c56f98SSadaf Ebrahimi     if (verbose != 0) {
603*62c56f98SSadaf Ebrahimi         mbedtls_printf("  HMAC_DRBG (PR = False) : ");
604*62c56f98SSadaf Ebrahimi     }
605*62c56f98SSadaf Ebrahimi 
606*62c56f98SSadaf Ebrahimi     mbedtls_hmac_drbg_init(&ctx);
607*62c56f98SSadaf Ebrahimi 
608*62c56f98SSadaf Ebrahimi     test_offset = 0;
609*62c56f98SSadaf Ebrahimi     CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,
610*62c56f98SSadaf Ebrahimi                                hmac_drbg_self_test_entropy, (void *) entropy_nopr,
611*62c56f98SSadaf Ebrahimi                                NULL, 0));
612*62c56f98SSadaf Ebrahimi     CHK(mbedtls_hmac_drbg_reseed(&ctx, NULL, 0));
613*62c56f98SSadaf Ebrahimi     CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
614*62c56f98SSadaf Ebrahimi     CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
615*62c56f98SSadaf Ebrahimi     CHK(memcmp(buf, result_nopr, OUTPUT_LEN));
616*62c56f98SSadaf Ebrahimi     mbedtls_hmac_drbg_free(&ctx);
617*62c56f98SSadaf Ebrahimi 
618*62c56f98SSadaf Ebrahimi     mbedtls_hmac_drbg_free(&ctx);
619*62c56f98SSadaf Ebrahimi 
620*62c56f98SSadaf Ebrahimi     if (verbose != 0) {
621*62c56f98SSadaf Ebrahimi         mbedtls_printf("passed\n");
622*62c56f98SSadaf Ebrahimi     }
623*62c56f98SSadaf Ebrahimi 
624*62c56f98SSadaf Ebrahimi     if (verbose != 0) {
625*62c56f98SSadaf Ebrahimi         mbedtls_printf("\n");
626*62c56f98SSadaf Ebrahimi     }
627*62c56f98SSadaf Ebrahimi 
628*62c56f98SSadaf Ebrahimi     return 0;
629*62c56f98SSadaf Ebrahimi }
630*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_MD_CAN_SHA1 */
631*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_SELF_TEST */
632*62c56f98SSadaf Ebrahimi 
633*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_HMAC_DRBG_C */
634