• 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 #if defined(HITLS_CRYPTO_EAL) && defined(HITLS_CRYPTO_ENTROPY)
18 #include "securec.h"
19 #include "bsl_err_internal.h"
20 #include "crypt_errno.h"
21 #include "eal_entropy.h"
22 
23 #define EAL_MAX_ENTROPY_EVERY_BYTE 8
24 #define EAL_ECF_OUT_LEN 16
25 
GetMinLen(void * pool,uint32_t entropy,uint32_t minLen)26 static uint32_t GetMinLen(void *pool, uint32_t entropy, uint32_t minLen)
27 {
28     uint32_t minEntropy = ENTROPY_SeedPoolGetMinEntropy(pool);
29     if (minEntropy == 0) {
30         return 0;
31     }
32     uint32_t len = (uint32_t)(((uint64_t)entropy + (uint64_t)minEntropy - 1) / (uint64_t)minEntropy);
33     /* '<' indicates that the data with a length of len can provide sufficient bit entropy. */
34     if (len < minLen) {
35         len = minLen;
36     }
37     return len;
38 }
39 
EAL_EntropyNewCtx(CRYPT_EAL_SeedPoolCtx * seedPool,uint8_t isNpesUsed,uint32_t minLen,uint32_t maxLen,uint32_t entropy)40 EAL_EntropyCtx *EAL_EntropyNewCtx(CRYPT_EAL_SeedPoolCtx *seedPool, uint8_t isNpesUsed, uint32_t minLen,
41     uint32_t maxLen, uint32_t entropy)
42 {
43     if (minLen > maxLen || maxLen == 0) {
44         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
45         return NULL;
46     }
47     if (!ENTROPY_SeedPoolCheckState(seedPool->pool, isNpesUsed)) {
48         BSL_ERR_PUSH_ERROR(CRYPT_SEED_POOL_STATE_ERROR);
49         return NULL;
50     }
51     if (entropy > maxLen * EAL_MAX_ENTROPY_EVERY_BYTE) {
52         BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_RANGE_ERROR);
53         return NULL;
54     }
55     EAL_EntropyCtx *ctx = BSL_SAL_Malloc(sizeof(EAL_EntropyCtx));
56     if (ctx == NULL) {
57         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
58         return NULL;
59     }
60     (void)memset_s(ctx, sizeof(EAL_EntropyCtx), 0, sizeof(EAL_EntropyCtx));
61     ctx->minLen = minLen;
62     ctx->maxLen = maxLen;
63     ctx->isNpesUsed = isNpesUsed;
64     ctx->requestEntropy = entropy;
65     ctx->isNeedFe = (minLen == maxLen) ? true : false;
66     uint32_t needLen;
67     if (ctx->isNeedFe) {
68         ctx->ecfuncId = CRYPT_MAC_CMAC_AES128;
69         ctx->ecfOutLen = EAL_ECF_OUT_LEN;
70         ctx->ecfunc = EAL_EntropyGetECF(CRYPT_MAC_CMAC_AES128);
71         needLen = minLen;
72     } else {
73         needLen = GetMinLen(seedPool->pool, entropy, minLen);
74     }
75     ctx->buf = BSL_SAL_Malloc(needLen);
76     if (ctx->buf == NULL) {
77         BSL_SAL_Free(ctx);
78         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
79         return NULL;
80     }
81     ctx->bufLen = needLen;
82     return ctx;
83 }
84 
EAL_EntropyFreeCtx(EAL_EntropyCtx * ctx)85 void EAL_EntropyFreeCtx(EAL_EntropyCtx *ctx)
86 {
87     if (ctx->buf != NULL) {
88         (void)memset_s(ctx->buf, ctx->bufLen, 0, ctx->bufLen);
89         BSL_SAL_FREE(ctx->buf);
90     }
91     BSL_SAL_Free(ctx);
92 }
93 
EAL_EntropyObtain(void * seedPool,EAL_EntropyCtx * ctx)94 static int32_t EAL_EntropyObtain(void *seedPool, EAL_EntropyCtx *ctx)
95 {
96     while (ctx->curEntropy < ctx->requestEntropy) {
97         uint32_t needEntropy = ctx->requestEntropy - ctx->curEntropy;
98         uint8_t *buff = ctx->buf + ctx->curLen;
99         uint32_t len = ctx->bufLen - ctx->curLen;
100         uint32_t entropy = ENTROPY_SeedPoolCollect(seedPool, ctx->isNpesUsed, needEntropy, buff, &len);
101         if (entropy == 0) {
102             BSL_ERR_PUSH_ERROR(CRYPT_SEED_POOL_NO_ENTROPY_OBTAINED);
103             return CRYPT_SEED_POOL_NO_ENTROPY_OBTAINED;
104         }
105 
106         ctx->curEntropy += entropy;
107         ctx->curLen += len;
108     }
109     /*
110      * If the entropy data length is greater than the upper limit, the entropy source quality cannot meet the
111      * requirements and an error is reported.
112      */
113     if (ctx->curLen > ctx->maxLen) {
114         BSL_ERR_PUSH_ERROR(CRYPT_SEED_POOL_NOT_MEET_REQUIREMENT);
115         return CRYPT_SEED_POOL_NOT_MEET_REQUIREMENT;
116     }
117     if (ctx->curLen < ctx->minLen) {
118         /*
119          * If the length of the entropy data is less than the lower limit of the required length,
120          * the entropy data that meets the length requirement is read without considering the entropy.
121          */
122         uint32_t len = ctx->minLen - ctx->curLen;
123         uint32_t ent = ENTROPY_SeedPoolCollect(seedPool, true, 0, ctx->buf + ctx->curLen, &len);
124         if (ent == 0 || len != ctx->minLen - ctx->curLen) {
125             BSL_ERR_PUSH_ERROR(CRYPT_SEED_POOL_NO_SUFFICIENT_ENTROPY);
126             return CRYPT_SEED_POOL_NO_SUFFICIENT_ENTROPY;
127         }
128         ctx->curLen = ctx->minLen;
129     }
130     return CRYPT_SUCCESS;
131 }
132 
EAL_EntropyFesObtain(void * seedPool,EAL_EntropyCtx * ctx)133 static int32_t EAL_EntropyFesObtain(void *seedPool, EAL_EntropyCtx *ctx)
134 {
135     ENTROPY_ECFCtx seedCtx = {ctx->ecfuncId, ctx->ecfOutLen, ctx->ecfunc};
136     int32_t ret = ENTROPY_GetFullEntropyInput(&seedCtx, seedPool, ctx->isNpesUsed, ctx->requestEntropy, ctx->buf,
137         ctx->bufLen);
138     if (ret != CRYPT_SUCCESS) {
139         BSL_ERR_PUSH_ERROR(ret);
140         return ret;
141     }
142     ctx->curEntropy = ctx->requestEntropy;
143     ctx->curLen = ctx->bufLen;
144     return ret;
145 }
146 
EAL_EntropyCollection(CRYPT_EAL_SeedPoolCtx * seedPool,EAL_EntropyCtx * ctx)147 int32_t EAL_EntropyCollection(CRYPT_EAL_SeedPoolCtx *seedPool, EAL_EntropyCtx *ctx)
148 {
149     if (!ENTROPY_SeedPoolCheckState(seedPool->pool, true)) {
150         BSL_ERR_PUSH_ERROR(CRYPT_SEED_POOL_STATE_ERROR);
151         return CRYPT_SEED_POOL_STATE_ERROR;
152     }
153     if (!ctx->isNeedFe || ENTROPY_SeedPoolGetMinEntropy(seedPool->pool) == EAL_MAX_ENTROPY_EVERY_BYTE) {
154         return EAL_EntropyObtain(seedPool->pool, ctx);
155     } else {
156         return EAL_EntropyFesObtain(seedPool->pool, ctx);
157     }
158 }
159 
EAL_EntropyDetachBuf(EAL_EntropyCtx * ctx,uint32_t * len)160 uint8_t *EAL_EntropyDetachBuf(EAL_EntropyCtx *ctx, uint32_t *len)
161 {
162     if (ctx->curEntropy < ctx->requestEntropy) {
163         BSL_ERR_PUSH_ERROR(CRYPT_DRBG_FAIL_GET_ENTROPY);
164         return NULL;
165     }
166     uint8_t *data = ctx->buf;
167     *len = ctx->curLen;
168     ctx->buf = NULL;
169     ctx->bufLen = 0;
170     ctx->curLen = 0;
171     ctx->curEntropy = 0;
172     return data;
173 }
174 
GetEntropy(void * seedCtx,CRYPT_Data * entropy,uint32_t strength,CRYPT_Range * lenRange)175 static int32_t GetEntropy(void *seedCtx, CRYPT_Data *entropy, uint32_t strength, CRYPT_Range *lenRange)
176 {
177     return CRYPT_EAL_SeedPoolGetEntropy(seedCtx, entropy, strength, lenRange);
178 }
179 
CleanEntropy(void * ctx,CRYPT_Data * entropy)180 static void CleanEntropy(void *ctx, CRYPT_Data *entropy)
181 {
182     (void)ctx;
183     BSL_SAL_CleanseData(entropy->data, entropy->len);
184     BSL_SAL_FREE(entropy->data);
185 }
186 
GetNonce(void * ctx,CRYPT_Data * nonce,uint32_t strength,CRYPT_Range * lenRange)187 static int32_t GetNonce(void *ctx, CRYPT_Data *nonce, uint32_t strength, CRYPT_Range *lenRange)
188 {
189     return GetEntropy(ctx, nonce, strength, lenRange);
190 }
191 
CleanNonce(void * ctx,CRYPT_Data * nonce)192 static void CleanNonce(void *ctx, CRYPT_Data *nonce)
193 {
194     CleanEntropy(ctx, nonce);
195 }
196 
EAL_SetDefaultEntropyMeth(CRYPT_RandSeedMethod * meth)197 int32_t EAL_SetDefaultEntropyMeth(CRYPT_RandSeedMethod *meth)
198 {
199     if (meth == NULL) {
200         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
201         return CRYPT_NULL_INPUT;
202     }
203 
204     meth->getEntropy = GetEntropy;
205     meth->cleanEntropy = CleanEntropy;
206     meth->cleanNonce = CleanNonce;
207     meth->getNonce = GetNonce;
208     return CRYPT_SUCCESS;
209 }
210 
211 #endif
212