]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/rand/drbg_ctr.c
28db4eed7f046e585ab8693577ffb8c569b44582
[thirdparty/openssl.git] / crypto / rand / drbg_ctr.c
1 /*
2 * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <stdlib.h>
11 #include <string.h>
12 #include <openssl/crypto.h>
13 #include <openssl/err.h>
14 #include <openssl/rand.h>
15 #include "internal/thread_once.h"
16 #include "rand_lcl.h"
17
18 /*
19 * Implementation of NIST SP 800-90A CTR DRBG.
20 */
21 static void inc_128(RAND_DRBG_CTR *ctr)
22 {
23 int i;
24 unsigned char c;
25 unsigned char *p = &ctr->V[15];
26
27 for (i = 0; i < 16; i++, p--) {
28 c = *p;
29 c++;
30 *p = c;
31 if (c != 0) {
32 /* If we didn't wrap around, we're done. */
33 break;
34 }
35 }
36 }
37
38 static void ctr_XOR(RAND_DRBG_CTR *ctr, const unsigned char *in, size_t inlen)
39 {
40 size_t i, n;
41
42 if (in == NULL || inlen == 0)
43 return;
44
45 /*
46 * Any zero padding will have no effect on the result as we
47 * are XORing. So just process however much input we have.
48 */
49 n = inlen < ctr->keylen ? inlen : ctr->keylen;
50 for (i = 0; i < n; i++)
51 ctr->K[i] ^= in[i];
52 if (inlen <= ctr->keylen)
53 return;
54
55 n = inlen - ctr->keylen;
56 if (n > 16) {
57 /* Should never happen */
58 n = 16;
59 }
60 for (i = 0; i < n; i++)
61 ctr->V[i] ^= in[i + ctr->keylen];
62 }
63
64 /*
65 * Process a complete block using BCC algorithm of SP 800-90A 10.3.3
66 */
67 __owur static int ctr_BCC_block(RAND_DRBG_CTR *ctr, unsigned char *out,
68 const unsigned char *in)
69 {
70 int i, outlen = AES_BLOCK_SIZE;
71
72 for (i = 0; i < 16; i++)
73 out[i] ^= in[i];
74
75 if (!EVP_CipherUpdate(ctr->ctx_df, out, &outlen, out, AES_BLOCK_SIZE)
76 || outlen != AES_BLOCK_SIZE)
77 return 0;
78 return 1;
79 }
80
81
82 /*
83 * Handle several BCC operations for as much data as we need for K and X
84 */
85 __owur static int ctr_BCC_blocks(RAND_DRBG_CTR *ctr, const unsigned char *in)
86 {
87 if (!ctr_BCC_block(ctr, ctr->KX, in)
88 || !ctr_BCC_block(ctr, ctr->KX + 16, in))
89 return 0;
90 if (ctr->keylen != 16 && !ctr_BCC_block(ctr, ctr->KX + 32, in))
91 return 0;
92 return 1;
93 }
94
95 /*
96 * Initialise BCC blocks: these have the value 0,1,2 in leftmost positions:
97 * see 10.3.1 stage 7.
98 */
99 __owur static int ctr_BCC_init(RAND_DRBG_CTR *ctr)
100 {
101 memset(ctr->KX, 0, 48);
102 memset(ctr->bltmp, 0, 16);
103 if (!ctr_BCC_block(ctr, ctr->KX, ctr->bltmp))
104 return 0;
105 ctr->bltmp[3] = 1;
106 if (!ctr_BCC_block(ctr, ctr->KX + 16, ctr->bltmp))
107 return 0;
108 if (ctr->keylen != 16) {
109 ctr->bltmp[3] = 2;
110 if (!ctr_BCC_block(ctr, ctr->KX + 32, ctr->bltmp))
111 return 0;
112 }
113 return 1;
114 }
115
116 /*
117 * Process several blocks into BCC algorithm, some possibly partial
118 */
119 __owur static int ctr_BCC_update(RAND_DRBG_CTR *ctr,
120 const unsigned char *in, size_t inlen)
121 {
122 if (in == NULL || inlen == 0)
123 return 1;
124
125 /* If we have partial block handle it first */
126 if (ctr->bltmp_pos) {
127 size_t left = 16 - ctr->bltmp_pos;
128
129 /* If we now have a complete block process it */
130 if (inlen >= left) {
131 memcpy(ctr->bltmp + ctr->bltmp_pos, in, left);
132 if (!ctr_BCC_blocks(ctr, ctr->bltmp))
133 return 0;
134 ctr->bltmp_pos = 0;
135 inlen -= left;
136 in += left;
137 }
138 }
139
140 /* Process zero or more complete blocks */
141 for (; inlen >= 16; in += 16, inlen -= 16) {
142 if (!ctr_BCC_blocks(ctr, in))
143 return 0;
144 }
145
146 /* Copy any remaining partial block to the temporary buffer */
147 if (inlen > 0) {
148 memcpy(ctr->bltmp + ctr->bltmp_pos, in, inlen);
149 ctr->bltmp_pos += inlen;
150 }
151 return 1;
152 }
153
154 __owur static int ctr_BCC_final(RAND_DRBG_CTR *ctr)
155 {
156 if (ctr->bltmp_pos) {
157 memset(ctr->bltmp + ctr->bltmp_pos, 0, 16 - ctr->bltmp_pos);
158 if (!ctr_BCC_blocks(ctr, ctr->bltmp))
159 return 0;
160 }
161 return 1;
162 }
163
164 __owur static int ctr_df(RAND_DRBG_CTR *ctr,
165 const unsigned char *in1, size_t in1len,
166 const unsigned char *in2, size_t in2len,
167 const unsigned char *in3, size_t in3len)
168 {
169 static unsigned char c80 = 0x80;
170 size_t inlen;
171 unsigned char *p = ctr->bltmp;
172 int outlen = AES_BLOCK_SIZE;
173
174 if (!ctr_BCC_init(ctr))
175 return 0;
176 if (in1 == NULL)
177 in1len = 0;
178 if (in2 == NULL)
179 in2len = 0;
180 if (in3 == NULL)
181 in3len = 0;
182 inlen = in1len + in2len + in3len;
183 /* Initialise L||N in temporary block */
184 *p++ = (inlen >> 24) & 0xff;
185 *p++ = (inlen >> 16) & 0xff;
186 *p++ = (inlen >> 8) & 0xff;
187 *p++ = inlen & 0xff;
188
189 /* NB keylen is at most 32 bytes */
190 *p++ = 0;
191 *p++ = 0;
192 *p++ = 0;
193 *p = (unsigned char)((ctr->keylen + 16) & 0xff);
194 ctr->bltmp_pos = 8;
195 if (!ctr_BCC_update(ctr, in1, in1len)
196 || !ctr_BCC_update(ctr, in2, in2len)
197 || !ctr_BCC_update(ctr, in3, in3len)
198 || !ctr_BCC_update(ctr, &c80, 1)
199 || !ctr_BCC_final(ctr))
200 return 0;
201 /* Set up key K */
202 if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->KX, NULL, 1))
203 return 0;
204 /* X follows key K */
205 if (!EVP_CipherUpdate(ctr->ctx, ctr->KX, &outlen, ctr->KX + ctr->keylen,
206 AES_BLOCK_SIZE)
207 || outlen != AES_BLOCK_SIZE)
208 return 0;
209 if (!EVP_CipherUpdate(ctr->ctx, ctr->KX + 16, &outlen, ctr->KX,
210 AES_BLOCK_SIZE)
211 || outlen != AES_BLOCK_SIZE)
212 return 0;
213 if (ctr->keylen != 16)
214 if (!EVP_CipherUpdate(ctr->ctx, ctr->KX + 32, &outlen, ctr->KX + 16,
215 AES_BLOCK_SIZE)
216 || outlen != AES_BLOCK_SIZE)
217 return 0;
218 return 1;
219 }
220
221 /*
222 * NB the no-df Update in SP800-90A specifies a constant input length
223 * of seedlen, however other uses of this algorithm pad the input with
224 * zeroes if necessary and have up to two parameters XORed together,
225 * so we handle both cases in this function instead.
226 */
227 __owur static int ctr_update(RAND_DRBG *drbg,
228 const unsigned char *in1, size_t in1len,
229 const unsigned char *in2, size_t in2len,
230 const unsigned char *nonce, size_t noncelen)
231 {
232 RAND_DRBG_CTR *ctr = &drbg->data.ctr;
233 int outlen = AES_BLOCK_SIZE;
234
235 /* correct key is already set up. */
236 inc_128(ctr);
237 if (!EVP_CipherUpdate(ctr->ctx, ctr->K, &outlen, ctr->V, AES_BLOCK_SIZE)
238 || outlen != AES_BLOCK_SIZE)
239 return 0;
240
241 /* If keylen longer than 128 bits need extra encrypt */
242 if (ctr->keylen != 16) {
243 inc_128(ctr);
244 if (!EVP_CipherUpdate(ctr->ctx, ctr->K+16, &outlen, ctr->V,
245 AES_BLOCK_SIZE)
246 || outlen != AES_BLOCK_SIZE)
247 return 0;
248 }
249 inc_128(ctr);
250 if (!EVP_CipherUpdate(ctr->ctx, ctr->V, &outlen, ctr->V, AES_BLOCK_SIZE)
251 || outlen != AES_BLOCK_SIZE)
252 return 0;
253
254 /* If 192 bit key part of V is on end of K */
255 if (ctr->keylen == 24) {
256 memcpy(ctr->V + 8, ctr->V, 8);
257 memcpy(ctr->V, ctr->K + 24, 8);
258 }
259
260 if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
261 /* If no input reuse existing derived value */
262 if (in1 != NULL || nonce != NULL || in2 != NULL)
263 if (!ctr_df(ctr, in1, in1len, nonce, noncelen, in2, in2len))
264 return 0;
265 /* If this a reuse input in1len != 0 */
266 if (in1len)
267 ctr_XOR(ctr, ctr->KX, drbg->seedlen);
268 } else {
269 ctr_XOR(ctr, in1, in1len);
270 ctr_XOR(ctr, in2, in2len);
271 }
272
273 if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->K, NULL, 1))
274 return 0;
275 return 1;
276 }
277
278 __owur static int drbg_ctr_instantiate(RAND_DRBG *drbg,
279 const unsigned char *entropy, size_t entropylen,
280 const unsigned char *nonce, size_t noncelen,
281 const unsigned char *pers, size_t perslen)
282 {
283 RAND_DRBG_CTR *ctr = &drbg->data.ctr;
284
285 if (entropy == NULL)
286 return 0;
287
288 memset(ctr->K, 0, sizeof(ctr->K));
289 memset(ctr->V, 0, sizeof(ctr->V));
290 if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->K, NULL, 1))
291 return 0;
292 if (!ctr_update(drbg, entropy, entropylen, pers, perslen, nonce, noncelen))
293 return 0;
294 return 1;
295 }
296
297 __owur static int drbg_ctr_reseed(RAND_DRBG *drbg,
298 const unsigned char *entropy, size_t entropylen,
299 const unsigned char *adin, size_t adinlen)
300 {
301 if (entropy == NULL)
302 return 0;
303 if (!ctr_update(drbg, entropy, entropylen, adin, adinlen, NULL, 0))
304 return 0;
305 return 1;
306 }
307
308 __owur static int drbg_ctr_generate(RAND_DRBG *drbg,
309 unsigned char *out, size_t outlen,
310 const unsigned char *adin, size_t adinlen)
311 {
312 RAND_DRBG_CTR *ctr = &drbg->data.ctr;
313
314 if (adin != NULL && adinlen != 0) {
315 if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
316 return 0;
317 /* This means we reuse derived value */
318 if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
319 adin = NULL;
320 adinlen = 1;
321 }
322 } else {
323 adinlen = 0;
324 }
325
326 for ( ; ; ) {
327 int outl = AES_BLOCK_SIZE;
328
329 inc_128(ctr);
330 if (outlen < 16) {
331 /* Use K as temp space as it will be updated */
332 if (!EVP_CipherUpdate(ctr->ctx, ctr->K, &outl, ctr->V,
333 AES_BLOCK_SIZE)
334 || outl != AES_BLOCK_SIZE)
335 return 0;
336 memcpy(out, ctr->K, outlen);
337 break;
338 }
339 if (!EVP_CipherUpdate(ctr->ctx, out, &outl, ctr->V, AES_BLOCK_SIZE)
340 || outl != AES_BLOCK_SIZE)
341 return 0;
342 out += 16;
343 outlen -= 16;
344 if (outlen == 0)
345 break;
346 }
347
348 if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
349 return 0;
350 return 1;
351 }
352
353 static int drbg_ctr_uninstantiate(RAND_DRBG *drbg)
354 {
355 EVP_CIPHER_CTX_free(drbg->data.ctr.ctx);
356 EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_df);
357 EVP_CIPHER_free(drbg->data.ctr.cipher);
358 OPENSSL_cleanse(&drbg->data.ctr, sizeof(drbg->data.ctr));
359 return 1;
360 }
361
362 static RAND_DRBG_METHOD drbg_ctr_meth = {
363 drbg_ctr_instantiate,
364 drbg_ctr_reseed,
365 drbg_ctr_generate,
366 drbg_ctr_uninstantiate
367 };
368
369 int drbg_ctr_init(RAND_DRBG *drbg)
370 {
371 RAND_DRBG_CTR *ctr = &drbg->data.ctr;
372 size_t keylen;
373 EVP_CIPHER *cipher = NULL;
374
375 switch (drbg->type) {
376 default:
377 /* This can't happen, but silence the compiler warning. */
378 return 0;
379 case NID_aes_128_ctr:
380 keylen = 16;
381 cipher = EVP_CIPHER_fetch(drbg->libctx, "AES-128-ECB", "");
382 break;
383 case NID_aes_192_ctr:
384 keylen = 24;
385 cipher = EVP_CIPHER_fetch(drbg->libctx, "AES-192-ECB", "");
386 break;
387 case NID_aes_256_ctr:
388 keylen = 32;
389 cipher = EVP_CIPHER_fetch(drbg->libctx, "AES-256-ECB", "");
390 break;
391 }
392 if (cipher == NULL)
393 return 0;
394
395 EVP_CIPHER_free(ctr->cipher);
396 ctr->cipher = cipher;
397
398 drbg->meth = &drbg_ctr_meth;
399
400 ctr->keylen = keylen;
401 if (ctr->ctx == NULL)
402 ctr->ctx = EVP_CIPHER_CTX_new();
403 if (ctr->ctx == NULL)
404 return 0;
405 drbg->strength = keylen * 8;
406 drbg->seedlen = keylen + 16;
407
408 if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
409 /* df initialisation */
410 static const unsigned char df_key[32] = {
411 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
412 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
413 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
414 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
415 };
416
417 if (ctr->ctx_df == NULL)
418 ctr->ctx_df = EVP_CIPHER_CTX_new();
419 if (ctr->ctx_df == NULL)
420 return 0;
421 /* Set key schedule for df_key */
422 if (!EVP_CipherInit_ex(ctr->ctx_df, ctr->cipher, NULL, df_key, NULL, 1))
423 return 0;
424
425 drbg->min_entropylen = ctr->keylen;
426 drbg->max_entropylen = DRBG_MAX_LENGTH;
427 drbg->min_noncelen = drbg->min_entropylen / 2;
428 drbg->max_noncelen = DRBG_MAX_LENGTH;
429 drbg->max_perslen = DRBG_MAX_LENGTH;
430 drbg->max_adinlen = DRBG_MAX_LENGTH;
431 } else {
432 #ifdef FIPS_MODE
433 RANDerr(RAND_F_DRBG_CTR_INIT,
434 RAND_R_DERIVATION_FUNCTION_MANDATORY_FOR_FIPS);
435 return 0;
436 #else
437 drbg->min_entropylen = drbg->seedlen;
438 drbg->max_entropylen = drbg->seedlen;
439 /* Nonce not used */
440 drbg->min_noncelen = 0;
441 drbg->max_noncelen = 0;
442 drbg->max_perslen = drbg->seedlen;
443 drbg->max_adinlen = drbg->seedlen;
444 #endif
445 }
446
447 drbg->max_request = 1 << 16;
448
449 return 1;
450 }