• 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_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