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_sal.h"
23 #include "crypt_local_types.h"
24 #include "crypt_errno.h"
25 #include "es_cf.h"
26
27 /*
28 * see FIPS 140-3 section Full Entropy
29 * To receive full entropy from the output of a conditioning component, the following criteria must be met:
30 * The conditioning component shall be vetted,
31 * ℎin shall be greater than or equal to out + 64 bits,
32 * out shall be less than or equal to the security strength of the cryptographic function used as the
33 * conditioning component.
34 */
35 #define CF_FE_EXLEN 64
36 #define CF_BYTE_TO_BIT 8
37
38 typedef struct {
39 void *ctx; // Hash algorithm handle
40 EAL_MdMethod meth; // Hash algorithm operation function
41 } ES_CfDfCtx;
42
ES_CfDfDeinit(void * ctx)43 static void ES_CfDfDeinit(void *ctx)
44 {
45 ES_CfDfCtx *cfCtx = (ES_CfDfCtx *)ctx;
46 if (cfCtx == NULL) {
47 return;
48 }
49 if (cfCtx->ctx != NULL) {
50 cfCtx->meth.freeCtx(cfCtx->ctx);
51 }
52 BSL_SAL_Free(cfCtx);
53 return;
54 }
55
ES_CfDfInit(void * mdMeth)56 static void *ES_CfDfInit(void *mdMeth)
57 {
58 ES_CfDfCtx *ctx = BSL_SAL_Malloc(sizeof(ES_CfDfCtx));
59 EAL_MdMethod *meth = (EAL_MdMethod *)mdMeth;
60 if (ctx == NULL) {
61 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
62 return NULL;
63 }
64 (void)memcpy_s(&ctx->meth, sizeof(EAL_MdMethod), meth, sizeof(EAL_MdMethod));
65 ctx->ctx = meth->newCtx();
66 if (ctx->ctx == NULL) {
67 BSL_SAL_Free(ctx);
68 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
69 return NULL;
70 }
71 int32_t ret = meth->init(ctx->ctx, NULL);
72 if (ret != CRYPT_SUCCESS) {
73 ES_CfDfDeinit(ctx);
74 BSL_ERR_PUSH_ERROR(ret);
75 return NULL;
76 }
77 return ctx;
78 }
79
DfI32ToByte(uint8_t values[4],uint32_t len)80 static void DfI32ToByte(uint8_t values[4], uint32_t len)
81 {
82 values[0] = (uint8_t)(((len << 3) >> 24) & 0xff); /* leftward by 3, rightwards by 24 */
83 values[1] = (uint8_t)(((len << 3) >> 16) & 0xff); /* leftward by 3, rightwards by 16 */
84 values[2] = (uint8_t)(((len << 3) >> 8) & 0xff); /* leftward by 3, rightwards by 8 */
85 values[3] = (uint8_t)((len << 3) & 0xff); /* leftward by 3 */
86 return;
87 }
88
ES_CfDfUpdateData(void * ctx,uint8_t * data,uint32_t dataLen)89 static int32_t ES_CfDfUpdateData(void *ctx, uint8_t *data, uint32_t dataLen)
90 {
91 ES_CfDfCtx *cfCtx = (ES_CfDfCtx *)ctx;
92 uint8_t tmp[1] = { 0x01};
93 int32_t ret = cfCtx->meth.update(cfCtx->ctx, tmp, 1);
94 if (ret != CRYPT_SUCCESS) {
95 BSL_ERR_PUSH_ERROR(ret);
96 return ret;
97 }
98 uint8_t values[4] = {0}; // 4 is sizeof(uint32_t)
99 DfI32ToByte(values, cfCtx->meth.mdSize);
100 ret = cfCtx->meth.update(cfCtx->ctx, values, sizeof(values));
101 if (ret != CRYPT_SUCCESS) {
102 BSL_ERR_PUSH_ERROR(ret);
103 return ret;
104 }
105 ret = cfCtx->meth.update(cfCtx->ctx, data, dataLen);
106 if (ret != CRYPT_SUCCESS) {
107 BSL_ERR_PUSH_ERROR(ret);
108 }
109 return ret;
110 }
111
ES_CfDfGetEntropyData(void * cfCtx,uint32_t * len)112 static uint8_t *ES_CfDfGetEntropyData(void *cfCtx, uint32_t *len)
113 {
114 ES_CfDfCtx *ctx = (ES_CfDfCtx *)cfCtx;
115 uint32_t bufLen = ctx->meth.mdSize;
116 uint8_t *buf = BSL_SAL_Malloc(bufLen);
117 if (buf == NULL) {
118 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
119 return NULL;
120 }
121 int32_t ret = ctx->meth.final(ctx->ctx, buf, &bufLen);
122 if (ret != CRYPT_SUCCESS) {
123 BSL_SAL_Free(buf);
124 BSL_ERR_PUSH_ERROR(ret);
125 return NULL;
126 }
127 ctx->meth.deinit(ctx->ctx);
128 ret = ctx->meth.init(ctx->ctx, NULL);
129 if (ret != CRYPT_SUCCESS) {
130 BSL_SAL_Free(buf);
131 BSL_ERR_PUSH_ERROR(ret);
132 return NULL;
133 }
134 *len = bufLen;
135 return buf;
136 }
137
ES_CfDfGetCfOutLen(void * cfCtx)138 static uint32_t ES_CfDfGetCfOutLen(void *cfCtx)
139 {
140 ES_CfDfCtx *ctx = (ES_CfDfCtx *)cfCtx;
141 return ctx->meth.mdSize;
142 }
143
ES_CfDfGetNeedEntropy(void * cfCtx)144 static uint32_t ES_CfDfGetNeedEntropy(void *cfCtx)
145 {
146 ES_CfDfCtx *ctx = (ES_CfDfCtx *)cfCtx;
147 return ctx->meth.mdSize * CF_BYTE_TO_BIT + CF_FE_EXLEN;
148 }
149
ES_CFGetDfMethod(EAL_MdMethod * mdMeth)150 ES_CfMethod *ES_CFGetDfMethod(EAL_MdMethod *mdMeth)
151 {
152 ES_CfMethod *meth = BSL_SAL_Malloc(sizeof(ES_CfMethod));
153 if (meth == NULL) {
154 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
155 return NULL;
156 }
157 meth->ctx = NULL;
158 meth->meth.mdMeth = *mdMeth;
159 meth->init = ES_CfDfInit;
160 meth->update = ES_CfDfUpdateData;
161 meth->deinit = ES_CfDfDeinit;
162 meth->getCfOutLen = ES_CfDfGetCfOutLen;
163 meth->getEntropyData = ES_CfDfGetEntropyData;
164 meth->getNeedEntropy = ES_CfDfGetNeedEntropy;
165 return meth;
166 }
167 #endif