1 /* fips/rand/fips_drbg_hash.c */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
5 /* ====================================================================
6 * Copyright (c) 2011 The OpenSSL Project. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
34 * 6. Redistributions of any form whatsoever must retain the following
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
54 #define OPENSSL_FIPSAPI
58 #include <openssl/crypto.h>
59 #include <openssl/fips.h>
60 #include <openssl/fips_rand.h>
61 #include "fips_rand_lcl.h"
63 /* This is Hash_df from SP 800-90 10.4.1 */
65 static int hash_df(DRBG_CTX *dctx, unsigned char *out,
66 const unsigned char *in1, size_t in1len,
67 const unsigned char *in2, size_t in2len,
68 const unsigned char *in3, size_t in3len,
69 const unsigned char *in4, size_t in4len)
71 EVP_MD_CTX *mctx = &dctx->d.hash.mctx;
72 unsigned char *vtmp = dctx->d.hash.vtmp;
74 /* Standard only ever needs seedlen bytes which is always less than
75 * maximum permitted so no need to check length.
77 size_t outlen = dctx->seedlen;
79 tmp[1] = ((outlen * 8) >> 24) & 0xff;
80 tmp[2] = ((outlen * 8) >> 16) & 0xff;
81 tmp[3] = ((outlen * 8) >> 8) & 0xff;
82 tmp[4] = (outlen * 8) & 0xff;
85 tmp[5] = (unsigned char)in1len;
91 if (!FIPS_digestinit(mctx, dctx->d.hash.md))
93 if (!FIPS_digestupdate(mctx, tmp, 5))
95 if (in1 && !FIPS_digestupdate(mctx, in1, in1len))
97 if (in2 && !FIPS_digestupdate(mctx, in2, in2len))
99 if (in3 && !FIPS_digestupdate(mctx, in3, in3len))
101 if (in4 && !FIPS_digestupdate(mctx, in4, in4len))
103 if (outlen < dctx->blocklength)
105 if (!FIPS_digestfinal(mctx, vtmp, NULL))
107 memcpy(out, vtmp, outlen);
108 OPENSSL_cleanse(vtmp, dctx->blocklength);
111 else if(!FIPS_digestfinal(mctx, out, NULL))
114 outlen -= dctx->blocklength;
118 out += dctx->blocklength;
123 /* Add an unsigned buffer to the buf value, storing the result in buf. For
124 * this algorithm the length of input never exceeds the seed length.
127 static void ctx_add_buf(DRBG_CTX *dctx, unsigned char *buf,
128 unsigned char *in, size_t inlen)
131 const unsigned char *q;
133 p = buf + dctx->seedlen;
136 OPENSSL_assert(i <= dctx->seedlen);
138 /* Special case: zero length, just increment buffer */
159 i = dctx->seedlen - inlen;
161 /* If not adding whole buffer handle final carries */
176 /* Finalise and add hash to V */
178 static int ctx_add_md(DRBG_CTX *dctx)
180 if (!FIPS_digestfinal(&dctx->d.hash.mctx, dctx->d.hash.vtmp, NULL))
182 ctx_add_buf(dctx, dctx->d.hash.V, dctx->d.hash.vtmp, dctx->blocklength);
186 static int hash_gen(DRBG_CTX *dctx, unsigned char *out, size_t outlen)
188 DRBG_HASH_CTX *hctx = &dctx->d.hash;
191 memcpy(hctx->vtmp, hctx->V, dctx->seedlen);
194 FIPS_digestinit(&hctx->mctx, hctx->md);
195 FIPS_digestupdate(&hctx->mctx, hctx->vtmp, dctx->seedlen);
196 if (!(dctx->xflags & DRBG_FLAG_TEST) && !dctx->lb_valid)
198 FIPS_digestfinal(&hctx->mctx, dctx->lb, NULL);
201 else if (outlen < dctx->blocklength)
203 FIPS_digestfinal(&hctx->mctx, hctx->vtmp, NULL);
204 if (!fips_drbg_cprng_test(dctx, hctx->vtmp))
206 memcpy(out, hctx->vtmp, outlen);
211 FIPS_digestfinal(&hctx->mctx, out, NULL);
212 if (!fips_drbg_cprng_test(dctx, out))
214 outlen -= dctx->blocklength;
217 out += dctx->blocklength;
219 ctx_add_buf(dctx, hctx->vtmp, NULL, 0);
223 static int drbg_hash_instantiate(DRBG_CTX *dctx,
224 const unsigned char *ent, size_t ent_len,
225 const unsigned char *nonce, size_t nonce_len,
226 const unsigned char *pstr, size_t pstr_len)
228 DRBG_HASH_CTX *hctx = &dctx->d.hash;
229 if (!hash_df(dctx, hctx->V,
230 ent, ent_len, nonce, nonce_len, pstr, pstr_len,
233 if (!hash_df(dctx, hctx->C,
234 NULL, 0, hctx->V, dctx->seedlen,
238 #ifdef HASH_DRBG_TRACE
239 fprintf(stderr, "V+C after instantiate:\n");
240 hexprint(stderr, hctx->V, dctx->seedlen);
241 hexprint(stderr, hctx->C, dctx->seedlen);
247 static int drbg_hash_reseed(DRBG_CTX *dctx,
248 const unsigned char *ent, size_t ent_len,
249 const unsigned char *adin, size_t adin_len)
251 DRBG_HASH_CTX *hctx = &dctx->d.hash;
252 /* V about to be updated so use C as output instead */
253 if (!hash_df(dctx, hctx->C,
254 NULL, 1, hctx->V, dctx->seedlen,
255 ent, ent_len, adin, adin_len))
257 memcpy(hctx->V, hctx->C, dctx->seedlen);
258 if (!hash_df(dctx, hctx->C, NULL, 0,
259 hctx->V, dctx->seedlen, NULL, 0, NULL, 0))
261 #ifdef HASH_DRBG_TRACE
262 fprintf(stderr, "V+C after reseed:\n");
263 hexprint(stderr, hctx->V, dctx->seedlen);
264 hexprint(stderr, hctx->C, dctx->seedlen);
269 static int drbg_hash_generate(DRBG_CTX *dctx,
270 unsigned char *out, size_t outlen,
271 const unsigned char *adin, size_t adin_len)
273 DRBG_HASH_CTX *hctx = &dctx->d.hash;
274 EVP_MD_CTX *mctx = &hctx->mctx;
275 unsigned char tmp[4];
276 if (adin && adin_len)
279 if (!FIPS_digestinit(mctx, hctx->md))
281 if (!EVP_DigestUpdate(mctx, tmp, 1))
283 if (!EVP_DigestUpdate(mctx, hctx->V, dctx->seedlen))
285 if (!EVP_DigestUpdate(mctx, adin, adin_len))
287 if (!ctx_add_md(dctx))
290 if (!hash_gen(dctx, out, outlen))
294 if (!FIPS_digestinit(mctx, hctx->md))
296 if (!EVP_DigestUpdate(mctx, tmp, 1))
298 if (!EVP_DigestUpdate(mctx, hctx->V, dctx->seedlen))
301 if (!ctx_add_md(dctx))
304 ctx_add_buf(dctx, hctx->V, hctx->C, dctx->seedlen);
306 tmp[0] = (dctx->reseed_counter >> 24) & 0xff;
307 tmp[1] = (dctx->reseed_counter >> 16) & 0xff;
308 tmp[2] = (dctx->reseed_counter >> 8) & 0xff;
309 tmp[3] = dctx->reseed_counter & 0xff;
310 ctx_add_buf(dctx, hctx->V, tmp, 4);
311 #ifdef HASH_DRBG_TRACE
312 fprintf(stderr, "V+C after generate:\n");
313 hexprint(stderr, hctx->V, dctx->seedlen);
314 hexprint(stderr, hctx->C, dctx->seedlen);
319 static int drbg_hash_uninstantiate(DRBG_CTX *dctx)
321 EVP_MD_CTX_cleanup(&dctx->d.hash.mctx);
322 OPENSSL_cleanse(&dctx->d.hash, sizeof(DRBG_HASH_CTX));
326 int fips_drbg_hash_init(DRBG_CTX *dctx)
329 DRBG_HASH_CTX *hctx = &dctx->d.hash;
330 md = FIPS_get_digestbynid(dctx->type);
336 dctx->strength = 128;
340 dctx->strength = 192;
344 dctx->strength = 256;
348 dctx->instantiate = drbg_hash_instantiate;
349 dctx->reseed = drbg_hash_reseed;
350 dctx->generate = drbg_hash_generate;
351 dctx->uninstantiate = drbg_hash_uninstantiate;
353 dctx->d.hash.md = md;
354 EVP_MD_CTX_init(&hctx->mctx);
356 /* These are taken from SP 800-90 10.1 table 2 */
358 dctx->blocklength = M_EVP_MD_size(md);
359 if (dctx->blocklength > 32)
365 dctx->min_entropy = dctx->strength / 8;
366 dctx->max_entropy = DRBG_MAX_LENGTH;
368 dctx->min_nonce = dctx->min_entropy / 2;
369 dctx->max_nonce = DRBG_MAX_LENGTH;
371 dctx->max_pers = DRBG_MAX_LENGTH;
372 dctx->max_adin = DRBG_MAX_LENGTH;
374 dctx->max_request = 1<<16;
375 dctx->reseed_interval = 1<<24;