• 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_BSL_OBJ
18 #include <stddef.h>
19 #include "securec.h"
20 #include "bsl_obj.h"
21 #include "bsl_sal.h"
22 #include "bsl_obj_internal.h"
23 #include "bsl_err_internal.h"
24 #ifdef HITLS_BSL_HASH
25 #include "bsl_hash.h"
26 
27 // Hash table for signature algorithm mappings
28 BSL_HASH_Hash *g_signHashTable = NULL;
29 // Read-write lock for thread-safe access to g_signHashTable
30 static BSL_SAL_ThreadLockHandle g_signHashRwLock = NULL;
31 // Once control for thread-safe initialization
32 static uint32_t g_signHashInitOnce = BSL_SAL_ONCE_INIT;
33 
34 #define BSL_OBJ_SIGN_HASH_BKT_SIZE 64u
35 #endif // HITLS_BSL_HASH
36 
37 typedef struct BslSignIdMap {
38     BslCid signId;
39     BslCid asymId;
40     BslCid hashId;
41 } BSL_SignIdMap;
42 
43 static BSL_SignIdMap g_signIdMap[] = {
44     {BSL_CID_MD5WITHRSA, BSL_CID_RSA, BSL_CID_MD5},
45     {BSL_CID_SHA1WITHRSA, BSL_CID_RSA, BSL_CID_SHA1},
46     {BSL_CID_SHA224WITHRSAENCRYPTION, BSL_CID_RSA, BSL_CID_SHA224},
47     {BSL_CID_SHA256WITHRSAENCRYPTION, BSL_CID_RSA, BSL_CID_SHA256},
48     {BSL_CID_SHA384WITHRSAENCRYPTION, BSL_CID_RSA, BSL_CID_SHA384},
49     {BSL_CID_SHA512WITHRSAENCRYPTION, BSL_CID_RSA, BSL_CID_SHA512},
50     {BSL_CID_RSASSAPSS, BSL_CID_RSA, BSL_CID_UNKNOWN},
51     {BSL_CID_SM3WITHRSAENCRYPTION, BSL_CID_RSA, BSL_CID_SM3},
52     {BSL_CID_DSAWITHSHA1, BSL_CID_DSA, BSL_CID_SHA1},
53     {BSL_CID_DSAWITHSHA224, BSL_CID_DSA, BSL_CID_SHA224},
54     {BSL_CID_DSAWITHSHA256, BSL_CID_DSA, BSL_CID_SHA256},
55     {BSL_CID_DSAWITHSHA384, BSL_CID_DSA, BSL_CID_SHA384},
56     {BSL_CID_DSAWITHSHA512, BSL_CID_DSA, BSL_CID_SHA512},
57     {BSL_CID_ECDSAWITHSHA1, BSL_CID_ECDSA, BSL_CID_SHA1},
58     {BSL_CID_ECDSAWITHSHA224, BSL_CID_ECDSA, BSL_CID_SHA224},
59     {BSL_CID_ECDSAWITHSHA256, BSL_CID_ECDSA, BSL_CID_SHA256},
60     {BSL_CID_ECDSAWITHSHA384, BSL_CID_ECDSA, BSL_CID_SHA384},
61     {BSL_CID_ECDSAWITHSHA512, BSL_CID_ECDSA, BSL_CID_SHA512},
62     {BSL_CID_SM2DSAWITHSM3, BSL_CID_SM2DSA, BSL_CID_SM3},
63     {BSL_CID_SM2DSAWITHSHA1, BSL_CID_SM2DSA, BSL_CID_SHA1},
64     {BSL_CID_SM2DSAWITHSHA256, BSL_CID_SM2DSA, BSL_CID_SHA256},
65     {BSL_CID_ED25519, BSL_CID_ED25519, BSL_CID_SHA512},
66 };
67 
68 #ifdef HITLS_BSL_HASH
FreeBslSignIdMap(void * data)69 static void FreeBslSignIdMap(void *data)
70 {
71     BSL_SignIdMap *signIdMap = (BSL_SignIdMap *)data;
72     BSL_SAL_Free(signIdMap);
73 }
74 
DupBslSignIdMap(void * data,size_t size)75 static void *DupBslSignIdMap(void *data, size_t size)
76 {
77     if (data == NULL || size != sizeof(BSL_SignIdMap)) {
78         BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
79         return NULL;
80     }
81     BSL_SignIdMap *signIdMap = (BSL_SignIdMap *)data;
82     BSL_SignIdMap *newSignIdMap = BSL_SAL_Malloc(sizeof(BSL_SignIdMap));
83     if (newSignIdMap == NULL) {
84         BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
85         return NULL;
86     }
87     newSignIdMap->signId = signIdMap->signId;
88     newSignIdMap->asymId = signIdMap->asymId;
89     newSignIdMap->hashId = signIdMap->hashId;
90     return (void *)newSignIdMap;
91 }
92 
InitSignHashTableOnce(void)93 static void InitSignHashTableOnce(void)
94 {
95     int32_t ret = BSL_SAL_ThreadLockNew(&g_signHashRwLock);
96     if (ret != BSL_SUCCESS) {
97         BSL_ERR_PUSH_ERROR(ret);
98         return;
99     }
100 
101     ListDupFreeFuncPair valueFunc = {DupBslSignIdMap, FreeBslSignIdMap};
102     g_signHashTable = BSL_HASH_Create(BSL_OBJ_SIGN_HASH_BKT_SIZE, NULL, NULL, NULL, &valueFunc);
103     if (g_signHashTable == NULL) {
104         (void)BSL_SAL_ThreadLockFree(g_signHashRwLock);
105         g_signHashRwLock = NULL;
106         BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
107     }
108 }
109 #endif
110 
BSL_OBJ_GetHashIdFromSignId(BslCid signAlg)111 BslCid BSL_OBJ_GetHashIdFromSignId(BslCid signAlg)
112 {
113     if (signAlg == BSL_CID_UNKNOWN) {
114         return BSL_CID_UNKNOWN;
115     }
116 
117     // First, search in the static g_signIdMap table
118     for (uint32_t iter = 0; iter < sizeof(g_signIdMap) / sizeof(BSL_SignIdMap); iter++) {
119         if (signAlg == g_signIdMap[iter].signId) {
120             return g_signIdMap[iter].hashId;
121         }
122     }
123 #ifndef HITLS_BSL_HASH
124     return BSL_CID_UNKNOWN;
125 #else
126     if (g_signHashTable == NULL) {
127         BSL_ERR_PUSH_ERROR(BSL_OBJ_INVALID_HASH_TABLE);
128         return BSL_CID_UNKNOWN;
129     }
130     // Second, search in the dynamic hash table with read lock
131     BSL_SignIdMap *signIdMap = NULL;
132     int32_t ret = BSL_SAL_ThreadReadLock(g_signHashRwLock);
133     if (ret != BSL_SUCCESS) {
134         BSL_ERR_PUSH_ERROR(ret);
135         return BSL_CID_UNKNOWN;
136     }
137     ret = BSL_HASH_At(g_signHashTable, (uintptr_t)signAlg, (uintptr_t *)&signIdMap);
138     BslCid result = (ret == BSL_SUCCESS && signIdMap != NULL) ? signIdMap->hashId : BSL_CID_UNKNOWN;
139     (void)BSL_SAL_ThreadUnlock(g_signHashRwLock);
140 
141     if (ret != BSL_SUCCESS) {
142         BSL_ERR_PUSH_ERROR(BSL_OBJ_ERR_FIND_HASH_TABLE);
143     }
144 
145     return result;
146 #endif
147 }
148 
BSL_OBJ_GetAsymAlgIdFromSignId(BslCid signAlg)149 BslCid BSL_OBJ_GetAsymAlgIdFromSignId(BslCid signAlg)
150 {
151     if (signAlg == BSL_CID_UNKNOWN) {
152         return BSL_CID_UNKNOWN;
153     }
154 
155     // First, search in the static g_signIdMap table
156     for (uint32_t iter = 0; iter < sizeof(g_signIdMap) / sizeof(BSL_SignIdMap); iter++) {
157         if (signAlg == g_signIdMap[iter].signId) {
158             return g_signIdMap[iter].asymId;
159         }
160     }
161 
162 #ifndef HITLS_BSL_HASH
163     return BSL_CID_UNKNOWN;
164 #else
165     if (g_signHashTable == NULL) {
166         BSL_ERR_PUSH_ERROR(BSL_OBJ_INVALID_HASH_TABLE);
167         return BSL_CID_UNKNOWN;
168     }
169     // Second, search in the dynamic hash table with read lock
170     BSL_SignIdMap *signIdMap = NULL;
171     int32_t ret = BSL_SAL_ThreadReadLock(g_signHashRwLock);
172     if (ret != BSL_SUCCESS) {
173         BSL_ERR_PUSH_ERROR(ret);
174         return BSL_CID_UNKNOWN;
175     }
176     ret = BSL_HASH_At(g_signHashTable, (uintptr_t)signAlg, (uintptr_t *)&signIdMap);
177     BslCid asymCid = (ret == BSL_SUCCESS && signIdMap != NULL) ? signIdMap->asymId : BSL_CID_UNKNOWN;
178     (void)BSL_SAL_ThreadUnlock(g_signHashRwLock);
179 
180     if (ret != BSL_SUCCESS) {
181         BSL_ERR_PUSH_ERROR(BSL_OBJ_ERR_FIND_HASH_TABLE);
182     }
183 
184     return asymCid;
185 #endif
186 }
187 
BSL_OBJ_GetSignIdFromHashAndAsymId(BslCid asymAlg,BslCid hashAlg)188 BslCid BSL_OBJ_GetSignIdFromHashAndAsymId(BslCid asymAlg, BslCid hashAlg)
189 {
190     if (asymAlg == BSL_CID_ED25519) {
191         return BSL_CID_ED25519;
192     }
193     if (asymAlg == BSL_CID_UNKNOWN || hashAlg == BSL_CID_UNKNOWN) {
194         return BSL_CID_UNKNOWN;
195     }
196 
197     // First, search in the static g_signIdMap table
198     for (uint32_t i = 0; i < sizeof(g_signIdMap) / sizeof(g_signIdMap[0]); i++) {
199         if (g_signIdMap[i].asymId == asymAlg && g_signIdMap[i].hashId == hashAlg) {
200             return g_signIdMap[i].signId;
201         }
202     }
203 #ifndef HITLS_BSL_HASH
204     return BSL_CID_UNKNOWN;
205 #else
206     if (g_signHashTable == NULL) {
207         BSL_ERR_PUSH_ERROR(BSL_OBJ_INVALID_HASH_TABLE);
208         return BSL_CID_UNKNOWN;
209     }
210 
211     // Second, search in the dynamic hash table with read lock
212     BSL_SignIdMap *signIdMap = NULL;
213     uint64_t asymAndHashKey = ((uint64_t)asymAlg << 32) | ((uint64_t)hashAlg & 0xFFFFFFFF);
214     int32_t ret = BSL_SAL_ThreadReadLock(g_signHashRwLock);
215     if (ret != BSL_SUCCESS) {
216         BSL_ERR_PUSH_ERROR(ret);
217         return BSL_CID_UNKNOWN;
218     }
219     ret = BSL_HASH_At(g_signHashTable, (uintptr_t)asymAndHashKey, (uintptr_t *)&signIdMap);
220     BslCid signCid = (ret == BSL_SUCCESS && signIdMap != NULL) ? signIdMap->signId : BSL_CID_UNKNOWN;
221     (void)BSL_SAL_ThreadUnlock(g_signHashRwLock);
222 
223     if (ret != BSL_SUCCESS) {
224         BSL_ERR_PUSH_ERROR(BSL_OBJ_ERR_FIND_HASH_TABLE);
225     }
226 
227     return signCid;
228 #endif
229 }
230 
231 #ifdef HITLS_BSL_HASH
IsSignIdInStaticTable(int32_t signId)232 static bool IsSignIdInStaticTable(int32_t signId)
233 {
234     for (uint32_t iter = 0; iter < sizeof(g_signIdMap) / sizeof(BSL_SignIdMap); iter++) {
235         if (signId == (int32_t)g_signIdMap[iter].signId) {
236             return true;
237         }
238     }
239     return false;
240 }
241 
IsSignIdInHashTable(int32_t signId)242 static int32_t IsSignIdInHashTable(int32_t signId)
243 {
244     BSL_SignIdMap *signIdMap = NULL;
245     int32_t ret = BSL_SAL_ThreadReadLock(g_signHashRwLock);
246     if (ret != BSL_SUCCESS) {
247         BSL_ERR_PUSH_ERROR(ret);
248         return ret;
249     }
250 
251     ret = BSL_HASH_At(g_signHashTable, (uintptr_t)signId, (uintptr_t *)&signIdMap);
252     (void)BSL_SAL_ThreadUnlock(g_signHashRwLock);
253     if (ret != BSL_SUCCESS || signIdMap == NULL) {
254         BSL_ERR_PUSH_ERROR(BSL_OBJ_ERR_FIND_HASH_TABLE);
255         return BSL_OBJ_ERR_FIND_HASH_TABLE;
256     }
257     return BSL_SUCCESS;
258 }
259 
260 // Inserts a new signature ID mapping into the hash table (using write lock)
InsertSignIdMapping(int32_t signId,int32_t asymId,int32_t hashId)261 static int32_t InsertSignIdMapping(int32_t signId, int32_t asymId, int32_t hashId)
262 {
263     BSL_SignIdMap *signIdMap = NULL;
264     BSL_SignIdMap newSignIdMap = {signId, asymId, hashId};
265     uint64_t asymAndHashKey;
266     int32_t ret = BSL_SAL_ThreadWriteLock(g_signHashRwLock);
267     if (ret != BSL_SUCCESS) {
268         BSL_ERR_PUSH_ERROR(ret);
269         return ret;
270     }
271 
272     ret = BSL_HASH_At(g_signHashTable, (uintptr_t)signId, (uintptr_t *)&signIdMap);
273     if (ret == BSL_SUCCESS && signIdMap != NULL) {
274         (void)BSL_SAL_ThreadUnlock(g_signHashRwLock);
275         return BSL_SUCCESS;
276     }
277     ret = BSL_HASH_Insert(g_signHashTable, (uintptr_t)signId, sizeof(BslCid),
278         (uintptr_t)&newSignIdMap, sizeof(BSL_SignIdMap));
279     if (ret != BSL_SUCCESS) {
280         (void)BSL_SAL_ThreadUnlock(g_signHashRwLock);
281         BSL_ERR_PUSH_ERROR(BSL_OBJ_ERR_INSERT_HASH_TABLE);
282         return BSL_OBJ_ERR_INSERT_HASH_TABLE;
283     }
284     asymAndHashKey = ((uint64_t)asymId << 32) | ((uint64_t)hashId & 0xFFFFFFFF);
285     ret = BSL_HASH_Insert(g_signHashTable, (uintptr_t)asymAndHashKey, sizeof(uintptr_t),
286         (uintptr_t)&newSignIdMap, sizeof(BSL_SignIdMap));
287     if (ret != BSL_SUCCESS) {
288         BSL_HASH_Erase(g_signHashTable, (uintptr_t)signId);
289         (void)BSL_SAL_ThreadUnlock(g_signHashRwLock);
290         BSL_ERR_PUSH_ERROR(BSL_OBJ_ERR_INSERT_HASH_TABLE);
291         return BSL_OBJ_ERR_INSERT_HASH_TABLE;
292     }
293 
294     (void)BSL_SAL_ThreadUnlock(g_signHashRwLock);
295     return BSL_SUCCESS;
296 }
297 
298 // Main function - now more concise
BSL_OBJ_CreateSignId(int32_t signId,int32_t asymId,int32_t hashId)299 int32_t BSL_OBJ_CreateSignId(int32_t signId, int32_t asymId, int32_t hashId)
300 {
301     // Parameter validation
302     if (signId == BSL_CID_UNKNOWN || asymId == BSL_CID_UNKNOWN || hashId == BSL_CID_UNKNOWN) {
303         BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
304         return BSL_INVALID_ARG;
305     }
306 
307     if (IsSignIdInStaticTable(signId)) {
308         return BSL_SUCCESS;
309     }
310 
311     int32_t ret = BSL_SAL_ThreadRunOnce(&g_signHashInitOnce, InitSignHashTableOnce);
312     if (ret != BSL_SUCCESS) {
313         BSL_ERR_PUSH_ERROR(ret);
314         return ret;
315     }
316     if (g_signHashTable == NULL) {
317         BSL_ERR_PUSH_ERROR(BSL_OBJ_INVALID_HASH_TABLE);
318         return BSL_OBJ_INVALID_HASH_TABLE;
319     }
320     ret = IsSignIdInHashTable(signId);
321     if (ret == BSL_SUCCESS) {
322         return BSL_SUCCESS;
323     }
324 
325     return InsertSignIdMapping(signId, asymId, hashId);
326 }
327 
BSL_OBJ_FreeSignHashTable(void)328 void BSL_OBJ_FreeSignHashTable(void)
329 {
330     if (g_signHashTable != NULL) {
331         int32_t ret = BSL_SAL_ThreadWriteLock(g_signHashRwLock);
332         if (ret != BSL_SUCCESS) {
333             BSL_ERR_PUSH_ERROR(ret);
334             return;
335         }
336         BSL_HASH_Destory(g_signHashTable);
337         g_signHashTable = NULL;
338         (void)BSL_SAL_ThreadUnlock(g_signHashRwLock);
339         if (g_signHashRwLock != NULL) {
340             (void)BSL_SAL_ThreadLockFree(g_signHashRwLock);
341             g_signHashRwLock = NULL;
342         }
343         g_signHashInitOnce = BSL_SAL_ONCE_INIT;
344     }
345 }
346 #endif // HITLS_BSL_HASH
347 
348 #endif
349