• 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
18 
19 #include <stdlib.h>
20 #include <stdbool.h>
21 #include <securec.h>
22 #include "crypt_types.h"
23 #include "crypt_errno.h"
24 #include "crypt_utils.h"
25 #include "crypt_ealinit.h"
26 #include "eal_entropy.h"
27 #include "bsl_err_internal.h"
28 #include "drbg_local.h"
29 #include "crypt_drbg_local.h"
30 #include "bsl_params.h"
31 #include "crypt_params_key.h"
32 
33 #define DRBG_NONCE_FROM_ENTROPY (2)
34 
35 // According to the definition of DRBG_Ctx, ctx->seedMeth is not NULL
DRBG_CleanEntropy(DRBG_Ctx * ctx,CRYPT_Data * entropy)36 static void DRBG_CleanEntropy(DRBG_Ctx *ctx, CRYPT_Data *entropy)
37 {
38     CRYPT_RandSeedMethod *seedMeth = NULL;
39 
40     if (ctx == NULL || CRYPT_IsDataNull(entropy)) {
41         return;
42     }
43 
44     seedMeth = &ctx->seedMeth;
45 
46     if (seedMeth->cleanEntropy != NULL) {
47         seedMeth->cleanEntropy(ctx->seedCtx, entropy);
48     }
49 
50     entropy->data = NULL;
51     entropy->len = 0;
52 
53     return;
54 }
55 
56 // According to the definition of DRBG_Ctx, ctx->seedMeth is not NULL
DRBG_GetEntropy(DRBG_Ctx * ctx,CRYPT_Data * entropy,bool addEntropy)57 static int32_t DRBG_GetEntropy(DRBG_Ctx *ctx, CRYPT_Data *entropy, bool addEntropy)
58 {
59     int32_t ret;
60     CRYPT_RandSeedMethod *seedMeth = NULL;
61     CRYPT_Range entropyRange = ctx->entropyRange;
62     uint32_t strength = ctx->strength;
63 
64     seedMeth = &ctx->seedMeth;
65 
66     if (addEntropy) {
67         strength += strength / DRBG_NONCE_FROM_ENTROPY;
68         entropyRange.min += ctx->nonceRange.min;
69         entropyRange.max += ctx->nonceRange.max;
70     }
71 
72     if (seedMeth->getEntropy == NULL) {
73         BSL_ERR_PUSH_ERROR(CRYPT_DRBG_FAIL_GET_ENTROPY);
74         return CRYPT_DRBG_FAIL_GET_ENTROPY;
75     }
76 
77     // CPRNG is implemented by hooks, in DRBG, the CPRNG is not verified,
78     // but only the entropy source pointer and its length are verified.
79     ret = seedMeth->getEntropy(ctx->seedCtx, entropy, strength, &entropyRange);
80     if (ret != CRYPT_SUCCESS) {
81         BSL_ERR_PUSH_ERROR(CRYPT_DRBG_FAIL_GET_ENTROPY);
82         return CRYPT_DRBG_FAIL_GET_ENTROPY;
83     }
84 
85     if (CRYPT_CHECK_DATA_INVALID(entropy)) {
86         goto ERR;
87     }
88 
89     if (!CRYPT_IN_RANGE(entropy->len, &entropyRange)) {
90         goto ERR;
91     }
92     return CRYPT_SUCCESS;
93 
94 ERR:
95     DRBG_CleanEntropy(ctx, entropy);
96     BSL_ERR_PUSH_ERROR(CRYPT_DRBG_FAIL_GET_ENTROPY);
97     return CRYPT_DRBG_FAIL_GET_ENTROPY;
98 }
99 
100 // According to the definition of DRBG_Ctx, ctx->seedMeth is not NULL
DRBG_CleanNonce(DRBG_Ctx * ctx,CRYPT_Data * nonce)101 static void DRBG_CleanNonce(DRBG_Ctx *ctx, CRYPT_Data *nonce)
102 {
103     CRYPT_RandSeedMethod *seedMeth = NULL;
104 
105     if (ctx == NULL || CRYPT_IsDataNull(nonce)) {
106         return;
107     }
108 
109     seedMeth = &ctx->seedMeth;
110 
111     if (seedMeth->cleanNonce != NULL) {
112         seedMeth->cleanNonce(ctx->seedCtx, nonce);
113     }
114     nonce->data = NULL;
115     nonce->len = 0;
116     return;
117 }
118 
119 // According to the definition of DRBG_Ctx, ctx->seedMeth is not NULL
DRBG_GetNonce(DRBG_Ctx * ctx,CRYPT_Data * nonce,bool * addEntropy)120 static int32_t DRBG_GetNonce(DRBG_Ctx *ctx, CRYPT_Data *nonce, bool *addEntropy)
121 {
122     int32_t ret;
123     CRYPT_RandSeedMethod *seedMeth = NULL;
124 
125     seedMeth = &ctx->seedMeth;
126 
127     // Allowed nonce which entered by the user can be NULL.
128     // In this case, set *addEntropy to true to obtain the nonce from the entropy.
129     if (seedMeth->getNonce == NULL || ctx->nonceRange.max == 0) {
130         if (ctx->nonceRange.min > 0) {
131             *addEntropy = true;
132         }
133         return CRYPT_SUCCESS;
134     }
135 
136     ret = seedMeth->getNonce(ctx->seedCtx, nonce, ctx->strength, &ctx->nonceRange);
137     if (ret != CRYPT_SUCCESS) {
138         BSL_ERR_PUSH_ERROR(CRYPT_DRBG_FAIL_GET_NONCE);
139         return CRYPT_DRBG_FAIL_GET_NONCE;
140     }
141 
142     if (CRYPT_CHECK_DATA_INVALID(nonce)) {
143         goto ERR;
144     }
145 
146     if (!CRYPT_IN_RANGE(nonce->len, &ctx->nonceRange)) {
147         goto ERR;
148     }
149 
150     return CRYPT_SUCCESS;
151 
152 ERR:
153     DRBG_CleanNonce(ctx, nonce);
154     BSL_ERR_PUSH_ERROR(CRYPT_DRBG_FAIL_GET_NONCE);
155     return CRYPT_DRBG_FAIL_GET_NONCE;
156 }
157 
158 #ifdef HITLS_CRYPTO_DRBG_CTR
159 #define RAND_AES128_KEYLEN  16
160 #define RAND_AES192_KEYLEN  24
161 #define RAND_AES256_KEYLEN  32
162 #define RAND_SM4_KEYLEN     16
163 
GetCipherKeyLen(int32_t id,uint32_t * keyLen)164 static int32_t GetCipherKeyLen(int32_t id, uint32_t *keyLen)
165 {
166     switch (id) {
167         case CRYPT_CIPHER_AES128_CTR:
168             *keyLen = RAND_AES128_KEYLEN;
169             break;
170         case CRYPT_CIPHER_AES192_CTR:
171             *keyLen = RAND_AES192_KEYLEN;
172             break;
173         case CRYPT_CIPHER_AES256_CTR:
174             *keyLen = RAND_AES256_KEYLEN;
175             break;
176         case CRYPT_CIPHER_SM4_CTR:
177             *keyLen = RAND_SM4_KEYLEN;
178             break;
179         default:
180             BSL_ERR_PUSH_ERROR(CRYPT_DRBG_ALG_NOT_SUPPORT);
181             return CRYPT_DRBG_ALG_NOT_SUPPORT;
182     }
183     return CRYPT_SUCCESS;
184 }
185 #endif
186 
DRBG_Restart(DRBG_Ctx * ctx)187 static int32_t DRBG_Restart(DRBG_Ctx *ctx)
188 {
189     if (ctx->state == DRBG_STATE_ERROR) {
190         (void)DRBG_Uninstantiate(ctx);
191     }
192     if (ctx->state == DRBG_STATE_UNINITIALISED) {
193         int32_t ret = DRBG_Instantiate(ctx, NULL, 0, NULL);
194         if (ret != CRYPT_SUCCESS) {
195             BSL_ERR_PUSH_ERROR(ret);
196             return ret;
197         }
198     }
199     return CRYPT_SUCCESS;
200 }
201 
DRBG_New(int32_t algId,BSL_Param * param)202 DRBG_Ctx *DRBG_New(int32_t algId, BSL_Param *param)
203 {
204     int32_t ret;
205 
206     CRYPT_RandSeedMethod seedMethArray = {0};
207     CRYPT_RandSeedMethod *seedMeth = &seedMethArray;
208     void *seedCtx = NULL;
209 
210     const BSL_Param *temp = NULL;
211     if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_RAND_SEED_GETENTROPY)) != NULL) {
212         GOTO_ERR_IF(BSL_PARAM_GetPtrValue(temp, CRYPT_PARAM_RAND_SEED_GETENTROPY, BSL_PARAM_TYPE_FUNC_PTR,
213             (void **)&(seedMethArray.getEntropy), NULL), ret);
214     }
215     if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_RAND_SEED_CLEANENTROPY)) != NULL) {
216         GOTO_ERR_IF(BSL_PARAM_GetPtrValue(temp, CRYPT_PARAM_RAND_SEED_CLEANENTROPY, BSL_PARAM_TYPE_FUNC_PTR,
217             (void **)&(seedMethArray.cleanEntropy), NULL), ret);
218     }
219     if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_RAND_SEED_GETNONCE)) != NULL) {
220         GOTO_ERR_IF(BSL_PARAM_GetPtrValue(temp, CRYPT_PARAM_RAND_SEED_GETNONCE, BSL_PARAM_TYPE_FUNC_PTR,
221             (void **)&(seedMethArray.getNonce), NULL), ret);
222     }
223     if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_RAND_SEED_CLEANNONCE)) != NULL) {
224         GOTO_ERR_IF(BSL_PARAM_GetPtrValue(temp, CRYPT_PARAM_RAND_SEED_CLEANNONCE, BSL_PARAM_TYPE_FUNC_PTR,
225             (void **)&(seedMethArray.cleanNonce), NULL), ret);
226     }
227 
228     if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_RAND_SEEDCTX)) != NULL) {
229         GOTO_ERR_IF(BSL_PARAM_GetPtrValue(temp, CRYPT_PARAM_RAND_SEEDCTX, BSL_PARAM_TYPE_CTX_PTR, &seedCtx, NULL), ret);
230     }
231 
232     DRBG_Ctx *drbg = NULL;
233     EAL_RandMethLookup lu = { 0 };
234     if (EAL_RandFindMethod(algId, &lu) != CRYPT_SUCCESS) {
235         return NULL;
236     }
237     switch (lu.type) {
238 #ifdef HITLS_CRYPTO_DRBG_HASH
239         case RAND_TYPE_MD:
240             drbg = DRBG_NewHashCtx((const EAL_MdMethod *)(lu.method), algId == CRYPT_RAND_SM3, seedMeth, seedCtx);
241             break;
242 #endif
243 #ifdef HITLS_CRYPTO_DRBG_HMAC
244         case RAND_TYPE_MAC:
245             drbg = DRBG_NewHmacCtx((const EAL_MacMethod *)(lu.method), lu.methodId, seedMeth, seedCtx);
246             break;
247 #endif
248 #ifdef HITLS_CRYPTO_DRBG_CTR
249         case RAND_TYPE_SM4_DF:
250         case RAND_TYPE_AES:
251         case RAND_TYPE_AES_DF: {
252             bool isUsedDF = (lu.type == RAND_TYPE_AES_DF || lu.type == RAND_TYPE_SM4_DF) ? true : false;
253             uint32_t keyLen;
254             if (GetCipherKeyLen(lu.methodId, &keyLen) != CRYPT_SUCCESS) {
255                 return NULL;
256             }
257             drbg = DRBG_NewCtrCtx((const EAL_SymMethod *)(lu.method), keyLen, algId == CRYPT_RAND_SM4_CTR_DF, isUsedDF,
258                 seedMeth, seedCtx);
259             break;
260         }
261 #endif
262         default:
263             BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_ALGID);
264             return NULL;
265     }
266     return drbg;
267 
268 ERR:
269     return NULL;
270 }
271 
DRBG_Free(DRBG_Ctx * ctx)272 void DRBG_Free(DRBG_Ctx *ctx)
273 {
274     if (ctx == NULL || ctx->meth == NULL || ctx->meth->free == NULL) {
275         return;
276     }
277 
278     void (*ctxFree)(DRBG_Ctx *ctx) = ctx->meth->free;
279 
280     DRBG_Uninstantiate(ctx);
281     ctxFree(ctx);
282 
283     return;
284 }
285 
DRBG_Instantiate(DRBG_Ctx * ctx,const uint8_t * person,uint32_t persLen,BSL_Param * param)286 int32_t DRBG_Instantiate(DRBG_Ctx *ctx, const uint8_t *person, uint32_t persLen, BSL_Param *param)
287 {
288     (void) param;
289     int32_t ret;
290     CRYPT_Data entropy = {NULL, 0};
291     CRYPT_Data nonce = {NULL, 0};
292     CRYPT_Data pers = {(uint8_t *)(uintptr_t)person, persLen};
293     bool addEntropy = false;
294 
295     if (ctx == NULL) {
296         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
297         return CRYPT_NULL_INPUT;
298     }
299 
300     if (CRYPT_CHECK_DATA_INVALID(&pers)) {
301         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
302         return CRYPT_NULL_INPUT;
303     }
304 
305     if (persLen > ctx->maxPersLen) {
306         BSL_ERR_PUSH_ERROR(CRYPT_DRBG_INVALID_LEN);
307         return CRYPT_DRBG_INVALID_LEN;
308     }
309 
310     if (ctx->state != DRBG_STATE_UNINITIALISED) {
311         BSL_ERR_PUSH_ERROR(CRYPT_DRBG_ERR_STATE);
312         return CRYPT_DRBG_ERR_STATE;
313     }
314 
315     ctx->state = DRBG_STATE_ERROR;
316 
317     ret = DRBG_GetNonce(ctx, &nonce, &addEntropy);
318     if (ret != CRYPT_SUCCESS) {
319         goto ERR_NONCE;
320     }
321 
322     ret = DRBG_GetEntropy(ctx, &entropy, addEntropy);
323     if (ret != CRYPT_SUCCESS) {
324         goto ERR_ENTROPY;
325     }
326 
327     ret = ctx->meth->instantiate(ctx, &entropy, &nonce, &pers);
328     if (ret != CRYPT_SUCCESS) {
329         BSL_ERR_PUSH_ERROR(ret);
330         goto ERR_ENTROPY;
331     }
332 
333     ctx->state = DRBG_STATE_READY;
334     ctx->reseedCtr = 1;
335 #if defined(HITLS_CRYPTO_DRBG_GM)
336     if (ctx->reseedIntervalTime != 0) {
337         ctx->lastReseedTime = BSL_SAL_CurrentSysTimeGet();
338     }
339 #endif
340 ERR_ENTROPY:
341     DRBG_CleanEntropy(ctx, &entropy);
342 ERR_NONCE:
343     DRBG_CleanNonce(ctx, &nonce);
344 
345     return ret;
346 }
347 
DRBG_IsNeedReseed(const DRBG_Ctx * ctx,bool pr)348 static inline bool DRBG_IsNeedReseed(const DRBG_Ctx *ctx, bool pr)
349 {
350     if (pr) {
351         return true;
352     }
353 
354     if (ctx->reseedCtr > ctx->reseedInterval) {
355         return true;
356     }
357 #if defined(HITLS_CRYPTO_DRBG_GM)
358     if (ctx->reseedIntervalTime != 0) {
359         int64_t time = BSL_SAL_CurrentSysTimeGet();
360         return ((time - ctx->lastReseedTime) > ctx->reseedIntervalTime) ? true : false;
361     }
362 #endif
363     return false;
364 }
365 
DRBG_Reseed(DRBG_Ctx * ctx,const uint8_t * adin,uint32_t adinLen,BSL_Param * param)366 int32_t DRBG_Reseed(DRBG_Ctx *ctx, const uint8_t *adin, uint32_t adinLen, BSL_Param *param)
367 {
368     (void) param;
369     int32_t ret;
370     CRYPT_Data entropy = {NULL, 0};
371     CRYPT_Data adinData = {(uint8_t*)(uintptr_t)adin, adinLen};
372 
373     if (ctx == NULL) {
374         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
375         return CRYPT_NULL_INPUT;
376     }
377 
378     if (CRYPT_CHECK_BUF_INVALID(adin, adinLen)) {
379         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
380         return CRYPT_NULL_INPUT;
381     }
382 
383     if (adinLen > ctx->maxAdinLen) {
384         BSL_ERR_PUSH_ERROR(CRYPT_DRBG_INVALID_LEN);
385         return CRYPT_DRBG_INVALID_LEN;
386     }
387 
388     if (ctx->state != DRBG_STATE_READY) {
389         if (DRBG_Restart(ctx) != CRYPT_SUCCESS) {
390             return CRYPT_DRBG_ERR_STATE;
391         }
392     }
393 
394     ctx->state = DRBG_STATE_ERROR;
395 
396     ret = DRBG_GetEntropy(ctx, &entropy, false);
397     if (ret != CRYPT_SUCCESS) {
398         BSL_ERR_PUSH_ERROR(ret);
399         goto ERR;
400     }
401 
402     ret = ctx->meth->reseed(ctx, &entropy, &adinData);
403     if (ret != CRYPT_SUCCESS) {
404         BSL_ERR_PUSH_ERROR(ret);
405         goto ERR;
406     }
407 
408     ctx->reseedCtr = 1;
409 #if defined(HITLS_CRYPTO_DRBG_GM)
410     if (ctx->reseedIntervalTime != 0) {
411         ctx->lastReseedTime = BSL_SAL_CurrentSysTimeGet();
412     }
413 #endif
414     ctx->state = DRBG_STATE_READY;
415 
416 ERR:
417     DRBG_CleanEntropy(ctx, &entropy);
418 
419     return ret;
420 }
421 
DRBG_Generate(DRBG_Ctx * ctx,uint8_t * out,uint32_t outLen,const uint8_t * adin,uint32_t adinLen,bool pr)422 int32_t DRBG_Generate(DRBG_Ctx *ctx, uint8_t *out, uint32_t outLen,
423     const uint8_t *adin, uint32_t adinLen,  bool pr)
424 {
425     int32_t ret;
426     CRYPT_Data adinData = {(uint8_t*)(uintptr_t)adin, adinLen};
427     if (CRYPT_CHECK_BUF_INVALID(adin, adinLen)) {
428         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
429         return CRYPT_NULL_INPUT;
430     }
431 
432     if (outLen > ctx->maxRequest || adinLen > ctx->maxAdinLen) {
433         BSL_ERR_PUSH_ERROR(CRYPT_DRBG_INVALID_LEN);
434         return CRYPT_DRBG_INVALID_LEN;
435     }
436 
437     if (ctx->state != DRBG_STATE_READY) {
438         if (DRBG_Restart(ctx) != CRYPT_SUCCESS) {
439             return CRYPT_DRBG_ERR_STATE;
440         }
441     }
442 
443     if (DRBG_IsNeedReseed(ctx, pr)) {
444         ret = DRBG_Reseed(ctx, adin, adinLen, NULL);
445         if (ret != CRYPT_SUCCESS) {
446             BSL_ERR_PUSH_ERROR(ret);
447             return ret;
448         }
449         adinData.data = NULL;
450         adinData.len = 0;
451     }
452 
453     ret = ctx->meth->generate(ctx, out, outLen, &adinData);
454     if (ret != CRYPT_SUCCESS) {
455         BSL_ERR_PUSH_ERROR(ret);
456         return ret;
457     }
458 
459     ctx->reseedCtr++;
460 
461     return ret;
462 }
463 
DRBG_GenerateBytes(DRBG_Ctx * ctx,uint8_t * out,uint32_t outLen,const uint8_t * adin,uint32_t adinLen,BSL_Param * param)464 int32_t DRBG_GenerateBytes(DRBG_Ctx *ctx, uint8_t *out, uint32_t outLen,
465     const uint8_t *adin, uint32_t adinLen,  BSL_Param *param)
466 {
467     if (ctx == NULL || out == NULL) {
468         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
469         return CRYPT_NULL_INPUT;
470     }
471     int32_t ret;
472     bool pr = false;
473     const BSL_Param *temp = NULL;
474     if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_RAND_PR)) != NULL) {
475         uint32_t boolSize = sizeof(bool);
476         ret = BSL_PARAM_GetValue(temp, CRYPT_PARAM_RAND_PR, BSL_PARAM_TYPE_BOOL, (void *)&pr, &boolSize);
477         if (ret != CRYPT_SUCCESS) {
478             BSL_ERR_PUSH_ERROR(ret);
479             return ret;
480         }
481     }
482     uint32_t block = ctx->maxRequest;
483     if (block == 0) {
484         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
485         return CRYPT_INVALID_ARG;
486     }
487     for (uint32_t leftLen = outLen; leftLen > 0; leftLen -= block, out += block) {
488         block = leftLen > block ? block : leftLen;
489         ret = DRBG_Generate(ctx, out, block, adin, adinLen, pr);
490         if (ret != CRYPT_SUCCESS) {
491             BSL_ERR_PUSH_ERROR(ret);
492             return ret;
493         }
494     }
495     return CRYPT_SUCCESS;
496 }
497 
DRBG_Uninstantiate(DRBG_Ctx * ctx)498 int32_t DRBG_Uninstantiate(DRBG_Ctx *ctx)
499 {
500     if (ctx == NULL) {
501         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
502         return CRYPT_NULL_INPUT;
503     }
504 
505     ctx->meth->uninstantiate(ctx);
506 
507     ctx->reseedCtr = 0;
508     ctx->state = DRBG_STATE_UNINITIALISED;
509 
510     return CRYPT_SUCCESS;
511 }
512 
513 #if defined(HITLS_CRYPTO_DRBG_GM)
DRBG_SetGmlevel(DRBG_Ctx * ctx,const void * val,uint32_t len)514 static int32_t DRBG_SetGmlevel(DRBG_Ctx *ctx, const void *val, uint32_t len)
515 {
516     if (val == NULL || len != sizeof(uint32_t)) {
517         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
518         return CRYPT_INVALID_ARG;
519     }
520     if (*(const uint32_t *)val == 1) {
521         ctx->reseedInterval = DRBG_RESEED_INTERVAL_GM1;
522         ctx->reseedIntervalTime = DRBG_RESEED_TIME_GM1;
523     } else {
524         ctx->reseedInterval = DRBG_RESEED_INTERVAL_GM2;
525         ctx->reseedIntervalTime = DRBG_RESEED_TIME_GM2;
526     }
527     return CRYPT_SUCCESS;
528 }
529 
DRBG_SetReseedIntervalTime(DRBG_Ctx * ctx,const void * val,uint32_t len)530 static int32_t DRBG_SetReseedIntervalTime(DRBG_Ctx *ctx, const void *val, uint32_t len)
531 {
532     if (val == NULL || len != sizeof(uint64_t)) {
533         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
534         return CRYPT_INVALID_ARG;
535     }
536     ctx->reseedIntervalTime = *(const uint64_t *)val;
537     return CRYPT_SUCCESS;
538 }
539 #endif // HITLS_CRYPTO_DRBG_GM
540 
DRBG_SetReseedInterval(DRBG_Ctx * ctx,const void * val,uint32_t len)541 static int32_t DRBG_SetReseedInterval(DRBG_Ctx *ctx, const void *val, uint32_t len)
542 {
543     if (val == NULL || len != sizeof(uint32_t)) {
544         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
545         return CRYPT_INVALID_ARG;
546     }
547     ctx->reseedInterval = *(const uint32_t *)val;
548     return CRYPT_SUCCESS;
549 }
550 
DRBG_Ctrl(DRBG_Ctx * ctx,int32_t opt,void * val,uint32_t len)551 int32_t DRBG_Ctrl(DRBG_Ctx *ctx, int32_t opt, void *val, uint32_t len)
552 {
553     if (ctx == NULL) {
554         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
555         return CRYPT_NULL_INPUT;
556     }
557     switch (opt) {
558 #if defined(HITLS_CRYPTO_DRBG_GM)
559         case CRYPT_CTRL_SET_GM_LEVEL:
560             return DRBG_SetGmlevel(ctx, val, len);
561         case CRYPT_CTRL_SET_RESEED_TIME:
562             return DRBG_SetReseedIntervalTime(ctx, val, len);
563 #endif // HITLS_CRYPTO_DRBG_GM
564         case CRYPT_CTRL_SET_RESEED_INTERVAL:
565             return DRBG_SetReseedInterval(ctx, val, len);
566         default:
567             break;
568     }
569     BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
570     return CRYPT_INVALID_ARG;
571 }
572 
573 static const DrbgIdMap DRBG_METHOD_MAP[] = {
574 #if defined(HITLS_CRYPTO_DRBG_HASH)
575     { CRYPT_RAND_SHA1, CRYPT_MD_SHA1, RAND_TYPE_MD },
576     { CRYPT_RAND_SHA224, CRYPT_MD_SHA224, RAND_TYPE_MD },
577     { CRYPT_RAND_SHA256, CRYPT_MD_SHA256, RAND_TYPE_MD },
578     { CRYPT_RAND_SHA384, CRYPT_MD_SHA384, RAND_TYPE_MD },
579     { CRYPT_RAND_SHA512, CRYPT_MD_SHA512, RAND_TYPE_MD },
580 #ifdef HITLS_CRYPTO_DRBG_GM
581     { CRYPT_RAND_SM3, CRYPT_MD_SM3, RAND_TYPE_MD },
582 #endif
583 #endif
584 #if defined(HITLS_CRYPTO_DRBG_HMAC)
585     { CRYPT_RAND_HMAC_SHA1, CRYPT_MAC_HMAC_SHA1, RAND_TYPE_MAC },
586     { CRYPT_RAND_HMAC_SHA224, CRYPT_MAC_HMAC_SHA224, RAND_TYPE_MAC },
587     { CRYPT_RAND_HMAC_SHA256, CRYPT_MAC_HMAC_SHA256, RAND_TYPE_MAC },
588     { CRYPT_RAND_HMAC_SHA384, CRYPT_MAC_HMAC_SHA384, RAND_TYPE_MAC },
589     { CRYPT_RAND_HMAC_SHA512, CRYPT_MAC_HMAC_SHA512, RAND_TYPE_MAC },
590 #endif
591 #if defined(HITLS_CRYPTO_DRBG_CTR)
592     { CRYPT_RAND_AES128_CTR, CRYPT_CIPHER_AES128_CTR, RAND_TYPE_AES },
593     { CRYPT_RAND_AES192_CTR, CRYPT_CIPHER_AES192_CTR, RAND_TYPE_AES },
594     { CRYPT_RAND_AES256_CTR, CRYPT_CIPHER_AES256_CTR, RAND_TYPE_AES },
595     { CRYPT_RAND_AES128_CTR_DF, CRYPT_CIPHER_AES128_CTR, RAND_TYPE_AES_DF },
596     { CRYPT_RAND_AES192_CTR_DF, CRYPT_CIPHER_AES192_CTR, RAND_TYPE_AES_DF },
597     { CRYPT_RAND_AES256_CTR_DF, CRYPT_CIPHER_AES256_CTR, RAND_TYPE_AES_DF },
598 #ifdef HITLS_CRYPTO_DRBG_GM
599     { CRYPT_RAND_SM4_CTR_DF, CRYPT_CIPHER_SM4_CTR, RAND_TYPE_SM4_DF }
600 #endif
601 #endif
602 };
603 
DRBG_GetIdMap(CRYPT_RAND_AlgId id)604 const DrbgIdMap *DRBG_GetIdMap(CRYPT_RAND_AlgId id)
605 {
606     uint32_t num = sizeof(DRBG_METHOD_MAP) / sizeof(DRBG_METHOD_MAP[0]);
607     for (uint32_t i = 0; i < num; i++) {
608         if (DRBG_METHOD_MAP[i].drbgId == id) {
609             return &DRBG_METHOD_MAP[i];
610         }
611     }
612     return NULL;
613 }
614 
615 #endif /* HITLS_CRYPTO_DRBG */
616