1 /*
2 * This file is part of the openHiTLS project.
3 *
4 * openHiTLS is licensed under the Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *
8 * http://license.coscl.org.cn/MulanPSL2
9 *
10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13 * See the Mulan PSL v2 for more details.
14 */
15
16 #include "hitls_build.h"
17 #ifdef HITLS_CRYPTO_DRBG_CTR
18
19 #include <stdlib.h>
20 #include <securec.h>
21 #include "crypt_errno.h"
22 #include "crypt_local_types.h"
23 #include "crypt_utils.h"
24 #include "bsl_sal.h"
25 #include "crypt_types.h"
26 #include "bsl_err_internal.h"
27 #include "drbg_local.h"
28
29
30 #define DRBG_CTR_MAX_KEYLEN (32)
31 #define AES_BLOCK_LEN (16)
32 #define DRBG_CTR_MAX_SEEDLEN (48)
33 #define DRBG_CTR_MIN_ENTROPYLEN (32)
34
35 typedef struct {
36 uint8_t k[DRBG_CTR_MAX_KEYLEN]; // DRBG_CTR_MAX_KEYLEN 32
37 uint8_t v[AES_BLOCK_LEN]; // AES_BLOCK_LEN 16 (blockLen)
38 uint8_t kx[DRBG_CTR_MAX_SEEDLEN]; // DRBG_CTR_MAX_SEEDLEN 48
39 uint32_t keyLen;
40 uint32_t seedLen;
41 const EAL_SymMethod *ciphMeth;
42 void *ctrCtx;
43 void *dfCtx;
44 bool isUsedDf;
45 } DRBG_CtrCtx;
46
DRBG_CtrXor(CRYPT_Data * dst,const CRYPT_Data * src)47 static void DRBG_CtrXor(CRYPT_Data *dst, const CRYPT_Data *src)
48 {
49 uint32_t xorlen;
50
51 if (CRYPT_IsDataNull(dst) || CRYPT_IsDataNull(src)) {
52 return;
53 }
54
55 xorlen = (dst->len > src->len) ? src->len : dst->len;
56
57 DATA_XOR(dst->data, src->data, dst->data, xorlen);
58 }
59
DRBG_CtrInc(uint8_t * v,uint32_t len)60 static void DRBG_CtrInc(uint8_t *v, uint32_t len)
61 {
62 uint32_t i;
63 uint8_t *p = v + len - 1;
64 for (i = 0; i < len; i++, p--) {
65 (*p)++;
66 if (*p != 0) {
67 break;
68 }
69 }
70 }
71
DRBG_CtrUpdate(DRBG_Ctx * drbg,const CRYPT_Data * in1,const CRYPT_Data * in2)72 int32_t DRBG_CtrUpdate(DRBG_Ctx *drbg, const CRYPT_Data *in1, const CRYPT_Data *in2)
73 {
74 DRBG_CtrCtx *ctx = (DRBG_CtrCtx *)drbg->ctx;
75 const EAL_SymMethod *ciphMeth = ctx->ciphMeth;
76 int32_t ret;
77 uint8_t tempData[DRBG_CTR_MAX_SEEDLEN];
78 CRYPT_Data temp;
79 uint32_t offset;
80
81 if ((ret = ciphMeth->setEncryptKey(ctx->ctrCtx, ctx->k, ctx->keyLen)) != CRYPT_SUCCESS) {
82 BSL_ERR_PUSH_ERROR(ret);
83 return ret;
84 }
85
86 /**
87 While (len (temp) < seedlen) do
88 If ctr_len < blocklen
89 inc = (rightmost (V, ctr_len) + 1) mod 2ctr_len .
90 V = leftmost (V, blocklen-ctr_len) || inc.
91 Else V = (V+1) mod 2blocklen .
92 output_block = Block_Encrypt (Key, V).
93 temp = temp || output_block.
94 */
95 for (offset = 0; offset < ctx->seedLen; offset += AES_BLOCK_LEN) {
96 DRBG_CtrInc(ctx->v, AES_BLOCK_LEN);
97 if ((ret = ciphMeth->encryptBlock(ctx->ctrCtx, ctx->v, tempData + offset, AES_BLOCK_LEN)) != CRYPT_SUCCESS) {
98 BSL_ERR_PUSH_ERROR(ret);
99 goto EXIT;
100 }
101 }
102
103 // temp = temp ⊕ provided_data
104 temp.data = tempData;
105 temp.len = ctx->seedLen;
106 DRBG_CtrXor(&temp, in1);
107 DRBG_CtrXor(&temp, in2);
108
109 // Key = leftmost (temp, keylen). V = rightmost (temp, blocklen).
110 if (memcpy_s(ctx->k, DRBG_CTR_MAX_KEYLEN, temp.data, ctx->keyLen) != EOK) {
111 BSL_ERR_PUSH_ERROR(CRYPT_SECUREC_FAIL);
112 ret = CRYPT_SECUREC_FAIL;
113 goto EXIT;
114 }
115 // The length to be copied of ctx->V is AES_BLOCK_LEN, which is also the array length.
116 // The lower bits of temp.data are used for ctx->K, and the upper bits are used for ctx->V.
117 (void)memcpy_s(ctx->v, AES_BLOCK_LEN, temp.data + ctx->keyLen, AES_BLOCK_LEN);
118 EXIT:
119 ciphMeth->cipherDeInitCtx(ctx->ctrCtx);
120 return ret;
121 }
122
123 // BCC implementation, BCC is CBC-MAC: CBC encryption + IV(0) + last ciphertext returned.
DRBG_CtrBCCUpdateBlock(DRBG_Ctx * drbg,const uint8_t * in,uint8_t * out,uint32_t len)124 static int32_t DRBG_CtrBCCUpdateBlock(DRBG_Ctx *drbg, const uint8_t *in, uint8_t *out, uint32_t len)
125 {
126 DRBG_CtrCtx *ctx = (DRBG_CtrCtx *)drbg->ctx;
127 int32_t ret;
128 /**
129 4. For i = 1 to n do
130 4.1 input_block = chaining_value ⊕ blocki.
131 4.2 chaining_value = Block_Encrypt (Key, input_block).
132 */
133 DATA_XOR(out, in, out, len);
134 if ((ret = ctx->ciphMeth->encryptBlock(ctx->dfCtx, out, out, AES_BLOCK_LEN)) != CRYPT_SUCCESS) {
135 BSL_ERR_PUSH_ERROR(ret);
136 ctx->ciphMeth->cipherDeInitCtx(ctx->dfCtx);
137 }
138
139 return ret;
140 }
141
DRBG_CtrBCCInit(DRBG_Ctx * drbg)142 static int32_t DRBG_CtrBCCInit(DRBG_Ctx *drbg)
143 {
144 DRBG_CtrCtx *ctx = (DRBG_CtrCtx *)drbg->ctx;
145 uint8_t *out = ctx->kx;
146 int32_t ret = CRYPT_SUCCESS;
147 uint8_t in[16] = { 0 };
148 uint32_t offset = 0;
149
150 while (offset < ctx->seedLen) {
151 if ((ret = DRBG_CtrBCCUpdateBlock(drbg, in, out + offset, AES_BLOCK_LEN)) != CRYPT_SUCCESS) {
152 BSL_ERR_PUSH_ERROR(ret);
153 return ret;
154 }
155 in[3]++; // Each cycle is incremented by 1 at the 3rd position.
156 offset += AES_BLOCK_LEN;
157 }
158
159 return ret;
160 }
161
DRBG_CtrBCCUpdateKX(DRBG_Ctx * drbg,const uint8_t * in)162 static int32_t DRBG_CtrBCCUpdateKX(DRBG_Ctx *drbg, const uint8_t *in)
163 {
164 DRBG_CtrCtx *ctx = (DRBG_CtrCtx *)drbg->ctx;
165 uint8_t *out = ctx->kx;
166 int32_t ret = CRYPT_SUCCESS;
167 uint32_t offset = 0;
168
169 while (offset < ctx->seedLen) {
170 if ((ret = DRBG_CtrBCCUpdateBlock(drbg, in, out + offset, AES_BLOCK_LEN)) != CRYPT_SUCCESS) {
171 BSL_ERR_PUSH_ERROR(ret);
172 return ret;
173 }
174 offset += AES_BLOCK_LEN;
175 }
176
177 return ret;
178 }
179
180 // Temporary block storage used by ctr_df
DRBG_CtrBCCUpdate(DRBG_Ctx * drbg,const CRYPT_Data * in,uint8_t temp[16],uint32_t * tempLen)181 static int32_t DRBG_CtrBCCUpdate(DRBG_Ctx *drbg, const CRYPT_Data *in, uint8_t temp[16], uint32_t *tempLen)
182 {
183 uint32_t dataLeft;
184 uint32_t offset = 0;
185 uint32_t tempPos = *tempLen;
186 int32_t ret = CRYPT_SUCCESS;
187
188 if (CRYPT_IsDataNull(in) || in->len == 0) {
189 return ret;
190 }
191
192 dataLeft = in->len;
193
194 do {
195 const uint32_t left = AES_BLOCK_LEN - tempPos;
196 const uint32_t cpyLen = (left > dataLeft) ? dataLeft : left;
197 if (memcpy_s(temp + tempPos, left, in->data + offset, cpyLen) != EOK) {
198 BSL_ERR_PUSH_ERROR(CRYPT_SECUREC_FAIL);
199 return CRYPT_SECUREC_FAIL;
200 }
201
202 if (left == cpyLen) {
203 if ((ret = DRBG_CtrBCCUpdateKX(drbg, temp)) != CRYPT_SUCCESS) {
204 BSL_ERR_PUSH_ERROR(ret);
205 return ret;
206 }
207 tempPos = 0;
208 } else {
209 tempPos += cpyLen;
210 }
211
212 dataLeft -= cpyLen;
213 offset += cpyLen;
214 } while (dataLeft > 0);
215
216 *tempLen = tempPos;
217
218 return ret;
219 }
220
DRBG_CtrBCCFinal(DRBG_Ctx * drbg,uint8_t temp[16],uint32_t tempLen)221 static int32_t DRBG_CtrBCCFinal(DRBG_Ctx *drbg, uint8_t temp[16], uint32_t tempLen)
222 {
223 int32_t ret;
224 uint32_t i;
225
226 for (i = tempLen; i < AES_BLOCK_LEN; i++) {
227 temp[i] = 0;
228 }
229
230 if ((ret = DRBG_CtrBCCUpdateKX(drbg, temp)) != CRYPT_SUCCESS) {
231 BSL_ERR_PUSH_ERROR(ret);
232 }
233
234 return ret;
235 }
236
BlockCipherDfCal(DRBG_Ctx * drbg,CRYPT_Data * out)237 static int32_t BlockCipherDfCal(DRBG_Ctx *drbg, CRYPT_Data *out)
238 {
239 DRBG_CtrCtx *ctx = (DRBG_CtrCtx *)drbg->ctx;
240 const EAL_SymMethod *ciphMeth = ctx->ciphMeth;
241 int32_t ret;
242 uint32_t kOffset = 0;
243 uint32_t vOffset = ctx->keyLen;
244
245 /* Set up key K */
246 if ((ret = ciphMeth->setEncryptKey(ctx->ctrCtx, ctx->kx, ctx->keyLen)) != CRYPT_SUCCESS) {
247 BSL_ERR_PUSH_ERROR(ret);
248 return ret;
249 }
250
251 while (kOffset < ctx->seedLen) {
252 ret = ciphMeth->encryptBlock(ctx->ctrCtx, ctx->kx + vOffset, ctx->kx + kOffset, AES_BLOCK_LEN);
253 if (ret != CRYPT_SUCCESS) {
254 BSL_ERR_PUSH_ERROR(ret);
255 goto EXIT;
256 }
257
258 vOffset = kOffset;
259 kOffset += AES_BLOCK_LEN;
260 }
261
262 out->data = ctx->kx;
263 out->len = ctx->seedLen;
264
265 EXIT:
266 ciphMeth->cipherDeInitCtx(ctx->ctrCtx);
267 return ret;
268 }
269
BlockCipherDf(DRBG_Ctx * drbg,const CRYPT_Data * in1,const CRYPT_Data * in2,const CRYPT_Data * in3,CRYPT_Data * out)270 static int32_t BlockCipherDf(DRBG_Ctx *drbg, const CRYPT_Data *in1, const CRYPT_Data *in2,
271 const CRYPT_Data *in3, CRYPT_Data *out)
272 {
273 DRBG_CtrCtx *ctx = (DRBG_CtrCtx *)drbg->ctx;
274 int32_t ret;
275 uint32_t tempLen = 8;
276 uint8_t temp[16] = { 0 };
277 uint32_t l;
278
279 BSL_SAL_CleanseData(ctx->kx, sizeof(ctx->kx));
280
281 if ((ret = DRBG_CtrBCCInit(drbg)) != CRYPT_SUCCESS) {
282 BSL_ERR_PUSH_ERROR(ret);
283 return ret;
284 }
285
286 /**
287 2. L = len (input_string)/8.
288 3. N = number_of_bits_to_return/8.
289 4. S = L || N || input_string || 0x80.
290 5. While (len (S) mod outlen) ≠ 0, do
291 S = S || 0x00.
292 6. temp = the Null string.
293 9. While len (temp) < keylen + outlen, do
294 9.1 IV = i || 0^(outlen - len (i))
295 9.2 temp = temp || BCC (K, (IV || S)).
296 9.3 i = i + 1.
297 */
298
299 l = (in1 ? in1->len : 0) + (in2 ? in2->len : 0) + (in3 ? in3->len : 0);
300
301 temp[0] = (uint8_t)((l >> 24) & 0xff);
302 temp[1] = (uint8_t)((l >> 16) & 0xff);
303 temp[2] = (uint8_t)((l >> 8) & 0xff);
304 temp[3] = (uint8_t)(l & 0xff);
305 temp[4] = 0;
306 temp[5] = 0;
307 temp[6] = 0;
308 temp[7] = (uint8_t)ctx->seedLen;
309
310 if ((ret = DRBG_CtrBCCUpdate(drbg, in1, temp, &tempLen)) != CRYPT_SUCCESS) {
311 BSL_ERR_PUSH_ERROR(ret);
312 return ret;
313 }
314
315 if ((ret = DRBG_CtrBCCUpdate(drbg, in2, temp, &tempLen)) != CRYPT_SUCCESS) {
316 BSL_ERR_PUSH_ERROR(ret);
317 return ret;
318 }
319
320 if ((ret = DRBG_CtrBCCUpdate(drbg, in3, temp, &tempLen)) != CRYPT_SUCCESS) {
321 BSL_ERR_PUSH_ERROR(ret);
322 return ret;
323 }
324
325 temp[tempLen++] = 0x80;
326 if ((ret = DRBG_CtrBCCFinal(drbg, temp, tempLen)) != CRYPT_SUCCESS) {
327 BSL_ERR_PUSH_ERROR(ret);
328 return ret;
329 }
330
331 /**
332 13. While len (temp) < number_of_bits_to_return, do
333 13.1 X = Block_Encrypt (K, X).
334 13.2 temp = temp || X.
335 */
336 if ((ret = BlockCipherDfCal(drbg, out)) != CRYPT_SUCCESS) {
337 BSL_ERR_PUSH_ERROR(ret);
338 }
339
340 return ret;
341 }
342
DRBG_CtrSetDfKey(DRBG_Ctx * drbg)343 static int32_t DRBG_CtrSetDfKey(DRBG_Ctx *drbg)
344 {
345 DRBG_CtrCtx *ctx = (DRBG_CtrCtx *)drbg->ctx;
346 const EAL_SymMethod *ciphMeth = ctx->ciphMeth;
347 int32_t ret = CRYPT_SUCCESS;
348
349 BSL_SAL_CleanseData(ctx->ctrCtx, ciphMeth->ctxSize);
350
351 if (ctx->isUsedDf) {
352 /* df initialisation */
353 const uint8_t dfKey[32] = {
354 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
355 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
356 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
357 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
358 };
359
360 BSL_SAL_CleanseData(ctx->dfCtx, ciphMeth->ctxSize);
361
362 /* Set key schedule for dfKey */
363 if ((ret = ctx->ciphMeth->setEncryptKey(ctx->dfCtx, dfKey, ctx->keyLen)) != CRYPT_SUCCESS) {
364 BSL_ERR_PUSH_ERROR(ret);
365 }
366 }
367
368 return ret;
369 }
370
DRBG_CtrInstantiate(DRBG_Ctx * drbg,const CRYPT_Data * entropy,const CRYPT_Data * nonce,const CRYPT_Data * pers)371 int32_t DRBG_CtrInstantiate(DRBG_Ctx *drbg, const CRYPT_Data *entropy, const CRYPT_Data *nonce, const CRYPT_Data *pers)
372 {
373 DRBG_CtrCtx *ctx = (DRBG_CtrCtx *)drbg->ctx;
374 CRYPT_Data seedMaterial;
375 int32_t ret;
376
377 if ((ret = DRBG_CtrSetDfKey(drbg)) != CRYPT_SUCCESS) {
378 return ret;
379 }
380 /**
381 * 4. Key = 0(keylen)
382 * 5. V = 0(blocklen)
383 */
384 BSL_SAL_CleanseData(ctx->k, sizeof(ctx->k));
385 BSL_SAL_CleanseData(ctx->v, sizeof(ctx->v));
386
387 /* seed_material = entropy_input ⊕ personalization_string.
388 (Key, V) = CTR_DRBG_Update (seed_material, Key, V).
389 */
390 if (!ctx->isUsedDf) {
391 if ((ret = DRBG_CtrUpdate(drbg, entropy, pers)) != CRYPT_SUCCESS) {
392 BSL_ERR_PUSH_ERROR(ret);
393 }
394 return ret;
395 }
396 // seed_material = entropy_input || nonce || personalization_string.
397 if ((ret = BlockCipherDf(drbg, entropy, nonce, pers, &seedMaterial)) != CRYPT_SUCCESS) {
398 BSL_ERR_PUSH_ERROR(ret);
399 ctx->ciphMeth->cipherDeInitCtx(ctx->dfCtx);
400 return ret;
401 }
402
403 if ((ret = DRBG_CtrUpdate(drbg, &seedMaterial, NULL)) != CRYPT_SUCCESS) {
404 BSL_ERR_PUSH_ERROR(ret);
405 }
406
407 return ret;
408 }
409
DRBG_CtrReseed(DRBG_Ctx * drbg,const CRYPT_Data * entropy,const CRYPT_Data * adin)410 int32_t DRBG_CtrReseed(DRBG_Ctx *drbg, const CRYPT_Data *entropy, const CRYPT_Data *adin)
411 {
412 DRBG_CtrCtx *ctx = (DRBG_CtrCtx *)drbg->ctx;
413 CRYPT_Data seedMaterial;
414 int32_t ret;
415
416 if (!ctx->isUsedDf) {
417 if ((ret = DRBG_CtrUpdate(drbg, entropy, adin)) != CRYPT_SUCCESS) {
418 BSL_ERR_PUSH_ERROR(ret);
419 }
420 return ret;
421 }
422
423 // seed_material = entropy_input || additional_input.
424 if ((ret = BlockCipherDf(drbg, entropy, adin, NULL, &seedMaterial)) != CRYPT_SUCCESS) {
425 BSL_ERR_PUSH_ERROR(ret);
426 return ret;
427 }
428
429 if ((ret = DRBG_CtrUpdate(drbg, &seedMaterial, NULL)) != CRYPT_SUCCESS) {
430 BSL_ERR_PUSH_ERROR(ret);
431 }
432
433 return ret;
434 }
435
DRBG_CtrGenerateBlock(DRBG_Ctx * drbg,uint8_t * out,uint32_t outLen)436 static int32_t DRBG_CtrGenerateBlock(DRBG_Ctx *drbg, uint8_t *out, uint32_t outLen)
437 {
438 DRBG_CtrCtx *ctx = (DRBG_CtrCtx *)drbg->ctx;
439 int32_t ret;
440
441 DRBG_CtrInc(ctx->v, outLen);
442
443 if ((ret = ctx->ciphMeth->encryptBlock(ctx->ctrCtx, ctx->v, out, outLen)) != CRYPT_SUCCESS) {
444 BSL_ERR_PUSH_ERROR(ret);
445 ctx->ciphMeth->cipherDeInitCtx(ctx->ctrCtx);
446 }
447 return ret;
448 }
449
DRBG_CtrGenerateBlocks(DRBG_Ctx * drbg,uint8_t * out,uint32_t outLen)450 static int32_t DRBG_CtrGenerateBlocks(DRBG_Ctx *drbg, uint8_t *out, uint32_t outLen)
451 {
452 DRBG_CtrCtx *ctx = (DRBG_CtrCtx *)drbg->ctx;
453 uint32_t offset = 0;
454 uint32_t tmpOutLen = outLen;
455 int32_t ret;
456
457 if ((ret = ctx->ciphMeth->setEncryptKey(ctx->ctrCtx, ctx->k, ctx->keyLen)) != CRYPT_SUCCESS) {
458 BSL_ERR_PUSH_ERROR(ret);
459 return ret;
460 }
461
462 while (tmpOutLen >= AES_BLOCK_LEN) {
463 if ((ret = DRBG_CtrGenerateBlock(drbg, out + offset, AES_BLOCK_LEN)) != CRYPT_SUCCESS) {
464 BSL_ERR_PUSH_ERROR(ret);
465 return ret;
466 }
467
468 tmpOutLen -= AES_BLOCK_LEN;
469 offset += AES_BLOCK_LEN;
470 }
471
472 if (tmpOutLen > 0) {
473 uint8_t temp[AES_BLOCK_LEN];
474 if ((ret = DRBG_CtrGenerateBlock(drbg, temp, AES_BLOCK_LEN)) != CRYPT_SUCCESS) {
475 BSL_ERR_PUSH_ERROR(ret);
476 return ret;
477 }
478 // tmpOutLen indicates the length of the out remaining. In the last part of DRBG generation,
479 // truncate the length of tmpOutLen and assign it to the out remaining.
480 (void)memcpy_s(out + offset, tmpOutLen, temp, tmpOutLen);
481 }
482
483 return ret;
484 }
485
DRBG_CtrGenerate(DRBG_Ctx * drbg,uint8_t * out,uint32_t outLen,const CRYPT_Data * adin)486 int32_t DRBG_CtrGenerate(DRBG_Ctx *drbg, uint8_t *out, uint32_t outLen, const CRYPT_Data *adin)
487 {
488 DRBG_CtrCtx *ctx = (DRBG_CtrCtx *)drbg->ctx;
489 int32_t ret;
490 /**
491 If (additional_input ≠ Null), then
492 temp = len (additional_input)
493 If (temp < seedlen), then
494 additional_input = additional_input || 0^(seedlen - temp).
495 (Key, V) = CTR_DRBG_Update (additional_input, Key, V)
496 Else additional_input = 0seedlen.
497 */
498 if (adin != NULL && adin->data != NULL && adin->len != 0) {
499 if (!ctx->isUsedDf) {
500 if ((ret = DRBG_CtrUpdate(drbg, adin, NULL)) != CRYPT_SUCCESS) {
501 BSL_ERR_PUSH_ERROR(ret);
502 return ret;
503 }
504 } else {
505 // additional_input = Block_Cipher_df (additional_input, seedlen).
506 if ((ret = BlockCipherDf(drbg, adin, NULL, NULL, (CRYPT_Data *)(uintptr_t)adin)) != CRYPT_SUCCESS) {
507 BSL_ERR_PUSH_ERROR(ret);
508 return ret;
509 }
510 if ((ret = DRBG_CtrUpdate(drbg, adin, NULL)) != CRYPT_SUCCESS) {
511 BSL_ERR_PUSH_ERROR(ret);
512 return ret;
513 }
514 }
515 }
516
517 /**
518 3. temp = Null.
519 4. While (len (temp) < requested_number_of_bits) do:
520 4.1 If ctr_len < blocklen
521 4.1.1 inc = (rightmost (V, ctr_len) + 1) mod 2ctr_len .
522 4.1.2 V = leftmost (V, blocklen-ctr_len) || inc.
523 Else V = (V+1) mod 2blocklen .
524 4.2 output_block = Block_Encrypt (Key, V).
525 4.3 temp = temp || output_block.
526 5. returned_bits = leftmost (temp, requested_number_of_bits).
527 */
528
529 if ((ret = DRBG_CtrGenerateBlocks(drbg, out, outLen)) != CRYPT_SUCCESS) {
530 BSL_ERR_PUSH_ERROR(ret);
531 return ret;
532 }
533
534 // (Key, V) = CTR_DRBG_Update (additional_input, Key, V).
535 if ((ret = DRBG_CtrUpdate(drbg, adin, NULL)) != CRYPT_SUCCESS) {
536 BSL_ERR_PUSH_ERROR(ret);
537 }
538
539 return ret;
540 }
541
DRBG_CtrUnInstantiate(DRBG_Ctx * drbg)542 void DRBG_CtrUnInstantiate(DRBG_Ctx *drbg)
543 {
544 DRBG_CtrCtx *ctx = (DRBG_CtrCtx*)drbg->ctx;
545
546 ctx->ciphMeth->cipherDeInitCtx(ctx->ctrCtx);
547 ctx->ciphMeth->cipherDeInitCtx(ctx->dfCtx);
548 BSL_SAL_CleanseData((void *)(ctx->k), sizeof(ctx->k));
549 BSL_SAL_CleanseData((void *)(ctx->v), sizeof(ctx->v));
550 BSL_SAL_CleanseData((void *)(ctx->kx), sizeof(ctx->kx));
551 }
552
DRBG_CtrDup(DRBG_Ctx * drbg)553 DRBG_Ctx *DRBG_CtrDup(DRBG_Ctx *drbg)
554 {
555 DRBG_CtrCtx *ctx = NULL;
556
557 if (drbg == NULL) {
558 return NULL;
559 }
560
561 ctx = (DRBG_CtrCtx*)drbg->ctx;
562 return DRBG_NewCtrCtx(ctx->ciphMeth, ctx->keyLen, drbg->isGm, ctx->isUsedDf, &(drbg->seedMeth), drbg->seedCtx);
563 }
564
DRBG_CtrFree(DRBG_Ctx * drbg)565 void DRBG_CtrFree(DRBG_Ctx *drbg)
566 {
567 if (drbg == NULL) {
568 return;
569 }
570
571 DRBG_CtrUnInstantiate(drbg);
572 DRBG_CtrCtx *ctx = (DRBG_CtrCtx*)drbg->ctx;
573 BSL_SAL_FREE(ctx->dfCtx);
574 BSL_SAL_FREE(drbg);
575 return;
576 }
577
DRBG_NewCtrCtx(const EAL_SymMethod * ciphMeth,const uint32_t keyLen,bool isGm,const bool isUsedDf,const CRYPT_RandSeedMethod * seedMeth,void * seedCtx)578 DRBG_Ctx *DRBG_NewCtrCtx(const EAL_SymMethod *ciphMeth, const uint32_t keyLen, bool isGm, const bool isUsedDf,
579 const CRYPT_RandSeedMethod *seedMeth, void *seedCtx)
580 {
581 static DRBG_Method meth = {
582 DRBG_CtrInstantiate,
583 DRBG_CtrGenerate,
584 DRBG_CtrReseed,
585 DRBG_CtrUnInstantiate,
586 DRBG_CtrDup,
587 DRBG_CtrFree
588 };
589
590 if (ciphMeth == NULL || keyLen == 0 || seedMeth == NULL) {
591 return NULL;
592 }
593
594 DRBG_Ctx *drbg = (DRBG_Ctx*)BSL_SAL_Malloc(sizeof(DRBG_Ctx) + sizeof(DRBG_CtrCtx) + ciphMeth->ctxSize);
595 if (drbg == NULL) {
596 return NULL;
597 }
598 void *dfCtx = (void*)BSL_SAL_Malloc(ciphMeth->ctxSize); // have 2 contexts
599 if (dfCtx == NULL) {
600 BSL_SAL_FREE(drbg);
601 return NULL;
602 }
603
604 DRBG_CtrCtx *ctx = (DRBG_CtrCtx*)(drbg + 1);
605 ctx->ctrCtx = (void*)(ctx + 1);
606 ctx->dfCtx = dfCtx;
607
608 ctx->ciphMeth = ciphMeth;
609
610 drbg->state = DRBG_STATE_UNINITIALISED;
611 drbg->isGm = isGm;
612 drbg->reseedInterval = (drbg->isGm) ? HITLS_CRYPTO_RESEED_INTERVAL_GM : DRBG_MAX_RESEED_INTERVAL;
613 #if defined(HITLS_CRYPTO_DRBG_GM)
614 drbg->reseedIntervalTime = (drbg->isGm) ? HITLS_CRYPTO_DRBG_RESEED_TIME_GM : 0;
615 #endif
616
617 ctx->keyLen = keyLen;
618 ctx->seedLen = AES_BLOCK_LEN + keyLen;
619 ctx->isUsedDf = isUsedDf;
620 drbg->meth = &meth;
621 drbg->ctx = ctx;
622 drbg->seedMeth = *seedMeth;
623 drbg->seedCtx = seedCtx;
624
625 drbg->strength = keyLen * 8;
626 drbg->maxRequest = (drbg->isGm) ? DRBG_MAX_REQUEST_SM4 : DRBG_MAX_REQUEST;
627 // NIST.SP.800-90Ar1, Section 10.3.1 Table 3 defined those initial value.
628 if (isUsedDf) {
629 // shift rightwards by 3, converting from bit length to byte length
630 drbg->entropyRange.min = (drbg->isGm) ? DRBG_CTR_MIN_ENTROPYLEN : keyLen;
631 drbg->entropyRange.max = DRBG_MAX_LEN;
632 drbg->maxPersLen = DRBG_MAX_LEN;
633 drbg->maxAdinLen = DRBG_MAX_LEN;
634
635 // NIST.SP.800-90Ar1, Section 8.6.7 defined, a nonce needs (security_strength/2) bits of entropy at least.
636 drbg->nonceRange.min = drbg->entropyRange.min / DRBG_NONCE_FROM_ENTROPY;
637 drbg->nonceRange.max = DRBG_MAX_LEN;
638 } else {
639 drbg->entropyRange.min = ctx->seedLen;
640 drbg->entropyRange.max = ctx->seedLen;
641 drbg->maxPersLen = ctx->seedLen;
642 drbg->maxAdinLen = ctx->seedLen;
643
644 drbg->nonceRange.min = 0;
645 drbg->nonceRange.max = 0;
646 }
647
648 return drbg;
649 }
650 #endif
651