]> git.ipfire.org Git - thirdparty/openssl.git/blob - fips/rand/fips_drbg_ctr.c
Revise DRBG to split between internal and external flags.
[thirdparty/openssl.git] / fips / rand / fips_drbg_ctr.c
1 /* fips/rand/fips_drbg_ctr.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/fips.h>
58 #include <openssl/fips_rand.h>
59 #include "fips_rand_lcl.h"
60
61 static void inc_128(DRBG_CTR_CTX *cctx)
62 {
63 int i;
64 unsigned char c;
65 unsigned char *p = cctx->V + 15;
66 for (i = 0; i < 16; i++)
67 {
68 c = *p;
69 c++;
70 *p = c;
71 if (c)
72 return;
73 p--;
74 }
75 }
76
77 static void ctr_XOR(DRBG_CTR_CTX *cctx, const unsigned char *in, size_t inlen)
78 {
79 size_t i, n;
80 /* Any zero padding will have no effect on the result as we
81 * are XORing. So just process however much input we have.
82 */
83
84 if (!in || !inlen)
85 return;
86
87 if (inlen < cctx->keylen)
88 n = inlen;
89 else
90 n = cctx->keylen;
91
92 for (i = 0; i < n; i++)
93 cctx->K[i] ^= in[i];
94 if (inlen <= cctx->keylen)
95 return;
96
97 n = inlen - cctx->keylen;
98 /* Should never happen */
99 if (n > 16)
100 n = 16;
101 for (i = 0; i < 16; i++)
102 cctx->V[i] ^= in[i + cctx->keylen];
103 }
104
105 /* Process a complete block using BCC algorithm of SPP 800-90 10.4.3 */
106
107 static void ctr_BCC_block(DRBG_CTR_CTX *cctx, unsigned char *out,
108 const unsigned char *in)
109 {
110 int i;
111 for (i = 0; i < 16; i++)
112 out[i] ^= in[i];
113 AES_encrypt(out, out, &cctx->df_ks);
114 #if 0
115 fprintf(stderr, "BCC in+out\n");
116 BIO_dump_fp(stderr, in, 16);
117 BIO_dump_fp(stderr, out, 16);
118 #endif
119 }
120
121 /* Handle several BCC operations for as much data as we need for K and X */
122 static void ctr_BCC_blocks(DRBG_CTR_CTX *cctx, const unsigned char *in)
123 {
124 ctr_BCC_block(cctx, cctx->KX, in);
125 ctr_BCC_block(cctx, cctx->KX + 16, in);
126 if (cctx->keylen != 16)
127 ctr_BCC_block(cctx, cctx->KX + 32, in);
128 }
129 /* Initialise BCC blocks: these have the value 0,1,2 in leftmost positions:
130 * see 10.4.2 stage 7.
131 */
132 static void ctr_BCC_init(DRBG_CTR_CTX *cctx)
133 {
134 memset(cctx->KX, 0, 48);
135 memset(cctx->bltmp, 0, 16);
136 ctr_BCC_block(cctx, cctx->KX, cctx->bltmp);
137 cctx->bltmp[3] = 1;
138 ctr_BCC_block(cctx, cctx->KX + 16, cctx->bltmp);
139 if (cctx->keylen != 16)
140 {
141 cctx->bltmp[3] = 2;
142 ctr_BCC_block(cctx, cctx->KX + 32, cctx->bltmp);
143 }
144 }
145
146 /* Process several blocks into BCC algorithm, some possibly partial */
147 static void ctr_BCC_update(DRBG_CTR_CTX *cctx,
148 const unsigned char *in, size_t inlen)
149 {
150 if (!in || !inlen)
151 return;
152 /* If we have partial block handle it first */
153 if (cctx->bltmp_pos)
154 {
155 size_t left = 16 - cctx->bltmp_pos;
156 /* If we now have a complete block process it */
157 if (inlen >= left)
158 {
159 memcpy(cctx->bltmp + cctx->bltmp_pos, in, left);
160 ctr_BCC_blocks(cctx, cctx->bltmp);
161 cctx->bltmp_pos = 0;
162 inlen -= left;
163 in += left;
164 }
165 }
166 /* Process zero or more complete blocks */
167 while (inlen >= 16)
168 {
169 ctr_BCC_blocks(cctx, in);
170 in += 16;
171 inlen -= 16;
172 }
173 /* Copy any remaining partial block to the temporary buffer */
174 if (inlen > 0)
175 {
176 memcpy(cctx->bltmp + cctx->bltmp_pos, in, inlen);
177 cctx->bltmp_pos += inlen;
178 }
179 }
180
181 static void ctr_BCC_final(DRBG_CTR_CTX *cctx)
182 {
183 if (cctx->bltmp_pos)
184 {
185 memset(cctx->bltmp + cctx->bltmp_pos, 0, 16 - cctx->bltmp_pos);
186 ctr_BCC_blocks(cctx, cctx->bltmp);
187 }
188 }
189
190 static void ctr_df(DRBG_CTR_CTX *cctx,
191 const unsigned char *in1, size_t in1len,
192 const unsigned char *in2, size_t in2len,
193 const unsigned char *in3, size_t in3len)
194 {
195 size_t inlen;
196 unsigned char *p = cctx->bltmp;
197 static unsigned char c80 = 0x80;
198
199 ctr_BCC_init(cctx);
200 if (!in1)
201 in1len = 0;
202 if (!in2)
203 in2len = 0;
204 if (!in3)
205 in3len = 0;
206 inlen = in1len + in2len + in3len;
207 /* Initialise L||N in temporary block */
208 *p++ = (inlen >> 24) & 0xff;
209 *p++ = (inlen >> 16) & 0xff;
210 *p++ = (inlen >> 8) & 0xff;
211 *p++ = inlen & 0xff;
212 /* NB keylen is at most 32 bytes */
213 *p++ = 0;
214 *p++ = 0;
215 *p++ = 0;
216 *p = (unsigned char)((cctx->keylen + 16) & 0xff);
217 cctx->bltmp_pos = 8;
218 ctr_BCC_update(cctx, in1, in1len);
219 ctr_BCC_update(cctx, in2, in2len);
220 ctr_BCC_update(cctx, in3, in3len);
221 ctr_BCC_update(cctx, &c80, 1);
222 ctr_BCC_final(cctx);
223 /* Set up key K */
224 AES_set_encrypt_key(cctx->KX, cctx->keylen * 8, &cctx->df_kxks);
225 /* X follows key K */
226 AES_encrypt(cctx->KX + cctx->keylen, cctx->KX, &cctx->df_kxks);
227 AES_encrypt(cctx->KX, cctx->KX + 16, &cctx->df_kxks);
228 if (cctx->keylen != 16)
229 AES_encrypt(cctx->KX + 16, cctx->KX + 32, &cctx->df_kxks);
230 #if 0
231 fprintf(stderr, "Output of ctr_df:\n");
232 BIO_dump_fp(stderr, cctx->KX, cctx->keylen + 16);
233 #endif
234 }
235
236 /* NB the no-df Update in SP800-90 specifies a constant input length
237 * of seedlen, however other uses of this algorithm pad the input with
238 * zeroes if necessary and have up to two parameters XORed together,
239 * handle both cases in this function instead.
240 */
241
242 static void ctr_Update(DRBG_CTX *dctx,
243 const unsigned char *in1, size_t in1len,
244 const unsigned char *in2, size_t in2len,
245 const unsigned char *nonce, size_t noncelen)
246 {
247 DRBG_CTR_CTX *cctx = &dctx->d.ctr;
248 /* ks is already setup for correct key */
249 inc_128(cctx);
250 AES_encrypt(cctx->V, cctx->K, &cctx->ks);
251 /* If keylen longer than 128 bits need extra encrypt */
252 if (cctx->keylen != 16)
253 {
254 inc_128(cctx);
255 AES_encrypt(cctx->V, cctx->K + 16, &cctx->ks);
256 }
257 inc_128(cctx);
258 AES_encrypt(cctx->V, cctx->V, &cctx->ks);
259 /* If 192 bit key part of V is on end of K */
260 if (cctx->keylen == 24)
261 {
262 memcpy(cctx->V + 8, cctx->V, 8);
263 memcpy(cctx->V, cctx->K + 24, 8);
264 }
265
266 if (dctx->xflags & DRBG_FLAG_CTR_USE_DF)
267 {
268 /* If no input reuse existing derived value */
269 if (in1 || nonce || in2)
270 ctr_df(cctx, in1, in1len, nonce, noncelen, in2, in2len);
271 /* If this a reuse input in1len != 0 */
272 if (in1len)
273 ctr_XOR(cctx, cctx->KX, dctx->seedlen);
274 }
275 else
276 {
277 ctr_XOR(cctx, in1, in1len);
278 ctr_XOR(cctx, in2, in2len);
279 }
280
281 AES_set_encrypt_key(cctx->K, dctx->strength, &cctx->ks);
282 #if 0
283 fprintf(stderr, "K+V after update is:\n");
284 BIO_dump_fp(stderr, cctx->K, cctx->keylen);
285 BIO_dump_fp(stderr, cctx->V, 16);
286 #endif
287 }
288
289 static int drbg_ctr_instantiate(DRBG_CTX *dctx,
290 const unsigned char *ent, size_t entlen,
291 const unsigned char *nonce, size_t noncelen,
292 const unsigned char *pers, size_t perslen)
293 {
294 DRBG_CTR_CTX *cctx = &dctx->d.ctr;
295 memset(cctx->K, 0, sizeof(cctx->K));
296 memset(cctx->V, 0, sizeof(cctx->V));
297 AES_set_encrypt_key(cctx->K, dctx->strength, &cctx->ks);
298 ctr_Update(dctx, ent, entlen, pers, perslen, nonce, noncelen);
299 return 1;
300 }
301
302 static int drbg_ctr_reseed(DRBG_CTX *dctx,
303 const unsigned char *ent, size_t entlen,
304 const unsigned char *adin, size_t adinlen)
305 {
306 ctr_Update(dctx, ent, entlen, adin, adinlen, NULL, 0);
307 return 1;
308 }
309
310 static int drbg_ctr_generate(DRBG_CTX *dctx,
311 unsigned char *out, size_t outlen,
312 const unsigned char *adin, size_t adinlen)
313 {
314 DRBG_CTR_CTX *cctx = &dctx->d.ctr;
315 if (adin && adinlen)
316 {
317 ctr_Update(dctx, adin, adinlen, NULL, 0, NULL, 0);
318 /* This means we reuse derived value */
319 if (dctx->xflags & DRBG_FLAG_CTR_USE_DF)
320 {
321 adin = NULL;
322 adinlen = 1;
323 }
324 }
325 else
326 adinlen = 0;
327
328 for (;;)
329 {
330 inc_128(cctx);
331 if (!(dctx->xflags & DRBG_FLAG_TEST) && !dctx->lb_valid)
332 {
333 AES_encrypt(cctx->V, dctx->lb, &cctx->ks);
334 dctx->lb_valid = 1;
335 continue;
336 }
337 if (outlen < 16)
338 {
339 /* Use K as temp space as it will be updated */
340 AES_encrypt(cctx->V, cctx->K, &cctx->ks);
341 if (!fips_drbg_cprng_test(dctx, cctx->K))
342 return 0;
343 memcpy(out, cctx->K, outlen);
344 break;
345 }
346 AES_encrypt(cctx->V, out, &cctx->ks);
347 if (!fips_drbg_cprng_test(dctx, out))
348 return 0;
349 out += 16;
350 outlen -= 16;
351 if (outlen == 0)
352 break;
353 }
354
355 ctr_Update(dctx, adin, adinlen, NULL, 0, NULL, 0);
356
357 return 1;
358
359 }
360
361 static int drbg_ctr_uninstantiate(DRBG_CTX *dctx)
362 {
363 memset(&dctx->d.ctr, 0, sizeof(DRBG_CTR_CTX));
364 return 1;
365 }
366
367 int fips_drbg_ctr_init(DRBG_CTX *dctx)
368 {
369 DRBG_CTR_CTX *cctx = &dctx->d.ctr;
370
371 size_t keylen;
372
373 switch (dctx->type)
374 {
375 case NID_aes_128_ctr:
376 keylen = 16;
377 break;
378
379 case NID_aes_192_ctr:
380 keylen = 24;
381 break;
382
383 case NID_aes_256_ctr:
384 keylen = 32;
385 break;
386
387 default:
388 return -2;
389 }
390
391 dctx->instantiate = drbg_ctr_instantiate;
392 dctx->reseed = drbg_ctr_reseed;
393 dctx->generate = drbg_ctr_generate;
394 dctx->uninstantiate = drbg_ctr_uninstantiate;
395
396 cctx->keylen = keylen;
397 dctx->strength = keylen * 8;
398 dctx->blocklength = 16;
399 dctx->seedlen = keylen + 16;
400
401 if (dctx->xflags & DRBG_FLAG_CTR_USE_DF)
402 {
403 /* df initialisation */
404 static unsigned char df_key[32] =
405 {
406 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
407 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
408 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
409 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
410 };
411 /* Set key schedule for df_key */
412 AES_set_encrypt_key(df_key, dctx->strength, &cctx->df_ks);
413
414 dctx->min_entropy = cctx->keylen;
415 dctx->max_entropy = DRBG_MAX_LENGTH;
416 dctx->min_nonce = dctx->min_entropy / 2;
417 dctx->max_nonce = DRBG_MAX_LENGTH;
418 dctx->max_pers = DRBG_MAX_LENGTH;
419 dctx->max_adin = DRBG_MAX_LENGTH;
420 }
421 else
422 {
423 dctx->min_entropy = dctx->seedlen;
424 dctx->max_entropy = dctx->seedlen;
425 /* Nonce not used */
426 dctx->min_nonce = 0;
427 dctx->max_nonce = 0;
428 dctx->max_pers = dctx->seedlen;
429 dctx->max_adin = dctx->seedlen;
430 }
431
432 dctx->max_request = 1<<16;
433 dctx->reseed_interval = 1<<24;
434
435 return 1;
436 }