• 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 
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 *)&para, 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, &para);
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