VirtualBox

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

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

openssl-1.1.1g: Applied and adjusted our OpenSSL changes to 1.1.1g. bugref:9719

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