VirtualBox

source: vbox/trunk/src/libs/openssl-1.1.1f/crypto/rand/drbg_ctr.c@ 83531

Last change on this file since 83531 was 83531, checked in by vboxsync, 5 years ago

setting svn:sync-process=export for openssl-1.1.1f, all files except tests

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette