]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/rand/drbg_ctr.c
DOCS: Use "command" not "tool" or "utility"
[thirdparty/openssl.git] / crypto / rand / drbg_ctr.c
CommitLineData
12fb8c3d 1/*
3c7d0945 2 * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
12fb8c3d 3 *
0db63de9 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
12fb8c3d
RS
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>
12fb8c3d 15#include "internal/thread_once.h"
706457b7 16#include "rand_local.h"
8bf36651 17
12fb8c3d 18/*
75e2c877 19 * Implementation of NIST SP 800-90A CTR DRBG.
12fb8c3d 20 */
75e2c877 21static void inc_128(RAND_DRBG_CTR *ctr)
12fb8c3d
RS
22{
23 int i;
24 unsigned char c;
75e2c877 25 unsigned char *p = &ctr->V[15];
12fb8c3d
RS
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
75e2c877 38static void ctr_XOR(RAND_DRBG_CTR *ctr, const unsigned char *in, size_t inlen)
12fb8c3d
RS
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 */
75e2c877 49 n = inlen < ctr->keylen ? inlen : ctr->keylen;
12fb8c3d 50 for (i = 0; i < n; i++)
75e2c877
RS
51 ctr->K[i] ^= in[i];
52 if (inlen <= ctr->keylen)
12fb8c3d
RS
53 return;
54
75e2c877 55 n = inlen - ctr->keylen;
12fb8c3d
RS
56 if (n > 16) {
57 /* Should never happen */
58 n = 16;
59 }
b8a437ff 60 for (i = 0; i < n; i++)
75e2c877 61 ctr->V[i] ^= in[i + ctr->keylen];
12fb8c3d
RS
62}
63
64/*
65 * Process a complete block using BCC algorithm of SP 800-90A 10.3.3
66 */
dbdcc04f
KR
67__owur static int ctr_BCC_block(RAND_DRBG_CTR *ctr, unsigned char *out,
68 const unsigned char *in)
12fb8c3d 69{
dbdcc04f 70 int i, outlen = AES_BLOCK_SIZE;
12fb8c3d
RS
71
72 for (i = 0; i < 16; i++)
73 out[i] ^= in[i];
dbdcc04f
KR
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;
12fb8c3d
RS
79}
80
81
82/*
83 * Handle several BCC operations for as much data as we need for K and X
84 */
dbdcc04f 85__owur static int ctr_BCC_blocks(RAND_DRBG_CTR *ctr, const unsigned char *in)
12fb8c3d 86{
dbdcc04f
KR
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;
12fb8c3d
RS
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 */
dbdcc04f 99__owur static int ctr_BCC_init(RAND_DRBG_CTR *ctr)
12fb8c3d 100{
75e2c877
RS
101 memset(ctr->KX, 0, 48);
102 memset(ctr->bltmp, 0, 16);
dbdcc04f
KR
103 if (!ctr_BCC_block(ctr, ctr->KX, ctr->bltmp))
104 return 0;
75e2c877 105 ctr->bltmp[3] = 1;
dbdcc04f
KR
106 if (!ctr_BCC_block(ctr, ctr->KX + 16, ctr->bltmp))
107 return 0;
75e2c877
RS
108 if (ctr->keylen != 16) {
109 ctr->bltmp[3] = 2;
dbdcc04f
KR
110 if (!ctr_BCC_block(ctr, ctr->KX + 32, ctr->bltmp))
111 return 0;
12fb8c3d 112 }
dbdcc04f 113 return 1;
12fb8c3d
RS
114}
115
116/*
117 * Process several blocks into BCC algorithm, some possibly partial
118 */
dbdcc04f
KR
119__owur static int ctr_BCC_update(RAND_DRBG_CTR *ctr,
120 const unsigned char *in, size_t inlen)
12fb8c3d
RS
121{
122 if (in == NULL || inlen == 0)
dbdcc04f 123 return 1;
12fb8c3d
RS
124
125 /* If we have partial block handle it first */
75e2c877
RS
126 if (ctr->bltmp_pos) {
127 size_t left = 16 - ctr->bltmp_pos;
12fb8c3d
RS
128
129 /* If we now have a complete block process it */
130 if (inlen >= left) {
75e2c877 131 memcpy(ctr->bltmp + ctr->bltmp_pos, in, left);
dbdcc04f
KR
132 if (!ctr_BCC_blocks(ctr, ctr->bltmp))
133 return 0;
75e2c877 134 ctr->bltmp_pos = 0;
12fb8c3d
RS
135 inlen -= left;
136 in += left;
137 }
138 }
139
140 /* Process zero or more complete blocks */
141 for (; inlen >= 16; in += 16, inlen -= 16) {
dbdcc04f
KR
142 if (!ctr_BCC_blocks(ctr, in))
143 return 0;
12fb8c3d
RS
144 }
145
146 /* Copy any remaining partial block to the temporary buffer */
147 if (inlen > 0) {
75e2c877
RS
148 memcpy(ctr->bltmp + ctr->bltmp_pos, in, inlen);
149 ctr->bltmp_pos += inlen;
12fb8c3d 150 }
dbdcc04f 151 return 1;
12fb8c3d
RS
152}
153
dbdcc04f 154__owur static int ctr_BCC_final(RAND_DRBG_CTR *ctr)
12fb8c3d 155{
75e2c877
RS
156 if (ctr->bltmp_pos) {
157 memset(ctr->bltmp + ctr->bltmp_pos, 0, 16 - ctr->bltmp_pos);
dbdcc04f
KR
158 if (!ctr_BCC_blocks(ctr, ctr->bltmp))
159 return 0;
12fb8c3d 160 }
dbdcc04f 161 return 1;
12fb8c3d
RS
162}
163
dbdcc04f
KR
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)
12fb8c3d
RS
168{
169 static unsigned char c80 = 0x80;
170 size_t inlen;
75e2c877 171 unsigned char *p = ctr->bltmp;
dbdcc04f 172 int outlen = AES_BLOCK_SIZE;
12fb8c3d 173
dbdcc04f
KR
174 if (!ctr_BCC_init(ctr))
175 return 0;
12fb8c3d
RS
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;
75e2c877
RS
193 *p = (unsigned char)((ctr->keylen + 16) & 0xff);
194 ctr->bltmp_pos = 8;
dbdcc04f
KR
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;
12fb8c3d 201 /* Set up key K */
dbdcc04f
KR
202 if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->KX, NULL, 1))
203 return 0;
12fb8c3d 204 /* X follows key K */
dbdcc04f
KR
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;
75e2c877 213 if (ctr->keylen != 16)
dbdcc04f
KR
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;
12fb8c3d
RS
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,
75e2c877 225 * so we handle both cases in this function instead.
12fb8c3d 226 */
dbdcc04f
KR
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)
12fb8c3d 231{
8212d505 232 RAND_DRBG_CTR *ctr = &drbg->data.ctr;
dbdcc04f 233 int outlen = AES_BLOCK_SIZE;
12fb8c3d 234
dbdcc04f 235 /* correct key is already set up. */
75e2c877 236 inc_128(ctr);
dbdcc04f
KR
237 if (!EVP_CipherUpdate(ctr->ctx, ctr->K, &outlen, ctr->V, AES_BLOCK_SIZE)
238 || outlen != AES_BLOCK_SIZE)
239 return 0;
12fb8c3d
RS
240
241 /* If keylen longer than 128 bits need extra encrypt */
75e2c877
RS
242 if (ctr->keylen != 16) {
243 inc_128(ctr);
dbdcc04f
KR
244 if (!EVP_CipherUpdate(ctr->ctx, ctr->K+16, &outlen, ctr->V,
245 AES_BLOCK_SIZE)
246 || outlen != AES_BLOCK_SIZE)
247 return 0;
12fb8c3d 248 }
75e2c877 249 inc_128(ctr);
dbdcc04f
KR
250 if (!EVP_CipherUpdate(ctr->ctx, ctr->V, &outlen, ctr->V, AES_BLOCK_SIZE)
251 || outlen != AES_BLOCK_SIZE)
252 return 0;
12fb8c3d
RS
253
254 /* If 192 bit key part of V is on end of K */
75e2c877
RS
255 if (ctr->keylen == 24) {
256 memcpy(ctr->V + 8, ctr->V, 8);
257 memcpy(ctr->V, ctr->K + 24, 8);
12fb8c3d
RS
258 }
259
8164d91d 260 if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
12fb8c3d
RS
261 /* If no input reuse existing derived value */
262 if (in1 != NULL || nonce != NULL || in2 != NULL)
dbdcc04f
KR
263 if (!ctr_df(ctr, in1, in1len, nonce, noncelen, in2, in2len))
264 return 0;
12fb8c3d
RS
265 /* If this a reuse input in1len != 0 */
266 if (in1len)
75e2c877 267 ctr_XOR(ctr, ctr->KX, drbg->seedlen);
12fb8c3d 268 } else {
75e2c877
RS
269 ctr_XOR(ctr, in1, in1len);
270 ctr_XOR(ctr, in2, in2len);
12fb8c3d
RS
271 }
272
dbdcc04f
KR
273 if (!EVP_CipherInit_ex(ctr->ctx, ctr->cipher, NULL, ctr->K, NULL, 1))
274 return 0;
275 return 1;
12fb8c3d
RS
276}
277
dbdcc04f
KR
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)
12fb8c3d 282{
8212d505 283 RAND_DRBG_CTR *ctr = &drbg->data.ctr;
12fb8c3d 284
aa048aef 285 if (entropy == NULL)
4c78ba59
DSH
286 return 0;
287
75e2c877
RS
288 memset(ctr->K, 0, sizeof(ctr->K));
289 memset(ctr->V, 0, sizeof(ctr->V));
dbdcc04f
KR
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;
12fb8c3d
RS
294 return 1;
295}
296
dbdcc04f
KR
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)
12fb8c3d 300{
aa048aef 301 if (entropy == NULL)
4c78ba59 302 return 0;
dbdcc04f
KR
303 if (!ctr_update(drbg, entropy, entropylen, adin, adinlen, NULL, 0))
304 return 0;
12fb8c3d
RS
305 return 1;
306}
307
dbdcc04f
KR
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)
12fb8c3d 311{
8212d505 312 RAND_DRBG_CTR *ctr = &drbg->data.ctr;
12fb8c3d
RS
313
314 if (adin != NULL && adinlen != 0) {
dbdcc04f
KR
315 if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
316 return 0;
12fb8c3d 317 /* This means we reuse derived value */
8164d91d 318 if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
12fb8c3d
RS
319 adin = NULL;
320 adinlen = 1;
321 }
322 } else {
323 adinlen = 0;
324 }
325
326 for ( ; ; ) {
dbdcc04f
KR
327 int outl = AES_BLOCK_SIZE;
328
75e2c877 329 inc_128(ctr);
12fb8c3d
RS
330 if (outlen < 16) {
331 /* Use K as temp space as it will be updated */
dbdcc04f
KR
332 if (!EVP_CipherUpdate(ctr->ctx, ctr->K, &outl, ctr->V,
333 AES_BLOCK_SIZE)
334 || outl != AES_BLOCK_SIZE)
335 return 0;
75e2c877 336 memcpy(out, ctr->K, outlen);
12fb8c3d
RS
337 break;
338 }
dbdcc04f
KR
339 if (!EVP_CipherUpdate(ctr->ctx, out, &outl, ctr->V, AES_BLOCK_SIZE)
340 || outl != AES_BLOCK_SIZE)
341 return 0;
12fb8c3d
RS
342 out += 16;
343 outlen -= 16;
344 if (outlen == 0)
345 break;
346 }
347
dbdcc04f
KR
348 if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
349 return 0;
12fb8c3d
RS
350 return 1;
351}
352
8212d505 353static int drbg_ctr_uninstantiate(RAND_DRBG *drbg)
12fb8c3d 354{
dbdcc04f
KR
355 EVP_CIPHER_CTX_free(drbg->data.ctr.ctx);
356 EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_df);
550f974a 357 EVP_CIPHER_free(drbg->data.ctr.cipher);
8212d505 358 OPENSSL_cleanse(&drbg->data.ctr, sizeof(drbg->data.ctr));
12fb8c3d
RS
359 return 1;
360}
361
8212d505
DMSP
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)
12fb8c3d 370{
8212d505 371 RAND_DRBG_CTR *ctr = &drbg->data.ctr;
12fb8c3d 372 size_t keylen;
57ca171a 373 EVP_CIPHER *cipher = NULL;
12fb8c3d 374
31393fd9 375 switch (drbg->type) {
12fb8c3d
RS
376 default:
377 /* This can't happen, but silence the compiler warning. */
efb8128a 378 return 0;
12fb8c3d
RS
379 case NID_aes_128_ctr:
380 keylen = 16;
57ca171a 381 cipher = EVP_CIPHER_fetch(drbg->libctx, "AES-128-ECB", "");
12fb8c3d
RS
382 break;
383 case NID_aes_192_ctr:
384 keylen = 24;
57ca171a 385 cipher = EVP_CIPHER_fetch(drbg->libctx, "AES-192-ECB", "");
12fb8c3d
RS
386 break;
387 case NID_aes_256_ctr:
388 keylen = 32;
57ca171a 389 cipher = EVP_CIPHER_fetch(drbg->libctx, "AES-256-ECB", "");
12fb8c3d
RS
390 break;
391 }
57ca171a
MC
392 if (cipher == NULL)
393 return 0;
394
550f974a 395 EVP_CIPHER_free(ctr->cipher);
57ca171a 396 ctr->cipher = cipher;
12fb8c3d 397
8212d505
DMSP
398 drbg->meth = &drbg_ctr_meth;
399
75e2c877 400 ctr->keylen = keylen;
dbdcc04f
KR
401 if (ctr->ctx == NULL)
402 ctr->ctx = EVP_CIPHER_CTX_new();
403 if (ctr->ctx == NULL)
404 return 0;
75e2c877
RS
405 drbg->strength = keylen * 8;
406 drbg->seedlen = keylen + 16;
12fb8c3d 407
8164d91d 408 if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
12fb8c3d 409 /* df initialisation */
dbdcc04f 410 static const unsigned char df_key[32] = {
c2e33a05
F
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
12fb8c3d 415 };
dbdcc04f
KR
416
417 if (ctr->ctx_df == NULL)
418 ctr->ctx_df = EVP_CIPHER_CTX_new();
419 if (ctr->ctx_df == NULL)
420 return 0;
12fb8c3d 421 /* Set key schedule for df_key */
dbdcc04f
KR
422 if (!EVP_CipherInit_ex(ctr->ctx_df, ctr->cipher, NULL, df_key, NULL, 1))
423 return 0;
75e2c877 424
aa048aef 425 drbg->min_entropylen = ctr->keylen;
3064b551 426 drbg->max_entropylen = DRBG_MAX_LENGTH;
aa048aef 427 drbg->min_noncelen = drbg->min_entropylen / 2;
3064b551 428 drbg->max_noncelen = DRBG_MAX_LENGTH;
aa048aef
DMSP
429 drbg->max_perslen = DRBG_MAX_LENGTH;
430 drbg->max_adinlen = DRBG_MAX_LENGTH;
12fb8c3d 431 } else {
6c7d80ab
P
432#ifdef FIPS_MODE
433 RANDerr(RAND_F_DRBG_CTR_INIT,
434 RAND_R_DERIVATION_FUNCTION_MANDATORY_FOR_FIPS);
435 return 0;
436#else
aa048aef
DMSP
437 drbg->min_entropylen = drbg->seedlen;
438 drbg->max_entropylen = drbg->seedlen;
12fb8c3d 439 /* Nonce not used */
aa048aef
DMSP
440 drbg->min_noncelen = 0;
441 drbg->max_noncelen = 0;
442 drbg->max_perslen = drbg->seedlen;
443 drbg->max_adinlen = drbg->seedlen;
6c7d80ab 444#endif
12fb8c3d
RS
445 }
446
75e2c877 447 drbg->max_request = 1 << 16;
4917e911 448
12fb8c3d
RS
449 return 1;
450}