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