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_CODECS) && defined(HITLS_CRYPTO_PROVIDER)
18 #include <stdint.h>
19 #include <string.h>
20 #include "securec.h"
21 #include "crypt_eal_codecs.h"
22 #include "crypt_eal_implprovider.h"
23 #include "crypt_provider.h"
24 #include "crypt_params_key.h"
25 #include "crypt_types.h"
26 #include "crypt_errno.h"
27 #include "decode_local.h"
28 #include "bsl_list.h"
29 #include "bsl_errno.h"
30 #include "bsl_err_internal.h"
31
CreateDecoderNode(const char * format,const char * type,const char * targetFormat,const char * targetType,const BSL_Param * input)32 static CRYPT_DECODER_Node *CreateDecoderNode(const char *format, const char *type, const char *targetFormat,
33 const char *targetType, const BSL_Param *input)
34 {
35 CRYPT_DECODER_Node *decoderNode = BSL_SAL_Calloc(1, sizeof(CRYPT_DECODER_Node));
36 if (decoderNode == NULL) {
37 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
38 return NULL;
39 }
40
41 decoderNode->inData.format = format;
42 decoderNode->inData.type = type;
43 decoderNode->inData.data = (BSL_Param *)(uintptr_t)input;
44 decoderNode->outData.format = targetFormat;
45 decoderNode->outData.type = targetType;
46 return decoderNode;
47 }
48
FreeDecoderNode(CRYPT_DECODER_Node * decoderNode)49 static void FreeDecoderNode(CRYPT_DECODER_Node *decoderNode)
50 {
51 if (decoderNode == NULL) {
52 return;
53 }
54 CRYPT_DECODE_FreeOutData(decoderNode->decoderCtx, decoderNode->outData.data);
55 BSL_SAL_Free(decoderNode);
56 }
57
CRYPT_DECODE_PoolNewCtx(CRYPT_EAL_LibCtx * libCtx,const char * attrName,int32_t keyType,const char * format,const char * type)58 CRYPT_DECODER_PoolCtx *CRYPT_DECODE_PoolNewCtx(CRYPT_EAL_LibCtx *libCtx, const char *attrName,
59 int32_t keyType, const char *format, const char *type)
60 {
61 CRYPT_DECODER_PoolCtx *poolCtx = BSL_SAL_Calloc(1, sizeof(CRYPT_DECODER_PoolCtx));
62 if (poolCtx == NULL) {
63 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
64 return NULL;
65 }
66
67 poolCtx->libCtx = libCtx;
68 poolCtx->attrName = attrName;
69 poolCtx->decoders = BSL_LIST_New(sizeof(CRYPT_DECODER_Ctx));
70 if (poolCtx->decoders == NULL) {
71 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
72 BSL_SAL_Free(poolCtx);
73 return NULL;
74 }
75
76 poolCtx->decoderPath = BSL_LIST_New(sizeof(CRYPT_DECODER_Node));
77 if (poolCtx->decoderPath == NULL) {
78 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
79 goto ERR;
80 }
81 poolCtx->inputFormat = format;
82 poolCtx->inputType = type;
83 poolCtx->inputKeyType = keyType;
84 poolCtx->targetFormat = NULL;
85 poolCtx->targetType = NULL;
86 return poolCtx;
87 ERR:
88 BSL_LIST_FREE(poolCtx->decoders, NULL);
89 BSL_SAL_Free(poolCtx);
90 return NULL;
91 }
92
CRYPT_DECODE_PoolFreeCtx(CRYPT_DECODER_PoolCtx * poolCtx)93 void CRYPT_DECODE_PoolFreeCtx(CRYPT_DECODER_PoolCtx *poolCtx)
94 {
95 if (poolCtx == NULL) {
96 return;
97 }
98
99 /* Free decoder path list and all decoder nodes */
100 if (poolCtx->decoderPath != NULL) {
101 BSL_LIST_FREE(poolCtx->decoderPath, (BSL_LIST_PFUNC_FREE)FreeDecoderNode);
102 }
103 /* Free decoder list and all decoder contexts */
104 if (poolCtx->decoders != NULL) {
105 BSL_LIST_FREE(poolCtx->decoders, (BSL_LIST_PFUNC_FREE)CRYPT_DECODE_Free);
106 }
107
108 BSL_SAL_Free(poolCtx);
109 }
110
SetDecodeType(void * val,int32_t valLen,const char ** targetValue)111 static int32_t SetDecodeType(void *val, int32_t valLen, const char **targetValue)
112 {
113 if (valLen == 0 || valLen > MAX_CRYPT_DECODE_FORMAT_TYPE_SIZE) {
114 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
115 return CRYPT_INVALID_ARG;
116 }
117 *targetValue = val;
118 return CRYPT_SUCCESS;
119 }
120
SetFlagFreeOutData(CRYPT_DECODER_PoolCtx * poolCtx,void * val,int32_t valLen)121 static int32_t SetFlagFreeOutData(CRYPT_DECODER_PoolCtx *poolCtx, void *val, int32_t valLen)
122 {
123 if (valLen != sizeof(bool)) {
124 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
125 return CRYPT_INVALID_ARG;
126 }
127 if (poolCtx->decoderPath == NULL) {
128 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
129 return CRYPT_INVALID_ARG;
130 }
131 CRYPT_DECODER_Node *prevNode = BSL_LIST_GET_PREV(poolCtx->decoderPath);
132 if (prevNode == NULL) {
133 return CRYPT_SUCCESS;
134 }
135 bool isFreeOutData = *(bool *)val;
136 if (!isFreeOutData) {
137 prevNode->outData.data = NULL;
138 }
139 return CRYPT_SUCCESS;
140 }
141
CRYPT_DECODE_PoolCtrl(CRYPT_DECODER_PoolCtx * poolCtx,int32_t cmd,void * val,int32_t valLen)142 int32_t CRYPT_DECODE_PoolCtrl(CRYPT_DECODER_PoolCtx *poolCtx, int32_t cmd, void *val, int32_t valLen)
143 {
144 if (poolCtx == NULL || val == NULL) {
145 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
146 return CRYPT_NULL_INPUT;
147 }
148
149 switch (cmd) {
150 case CRYPT_DECODE_POOL_CMD_SET_TARGET_TYPE:
151 return SetDecodeType(val, valLen, &poolCtx->targetType);
152 case CRYPT_DECODE_POOL_CMD_SET_TARGET_FORMAT:
153 return SetDecodeType(val, valLen, &poolCtx->targetFormat);
154 case CRYPT_DECODE_POOL_CMD_SET_FLAG_FREE_OUT_DATA:
155 return SetFlagFreeOutData(poolCtx, val, valLen);
156 default:
157 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
158 return CRYPT_INVALID_ARG;
159 }
160 }
161
CollectDecoder(CRYPT_DECODER_Ctx * decoderCtx,void * args)162 static int32_t CollectDecoder(CRYPT_DECODER_Ctx *decoderCtx, void *args)
163 {
164 int32_t ret;
165 CRYPT_DECODER_PoolCtx *poolCtx = (CRYPT_DECODER_PoolCtx *)args;
166 if (poolCtx == NULL) {
167 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
168 return CRYPT_NULL_INPUT;
169 }
170 // TODO: Filter the decoder by input format and type According to poolCtx
171 BSL_Param param[3] = {
172 {CRYPT_PARAM_DECODE_LIB_CTX, BSL_PARAM_TYPE_CTX_PTR, poolCtx->libCtx, 0, 0},
173 {CRYPT_PARAM_DECODE_TARGET_ATTR_NAME, BSL_PARAM_TYPE_OCTETS_PTR, (void *)(uintptr_t)poolCtx->attrName, 0, 0},
174 BSL_PARAM_END
175 };
176 ret = CRYPT_DECODE_SetParam(decoderCtx, param);
177 if (ret != CRYPT_SUCCESS) {
178 BSL_ERR_PUSH_ERROR(ret);
179 return ret;
180 }
181 ret = BSL_LIST_AddElement(poolCtx->decoders, decoderCtx, BSL_LIST_POS_END);
182 if (ret != BSL_SUCCESS) {
183 BSL_ERR_PUSH_ERROR(ret);
184 return ret;
185 }
186
187 return CRYPT_SUCCESS;
188 }
189
GetUsableDecoderFromPool(CRYPT_DECODER_PoolCtx * poolCtx,CRYPT_DECODER_Node * currNode)190 static CRYPT_DECODER_Ctx* GetUsableDecoderFromPool(CRYPT_DECODER_PoolCtx *poolCtx, CRYPT_DECODER_Node *currNode)
191 {
192 CRYPT_DECODER_Ctx *decoderCtx = NULL;
193 const char *curFormat = currNode->inData.format;
194 const char *curType = currNode->inData.type;
195 CRYPT_DECODER_Ctx *node = BSL_LIST_GET_FIRST(poolCtx->decoders);
196 while (node != NULL) {
197 decoderCtx = node;
198 if (decoderCtx == NULL || decoderCtx->decoderState != CRYPT_DECODER_STATE_UNTRIED) {
199 node = BSL_LIST_GET_NEXT(poolCtx->decoders);
200 continue;
201 }
202 /* Check if decoder matches the current node's input format and type */
203 if (curFormat != NULL && curType != NULL) {
204 if ((decoderCtx->inFormat != NULL && BSL_SAL_StrcaseCmp(decoderCtx->inFormat, curFormat) == 0) &&
205 (decoderCtx->inType == NULL || BSL_SAL_StrcaseCmp(decoderCtx->inType, curType) == 0)) {
206 break;
207 }
208 } else if (curFormat == NULL && curType != NULL) {
209 if (decoderCtx->inType == NULL || BSL_SAL_StrcaseCmp(decoderCtx->inType, curType) == 0) {
210 break;
211 }
212 } else if (curFormat != NULL && curType == NULL) {
213 if (decoderCtx->inFormat != NULL && BSL_SAL_StrcaseCmp(decoderCtx->inFormat, curFormat) == 0) {
214 break;
215 }
216 } else {
217 break;
218 }
219 node = BSL_LIST_GET_NEXT(poolCtx->decoders);
220 }
221 if (node != NULL) {
222 decoderCtx = node;
223 decoderCtx->decoderState = CRYPT_DECODER_STATE_TRING;
224 }
225 return node != NULL ? decoderCtx : NULL;
226 }
227
UpdateDecoderPath(CRYPT_DECODER_PoolCtx * poolCtx,CRYPT_DECODER_Node * currNode)228 static int32_t UpdateDecoderPath(CRYPT_DECODER_PoolCtx *poolCtx, CRYPT_DECODER_Node *currNode)
229 {
230 /* Create new node */
231 CRYPT_DECODER_Node *newNode = CreateDecoderNode(currNode->outData.format, currNode->outData.type,
232 poolCtx->targetFormat, poolCtx->targetType, currNode->outData.data);
233 if (newNode == NULL) {
234 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
235 return CRYPT_MEM_ALLOC_FAIL;
236 }
237 int32_t ret = BSL_LIST_AddElement(poolCtx->decoderPath, newNode, BSL_LIST_POS_END);
238 if (ret != BSL_SUCCESS) {
239 BSL_SAL_FREE(newNode);
240 BSL_ERR_PUSH_ERROR(ret);
241 return ret;
242 }
243 return CRYPT_SUCCESS;
244 }
245
TryDecodeWithDecoder(CRYPT_DECODER_PoolCtx * poolCtx,CRYPT_DECODER_Node * currNode)246 static int32_t TryDecodeWithDecoder(CRYPT_DECODER_PoolCtx *poolCtx, CRYPT_DECODER_Node *currNode)
247 {
248 /* Convert password buffer to parameter if provided */
249 BSL_Param *decoderParam = NULL;
250 int32_t ret = CRYPT_DECODE_Decode(currNode->decoderCtx, currNode->inData.data, &decoderParam);
251 if (ret == CRYPT_SUCCESS) {
252 /* Get output format and type from decoder */
253 BSL_Param outParam[3] = {
254 {CRYPT_PARAM_DECODE_OUTPUT_FORMAT, BSL_PARAM_TYPE_OCTETS_PTR, NULL, 0, 0},
255 {CRYPT_PARAM_DECODE_OUTPUT_TYPE, BSL_PARAM_TYPE_OCTETS_PTR, NULL, 0, 0},
256 BSL_PARAM_END
257 };
258 ret = CRYPT_DECODE_GetParam(currNode->decoderCtx, outParam);
259 if (ret != CRYPT_SUCCESS) {
260 BSL_ERR_PUSH_ERROR(ret);
261 return ret;
262 }
263
264 currNode->outData.data = decoderParam;
265 currNode->outData.format = outParam[0].value;
266 currNode->outData.type = outParam[1].value;
267 currNode->decoderCtx->decoderState = CRYPT_DECODER_STATE_SUCCESS;
268 ret = UpdateDecoderPath(poolCtx, currNode);
269 if (ret != CRYPT_SUCCESS) {
270 BSL_ERR_PUSH_ERROR(ret);
271 return ret;
272 }
273
274 return CRYPT_SUCCESS;
275 } else {
276 /* Mark the node as tried */
277 currNode->decoderCtx->decoderState = CRYPT_DECODER_STATE_TRIED;
278 return CRYPT_DECODE_RETRY;
279 }
280 }
281
ResetLastNode(CRYPT_DECODER_PoolCtx * poolCtx,CRYPT_DECODER_Node * currNode)282 static void ResetLastNode(CRYPT_DECODER_PoolCtx *poolCtx, CRYPT_DECODER_Node *currNode)
283 {
284 (void)currNode;
285 CRYPT_DECODER_Node *prevNode = BSL_LIST_GET_PREV(poolCtx->decoderPath);
286 /* Reset the out data of previous node if found */
287 if (prevNode != NULL) {
288 CRYPT_DECODE_FreeOutData(prevNode->decoderCtx, prevNode->outData.data);
289 prevNode->outData.data = NULL;
290 prevNode->decoderCtx = NULL;
291 prevNode->outData.format = poolCtx->targetFormat;
292 prevNode->outData.type = poolCtx->targetType;
293 (void)BSL_LIST_GET_NEXT(poolCtx->decoderPath);
294 } else {
295 (void)BSL_LIST_GET_FIRST(poolCtx->decoderPath);
296 }
297 BSL_LIST_DeleteCurrent(poolCtx->decoderPath, (BSL_LIST_PFUNC_FREE)FreeDecoderNode);
298 (void)BSL_LIST_GET_LAST(poolCtx->decoderPath);
299 }
300
BackToLastLayerDecodeNode(CRYPT_DECODER_PoolCtx * poolCtx,CRYPT_DECODER_Node * currNode)301 static int32_t BackToLastLayerDecodeNode(CRYPT_DECODER_PoolCtx *poolCtx, CRYPT_DECODER_Node *currNode)
302 {
303 if (poolCtx == NULL || currNode == NULL) {
304 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
305 return CRYPT_NULL_INPUT;
306 }
307 ResetLastNode(poolCtx, currNode);
308 /* Reset all decoders marked as tried to untried state */
309 CRYPT_DECODER_Ctx *decoderCtx = BSL_LIST_GET_FIRST(poolCtx->decoders);
310 while (decoderCtx != NULL) {
311 if (decoderCtx->decoderState == CRYPT_DECODER_STATE_TRIED) {
312 decoderCtx->decoderState = CRYPT_DECODER_STATE_UNTRIED;
313 }
314 decoderCtx = BSL_LIST_GET_NEXT(poolCtx->decoders);
315 }
316
317 return CRYPT_SUCCESS;
318 }
319
IsStrMatch(const char * source,const char * target)320 static bool IsStrMatch(const char *source, const char *target)
321 {
322 if (source == NULL && target == NULL) {
323 return true;
324 }
325 if (source == NULL || target == NULL) {
326 return false;
327 }
328 return BSL_SAL_StrcaseCmp(source, target) == 0;
329 }
330
DecodeWithKeyChain(CRYPT_DECODER_PoolCtx * poolCtx,BSL_Param ** outParam)331 static int32_t DecodeWithKeyChain(CRYPT_DECODER_PoolCtx *poolCtx, BSL_Param **outParam)
332 {
333 int32_t ret;
334 CRYPT_DECODER_Ctx *decoderCtx = NULL;
335 CRYPT_DECODER_Node *currNode = BSL_LIST_GET_FIRST(poolCtx->decoderPath);
336 while (!BSL_LIST_EMPTY(poolCtx->decoderPath)) {
337 if (IsStrMatch(currNode->inData.format, poolCtx->targetFormat) &&
338 IsStrMatch(currNode->inData.type, poolCtx->targetType)) {
339 *outParam = currNode->inData.data;
340 return CRYPT_SUCCESS;
341 }
342 /* Get the usable decoder from the pool */
343 decoderCtx = GetUsableDecoderFromPool(poolCtx, currNode);
344 /* If the decoder is found, try to decode */
345 if (decoderCtx != NULL) {
346 currNode->decoderCtx = decoderCtx;
347 ret = TryDecodeWithDecoder(poolCtx, currNode);
348 if (ret == CRYPT_DECODE_RETRY) {
349 continue;
350 }
351 } else {
352 ret = BackToLastLayerDecodeNode(poolCtx, currNode);
353 }
354 if (ret != CRYPT_SUCCESS) {
355 BSL_ERR_PUSH_ERROR(ret);
356 return ret;
357 }
358 CRYPT_DECODER_Node **curNodePtr = (CRYPT_DECODER_Node **)BSL_LIST_Curr(poolCtx->decoderPath);
359 currNode = curNodePtr == NULL ? NULL : *curNodePtr;
360 }
361
362 BSL_ERR_PUSH_ERROR(CRYPT_DECODE_ERR_NO_USABLE_DECODER);
363 return CRYPT_DECODE_ERR_NO_USABLE_DECODER;
364 }
365
366 typedef int32_t (*CRYPT_DECODE_ProviderProcessCb)(CRYPT_DECODER_Ctx *decoderCtx, void *args);
367 typedef struct {
368 CRYPT_DECODE_ProviderProcessCb cb;
369 void *args;
370 } CRYPT_DECODE_ProviderProcessArgs;
371
ProcessEachProviderDecoder(CRYPT_EAL_ProvMgrCtx * ctx,void * args)372 static int32_t ProcessEachProviderDecoder(CRYPT_EAL_ProvMgrCtx *ctx, void *args)
373 {
374 CRYPT_DECODE_ProviderProcessArgs *processArgs = (CRYPT_DECODE_ProviderProcessArgs *)args;
375 CRYPT_DECODER_Ctx *decoderCtx = NULL;
376 CRYPT_EAL_AlgInfo *algInfos = NULL;
377 int32_t ret;
378
379 if (ctx == NULL || args == NULL) {
380 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
381 return CRYPT_NULL_INPUT;
382 }
383
384 ret = CRYPT_EAL_ProviderQuery(ctx, CRYPT_EAL_OPERAID_DECODER, &algInfos);
385 if (ret == CRYPT_NOT_SUPPORT) {
386 return CRYPT_SUCCESS;
387 }
388 if (ret != CRYPT_SUCCESS) {
389 BSL_ERR_PUSH_ERROR(ret);
390 return ret;
391 }
392
393 for (int32_t i = 0; algInfos != NULL && algInfos[i].algId != 0; i++) {
394 decoderCtx = CRYPT_DECODE_NewDecoderCtxByMethod(algInfos[i].implFunc, ctx, algInfos[i].attr);
395 if (decoderCtx == NULL) {
396 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
397 return CRYPT_MEM_ALLOC_FAIL;
398 }
399 ret = processArgs->cb(decoderCtx, processArgs->args);
400 if (ret != CRYPT_SUCCESS) {
401 CRYPT_DECODE_Free(decoderCtx);
402 BSL_ERR_PUSH_ERROR(ret);
403 return ret;
404 }
405 }
406
407 return CRYPT_SUCCESS;
408 }
409
CRYPT_DECODE_ProviderProcessAll(CRYPT_EAL_LibCtx * ctx,CRYPT_DECODE_ProviderProcessCb cb,void * args)410 int32_t CRYPT_DECODE_ProviderProcessAll(CRYPT_EAL_LibCtx *ctx, CRYPT_DECODE_ProviderProcessCb cb, void *args)
411 {
412 if (cb == NULL) {
413 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
414 return CRYPT_NULL_INPUT;
415 }
416 CRYPT_DECODE_ProviderProcessArgs processArgs = {
417 .cb = cb,
418 .args = args
419 };
420 int32_t ret = CRYPT_EAL_ProviderProcessAll(ctx, ProcessEachProviderDecoder, &processArgs);
421 if (ret != CRYPT_SUCCESS) {
422 return ret;
423 }
424
425 return CRYPT_SUCCESS;
426 }
427
CRYPT_DECODE_PoolDecode(CRYPT_DECODER_PoolCtx * poolCtx,const BSL_Param * inParam,BSL_Param ** outParam)428 int32_t CRYPT_DECODE_PoolDecode(CRYPT_DECODER_PoolCtx *poolCtx, const BSL_Param *inParam, BSL_Param **outParam)
429 {
430 if (poolCtx == NULL || inParam == NULL || outParam == NULL) {
431 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
432 return CRYPT_NULL_INPUT;
433 }
434 if (*outParam != NULL) {
435 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
436 return CRYPT_INVALID_ARG;
437 }
438 int32_t ret = CRYPT_DECODE_ProviderProcessAll(poolCtx->libCtx, CollectDecoder, poolCtx);
439 if (ret != CRYPT_SUCCESS) {
440 return ret;
441 }
442 if (BSL_LIST_COUNT(poolCtx->decoders) == 0) {
443 BSL_ERR_PUSH_ERROR(CRYPT_DECODE_ERR_NO_DECODER);
444 return CRYPT_DECODE_ERR_NO_DECODER;
445 }
446 CRYPT_DECODER_Node *initialNode = CreateDecoderNode(poolCtx->inputFormat, poolCtx->inputType,
447 poolCtx->targetFormat, poolCtx->targetType, inParam);
448 if (initialNode == NULL) {
449 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
450 return CRYPT_MEM_ALLOC_FAIL;
451 }
452 ret = BSL_LIST_AddElement(poolCtx->decoderPath, initialNode, BSL_LIST_POS_END);
453 if (ret != CRYPT_SUCCESS) {
454 BSL_SAL_Free(initialNode);
455 BSL_ERR_PUSH_ERROR(ret);
456 return ret;
457 }
458 return DecodeWithKeyChain(poolCtx, outParam);
459 }
460
461 #endif /* HITLS_CRYPTO_CODECS && HITLS_CRYPTO_PROVIDER */
462