• 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_ENTROPY) && defined(HITLS_CRYPTO_ENTROPY_SYS)
18 
19 #include <stdint.h>
20 #include "securec.h"
21 #include "bsl_err_internal.h"
22 #include "bsl_list.h"
23 #include "crypt_errno.h"
24 #include "crypt_entropy.h"
25 #include "es_entropy_pool.h"
26 #include "es_cf.h"
27 #include "es_noise_source.h"
28 
29 struct ES_Entropy {
30     bool isWork; // Whether in working state
31     bool enableTest; // Whether to enable the health test
32     uint32_t poolSize; // Entropy pool size
33     ES_EntropyPool *pool; // Entropy pool
34     ES_CfMethod *cfMeth; // compression function handle
35     BslList *nsList;
36 };
37 
38 #define ENTROPY_POOL_SIZE_DEFAULT 4096
39 #define ENTROPY_POOL_SIZE_MIN 512
40 #define ENTROPY_POOL_SIZE_MAX 4096
41 
ENTROPY_EsNew(void)42 ENTROPY_EntropySource *ENTROPY_EsNew(void)
43 {
44     ENTROPY_EntropySource *es = BSL_SAL_Malloc(sizeof(ENTROPY_EntropySource));
45     if (es == NULL) {
46         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
47         return NULL;
48     }
49     (void)memset_s(es, sizeof(ENTROPY_EntropySource), 0, sizeof(ENTROPY_EntropySource));
50     es->nsList = ES_NsListCreat();
51     if (es->nsList == NULL) {
52         BSL_SAL_Free(es);
53         return NULL;
54     }
55     es->poolSize = ENTROPY_POOL_SIZE_DEFAULT;
56     es->enableTest = false;
57     return es;
58 }
59 
ENTROPY_EsFree(ENTROPY_EntropySource * es)60 void ENTROPY_EsFree(ENTROPY_EntropySource *es)
61 {
62     if (es == NULL) {
63         return;
64     }
65     if (es->isWork == true) {
66         ENTROPY_EsDeinit(es);
67     }
68     BSL_SAL_FREE(es->cfMeth);
69     ES_NsListFree(es->nsList);
70     es->nsList = NULL;
71     BSL_SAL_Free(es);
72     return;
73 }
74 
ENTROPY_EsInit(ENTROPY_EntropySource * es)75 int32_t ENTROPY_EsInit(ENTROPY_EntropySource *es)
76 {
77     if (es == NULL || es->cfMeth == NULL) {
78         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
79         return CRYPT_NULL_INPUT;
80     }
81     if (es->isWork) {
82         return CRYPT_SUCCESS;
83     }
84     ES_CfMethod *meth = es->cfMeth;
85     if (meth->init != NULL) {
86         meth->ctx = meth->init(&meth->meth);
87         if (meth->ctx == NULL) {
88             ENTROPY_EsDeinit(es);
89             return CRYPT_ENTROPY_ES_CF_ERROR;
90         }
91     }
92     int32_t ret = ES_NsListInit(es->nsList, es->enableTest);
93     if (ret != CRYPT_SUCCESS) {
94         ENTROPY_EsDeinit(es);
95         return ret;
96     }
97     ES_EntropyPool *pool = ES_EntropyPoolInit(es->poolSize);
98     if (pool == NULL) {
99         ENTROPY_EsDeinit(es);
100         return CRYPT_ENTROPY_ES_POOL_ERROR;
101     }
102     es->pool = pool;
103     es->isWork = true;
104     return CRYPT_SUCCESS;
105 }
106 
ENTROPY_EsDeinit(ENTROPY_EntropySource * es)107 void ENTROPY_EsDeinit(ENTROPY_EntropySource *es)
108 {
109     if (es == NULL) {
110         return;
111     }
112     es->isWork = false;
113     ES_EntropyPoolDeInit(es->pool);
114     es->pool = NULL;
115     if (es->cfMeth != NULL && es->cfMeth->deinit != NULL) {
116         es->cfMeth->deinit(es->cfMeth->ctx);
117         es->cfMeth->ctx = NULL;
118     }
119     ES_NsListDeinit(es->nsList);
120     return;
121 }
EsPoolSizeSet(ENTROPY_EntropySource * es,void * data,uint32_t len)122 static int32_t EsPoolSizeSet(ENTROPY_EntropySource *es, void *data, uint32_t len)
123 {
124     if (es->isWork) {
125         BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ES_STATE_ERROR);
126         return CRYPT_ENTROPY_ES_STATE_ERROR;
127     }
128     if (len != sizeof(uint32_t) || *(uint32_t *)data < ENTROPY_POOL_SIZE_MIN ||
129         *(uint32_t *)data > ENTROPY_POOL_SIZE_MAX) {
130         BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_CTRL_INVALID_PARAM);
131         return CRYPT_ENTROPY_CTRL_INVALID_PARAM;
132     }
133     es->poolSize = *(uint32_t *)data;
134     return CRYPT_SUCCESS;
135 }
136 
EsNsAdd(ENTROPY_EntropySource * es,void * data,uint32_t len)137 static int32_t EsNsAdd(ENTROPY_EntropySource *es, void *data, uint32_t len)
138 {
139     if (es->isWork) {
140         BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ES_STATE_ERROR);
141         return CRYPT_ENTROPY_ES_STATE_ERROR;
142     }
143     if (data == NULL || len != sizeof(CRYPT_EAL_NsPara)) {
144         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
145         return CRYPT_NULL_INPUT;
146     }
147     CRYPT_EAL_NsPara *para = (CRYPT_EAL_NsPara *)data;
148     return ES_NsAdd(es->nsList, para->name, para->autoTest, para->minEntropy, &para->nsMeth,
149         (const CRYPT_EAL_NsTestPara *)&(para->nsPara));
150 }
151 
EsEnableTest(ENTROPY_EntropySource * es,void * data,uint32_t len)152 static int32_t EsEnableTest(ENTROPY_EntropySource *es, void *data, uint32_t len)
153 {
154     if (es->isWork) {
155         BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ES_STATE_ERROR);
156         return CRYPT_ENTROPY_ES_STATE_ERROR;
157     }
158     if (data == NULL || len != sizeof(bool)) {
159         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
160         return CRYPT_NULL_INPUT;
161     }
162     es->enableTest = *(bool *)data;
163     return CRYPT_SUCCESS;
164 }
165 
EsNsRemove(ENTROPY_EntropySource * es,void * data,uint32_t len)166 static int32_t EsNsRemove(ENTROPY_EntropySource *es, void *data, uint32_t len)
167 {
168     if (es->isWork) {
169         BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ES_STATE_ERROR);
170         return CRYPT_ENTROPY_ES_STATE_ERROR;
171     }
172     if (data == NULL || len == 0) {
173         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
174         return CRYPT_NULL_INPUT;
175     }
176     return ES_NsRemove(es->nsList, (const char *)data);
177 }
178 
EsSetCF(ENTROPY_EntropySource * es,ENTROPY_CFPara * data)179 static int32_t EsSetCF(ENTROPY_EntropySource *es, ENTROPY_CFPara *data)
180 {
181     if (es->isWork) {
182         BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ES_STATE_ERROR);
183         return CRYPT_ENTROPY_ES_STATE_ERROR;
184     }
185     if (es->cfMeth != NULL) {
186         BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ES_CF_ERROR);
187         return CRYPT_ENTROPY_ES_CF_ERROR;
188     }
189     es->cfMeth = ES_CFGetMethod(data->algId, data->md);
190     if (es->cfMeth == NULL) {
191         BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ES_CF_NOT_SUPPORT);
192         return CRYPT_ENTROPY_ES_CF_NOT_SUPPORT;
193     }
194     return CRYPT_SUCCESS;
195 }
196 
EsGetSize(ENTROPY_EntropySource * es,int32_t cmd,void * data,uint32_t len)197 static int32_t EsGetSize(ENTROPY_EntropySource *es, int32_t cmd, void *data, uint32_t len)
198 {
199     if (data == NULL || len != sizeof(uint32_t)) {
200         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
201         return CRYPT_NULL_INPUT;
202     }
203     if (!es->isWork) {
204         BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ES_STATE_ERROR);
205         return CRYPT_ENTROPY_ES_STATE_ERROR;
206     }
207     switch (cmd) {
208         case CRYPT_ENTROPY_GET_POOL_SIZE:
209             *(uint32_t *)data = es->poolSize;
210             return CRYPT_SUCCESS;
211         case CRYPT_ENTROPY_POOL_GET_CURRSIZE:
212             *(uint32_t *)data = ES_EntropyPoolGetCurSize(es->pool);
213             return CRYPT_SUCCESS;
214         case CRYPT_ENTROPY_GET_CF_SIZE:
215             *(uint32_t *)data = es->cfMeth->getCfOutLen(es->cfMeth->ctx);
216             return CRYPT_SUCCESS;
217         default:
218             BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ES_CTRL_ERROR);
219             return CRYPT_ENTROPY_ES_CTRL_ERROR;
220     }
221 }
EsGetState(ENTROPY_EntropySource * es,void * data,uint32_t len)222 static int32_t EsGetState(ENTROPY_EntropySource *es, void *data, uint32_t len)
223 {
224     if (data == NULL || len != sizeof(bool)) {
225         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
226         return CRYPT_INVALID_ARG;
227     }
228     *(bool *)data = es->isWork;
229     return CRYPT_SUCCESS;
230 }
231 
ENTROPY_EsCtrl(ENTROPY_EntropySource * es,int32_t cmd,void * data,uint32_t len)232 int32_t ENTROPY_EsCtrl(ENTROPY_EntropySource *es, int32_t cmd, void *data, uint32_t len)
233 {
234     if (es == NULL) {
235         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
236         return CRYPT_NULL_INPUT;
237     }
238     switch (cmd) {
239         case CRYPT_ENTROPY_SET_POOL_SIZE:
240             return EsPoolSizeSet(es, data, len);
241         case CRYPT_ENTROPY_ADD_NS:
242             return EsNsAdd(es, data, len);
243         case CRYPT_ENTROPY_REMOVE_NS:
244             return EsNsRemove(es, data, len);
245         case CRYPT_ENTROPY_ENABLE_TEST:
246             return EsEnableTest(es, data, len);
247         case CRYPT_ENTROPY_SET_CF:
248             return EsSetCF(es, data);
249         case CRYPT_ENTROPY_GET_STATE:
250             return EsGetState(es, data, len);
251         default:
252             return EsGetSize(es, cmd, data, len);
253     }
254 }
255 
ENTROPY_EsEntropyGet(ENTROPY_EntropySource * es,uint8_t * data,uint32_t len)256 uint32_t ENTROPY_EsEntropyGet(ENTROPY_EntropySource *es, uint8_t *data, uint32_t len)
257 {
258     if (es == NULL || !es->isWork || data == NULL) {
259         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
260         return 0;
261     }
262     if (ES_EntropyPoolGetCurSize(es->pool) <= 0) {
263         int32_t ret = ENTROPY_EsEntropyGather(es);
264         if (ret != CRYPT_SUCCESS) {
265             return 0;
266         }
267     }
268     return ES_EntropyPoolPopBytes(es->pool, data, len);
269 }
270 
EsGetEntropy(ENTROPY_EntropySource * es,uint8_t * buf,uint32_t bufLen,uint32_t entropy)271 static uint32_t EsGetEntropy(ENTROPY_EntropySource *es, uint8_t *buf, uint32_t bufLen, uint32_t entropy)
272 {
273     ES_NoiseSource *ns = NULL;
274     uint32_t needLen = 0;
275     uint32_t curEntropy = 0;
276     uint8_t *data = buf;
277     while (curEntropy < entropy) {
278         uint32_t tmpEntropy = curEntropy;
279         for (ns = BSL_LIST_GET_FIRST(es->nsList); ns != NULL && needLen < bufLen; ns = BSL_LIST_GET_NEXT(es->nsList)) {
280             int32_t ret = ES_NsRead(ns, data, 1);
281             if (ret == CRYPT_SUCCESS) {
282                 data++;
283                 needLen++;
284                 curEntropy += ns->minEntropy;
285             }
286             if (curEntropy >= entropy) {
287                 return needLen;
288             }
289         }
290         if (curEntropy == tmpEntropy) {
291             BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ES_NS_NOT_AVA);
292             needLen = 0;
293             break;
294         }
295     }
296     return needLen;
297 }
298 
GetMinLen(uint32_t entropy,uint32_t minEntropy)299 static uint32_t GetMinLen(uint32_t entropy, uint32_t minEntropy)
300 {
301     return (uint32_t)(((uint64_t)entropy + (uint64_t)minEntropy - 1) / (uint64_t)minEntropy);
302 }
303 
ENTROPY_EsEntropyGather(ENTROPY_EntropySource * es)304 int32_t ENTROPY_EsEntropyGather(ENTROPY_EntropySource *es)
305 {
306     if (es == NULL || es->isWork == false || es->cfMeth == NULL) {
307         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
308         return CRYPT_NULL_INPUT;
309     }
310     ES_CfMethod *meth = es->cfMeth;
311     if ((meth->getCfOutLen(meth->ctx) > (uint32_t)ES_EntropyPoolGetMaxSize(es->pool) -
312         ES_EntropyPoolGetCurSize(es->pool))) {
313         BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ES_POOL_INSUFFICIENT);
314         return CRYPT_ENTROPY_ES_POOL_INSUFFICIENT;
315     }
316     uint32_t minEntropy = ES_NsListGetMinEntropy(es->nsList);
317     uint32_t needEntropy = meth->getNeedEntropy(meth->ctx);
318     uint32_t bufLen = GetMinLen(needEntropy, minEntropy);
319     uint8_t *buf = BSL_SAL_Malloc(bufLen);
320     if (buf == NULL) {
321         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
322         return CRYPT_MEM_ALLOC_FAIL;
323     }
324     uint32_t needLen = EsGetEntropy(es, buf, bufLen, needEntropy);
325     if (needLen == 0) {
326         BSL_SAL_Free(buf);
327         BSL_ERR_PUSH_ERROR(CRYPT_ENTROPY_ES_ENTROPY_NOT_ENOUGH);
328         return CRYPT_ENTROPY_ES_ENTROPY_NOT_ENOUGH;
329     }
330     int32_t ret = meth->update(meth->ctx, buf, needLen);
331     BSL_SAL_Free(buf);
332     if (ret != CRYPT_SUCCESS) {
333         BSL_ERR_PUSH_ERROR(ret);
334         return ret;
335     }
336     uint32_t len;
337     uint8_t *data = meth->getEntropyData(meth->ctx, &len);
338     if (data == NULL) {
339         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
340         return CRYPT_MEM_ALLOC_FAIL;
341     }
342     ret = ES_EntropyPoolPushBytes(es->pool, data, len);
343     (void)memset_s(data, len, 0, len);
344     BSL_SAL_Free(data);
345     return ret;
346 }
347 #endif