]> git.ipfire.org Git - thirdparty/openssl.git/blame - fips/rand/fips_drbg_hmac.c
Revise DRBG to split between internal and external flags.
[thirdparty/openssl.git] / fips / rand / fips_drbg_hmac.c
CommitLineData
d1a70cc9
DSH
1/* fips/rand/fips_drbg_hmac.c */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project.
4 */
5/* ====================================================================
6 * Copyright (c) 2011 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
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
18 * distribution.
19 *
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/)"
24 *
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.
29 *
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.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
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 * ====================================================================
52 */
53
54#include <stdlib.h>
55#include <string.h>
56#include <openssl/crypto.h>
57#include <openssl/evp.h>
58#include <openssl/hmac.h>
59#include <openssl/aes.h>
60#include <openssl/fips.h>
61#include <openssl/fips_rand.h>
62#include "fips_rand_lcl.h"
63
20f12e63
DSH
64static int drbg_hmac_update(DRBG_CTX *dctx,
65 const unsigned char *in1, size_t in1len,
66 const unsigned char *in2, size_t in2len,
67 const unsigned char *in3, size_t in3len
68 )
69 {
70 static unsigned char c0 = 0, c1 = 1;
71 DRBG_HMAC_CTX *hmac = &dctx->d.hmac;
72 HMAC_CTX *hctx = &hmac->hctx;
73
74 if (!HMAC_Init_ex(hctx, hmac->K, dctx->blocklength, hmac->md, NULL))
75 return 0;
76 if (!HMAC_Update(hctx, hmac->V, dctx->blocklength))
77 return 0;
78 if (!HMAC_Update(hctx, &c0, 1))
79 return 0;
80 if (in1len && !HMAC_Update(hctx, in1, in1len))
81 return 0;
82 if (in2len && !HMAC_Update(hctx, in2, in2len))
83 return 0;
84 if (in3len && !HMAC_Update(hctx, in3, in3len))
85 return 0;
86
87 if (!HMAC_Final(hctx, hmac->K, NULL))
88 return 0;
89
90 if (!HMAC_Init_ex(hctx, hmac->K, dctx->blocklength, hmac->md, NULL))
91 return 0;
92 if (!HMAC_Update(hctx, hmac->V, dctx->blocklength))
93 return 0;
94
95 if (!HMAC_Final(hctx, hmac->V, NULL))
96 return 0;
97
98 if (!in1len && !in2len && !in3len)
99 return 1;
100
101 if (!HMAC_Init_ex(hctx, hmac->K, dctx->blocklength, hmac->md, NULL))
102 return 0;
103 if (!HMAC_Update(hctx, hmac->V, dctx->blocklength))
104 return 0;
105 if (!HMAC_Update(hctx, &c1, 1))
106 return 0;
107 if (in1len && !HMAC_Update(hctx, in1, in1len))
108 return 0;
109 if (in2len && !HMAC_Update(hctx, in2, in2len))
110 return 0;
111 if (in3len && !HMAC_Update(hctx, in3, in3len))
112 return 0;
113
114 if (!HMAC_Final(hctx, hmac->K, NULL))
115 return 0;
116
117 if (!HMAC_Init_ex(hctx, hmac->K, dctx->blocklength, hmac->md, NULL))
118 return 0;
119 if (!HMAC_Update(hctx, hmac->V, dctx->blocklength))
120 return 0;
121
122 if (!HMAC_Final(hctx, hmac->V, NULL))
123 return 0;
124
125 return 1;
126
127 }
128
129static int drbg_hmac_instantiate(DRBG_CTX *dctx,
130 const unsigned char *ent, size_t ent_len,
131 const unsigned char *nonce, size_t nonce_len,
132 const unsigned char *pstr, size_t pstr_len)
133 {
134 DRBG_HMAC_CTX *hmac = &dctx->d.hmac;
135 memset(hmac->K, 0, dctx->blocklength);
136 memset(hmac->V, 1, dctx->blocklength);
137 if (!drbg_hmac_update(dctx,
138 ent, ent_len, nonce, nonce_len, pstr, pstr_len))
139 return 0;
140
141#ifdef HMAC_DRBG_TRACE
142 fprintf(stderr, "K+V after instantiate:\n");
143 hexprint(stderr, hmac->K, hmac->blocklength);
144 hexprint(stderr, hmac->V, hmac->blocklength);
145#endif
146 return 1;
147 }
148
149static int drbg_hmac_reseed(DRBG_CTX *dctx,
150 const unsigned char *ent, size_t ent_len,
151 const unsigned char *adin, size_t adin_len)
152 {
153 if (!drbg_hmac_update(dctx,
154 ent, ent_len, adin, adin_len, NULL, 0))
155 return 0;
156
157#ifdef HMAC_DRBG_TRACE
158 {
159 DRBG_HMAC_CTX *hmac = &dctx->d.hmac;
160 fprintf(stderr, "K+V after reseed:\n");
161 hexprint(stderr, hmac->K, hmac->blocklength);
162 hexprint(stderr, hmac->V, hmac->blocklength);
163 }
164#endif
165 return 1;
166 }
167
168static int drbg_hmac_generate(DRBG_CTX *dctx,
169 unsigned char *out, size_t outlen,
170 const unsigned char *adin, size_t adin_len)
171 {
172 DRBG_HMAC_CTX *hmac = &dctx->d.hmac;
173 HMAC_CTX *hctx = &hmac->hctx;
174 const unsigned char *Vtmp = hmac->V;
175 if (adin_len && !drbg_hmac_update(dctx, adin, adin_len,
176 NULL, 0, NULL, 0))
177 return 0;
178 for (;;)
179 {
180 if (!HMAC_Init_ex(hctx, hmac->K, dctx->blocklength,
181 hmac->md, NULL))
182 return 0;
183 if (!HMAC_Update(hctx, Vtmp, dctx->blocklength))
184 return 0;
4420b3b1 185 if (!(dctx->xflags & DRBG_FLAG_TEST) && !dctx->lb_valid)
20f12e63
DSH
186 {
187 if (!HMAC_Final(hctx, dctx->lb, NULL))
188 return 0;
189 dctx->lb_valid = 1;
190 Vtmp = dctx->lb;
191 continue;
192 }
193 else if (outlen > dctx->blocklength)
194 {
195 if (!HMAC_Final(hctx, out, NULL))
196 return 0;
197 if (!fips_drbg_cprng_test(dctx, out))
198 return 0;
199 Vtmp = out;
200 }
201 else
202 {
203 if (!HMAC_Final(hctx, hmac->V, NULL))
204 return 0;
205 if (!fips_drbg_cprng_test(dctx, hmac->V))
206 return 0;
207 memcpy(out, hmac->V, outlen);
208 break;
209 }
210 out += dctx->blocklength;
211 outlen -= dctx->blocklength;
212 }
213 if (!drbg_hmac_update(dctx, adin, adin_len, NULL, 0, NULL, 0))
214 return 0;
215
216 return 1;
217 }
218
219static int drbg_hmac_uninstantiate(DRBG_CTX *dctx)
220 {
221 HMAC_CTX_cleanup(&dctx->d.hmac.hctx);
222 OPENSSL_cleanse(&dctx->d.hmac, sizeof(DRBG_HMAC_CTX));
223 return 1;
224 }
225
d1a70cc9
DSH
226int fips_drbg_hmac_init(DRBG_CTX *dctx)
227 {
20f12e63
DSH
228 const EVP_MD *md = NULL;
229 DRBG_HMAC_CTX *hctx = &dctx->d.hmac;
230 dctx->strength = 256;
231 switch (dctx->type)
232 {
233 case NID_hmacWithSHA1:
234 md = EVP_sha1();
235 dctx->strength = 128;
236 break;
237
238 case NID_hmacWithSHA224:
239 md = EVP_sha224();
240 dctx->strength = 192;
241 break;
242
243 case NID_hmacWithSHA256:
244 md = EVP_sha256();
245 break;
246
247 case NID_hmacWithSHA384:
248 md = EVP_sha384();
249 break;
250
251 case NID_hmacWithSHA512:
252 md = EVP_sha512();
253 break;
254
255 default:
256 dctx->strength = 0;
257 return -2;
258 }
259 dctx->instantiate = drbg_hmac_instantiate;
260 dctx->reseed = drbg_hmac_reseed;
261 dctx->generate = drbg_hmac_generate;
262 dctx->uninstantiate = drbg_hmac_uninstantiate;
263 HMAC_CTX_init(&hctx->hctx);
264 hctx->md = md;
265 dctx->blocklength = M_EVP_MD_size(md);
266 dctx->seedlen = M_EVP_MD_size(md);
267
268 dctx->min_entropy = dctx->strength / 8;
269 dctx->max_entropy = DRBG_MAX_LENGTH;
270
271 dctx->min_nonce = dctx->min_entropy / 2;
272 dctx->max_nonce = DRBG_MAX_LENGTH;
273
274 dctx->max_pers = DRBG_MAX_LENGTH;
275 dctx->max_adin = DRBG_MAX_LENGTH;
276
46883b67 277 dctx->max_request = 1<<16;
20f12e63
DSH
278 dctx->reseed_interval = 1<<24;
279
280 return 1;
d1a70cc9 281 }