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
19 #include "securec.h"
20 #include "bsl_err_internal.h"
21 #include "bsl_sal.h"
22 #include "crypt_errno.h"
23 #include "eal_entropy.h"
24 #include "eal_common.h"
25 #ifdef HITLS_CRYPTO_ENTROPY_SYS
26 #include "eal_md_local.h"
27 #endif
28 #include "crypt_eal_entropy.h"
29
30 #define CRYPT_ENTROPY_SOURCE_FULL_ENTROPY 8
31
32 #ifdef HITLS_CRYPTO_ENTROPY_SYS
CRYPT_EAL_EsNew(void)33 CRYPT_EAL_Es *CRYPT_EAL_EsNew(void)
34 {
35 CRYPT_EAL_Es *esCtx = BSL_SAL_Malloc(sizeof(CRYPT_EAL_Es));
36 if (esCtx == NULL) {
37 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
38 return NULL;
39 }
40 (void)memset_s(esCtx, sizeof(CRYPT_EAL_Es), 0, sizeof(CRYPT_EAL_Es));
41 esCtx->es = ENTROPY_EsNew();
42 if (esCtx->es == NULL) {
43 BSL_SAL_Free(esCtx);
44 BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ES_CREATE_ERROR);
45 return NULL;
46 }
47 int32_t ret = BSL_SAL_ThreadLockNew(&esCtx->lock);
48 if (ret != CRYPT_SUCCESS) {
49 ENTROPY_EsFree(esCtx->es);
50 BSL_SAL_FREE(esCtx);
51 BSL_ERR_PUSH_ERROR(ret);
52 return NULL;
53 }
54 return esCtx;
55 }
56
CRYPT_EAL_EsFree(CRYPT_EAL_Es * esCtx)57 void CRYPT_EAL_EsFree(CRYPT_EAL_Es *esCtx)
58 {
59 if (esCtx == NULL) {
60 return;
61 }
62 BSL_SAL_ThreadLockHandle lock = esCtx->lock;
63 esCtx->lock = NULL;
64 if (BSL_SAL_ThreadWriteLock(lock) != BSL_SUCCESS) {
65 ENTROPY_EsFree(esCtx->es);
66 BSL_SAL_ThreadLockFree(lock);
67 BSL_SAL_Free(esCtx);
68 return;
69 }
70 ENTROPY_EsFree(esCtx->es);
71 (void)BSL_SAL_ThreadUnlock(lock);
72 BSL_SAL_ThreadLockFree(lock);
73 BSL_SAL_Free(esCtx);
74 return;
75 }
76
CRYPT_EAL_EsInit(CRYPT_EAL_Es * ctx)77 int32_t CRYPT_EAL_EsInit(CRYPT_EAL_Es *ctx)
78 {
79 if (ctx == NULL) {
80 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
81 return CRYPT_NULL_INPUT;
82 }
83 int32_t ret = BSL_SAL_ThreadWriteLock(ctx->lock);
84 if (ret != BSL_SUCCESS) {
85 BSL_ERR_PUSH_ERROR(ret);
86 return ret;
87 }
88 ret = ENTROPY_EsInit(ctx->es);
89 if (ret != CRYPT_SUCCESS) {
90 BSL_ERR_PUSH_ERROR(ret);
91 }
92 (void)BSL_SAL_ThreadUnlock(ctx->lock);
93 return ret;
94 }
95
CRYPT_EAL_EsEntropyGet(CRYPT_EAL_Es * esCtx,uint8_t * data,uint32_t len)96 uint32_t CRYPT_EAL_EsEntropyGet(CRYPT_EAL_Es *esCtx, uint8_t *data, uint32_t len)
97 {
98 if (esCtx == NULL || data == NULL) {
99 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
100 return 0;
101 }
102 int32_t ret = BSL_SAL_ThreadWriteLock((esCtx->lock));
103 if (ret != BSL_SUCCESS) {
104 BSL_ERR_PUSH_ERROR((ret));
105 return 0;
106 }
107
108 uint32_t resLen = ENTROPY_EsEntropyGet(esCtx->es, data, len);
109 (void)BSL_SAL_ThreadUnlock(esCtx->lock);
110 return resLen;
111 }
112
113
EAL_CfGetAlgId(const char * name)114 static uint32_t EAL_CfGetAlgId(const char *name)
115 {
116 if (strcmp(name, "sm3_df") == 0) {
117 return CRYPT_MD_SM3;
118 }
119 if (strcmp(name, "sha224_df") == 0) {
120 return CRYPT_MD_SHA224;
121 }
122 if (strcmp(name, "sha256_df") == 0) {
123 return CRYPT_MD_SHA256;
124 }
125 if (strcmp(name, "sha384_df") == 0) {
126 return CRYPT_MD_SHA384;
127 }
128 if (strcmp(name, "sha512_df") == 0) {
129 return CRYPT_MD_SHA512;
130 }
131 return CRYPT_MD_MAX;
132 }
133
EAL_CFSetDfMethod(CRYPT_EAL_Es * esCtx,const char * name)134 static int32_t EAL_CFSetDfMethod(CRYPT_EAL_Es *esCtx, const char *name)
135 {
136 CRYPT_MD_AlgId alg = EAL_CfGetAlgId(name);
137 if (alg == CRYPT_MD_MAX) {
138 BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ECF_ALG_ERROR);
139 return CRYPT_ENTROPY_ECF_ALG_ERROR;
140 }
141 const EAL_MdMethod *md = EAL_MdFindMethod(alg);
142 if (md == NULL) {
143 EAL_ERR_REPORT(CRYPT_EVENT_ERR, CRYPT_ALGO_MD, alg, CRYPT_EAL_ERR_ALGID);
144 return CRYPT_ENTROPY_ECF_ALG_ERROR;
145 }
146 ENTROPY_CFPara para = {alg, (void *)(uintptr_t)md};
147 return ENTROPY_EsCtrl(esCtx->es, CRYPT_ENTROPY_SET_CF, (void *)¶, sizeof(ENTROPY_CFPara));
148 }
149
EAL_EsPoolCfSet(CRYPT_EAL_Es * esCtx,void * data,uint32_t len)150 static int32_t EAL_EsPoolCfSet(CRYPT_EAL_Es *esCtx, void *data, uint32_t len)
151 {
152 if (data == NULL || len == 0) {
153 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
154 return CRYPT_NULL_INPUT;
155 }
156 if (strstr(data, "df") != NULL) {
157 return EAL_CFSetDfMethod(esCtx, data);
158 }
159 BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ECF_ALG_ERROR);
160 return CRYPT_ENTROPY_ECF_ALG_ERROR;
161 }
162
EAL_EsCtrl(CRYPT_EAL_Es * esCtx,int32_t cmd,void * data,uint32_t len)163 static int32_t EAL_EsCtrl(CRYPT_EAL_Es *esCtx, int32_t cmd, void *data, uint32_t len)
164 {
165 switch (cmd) {
166 case CRYPT_ENTROPY_SET_CF:
167 return EAL_EsPoolCfSet(esCtx, data, len);
168 case CRYPT_ENTROPY_GATHER_ENTROPY:
169 return ENTROPY_EsEntropyGather(esCtx->es);
170 default:
171 return ENTROPY_EsCtrl(esCtx->es, cmd, data, len);
172 }
173 }
174
175
CRYPT_EAL_EsCtrl(CRYPT_EAL_Es * esCtx,int32_t type,void * data,uint32_t len)176 int32_t CRYPT_EAL_EsCtrl(CRYPT_EAL_Es *esCtx, int32_t type, void *data, uint32_t len)
177 {
178 if (esCtx == NULL) {
179 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
180 return CRYPT_NULL_INPUT;
181 }
182 if (type < CRYPT_ENTROPY_SET_POOL_SIZE || type >= CRYPT_ENTROPY_MAX) {
183 BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ES_CTRL_ERROR);
184 return CRYPT_ENTROPY_ES_CTRL_ERROR;
185 }
186 int32_t ret = BSL_SAL_ThreadWriteLock(esCtx->lock);
187 if (ret != BSL_SUCCESS) {
188 BSL_ERR_PUSH_ERROR(ret);
189 return ret;
190 }
191 ret = EAL_EsCtrl(esCtx, type, data, len);
192 (void)BSL_SAL_ThreadUnlock(esCtx->lock);
193 return ret;
194 }
195
EsDefaultCreate(void)196 static CRYPT_EAL_Es *EsDefaultCreate(void)
197 {
198 CRYPT_EAL_Es *es = CRYPT_EAL_EsNew();
199 if (es == NULL) {
200 return NULL;
201 }
202 char *data = "sha256_df";
203 int32_t ret = CRYPT_EAL_EsCtrl(es, CRYPT_ENTROPY_SET_CF, data, strlen(data));
204 if (ret != CRYPT_SUCCESS) {
205 CRYPT_EAL_EsFree(es);
206 return NULL;
207 }
208 ret = ENTROPY_EsInit(es->es);
209 if (ret != CRYPT_SUCCESS) {
210 CRYPT_EAL_EsFree(es);
211 return NULL;
212 }
213 return es;
214 }
215 #endif
216
CRYPT_EAL_SeedPoolNew(bool isCreateNullPool)217 CRYPT_EAL_SeedPoolCtx *CRYPT_EAL_SeedPoolNew(bool isCreateNullPool)
218 {
219 CRYPT_EAL_SeedPoolCtx *ctx = BSL_SAL_Malloc(sizeof(CRYPT_EAL_SeedPoolCtx));
220 if (ctx == NULL) {
221 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
222 return NULL;
223 }
224 (void)memset_s(ctx, sizeof(CRYPT_EAL_SeedPoolCtx), 0, sizeof(CRYPT_EAL_SeedPoolCtx));
225 int32_t ret = BSL_SAL_ThreadLockNew(&ctx->lock);
226 if (ret != CRYPT_SUCCESS) {
227 BSL_SAL_FREE(ctx);
228 BSL_ERR_PUSH_ERROR(ret);
229 return NULL;
230 }
231 ctx->pool = ENTROPY_SeedPoolNew(isCreateNullPool);
232 if (ctx->pool == NULL) {
233 CRYPT_EAL_SeedPoolFree(ctx);
234 BSL_ERR_PUSH_ERROR(CRYPT_SEED_POOL_NEW_ERROR);
235 return NULL;
236 }
237 #ifdef HITLS_CRYPTO_ENTROPY_SYS
238 if (isCreateNullPool) {
239 ctx->es = NULL;
240 return ctx;
241 }
242 ctx->es = EsDefaultCreate();
243 if (ctx->es == NULL) {
244 CRYPT_EAL_SeedPoolFree(ctx);
245 return NULL;
246 }
247 CRYPT_EAL_EsPara para = {false, CRYPT_ENTROPY_SOURCE_FULL_ENTROPY, ctx->es,
248 (CRYPT_EAL_EntropyGet)CRYPT_EAL_EsEntropyGet};
249 ret = ENTROPY_SeedPoolAddEs(ctx->pool, ¶);
250 if (ret != CRYPT_SUCCESS) {
251 CRYPT_EAL_SeedPoolFree(ctx);
252 BSL_ERR_PUSH_ERROR(ret);
253 return NULL;
254 }
255 #endif
256 return ctx;
257 }
258
CRYPT_EAL_SeedPoolAddEs(CRYPT_EAL_SeedPoolCtx * ctx,const CRYPT_EAL_EsPara * para)259 int32_t CRYPT_EAL_SeedPoolAddEs(CRYPT_EAL_SeedPoolCtx *ctx, const CRYPT_EAL_EsPara *para)
260 {
261 if (ctx == NULL || para == NULL || para->minEntropy == 0 || para->minEntropy > CRYPT_ENTROPY_SOURCE_FULL_ENTROPY ||
262 para->entropyGet == NULL) {
263 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
264 return CRYPT_NULL_INPUT;
265 }
266 int32_t ret = BSL_SAL_ThreadWriteLock(ctx->lock);
267 if (ret != BSL_SUCCESS) {
268 BSL_ERR_PUSH_ERROR(ret);
269 return ret;
270 }
271 ret = ENTROPY_SeedPoolAddEs(ctx->pool, para);
272 (void)BSL_SAL_ThreadUnlock(ctx->lock);
273 return ret;
274 }
275
CRYPT_EAL_SeedPoolFree(CRYPT_EAL_SeedPoolCtx * ctx)276 void CRYPT_EAL_SeedPoolFree(CRYPT_EAL_SeedPoolCtx *ctx)
277 {
278 if (ctx == NULL) {
279 return;
280 }
281 (void)BSL_SAL_ThreadWriteLock(ctx->lock);
282 if (ctx->pool != NULL) {
283 ENTROPY_SeedPoolFree(ctx->pool);
284 ctx->pool = NULL;
285 }
286 #ifdef HITLS_CRYPTO_ENTROPY_SYS
287 if (ctx->es != NULL) {
288 CRYPT_EAL_EsFree(ctx->es);
289 ctx->es = NULL;
290 }
291 #endif
292 (void)BSL_SAL_ThreadUnlock(ctx->lock);
293 BSL_SAL_ThreadLockFree(ctx->lock);
294 BSL_SAL_FREE(ctx);
295 return;
296 }
297
SeedPoolGetEntropy(CRYPT_EAL_SeedPoolCtx * poolCtx,CRYPT_Data * entropy,uint32_t strength,const CRYPT_Range * lenRange)298 static int32_t SeedPoolGetEntropy(CRYPT_EAL_SeedPoolCtx *poolCtx, CRYPT_Data *entropy, uint32_t strength,
299 const CRYPT_Range *lenRange)
300 {
301 EAL_EntropyCtx *ctx = EAL_EntropyNewCtx(poolCtx, true, lenRange->min, lenRange->max, strength);
302 if (ctx == NULL) {
303 BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_CTX_CREATE_FAILED);
304 return CRYPT_ENTROPY_CTX_CREATE_FAILED;
305 }
306 int32_t ret = EAL_EntropyCollection(poolCtx, ctx);
307 if (ret != CRYPT_SUCCESS) {
308 EAL_EntropyFreeCtx(ctx);
309 BSL_ERR_PUSH_ERROR(ret);
310 return ret;
311 }
312
313 entropy->data = EAL_EntropyDetachBuf(ctx, &entropy->len);
314 EAL_EntropyFreeCtx(ctx);
315 if (entropy->data == NULL) {
316 BSL_ERR_PUSH_ERROR(CRYPT_DRBG_FAIL_GET_ENTROPY);
317 return CRYPT_DRBG_FAIL_GET_ENTROPY;
318 }
319
320 return CRYPT_SUCCESS;
321 }
322
CRYPT_EAL_SeedPoolGetEntropy(CRYPT_EAL_SeedPoolCtx * ctx,CRYPT_Data * entropy,uint32_t strength,const CRYPT_Range * lenRange)323 int32_t CRYPT_EAL_SeedPoolGetEntropy(CRYPT_EAL_SeedPoolCtx *ctx, CRYPT_Data *entropy, uint32_t strength,
324 const CRYPT_Range *lenRange)
325 {
326 if (ctx == NULL || entropy == NULL || lenRange == NULL) {
327 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
328 return CRYPT_NULL_INPUT;
329 }
330 int32_t ret = BSL_SAL_ThreadWriteLock(ctx->lock);
331 if (ret != BSL_SUCCESS) {
332 BSL_ERR_PUSH_ERROR(ret);
333 return ret;
334 }
335 ret = SeedPoolGetEntropy(ctx, entropy, strength, lenRange);
336 (void)BSL_SAL_ThreadUnlock(ctx->lock);
337 return ret;
338 }
339 #endif