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/evp.h>
60 #include <openssl/aes.h>
61 #include <openssl/fips.h>
62 #include <openssl/fips_rand.h>
63 #include "fips_rand_lcl.h"
65 /* This is Hash_df from SP 800-90 10.4.1 */
67 static int hash_df(DRBG_CTX *dctx, unsigned char *out,
68 const unsigned char *in1, size_t in1len,
69 const unsigned char *in2, size_t in2len,
70 const unsigned char *in3, size_t in3len,
71 const unsigned char *in4, size_t in4len)
73 EVP_MD_CTX *mctx = &dctx->d.hash.mctx;
74 unsigned char *vtmp = dctx->d.hash.vtmp;
76 /* Standard only ever needs seedlen bytes which is always less than
77 * maximum permitted so no need to check length.
79 size_t outlen = dctx->seedlen;
81 tmp[1] = ((outlen * 8) >> 24) & 0xff;
82 tmp[2] = ((outlen * 8) >> 16) & 0xff;
83 tmp[3] = ((outlen * 8) >> 8) & 0xff;
84 tmp[4] = (outlen * 8) & 0xff;
87 tmp[5] = (unsigned char)in1len;
93 if (!FIPS_digestinit(mctx, dctx->d.hash.md))
95 if (!FIPS_digestupdate(mctx, tmp, 5))
97 if (in1 && !FIPS_digestupdate(mctx, in1, in1len))
99 if (in2 && !FIPS_digestupdate(mctx, in2, in2len))
101 if (in3 && !FIPS_digestupdate(mctx, in3, in3len))
103 if (in4 && !FIPS_digestupdate(mctx, in4, in4len))
105 if (outlen < dctx->blocklength)
107 if (!FIPS_digestfinal(mctx, vtmp, NULL))
109 memcpy(out, vtmp, outlen);
110 OPENSSL_cleanse(vtmp, dctx->blocklength);
113 else if(!FIPS_digestfinal(mctx, out, NULL))
116 outlen -= dctx->blocklength;
120 out += dctx->blocklength;
125 /* Add an unsigned buffer to the buf value, storing the result in buf. For
126 * this algorithm the length of input never exceeds the seed length.
129 static void ctx_add_buf(DRBG_CTX *dctx, unsigned char *buf,
130 unsigned char *in, size_t inlen)
133 const unsigned char *q;
135 p = buf + dctx->seedlen;
138 OPENSSL_assert(i <= dctx->seedlen);
140 /* Special case: zero length, just increment buffer */
161 i = dctx->seedlen - inlen;
163 /* If not adding whole buffer handle final carries */
178 /* Finalise and add hash to V */
180 static int ctx_add_md(DRBG_CTX *dctx)
182 if (!FIPS_digestfinal(&dctx->d.hash.mctx, dctx->d.hash.vtmp, NULL))
184 ctx_add_buf(dctx, dctx->d.hash.V, dctx->d.hash.vtmp, dctx->blocklength);
188 static int hash_gen(DRBG_CTX *dctx, unsigned char *out, size_t outlen)
190 DRBG_HASH_CTX *hctx = &dctx->d.hash;
193 memcpy(hctx->vtmp, hctx->V, dctx->seedlen);
196 FIPS_digestinit(&hctx->mctx, hctx->md);
197 FIPS_digestupdate(&hctx->mctx, hctx->vtmp, dctx->seedlen);
198 if (!(dctx->flags & DRBG_FLAG_TEST) && !dctx->lb_valid)
200 FIPS_digestfinal(&hctx->mctx, dctx->lb, NULL);
203 else if (outlen < dctx->blocklength)
205 FIPS_digestfinal(&hctx->mctx, hctx->vtmp, NULL);
206 if (!fips_drbg_cprng_test(dctx, hctx->vtmp))
208 memcpy(out, hctx->vtmp, outlen);
213 FIPS_digestfinal(&hctx->mctx, out, NULL);
214 if (!fips_drbg_cprng_test(dctx, out))
216 outlen -= dctx->blocklength;
219 out += dctx->blocklength;
221 ctx_add_buf(dctx, hctx->vtmp, NULL, 0);
225 static int drbg_hash_instantiate(DRBG_CTX *dctx,
226 const unsigned char *ent, size_t ent_len,
227 const unsigned char *nonce, size_t nonce_len,
228 const unsigned char *pstr, size_t pstr_len)
230 DRBG_HASH_CTX *hctx = &dctx->d.hash;
231 if (!hash_df(dctx, hctx->V,
232 ent, ent_len, nonce, nonce_len, pstr, pstr_len,
235 if (!hash_df(dctx, hctx->C,
236 NULL, 0, hctx->V, dctx->seedlen,
240 #ifdef HASH_DRBG_TRACE
241 fprintf(stderr, "V+C after instantiate:\n");
242 hexprint(stderr, hctx->V, dctx->seedlen);
243 hexprint(stderr, hctx->C, dctx->seedlen);
249 static int drbg_hash_reseed(DRBG_CTX *dctx,
250 const unsigned char *ent, size_t ent_len,
251 const unsigned char *adin, size_t adin_len)
253 DRBG_HASH_CTX *hctx = &dctx->d.hash;
254 /* V about to be updated so use C as output instead */
255 if (!hash_df(dctx, hctx->C,
256 NULL, 1, hctx->V, dctx->seedlen,
257 ent, ent_len, adin, adin_len))
259 memcpy(hctx->V, hctx->C, dctx->seedlen);
260 if (!hash_df(dctx, hctx->C, NULL, 0,
261 hctx->V, dctx->seedlen, NULL, 0, NULL, 0))
263 #ifdef HASH_DRBG_TRACE
264 fprintf(stderr, "V+C after reseed:\n");
265 hexprint(stderr, hctx->V, dctx->seedlen);
266 hexprint(stderr, hctx->C, dctx->seedlen);
271 static int drbg_hash_generate(DRBG_CTX *dctx,
272 unsigned char *out, size_t outlen,
273 const unsigned char *adin, size_t adin_len)
275 DRBG_HASH_CTX *hctx = &dctx->d.hash;
276 EVP_MD_CTX *mctx = &hctx->mctx;
277 unsigned char tmp[4];
278 if (adin && adin_len)
281 if (!FIPS_digestinit(mctx, hctx->md))
283 if (!EVP_DigestUpdate(mctx, tmp, 1))
285 if (!EVP_DigestUpdate(mctx, hctx->V, dctx->seedlen))
287 if (!EVP_DigestUpdate(mctx, adin, adin_len))
289 if (!ctx_add_md(dctx))
292 if (!hash_gen(dctx, out, outlen))
296 if (!FIPS_digestinit(mctx, hctx->md))
298 if (!EVP_DigestUpdate(mctx, tmp, 1))
300 if (!EVP_DigestUpdate(mctx, hctx->V, dctx->seedlen))
303 if (!ctx_add_md(dctx))
306 ctx_add_buf(dctx, hctx->V, hctx->C, dctx->seedlen);
308 tmp[0] = (dctx->reseed_counter >> 24) & 0xff;
309 tmp[1] = (dctx->reseed_counter >> 16) & 0xff;
310 tmp[2] = (dctx->reseed_counter >> 8) & 0xff;
311 tmp[3] = dctx->reseed_counter & 0xff;
312 ctx_add_buf(dctx, hctx->V, tmp, 4);
313 #ifdef HASH_DRBG_TRACE
314 fprintf(stderr, "V+C after generate:\n");
315 hexprint(stderr, hctx->V, dctx->seedlen);
316 hexprint(stderr, hctx->C, dctx->seedlen);
321 static int drbg_hash_uninstantiate(DRBG_CTX *dctx)
323 EVP_MD_CTX_cleanup(&dctx->d.hash.mctx);
324 OPENSSL_cleanse(&dctx->d.hash, sizeof(DRBG_HASH_CTX));
328 int fips_drbg_hash_init(DRBG_CTX *dctx)
331 DRBG_HASH_CTX *hctx = &dctx->d.hash;
332 md = FIPS_get_digestbynid(dctx->type);
339 dctx->strength = 128;
344 dctx->strength = 192;
348 dctx->strength = 256;
352 dctx->instantiate = drbg_hash_instantiate;
353 dctx->reseed = drbg_hash_reseed;
354 dctx->generate = drbg_hash_generate;
355 dctx->uninstantiate = drbg_hash_uninstantiate;
357 dctx->d.hash.md = md;
358 EVP_MD_CTX_init(&hctx->mctx);
360 /* These are taken from SP 800-90 10.1 table 2 */
362 dctx->blocklength = M_EVP_MD_size(md);
363 if (dctx->blocklength > 32)
369 dctx->min_entropy = dctx->strength / 8;
370 dctx->max_entropy = DRBG_MAX_LENGTH;
372 dctx->min_nonce = dctx->min_entropy / 2;
373 dctx->max_nonce = DRBG_MAX_LENGTH;
375 dctx->max_pers = DRBG_MAX_LENGTH;
376 dctx->max_adin = DRBG_MAX_LENGTH;
378 dctx->max_request = 1<<19;
379 dctx->reseed_interval = 1<<24;