• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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