]>
Commit | Line | Data |
---|---|---|
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 |
64 | static 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 | ||
129 | static 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 | ||
149 | static 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 | ||
168 | static 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 | ||
219 | static 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 |
226 | int 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 | } |