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 #ifdef HITLS_CRYPTO_PROVIDER
17
18 #include "securec.h"
19 #include "crypt_provider.h"
20 #include "bsl_list.h"
21 #include "crypt_provider_local.h"
22 #include "crypt_errno.h"
23 #include "crypt_eal_entropy.h"
24 #include "bsl_err_internal.h"
25 #include "eal_entropy.h"
26 #include "crypt_drbg_local.h"
27 #include "crypt_drbg.h"
28
29 static CRYPT_EAL_LibCtx *g_libCtx = NULL;
30
CRYPT_EAL_GetGlobalLibCtx(void)31 CRYPT_EAL_LibCtx *CRYPT_EAL_GetGlobalLibCtx(void)
32 {
33 return g_libCtx;
34 }
35
CRYPT_EAL_ProviderGetFuncs(CRYPT_EAL_LibCtx * libCtx,int32_t operaId,int32_t algId,const char * attribute,const CRYPT_EAL_Func ** funcs,void ** provCtx)36 int32_t CRYPT_EAL_ProviderGetFuncs(CRYPT_EAL_LibCtx *libCtx, int32_t operaId, int32_t algId,
37 const char *attribute, const CRYPT_EAL_Func **funcs, void **provCtx)
38 {
39 CRYPT_EAL_ProvMgrCtx *mgrCtx = NULL;
40 int32_t ret = CRYPT_EAL_ProviderGetFuncsAndMgrCtx(libCtx, operaId, algId, attribute, funcs, &mgrCtx);
41 if (ret != CRYPT_SUCCESS) {
42 BSL_ERR_PUSH_ERROR(ret);
43 return ret;
44 }
45 if (mgrCtx == NULL) {
46 BSL_ERR_PUSH_ERROR(CRYPT_PROVIDER_NOT_FOUND);
47 return CRYPT_PROVIDER_NOT_FOUND;
48 }
49 if (provCtx != NULL) {
50 *provCtx = mgrCtx->provCtx;
51 }
52 return CRYPT_SUCCESS;
53 }
54
CRYPT_EAL_ProviderGetFuncsAndMgrCtx(CRYPT_EAL_LibCtx * libCtx,int32_t operaId,int32_t algId,const char * attribute,const CRYPT_EAL_Func ** funcs,CRYPT_EAL_ProvMgrCtx ** mgrCtx)55 int32_t CRYPT_EAL_ProviderGetFuncsAndMgrCtx(CRYPT_EAL_LibCtx *libCtx, int32_t operaId, int32_t algId,
56 const char *attribute, const CRYPT_EAL_Func **funcs, CRYPT_EAL_ProvMgrCtx **mgrCtx)
57 {
58 if (funcs == NULL || mgrCtx == NULL) {
59 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
60 return CRYPT_NULL_INPUT;
61 }
62 CRYPT_EAL_LibCtx *localCtx = libCtx;
63 if (localCtx == NULL) {
64 localCtx = g_libCtx;
65 }
66
67 if (localCtx == NULL) {
68 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
69 return CRYPT_NULL_INPUT;
70 }
71 if (attribute != NULL && strlen(attribute) > (INT32_MAX >> 1)) {
72 BSL_ERR_PUSH_ERROR(CRYPT_PROVIDER_ERR_ATTRIBUTE);
73 return CRYPT_PROVIDER_ERR_ATTRIBUTE;
74 }
75
76 return CRYPT_EAL_CompareAlgAndAttr(localCtx, operaId, algId, attribute, funcs, mgrCtx);
77 }
78
CRYPT_EAL_ProvMgrCtrl(CRYPT_EAL_ProvMgrCtx * ctx,int32_t cmd,void * val,uint32_t valLen)79 int32_t CRYPT_EAL_ProvMgrCtrl(CRYPT_EAL_ProvMgrCtx *ctx, int32_t cmd, void *val, uint32_t valLen)
80 {
81 (void) valLen;
82 if (ctx == NULL || val == NULL) {
83 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
84 return CRYPT_INVALID_ARG;
85 }
86 switch (cmd) {
87 case CRYPT_EAL_MGR_GETSEEDCTX:
88 *(void **) val = ctx->providerSeed.seed;
89 return CRYPT_SUCCESS;
90 case CRYPT_EAL_MGR_GETLIBCTX:
91 *(void **) val = ctx->libCtx;
92 return CRYPT_SUCCESS;
93 default:
94 BSL_ERR_PUSH_ERROR(CRYPT_PROVIDER_NOT_FOUND);
95 return CRYPT_PROVIDER_NOT_FOUND;
96 }
97 }
98
MountMgrMethod(CRYPT_EAL_Func * funcs,CRYPT_EAL_ProvMgrCtx * ctx)99 static void MountMgrMethod(CRYPT_EAL_Func *funcs, CRYPT_EAL_ProvMgrCtx *ctx)
100 {
101 // Mount function addresses to corresponding positions in mgr according to method definition
102 for (uint32_t i = 0; funcs[i].id != 0; i++) {
103 switch (funcs[i].id) {
104 case CRYPT_EAL_PROVCB_FREE:
105 ctx->provFreeCb = (CRYPT_EAL_ProvFreeCb)funcs[i].func;
106 break;
107 case CRYPT_EAL_PROVCB_QUERY:
108 ctx->provQueryCb = (CRYPT_EAL_ProvQueryCb)funcs[i].func;
109 break;
110 case CRYPT_EAL_PROVCB_CTRL:
111 ctx->provCtrlCb = (CRYPT_EAL_ProvCtrlCb)funcs[i].func;
112 break;
113 case CRYPT_EAL_PROVCB_GETCAPS:
114 ctx->provGetCap = (CRYPT_EAL_ProvGetCapsCb)funcs[i].func;
115 break;
116 default:
117 break;
118 }
119 }
120 }
121
122 #ifdef HITLS_CRYPTO_ENTROPY_DEFAULT
ProviderSeedDeinit(EAL_SeedDrbg * seedDrbg)123 static void ProviderSeedDeinit(EAL_SeedDrbg *seedDrbg)
124 {
125 if (seedDrbg == NULL) {
126 return;
127 }
128 if (seedDrbg->seed != NULL) {
129 EAL_SeedDrbgRandDeinit(seedDrbg->seed);
130 seedDrbg->seed = NULL;
131 CRYPT_EAL_SeedPoolFree(seedDrbg->seedCtx);
132 seedDrbg->seedCtx = NULL;
133 BSL_SAL_ReferencesFree(&(seedDrbg->references));
134 (void)memset_s(seedDrbg, sizeof(EAL_SeedDrbg), 0, sizeof(EAL_SeedDrbg));
135 }
136 }
137 #endif
138
139 // Function to get provider methods
CRYPT_EAL_InitProviderMethod(CRYPT_EAL_ProvMgrCtx * ctx,BSL_Param * param,CRYPT_EAL_ImplProviderInit providerInit)140 int32_t CRYPT_EAL_InitProviderMethod(CRYPT_EAL_ProvMgrCtx *ctx, BSL_Param *param,
141 CRYPT_EAL_ImplProviderInit providerInit)
142 {
143 int32_t ret;
144 #ifdef HITLS_CRYPTO_ENTROPY_DEFAULT
145 CRYPT_RandSeedMethod meth = {0};
146 // The implementer of provider may not use the default entropy source
147 (void)EAL_SeedDrbgEntropyMeth(&meth);
148 ctx->providerSeed.id = HITLS_SEED_DRBG_INIT_RAND_ALG;
149 ret = EAL_SeedDrbgInit(&(ctx->providerSeed));
150 if (ret != CRYPT_SUCCESS) {
151 BSL_ERR_PUSH_ERROR(ret);
152 return ret;
153 }
154 #endif
155 // Construct input method structure array
156 CRYPT_EAL_Func capFuncs[] = {
157 #ifdef HITLS_CRYPTO_ENTROPY_DEFAULT
158 {CRYPT_EAL_CAP_GETENTROPY, (CRYPT_EAL_GetEntropyCb)meth.getEntropy},
159 {CRYPT_EAL_CAP_CLEANENTROPY, (CRYPT_EAL_CleanEntropyCb)meth.cleanEntropy},
160 {CRYPT_EAL_CAP_GETNONCE, (CRYPT_EAL_GetNonceCb)meth.getNonce},
161 {CRYPT_EAL_CAP_CLEANNONCE, (CRYPT_EAL_CleanNonceCb)meth.cleanNonce},
162 #endif
163 {CRYPT_EAL_CAP_MGRCTXCTRL, (CRYPT_EAL_ProvMgrCtrlCb)CRYPT_EAL_ProvMgrCtrl},
164 CRYPT_EAL_FUNC_END // End marker
165 };
166
167 CRYPT_EAL_Func *outFuncs = NULL;
168 // Call CRYPT_EAL_ImplProviderInit to get methods
169 ret = providerInit(ctx, param, capFuncs, &outFuncs, &ctx->provCtx);
170 if (ret != CRYPT_SUCCESS) {
171 BSL_ERR_PUSH_ERROR(ret);
172 goto ERR;
173 }
174 if (outFuncs == NULL) {
175 ret = CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL;
176 BSL_ERR_PUSH_ERROR(CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL);
177 goto ERR;
178 }
179 MountMgrMethod(outFuncs, ctx);
180
181 if (ctx->provQueryCb == NULL) {
182 if (ctx->provFreeCb != NULL) {
183 ctx->provFreeCb(ctx->provCtx);
184 ctx->provCtx = NULL;
185 }
186 ret = CRYPT_PROVIDER_ERR_IMPL_NULL;
187 BSL_ERR_PUSH_ERROR(CRYPT_PROVIDER_ERR_IMPL_NULL);
188 goto ERR;
189 }
190
191 return CRYPT_SUCCESS;
192 ERR:
193 #ifdef HITLS_CRYPTO_ENTROPY_DEFAULT
194 ProviderSeedDeinit(&(ctx->providerSeed));
195 #endif
196 return ret;
197 }
198
CRYPT_EAL_LibCtxNewInternal(void)199 CRYPT_EAL_LibCtx *CRYPT_EAL_LibCtxNewInternal(void)
200 {
201 CRYPT_EAL_LibCtx *libCtx = (CRYPT_EAL_LibCtx *)BSL_SAL_Calloc(1, sizeof(CRYPT_EAL_LibCtx));
202 if (libCtx == NULL) {
203 BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
204 return NULL;
205 }
206
207 // Initialize providers list
208 libCtx->providers = BSL_LIST_New(sizeof(struct EAL_ProviderMgrCtx *));
209 if (libCtx->providers == NULL) {
210 goto ERR;
211 }
212
213 // Initialize thread lock
214 if (BSL_SAL_ThreadLockNew(&libCtx->lock) != BSL_SUCCESS) {
215 BSL_LIST_FREE(libCtx->providers, NULL);
216 goto ERR;
217 }
218
219 return libCtx;
220 ERR:
221 BSL_SAL_Free(libCtx);
222 libCtx = NULL;
223 return NULL;
224 }
225
CRYPT_EAL_ProviderMgrCtxFree(CRYPT_EAL_ProvMgrCtx * ctx)226 void CRYPT_EAL_ProviderMgrCtxFree(CRYPT_EAL_ProvMgrCtx *ctx)
227 {
228 if (ctx == NULL) {
229 return;
230 }
231 if (ctx->provFreeCb != NULL) {
232 ctx->provFreeCb(ctx->provCtx);
233 ctx->provCtx = NULL;
234 }
235 BSL_SAL_FREE(ctx->providerName);
236 BSL_SAL_FREE(ctx->providerPath);
237
238 BSL_SAL_ReferencesFree(&(ctx->ref));
239
240 if (ctx->handle != NULL) {
241 BSL_SAL_UnLoadLib(ctx->handle);
242 ctx->handle = NULL;
243 }
244 #ifdef HITLS_CRYPTO_ENTROPY_DEFAULT
245 ProviderSeedDeinit(&(ctx->providerSeed));
246 #endif
247 BSL_SAL_Free(ctx);
248 }
249
CRYPT_EAL_LoadPreDefinedProvider(CRYPT_EAL_LibCtx * libCtx,const char * providerName,CRYPT_EAL_ProvMgrCtx ** ctx)250 int32_t CRYPT_EAL_LoadPreDefinedProvider(CRYPT_EAL_LibCtx *libCtx, const char* providerName,
251 CRYPT_EAL_ProvMgrCtx **ctx)
252 {
253 char *name = BSL_SAL_Dump(providerName, BSL_SAL_Strnlen(providerName, DEFAULT_PROVIDER_NAME_LEN_MAX) + 1);
254 if (name == NULL) {
255 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
256 return CRYPT_MEM_ALLOC_FAIL;
257 }
258 CRYPT_EAL_ProvMgrCtx *mgrCtx = (CRYPT_EAL_ProvMgrCtx *)BSL_SAL_Calloc(1, sizeof(CRYPT_EAL_ProvMgrCtx));
259 if (mgrCtx == NULL) {
260 BSL_SAL_Free(name);
261 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
262 return CRYPT_MEM_ALLOC_FAIL;
263 }
264 int32_t ret = BSL_SAL_ReferencesInit(&mgrCtx->ref);
265 if (ret != BSL_SUCCESS) {
266 BSL_SAL_Free(name);
267 BSL_SAL_Free(mgrCtx);
268 BSL_ERR_PUSH_ERROR(ret);
269 return ret;
270 }
271
272 mgrCtx->libCtx = libCtx;
273 mgrCtx->providerName = name;
274 ret = CRYPT_EAL_InitProviderMethod(mgrCtx, NULL, CRYPT_EAL_DefaultProvInit);
275 if (ret == BSL_SUCCESS) {
276 ret = BSL_LIST_AddElement(libCtx->providers, mgrCtx, BSL_LIST_POS_END);
277 if (ctx != NULL) {
278 *ctx = mgrCtx;
279 }
280 }
281 if (ret != BSL_SUCCESS) {
282 CRYPT_EAL_ProviderMgrCtxFree(mgrCtx);
283 }
284 return ret;
285 }
286
CRYPT_EAL_InitPreDefinedProviders(void)287 int32_t CRYPT_EAL_InitPreDefinedProviders(void)
288 {
289 CRYPT_EAL_LibCtx *libCtx = CRYPT_EAL_LibCtxNewInternal();
290 if (libCtx == NULL) {
291 BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
292 return BSL_MALLOC_FAIL;
293 }
294 int32_t ret = CRYPT_EAL_LoadPreDefinedProvider(libCtx, CRYPT_EAL_DEFAULT_PROVIDER, NULL);
295 if (ret != CRYPT_SUCCESS) {
296 BSL_LIST_FREE(libCtx->providers, NULL);
297 BSL_SAL_ThreadLockFree(libCtx->lock);
298 BSL_SAL_FREE(libCtx);
299 return ret;
300 }
301 g_libCtx = libCtx;
302 return ret;
303 }
304
CRYPT_EAL_FreePreDefinedProviders(void)305 void CRYPT_EAL_FreePreDefinedProviders(void)
306 {
307 CRYPT_EAL_LibCtx *libCtx = g_libCtx;
308 if (libCtx == NULL) {
309 return;
310 }
311
312 if (libCtx->drbg != NULL) {
313 EAL_RandDeinit(libCtx->drbg);
314 libCtx->drbg = NULL;
315 }
316 // Free the providers list and each EAL_ProviderMgrCtx in it
317 if (libCtx->providers != NULL) {
318 BSL_LIST_FREE(libCtx->providers, (BSL_LIST_PFUNC_FREE)CRYPT_EAL_ProviderMgrCtxFree);
319 }
320
321 BSL_SAL_FREE(libCtx->searchProviderPath);
322
323 // Free thread lock
324 if (libCtx->lock != NULL) {
325 BSL_SAL_ThreadLockFree(libCtx->lock);
326 libCtx->lock = NULL;
327 }
328
329 // Free the libctx structure itself
330 BSL_SAL_Free(libCtx);
331 g_libCtx = NULL;
332 }
333
334 #endif /* HITLS_CRYPTO_PROVIDER */