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_ENTROPY
18
19 #include <stdint.h>
20 #include "securec.h"
21 #include "bsl_err_internal.h"
22 #include "bsl_sal.h"
23 #include "crypt_algid.h"
24 #include "crypt_errno.h"
25 #include "crypt_utils.h"
26 #include "crypt_entropy.h"
27
28 #define ECF_MAX_OUTPUT_LEN 64
29 #define ECF_ADDITION_ENTROPY 64 // reference nist-800 90c-3pd section 3.3.2
30 #define ECF_BYTE_TO_BIT 8
31
EntropyEcf(ENTROPY_ECFCtx * enCtx,uint8_t * data,uint32_t dataLen,uint8_t * out,uint32_t * outLen)32 static int32_t EntropyEcf(ENTROPY_ECFCtx *enCtx, uint8_t *data, uint32_t dataLen, uint8_t *out, uint32_t *outLen)
33 {
34 uint8_t conData[ECF_MAX_OUTPUT_LEN] = {0};
35 uint32_t conLen = ECF_MAX_OUTPUT_LEN;
36 int32_t ret = enCtx->conFunc(enCtx->algId, data, dataLen, conData, &conLen);
37 if (ret != CRYPT_SUCCESS) {
38 BSL_ERR_PUSH_ERROR(ret);
39 return ret;
40 }
41 uint32_t cpLen = (conLen > *outLen) ? *outLen : conLen;
42 (void)memcpy_s(out, cpLen, conData, cpLen);
43 (void)memset_s(conData, conLen, 0, conLen);
44 *outLen = cpLen;
45 return CRYPT_SUCCESS;
46 }
47
ENTROPY_GetFullEntropyInput(void * ctx,ENTROPY_SeedPool * pool,bool isNpesUsed,uint32_t needEntropy,uint8_t * data,uint32_t len)48 int32_t ENTROPY_GetFullEntropyInput(void *ctx, ENTROPY_SeedPool *pool, bool isNpesUsed, uint32_t needEntropy,
49 uint8_t *data, uint32_t len)
50 {
51 int32_t ret = CRYPT_SUCCESS;
52 uint8_t *ptr = data;
53 if (ENTROPY_SeedPoolGetMinEntropy(pool) == 0) {
54 return CRYPT_INVALID_ARG;
55 }
56 ENTROPY_ECFCtx *enCtx = (ENTROPY_ECFCtx *)ctx;
57 if (enCtx == NULL || enCtx->conFunc == NULL) {
58 BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ECF_IS_ERROR);
59 return CRYPT_ENTROPY_ECF_IS_ERROR;
60 }
61 uint32_t conEnt = enCtx->outLen * ECF_BYTE_TO_BIT;
62 uint32_t tmpEntropy = conEnt + ECF_ADDITION_ENTROPY;
63 uint32_t tmpDataLen = (tmpEntropy + ECF_BYTE_TO_BIT - 1) / ENTROPY_SeedPoolGetMinEntropy(pool);
64 uint8_t *tmpData = BSL_SAL_Malloc(tmpDataLen);
65 if (tmpData == NULL) {
66 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
67 return CRYPT_MEM_ALLOC_FAIL;
68 }
69 uint32_t remEnt = needEntropy;
70 uint32_t remLen = len;
71 while (remEnt > 0) {
72 uint32_t tmpLen = tmpDataLen;
73 uint32_t oneEnt = (remEnt < conEnt) ? remEnt : conEnt;
74 uint32_t entropy = ENTROPY_SeedPoolCollect(pool, isNpesUsed, oneEnt, tmpData, &tmpLen);
75 if (entropy < oneEnt) {
76 GOTO_ERR_IF(CRYPT_SEED_POOL_NOT_MEET_REQUIREMENT, ret);
77 }
78 uint32_t cpLen;
79 /* If the data of the length specified by tmpLen can be provided, the value is the full entropy (tmpLen * 8). */
80 if (tmpLen * ECF_BYTE_TO_BIT == entropy) {
81 cpLen = tmpLen < remLen ? tmpLen : remLen;
82 (void)memcpy_s(ptr, remLen, tmpData, cpLen);
83 remEnt -= ((entropy > remEnt) ? remEnt : entropy);
84 } else {
85 uint32_t leftLen = tmpDataLen - tmpLen;
86 uint32_t leftEnt = ENTROPY_SeedPoolCollect(pool, isNpesUsed, tmpEntropy - entropy, tmpData + tmpLen,
87 &leftLen);
88 if (leftEnt < tmpEntropy - entropy) {
89 GOTO_ERR_IF(CRYPT_SEED_POOL_NOT_MEET_REQUIREMENT, ret);
90 }
91 cpLen = remLen;
92 GOTO_ERR_IF(EntropyEcf(ctx, tmpData, tmpLen + leftLen, ptr, &cpLen), ret);
93 remEnt -= (remEnt < conEnt ? remEnt : conEnt);
94 }
95 ptr += cpLen;
96 remLen -= cpLen;
97 }
98 if (remLen > 0) {
99 uint32_t leftLen = remLen;
100 uint32_t entropy = ENTROPY_SeedPoolCollect(pool, true, 0, ptr, &leftLen);
101 if (entropy == 0 || leftLen < remLen) {
102 GOTO_ERR_IF(CRYPT_SEED_POOL_NOT_MEET_REQUIREMENT, ret);
103 }
104 }
105 ERR:
106 (void)memset_s(tmpData, tmpDataLen, 0, tmpDataLen);
107 BSL_SAL_FREE(tmpData);
108 return ret;
109 }
110
111 #endif /* HITLS_CRYPTO_ENTROPY */
112