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 (outlen < dctx->blocklength)
200 FIPS_digestfinal(&hctx->mctx, hctx->vtmp, NULL);
201 memcpy(out, hctx->vtmp, outlen);
204 FIPS_digestfinal(&hctx->mctx, out, NULL);
205 outlen -= dctx->blocklength;
208 out += dctx->blocklength;
209 ctx_add_buf(dctx, hctx->vtmp, NULL, 0);
213 static int drbg_hash_instantiate(DRBG_CTX *dctx,
214 const unsigned char *ent, size_t ent_len,
215 const unsigned char *nonce, size_t nonce_len,
216 const unsigned char *pstr, size_t pstr_len)
218 DRBG_HASH_CTX *hctx = &dctx->d.hash;
219 if (!hash_df(dctx, hctx->V,
220 ent, ent_len, nonce, nonce_len, pstr, pstr_len,
223 if (!hash_df(dctx, hctx->C,
224 NULL, 0, hctx->V, dctx->seedlen,
228 #ifdef HASH_DRBG_TRACE
229 fprintf(stderr, "V+C after instantiate:\n");
230 hexprint(stderr, hctx->V, dctx->seedlen);
231 hexprint(stderr, hctx->C, dctx->seedlen);
237 static int drbg_hash_reseed(DRBG_CTX *dctx,
238 const unsigned char *ent, size_t ent_len,
239 const unsigned char *adin, size_t adin_len)
241 DRBG_HASH_CTX *hctx = &dctx->d.hash;
242 /* V about to be updated so use C as output instead */
243 if (!hash_df(dctx, hctx->C,
244 NULL, 1, hctx->V, dctx->seedlen,
245 ent, ent_len, adin, adin_len))
247 memcpy(hctx->V, hctx->C, dctx->seedlen);
248 if (!hash_df(dctx, hctx->C, NULL, 0,
249 hctx->V, dctx->seedlen, NULL, 0, NULL, 0))
251 #ifdef HASH_DRBG_TRACE
252 fprintf(stderr, "V+C after reseed:\n");
253 hexprint(stderr, hctx->V, dctx->seedlen);
254 hexprint(stderr, hctx->C, dctx->seedlen);
259 static int drbg_hash_generate(DRBG_CTX *dctx,
260 unsigned char *out, size_t outlen,
261 const unsigned char *adin, size_t adin_len)
263 DRBG_HASH_CTX *hctx = &dctx->d.hash;
264 EVP_MD_CTX *mctx = &hctx->mctx;
265 unsigned char tmp[4];
266 if (adin && adin_len)
269 if (!FIPS_digestinit(mctx, hctx->md))
271 if (!EVP_DigestUpdate(mctx, tmp, 1))
273 if (!EVP_DigestUpdate(mctx, hctx->V, dctx->seedlen))
275 if (!EVP_DigestUpdate(mctx, adin, adin_len))
277 if (!ctx_add_md(dctx))
280 if (!hash_gen(dctx, out, outlen))
284 if (!FIPS_digestinit(mctx, hctx->md))
286 if (!EVP_DigestUpdate(mctx, tmp, 1))
288 if (!EVP_DigestUpdate(mctx, hctx->V, dctx->seedlen))
291 if (!ctx_add_md(dctx))
294 ctx_add_buf(dctx, hctx->V, hctx->C, dctx->seedlen);
296 tmp[0] = (dctx->reseed_counter >> 24) & 0xff;
297 tmp[1] = (dctx->reseed_counter >> 16) & 0xff;
298 tmp[2] = (dctx->reseed_counter >> 8) & 0xff;
299 tmp[3] = dctx->reseed_counter & 0xff;
300 ctx_add_buf(dctx, hctx->V, tmp, 4);
301 #ifdef HASH_DRBG_TRACE
302 fprintf(stderr, "V+C after generate:\n");
303 hexprint(stderr, hctx->V, dctx->seedlen);
304 hexprint(stderr, hctx->C, dctx->seedlen);
309 static int drbg_hash_uninstantiate(DRBG_CTX *dctx)
311 EVP_MD_CTX_cleanup(&dctx->d.hash.mctx);
312 OPENSSL_cleanse(&dctx->d.hash, sizeof(DRBG_HASH_CTX));
316 int fips_drbg_hash_init(DRBG_CTX *dctx)
319 DRBG_HASH_CTX *hctx = &dctx->d.hash;
324 dctx->strength = 128;
329 dctx->strength = 192;
334 dctx->strength = 256;
339 dctx->strength = 256;
344 dctx->strength = 256;
353 dctx->instantiate = drbg_hash_instantiate;
354 dctx->reseed = drbg_hash_reseed;
355 dctx->generate = drbg_hash_generate;
356 dctx->uninstantiate = drbg_hash_uninstantiate;
358 dctx->d.hash.md = md;
359 EVP_MD_CTX_init(&hctx->mctx);
361 /* These are taken from SP 800-90 10.1 table 2 */
363 dctx->blocklength = M_EVP_MD_size(md);
364 if (dctx->blocklength > 32)
370 dctx->min_entropy = dctx->strength / 8;
371 dctx->max_entropy = DRBG_MAX_ENTROPY;
373 dctx->min_nonce = dctx->min_entropy / 2;
374 dctx->max_nonce = DRBG_MAX_NONCE;
376 dctx->max_pers = DRBG_MAX_LENGTH;
377 dctx->max_adin = DRBG_MAX_LENGTH;
379 dctx->max_request = 1<<19;
380 dctx->reseed_interval = 1<<24;