• 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 #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