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 #ifdef HITLS_CRYPTO_PROVIDER
18
19 #include <string.h>
20 #include "securec.h"
21 #include "bsl_list.h"
22 #include "bsl_err_internal.h"
23 #include "bsl_hash.h"
24 #include "list_base.h"
25 #include "crypt_errno.h"
26
27 #include "crypt_provider.h"
28 #include "crypt_provider_local.h"
29 #include "crypt_eal_provider.h"
30 #include "crypt_eal_implprovider.h"
31
32 #define HISH_SIZE 8
33 #define NOT_EQUAL_SIZE 2
34
35 // Store the information of the input attribute string
36 typedef struct {
37 const char *attribute; // Attribute string
38 BSL_HASH_Hash *hash; // Hash table
39 uint32_t attributeNum; // Number of attributes
40 uint32_t mustAttributeNum; // Number of mandatory attributes
41 bool repeatFlag; // Repeat search flag
42 } InputAttributeStrInfo;
43
44 // Define the data structure for values
45 typedef struct {
46 char *judgeStr; // Judge string
47 char *valueStr; // Value string
48 } AttributeValue;
49
50 // Define a function to free AttributeValue resources
AttributeValueFree(void * ptr)51 static void AttributeValueFree(void *ptr)
52 {
53 if (ptr == NULL) {
54 return;
55 }
56 AttributeValue *value = (AttributeValue *)ptr;
57 BSL_SAL_FREE(value->judgeStr);
58 BSL_SAL_FREE(value->valueStr);
59 BSL_SAL_Free(value);
60 }
61
62 // Define a function to free the value list
FreeValueList(void * ptr)63 static void FreeValueList(void *ptr)
64 {
65 if (ptr == NULL) {
66 return;
67 }
68 BslList *valueList = (BslList *)ptr;
69 BSL_LIST_DeleteAll(valueList, AttributeValueFree);
70 BSL_SAL_FREE(valueList);
71 }
72
73 // Value copy callback function, essentially a function to create a new value list
ValueDupFunc(void * ptr,size_t size)74 static void *ValueDupFunc(void *ptr, size_t size)
75 {
76 if (ptr == NULL || size == 0) {
77 return NULL;
78 }
79
80 int32_t ret;
81 AttributeValue *srcValue = (AttributeValue *)ptr;
82 BslList *newList = BSL_LIST_New(sizeof(AttributeValue));
83 if (newList == NULL) {
84 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
85 return NULL;
86 }
87
88 AttributeValue *newValue = BSL_SAL_Calloc(1, sizeof(AttributeValue));
89 if (newValue == NULL) {
90 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
91 goto ERR;
92 }
93
94 newValue->judgeStr = BSL_SAL_Dump(srcValue->judgeStr, BSL_SAL_Strnlen(srcValue->judgeStr, UINT32_MAX) + 1);
95 newValue->valueStr = BSL_SAL_Dump(srcValue->valueStr, BSL_SAL_Strnlen(srcValue->valueStr, UINT32_MAX) + 1);
96
97 if (newValue->judgeStr == NULL || newValue->valueStr == NULL) {
98 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
99 goto ERR;
100 }
101
102 ret = BSL_LIST_AddElement(newList, newValue, BSL_LIST_POS_END);
103 if (ret != BSL_SUCCESS) {
104 BSL_ERR_PUSH_ERROR(ret);
105 goto ERR;
106 }
107
108 return newList;
109
110 ERR:
111 AttributeValueFree(newValue);
112 BSL_SAL_Free(newList);
113 return NULL;
114 }
115
116 // Key copy callback function
KeyDupFunc(void * ptr,size_t size)117 static void *KeyDupFunc(void *ptr, size_t size)
118 {
119 if (ptr == NULL || size == 0) {
120 return NULL;
121 }
122 return BSL_SAL_Dump(ptr, size);
123 }
124
125 // Key release callback function
KeyFreeFunc(void * ptr)126 static void KeyFreeFunc(void *ptr)
127 {
128 BSL_SAL_FREE(ptr);
129 }
130
131 // Implement the BSL_HASH_UpdateNodeFunc callback function for BSL_HASH_Put to call
UpdateAttributeValueNode(BSL_HASH_Hash * hash,BSL_HASH_Iterator node,uintptr_t value,uint32_t valueSize)132 static int32_t UpdateAttributeValueNode(BSL_HASH_Hash *hash, BSL_HASH_Iterator node,
133 uintptr_t value, uint32_t valueSize)
134 {
135 if (hash == NULL || valueSize == 0) {
136 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
137 return CRYPT_INVALID_ARG;
138 }
139 AttributeValue *srcValue = (AttributeValue *)value;
140 AttributeValue *newValue = BSL_SAL_Calloc(1, sizeof(AttributeValue));
141 if (newValue == NULL) {
142 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
143 return CRYPT_MEM_ALLOC_FAIL;
144 }
145 newValue->judgeStr = BSL_SAL_Dump(srcValue->judgeStr, BSL_SAL_Strnlen(srcValue->judgeStr, UINT32_MAX) + 1);
146 newValue->valueStr = BSL_SAL_Dump(srcValue->valueStr, BSL_SAL_Strnlen(srcValue->valueStr, UINT32_MAX) + 1);
147 if (newValue->judgeStr == NULL || newValue->valueStr == NULL) {
148 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
149 AttributeValueFree(newValue);
150 return CRYPT_MEM_ALLOC_FAIL;
151 }
152
153 BslList *valueList = (BslList *)BSL_HASH_IterValue(hash, node);
154 int32_t ret = BSL_LIST_AddElement(valueList, (AttributeValue *)newValue, BSL_LIST_POS_END);
155 if (ret != BSL_SUCCESS) {
156 BSL_ERR_PUSH_ERROR(ret);
157 AttributeValueFree(newValue);
158 }
159 return ret;
160 }
161
162 // Get key-value pair positions
GetAttributePositions(const char * attribute,int32_t start,int32_t * keyStart,int32_t * keyEnd,int32_t * judgeStart,int32_t * judgeEnd,int32_t * valueStart,int32_t * valueEnd)163 static int32_t GetAttributePositions(const char *attribute, int32_t start, int32_t *keyStart, int32_t *keyEnd,
164 int32_t *judgeStart, int32_t *judgeEnd, int32_t *valueStart, int32_t *valueEnd)
165 {
166 int32_t temp = start;
167 *keyStart = *keyEnd = *judgeStart = *judgeEnd = *valueStart = *valueEnd = temp;
168
169 // Find key
170 while (attribute[temp] != '\0' && attribute[temp] != '=' && attribute[temp] != '?' && attribute[temp] != '!') {
171 temp++;
172 }
173 *keyEnd = temp;
174 if (*keyEnd <= *keyStart) {
175 return CRYPT_PROVIDER_ERR_ATTRIBUTE;
176 }
177
178 // Find judge string
179 *judgeStart = temp;
180 if (attribute[temp] == '!' && attribute[temp + 1] == '=') {
181 temp = temp + NOT_EQUAL_SIZE;
182 } else if (attribute[temp] == '=' || attribute[temp] == '?') {
183 temp++;
184 } else {
185 return CRYPT_PROVIDER_ERR_ATTRIBUTE;
186 }
187 *judgeEnd = temp;
188 if (*judgeEnd <= *judgeStart) {
189 return CRYPT_PROVIDER_ERR_ATTRIBUTE;
190 }
191
192 // Find value
193 *valueStart = temp;
194 while (attribute[temp] != '\0' && attribute[temp] != ',') {
195 temp++;
196 }
197 *valueEnd = temp;
198 if (*valueEnd <= *valueStart) {
199 return CRYPT_PROVIDER_ERR_ATTRIBUTE;
200 }
201
202 return CRYPT_SUCCESS;
203 }
204
ParseAttributeValue(const char * attribute,int32_t * startPos,char ** key,AttributeValue ** value)205 static int32_t ParseAttributeValue(const char *attribute, int32_t *startPos, char **key, AttributeValue **value)
206 {
207 int32_t start = *startPos;
208 char *tempKey = NULL;
209 AttributeValue *tempValue = NULL;
210
211 // Call the sub-function to get key-value pair positions
212 int32_t keyStart, keyEnd, judgeStart, judgeEnd, valueStart, valueEnd;
213 int32_t ret = GetAttributePositions(attribute, start, &keyStart, &keyEnd, &judgeStart, &judgeEnd, &valueStart, &valueEnd);
214 if (ret != CRYPT_SUCCESS) {
215 return ret;
216 }
217
218 int32_t keyLen = keyEnd - keyStart;
219 int32_t judgeLen = judgeEnd - judgeStart;
220 int32_t valueLen = valueEnd - valueStart;
221
222 // Allocate space for keys and values
223 tempValue = BSL_SAL_Calloc(1, sizeof(AttributeValue));
224 if (tempValue == NULL) {
225 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
226 return CRYPT_MEM_ALLOC_FAIL;
227 }
228 tempKey = BSL_SAL_Calloc(1, keyLen + 1);
229 tempValue->judgeStr = BSL_SAL_Calloc(1, judgeLen + 1);
230 tempValue->valueStr = BSL_SAL_Calloc(1, valueLen + 1);
231 if (tempKey == NULL || tempValue->judgeStr == NULL || tempValue->valueStr == NULL) {
232 ret = CRYPT_MEM_ALLOC_FAIL;
233 BSL_ERR_PUSH_ERROR(ret);
234 goto ERR;
235 }
236
237 // Copy the string corresponding to the key and value
238 if (memcpy_s(tempKey, keyLen + 1, attribute + keyStart, keyLen) != EOK ||
239 memcpy_s(tempValue->judgeStr, judgeLen + 1, attribute + judgeStart, judgeLen) != EOK ||
240 memcpy_s(tempValue->valueStr, valueLen + 1, attribute + valueStart, valueLen) != EOK) {
241 ret = CRYPT_SECUREC_FAIL;
242 BSL_ERR_PUSH_ERROR(ret);
243 goto ERR;
244 }
245
246 *startPos = attribute[valueEnd] == '\0'? valueEnd : valueEnd + 1;
247 *key = tempKey;
248 *value = tempValue;
249 return CRYPT_SUCCESS;
250
251 ERR:
252 BSL_SAL_FREE(tempKey);
253 AttributeValueFree(tempValue);
254 return ret;
255 }
256
ParseAttributeString(InputAttributeStrInfo * attrInfo)257 static int32_t ParseAttributeString(InputAttributeStrInfo *attrInfo)
258 {
259 int32_t ret;
260 const char *attribute = attrInfo->attribute;
261 BSL_HASH_Hash *hash = NULL;
262 int32_t startPos = 0;
263 char *key = NULL;
264 AttributeValue *value = NULL;
265 uint32_t tempMustAttributeNum = 0, tempAttributeNum = 0;
266
267 ListDupFreeFuncPair keyFunc = {KeyDupFunc, KeyFreeFunc};
268 ListDupFreeFuncPair valueFunc = {ValueDupFunc, FreeValueList};
269
270 // Create a hash table with a bucket size of 8
271 hash = BSL_HASH_Create(HISH_SIZE, BSL_HASH_CodeCalcStr, BSL_HASH_MatchStr, &keyFunc, &valueFunc);
272 if (hash == NULL) {
273 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
274 return CRYPT_MEM_ALLOC_FAIL;
275 }
276
277 while (attribute[startPos] != '\0') {
278 // Extract a key-value pair
279 ret = ParseAttributeValue(attribute, &startPos, &key, &value);
280 // An unknown error occurred during the lookup
281 if (ret != CRYPT_SUCCESS) {
282 BSL_HASH_Destory(hash);
283 return ret;
284 }
285
286 tempAttributeNum++;
287 if (value->judgeStr[0] == '=' || value->judgeStr[0] == '!') {
288 tempMustAttributeNum++;
289 }
290
291 ret = BSL_HASH_Put(hash, (uintptr_t)key, BSL_SAL_Strnlen(key, UINT32_MAX)+1,
292 (uintptr_t)value, sizeof(AttributeValue), UpdateAttributeValueNode);
293 BSL_SAL_FREE(key);
294 AttributeValueFree(value);
295 if (ret != BSL_SUCCESS) {
296 BSL_ERR_PUSH_ERROR(ret);
297 BSL_HASH_Destory(hash);
298 return ret;
299 }
300 }
301 if (tempAttributeNum == 0) {
302 BSL_ERR_PUSH_ERROR(CRYPT_PROVIDER_ERR_ATTRIBUTE);
303 BSL_HASH_Destory(hash);
304 return CRYPT_PROVIDER_ERR_ATTRIBUTE;
305 }
306 attrInfo->attributeNum = tempAttributeNum;
307 attrInfo->mustAttributeNum = tempMustAttributeNum;
308 attrInfo->hash = hash;
309 return CRYPT_SUCCESS;
310 }
311
CompareAttributeValue(AttributeValue * value,AttributeValue * hashValue,uint32_t * comparedCount,uint32_t * satisfiedMustCount,int32_t * totalScore)312 static int32_t CompareAttributeValue(AttributeValue *value, AttributeValue *hashValue,
313 uint32_t *comparedCount, uint32_t *satisfiedMustCount, int32_t *totalScore)
314 {
315 if (hashValue->judgeStr[0] == '=') {
316 if (strcmp(value->valueStr, hashValue->valueStr) == 0) {
317 (*comparedCount)++;
318 (*satisfiedMustCount)++;
319 } else {
320 return -1;
321 }
322 } else if (hashValue->judgeStr[0] == '!' && hashValue->judgeStr[1] == '=') {
323 if (strcmp(value->valueStr, hashValue->valueStr) != 0) {
324 (*comparedCount)++;
325 (*satisfiedMustCount)++;
326 } else {
327 return -1;
328 }
329 } else if (hashValue->judgeStr[0] == '?') {
330 (*comparedCount)++;
331 if (strcmp(value->valueStr, hashValue->valueStr) == 0) {
332 (*totalScore)++;
333 }
334 }
335 return 0;
336 }
337
CompareAttribute(BSL_HASH_Hash * hash,const char * attribute,uint32_t mustAttributeNum,uint32_t attributeNum)338 static int32_t CompareAttribute(BSL_HASH_Hash *hash, const char *attribute,
339 uint32_t mustAttributeNum, uint32_t attributeNum)
340 {
341 int32_t ret;
342 int32_t startPos = 0;
343 char *key = NULL;
344 AttributeValue *value = NULL;
345 uint32_t comparedCount = 0;
346 uint32_t satisfiedMustCount = 0;
347 int32_t totalScore = 0;
348
349 while (attribute[startPos] != '\0') {
350 ret = ParseAttributeValue(attribute, &startPos, &key, &value);
351 if (ret != CRYPT_SUCCESS) {
352 break;
353 }
354
355 BSL_HASH_Iterator it = BSL_HASH_Find(hash, (uintptr_t)key);
356 if (it == BSL_HASH_IterEnd(hash)) {
357 BSL_SAL_Free(key);
358 AttributeValueFree(value);
359 continue;
360 }
361 BslList *valueList = (BslList *)BSL_HASH_IterValue(hash, it);
362 for (void *listValue = BSL_LIST_GET_FIRST(valueList);
363 listValue != NULL; listValue = BSL_LIST_GET_NEXT(valueList)) {
364 AttributeValue *hashValue = (AttributeValue *)listValue;
365 ret = CompareAttributeValue(value, hashValue, &comparedCount,
366 &satisfiedMustCount, &totalScore);
367 if (ret == -1) {
368 BSL_SAL_Free(key);
369 AttributeValueFree(value);
370 return -1;
371 }
372
373 if (comparedCount == attributeNum) {
374 BSL_SAL_Free(key);
375 AttributeValueFree(value);
376 return (satisfiedMustCount < mustAttributeNum) ? -1 : totalScore;
377 }
378 }
379
380 BSL_SAL_Free(key);
381 AttributeValueFree(value);
382 }
383
384 if (satisfiedMustCount < mustAttributeNum) {
385 return -1;
386 }
387
388 return totalScore;
389 }
390
FindHighestScoreFunc(CRYPT_EAL_LibCtx * localCtx,int32_t operaId,int32_t algId,InputAttributeStrInfo attrInfo,const CRYPT_EAL_Func ** implFunc,CRYPT_EAL_ProvMgrCtx ** mgrCtx)391 static void FindHighestScoreFunc(CRYPT_EAL_LibCtx *localCtx, int32_t operaId, int32_t algId,
392 InputAttributeStrInfo attrInfo, const CRYPT_EAL_Func **implFunc, CRYPT_EAL_ProvMgrCtx **mgrCtx)
393 {
394 int32_t ret;
395 int32_t totalScore = -1;
396 int32_t index = 0;
397 const char *attribute = attrInfo.attribute;
398 BSL_HASH_Hash *hash = attrInfo.hash;
399 uint32_t attributeNum = attrInfo.attributeNum;
400 uint32_t mustAttributeNum = attrInfo.mustAttributeNum;
401 uint32_t repeatFlag = attrInfo.repeatFlag;
402
403 CRYPT_EAL_ProvMgrCtx *node = BSL_LIST_GET_FIRST(localCtx->providers);
404 for (; node!= NULL; node = BSL_LIST_GET_NEXT(localCtx->providers)) {
405 CRYPT_EAL_AlgInfo *algInfos = NULL;
406 ret = node->provQueryCb(node->provCtx, operaId, &algInfos);
407 if (ret != CRYPT_SUCCESS) {
408 continue;
409 }
410 for (index = 0; algInfos != NULL && algInfos[index].algId != 0; index++) {
411 if (algInfos[index].algId != algId) {
412 continue;
413 }
414 if (attribute == NULL) {
415 *implFunc = algInfos[index].implFunc;
416 *mgrCtx = node;
417 return;
418 }
419 int32_t tempScore;
420 tempScore = CompareAttribute(hash, algInfos[index].attr, mustAttributeNum, attributeNum);
421 if (tempScore <= totalScore) {
422 continue;
423 }
424 totalScore = tempScore;
425 *implFunc = algInfos[index].implFunc;
426 *mgrCtx = node;
427 if (repeatFlag) {
428 continue;
429 }
430 return;
431 }
432 }
433 }
434
CRYPT_EAL_CompareAlgAndAttr(CRYPT_EAL_LibCtx * localCtx,int32_t operaId,int32_t algId,const char * attribute,const CRYPT_EAL_Func ** funcs,CRYPT_EAL_ProvMgrCtx ** mgrCtx)435 int32_t CRYPT_EAL_CompareAlgAndAttr(CRYPT_EAL_LibCtx *localCtx, int32_t operaId,
436 int32_t algId, const char *attribute, const CRYPT_EAL_Func **funcs, CRYPT_EAL_ProvMgrCtx **mgrCtx)
437 {
438 int32_t ret;
439 const CRYPT_EAL_Func *implFunc = NULL;
440 CRYPT_EAL_ProvMgrCtx *ctx = NULL;
441 InputAttributeStrInfo attrInfo = {0};
442
443 if (attribute != NULL) {
444 attrInfo.attribute = attribute;
445 ret = ParseAttributeString(&attrInfo);
446 if (ret != BSL_SUCCESS) {
447 return ret;
448 }
449 attrInfo.repeatFlag = (attrInfo.attributeNum != attrInfo.mustAttributeNum) ? true : false;
450 }
451 ret = BSL_SAL_ThreadWriteLock(localCtx->lock);
452 if (ret != BSL_SUCCESS) {
453 BSL_ERR_PUSH_ERROR(ret);
454 BSL_HASH_Destory(attrInfo.hash);
455 return ret;
456 }
457
458 FindHighestScoreFunc(localCtx, operaId, algId, attrInfo, &implFunc, &ctx);
459
460 BSL_SAL_ThreadUnlock(localCtx->lock);
461 BSL_HASH_Destory(attrInfo.hash);
462 if (implFunc == NULL) {
463 BSL_ERR_PUSH_ERROR(CRYPT_NOT_SUPPORT);
464 return CRYPT_NOT_SUPPORT;
465 }
466 *funcs = implFunc;
467 if (mgrCtx != NULL) {
468 *mgrCtx = ctx;
469 }
470 return CRYPT_SUCCESS;
471 }
472
473 #endif // HITLS_CRYPTO_PROVIDER
474