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 #ifndef CRYPT_UTILS_H
17 #define CRYPT_UTILS_H
18
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <stdbool.h>
22 #include "bsl_err_internal.h"
23 #include "crypt_errno.h"
24 #include "crypt_algid.h"
25 #include "crypt_local_types.h"
26
27 #ifdef __cplusplus
28 extern "C" {
29 #endif // __cplusplus
30
31 #if defined(__GNUC__) || defined(__clang__)
32 #define LIKELY(x) __builtin_expect(!!(x), 1)
33 #define UNLIKELY(x) __builtin_expect(!!(x), 0)
34 #define ALIGN32 __attribute__((aligned(32)))
35 #define ALIGN64 __attribute__((aligned(64)))
36 #else
37 #define LIKELY(x) x
38 #define UNLIKELY(x) x
39 #define ALIGN32
40 #define ALIGN64
41 #endif
42
43 #define BITS_PER_BYTE 8
44 #define SHIFTS_PER_BYTE 3
45 #define BITSIZE(t) (sizeof(t) * BITS_PER_BYTE)
46
47 #define PUT_UINT32_BE(v, p, i) \
48 do { \
49 (p)[(i) + 0] = (uint8_t)((v) >> 24); \
50 (p)[(i) + 1] = (uint8_t)((v) >> 16); \
51 (p)[(i) + 2] = (uint8_t)((v) >> 8); \
52 (p)[(i) + 3] = (uint8_t)((v) >> 0); \
53 } while (0)
54
55 #define PUT_UINT64_BE(v, p, i) \
56 do { \
57 (p)[(i) + 0] = (uint8_t)((v) >> 56); \
58 (p)[(i) + 1] = (uint8_t)((v) >> 48); \
59 (p)[(i) + 2] = (uint8_t)((v) >> 40); \
60 (p)[(i) + 3] = (uint8_t)((v) >> 32); \
61 (p)[(i) + 4] = (uint8_t)((v) >> 24); \
62 (p)[(i) + 5] = (uint8_t)((v) >> 16); \
63 (p)[(i) + 6] = (uint8_t)((v) >> 8); \
64 (p)[(i) + 7] = (uint8_t)((v) >> 0); \
65 } while (0)
66
67 #define GET_UINT32_BE(p, i) \
68 ( \
69 ((uint32_t)(p)[(i) + 0] << 24) | \
70 ((uint32_t)(p)[(i) + 1] << 16) | \
71 ((uint32_t)(p)[(i) + 2] << 8) | \
72 ((uint32_t)(p)[(i) + 3] << 0) \
73 )
74
75 #define PUT_UINT32_LE(v, p, i) \
76 do { \
77 (p)[(i) + 3] = (uint8_t)((v) >> 24); \
78 (p)[(i) + 2] = (uint8_t)((v) >> 16); \
79 (p)[(i) + 1] = (uint8_t)((v) >> 8); \
80 (p)[(i) + 0] = (uint8_t)((v) >> 0); \
81 } while (0)
82
83 #define PUT_UINT64_LE(v, p, i) do { \
84 (p)[(i) + 7] = (uint8_t)((v) >> 56); \
85 (p)[(i) + 6] = (uint8_t)((v) >> 48); \
86 (p)[(i) + 5] = (uint8_t)((v) >> 40); \
87 (p)[(i) + 4] = (uint8_t)((v) >> 32); \
88 (p)[(i) + 3] = (uint8_t)((v) >> 24); \
89 (p)[(i) + 2] = (uint8_t)((v) >> 16); \
90 (p)[(i) + 1] = (uint8_t)((v) >> 8); \
91 (p)[(i) + 0] = (uint8_t)((v) >> 0); \
92 } while (0)
93
94 #define GET_UINT64_LE(p, i) \
95 ( \
96 ((uint64_t)(p)[(i) + 7] << 56) | ((uint64_t)(p)[(i) + 6] << 48) | \
97 ((uint64_t)(p)[(i) + 5] << 40) | ((uint64_t)(p)[(i) + 4] << 32) | \
98 ((uint64_t)(p)[(i) + 3] << 24) | ((uint64_t)(p)[(i) + 2] << 16) | \
99 ((uint64_t)(p)[(i) + 1] << 8) | ((uint64_t)(p)[(i) + 0] << 0) \
100 )
101
102
103 /**
104 * Check whether conditions are met. If conditions are met, go to the label EXIT.
105 */
106 #define GOTO_EXIT_IF(condition, ret) \
107 do { \
108 if (condition) { \
109 BSL_ERR_PUSH_ERROR((ret)); \
110 goto EXIT; \
111 } \
112 } while (0)
113
114 /**
115 * Check whether conditions are met. If yes, an error code is returned.
116 */
117 #define RETURN_RET_IF(condition, ret) \
118 do { \
119 if (condition) { \
120 BSL_ERR_PUSH_ERROR(ret); \
121 return ret; \
122 } \
123 } while (0)
124
125 /**
126 * If the return value of func is not CRYPT_SUCCESS, go to the label ERR.
127 */
128 #define GOTO_ERR_IF(func, ret) do { \
129 (ret) = (func); \
130 if ((ret) != CRYPT_SUCCESS) { \
131 BSL_ERR_PUSH_ERROR((ret)); \
132 goto ERR; \
133 } \
134 } while (0)
135
136 #define GOTO_ERR_IF_EX(func, ret) do { \
137 (ret) = (func); \
138 if ((ret) != CRYPT_SUCCESS) { \
139 goto ERR; \
140 } \
141 } while (0)
142
143 /**
144 * Check whether conditions are met. If yes, an error code is returned.
145 */
146 #define RETURN_RET_IF_ERR(func, ret) \
147 do { \
148 (ret) = (func); \
149 if ((ret) != CRYPT_SUCCESS) { \
150 BSL_ERR_PUSH_ERROR((ret)); \
151 return ret; \
152 } \
153 } while (0)
154
155 #define RETURN_RET_IF_ERR_EX(func, ret) \
156 do { \
157 (ret) = (func); \
158 if ((ret) != CRYPT_SUCCESS) { \
159 return ret; \
160 } \
161 } while (0)
162
163 #define BREAK_IF(condition) \
164 do { \
165 if (condition) { \
166 break; \
167 } \
168 } while (0)
169
170 /**
171 * If src is not NULL, then execute the fun function. If the operation fails, go to the label ERR.
172 */
173 #define GOTO_ERR_IF_SRC_NOT_NULL(dest, src, func, ret) \
174 do { \
175 if ((src) != NULL) { \
176 (dest) = (func); \
177 if ((dest) == NULL) { \
178 BSL_ERR_PUSH_ERROR((ret)); \
179 goto ERR; \
180 } \
181 } \
182 } while (0)
183
184 /**
185 * @brief Perform the XOR operation on the data of two arrays.
186 *
187 * @param a [IN] Input data a
188 * @param b [IN] Input data b
189 * @param r [out] Output the result data.
190 * @param len [IN] Output result data length
191 */
192 #define DATA_XOR(a, b, r, len) \
193 do { \
194 uint32_t subscript; \
195 for (subscript = 0; subscript < (len); subscript++) { \
196 (r)[subscript] = (a)[subscript] ^ (b)[subscript]; \
197 } \
198 } while (0)
199
200 /**
201 * @brief Perform the XOR operation on the data of 32 bits in two arrays each time.
202 * Ensure that the input and output are integer multiples of 32 bits.
203 * Type conversion is performed only when the address is 4-byte aligned.
204 *
205 * @param a [IN] Input data a
206 * @param b [IN] Input data b
207 * @param r [out] Output the result data.
208 * @param len [IN] Output result data length
209 */
210 #define DATA32_XOR(a, b, r, len) \
211 do { \
212 uint32_t ii; \
213 uintptr_t aPtr = (uintptr_t)(a); \
214 uintptr_t bPtr = (uintptr_t)(b); \
215 uintptr_t rPtr = (uintptr_t)(r); \
216 if (((aPtr & 0x3) != 0) || ((bPtr & 0x3) != 0) || ((rPtr & 0x3) != 0)) { \
217 for (ii = 0; ii < (len); ii++) { \
218 (r)[ii] = (a)[ii] ^ (b)[ii]; \
219 } \
220 } else { \
221 for (ii = 0; ii < (len); ii += 4) { \
222 *(uint32_t *)((r) + ii) = (*(const uint32_t *)((a) + ii)) ^ (*(const uint32_t *)((b) + ii)); \
223 } \
224 } \
225 } while (0)
226
227 /**
228 * @brief Perform the XOR operation on 64 bits of data in two arrays each time.
229 * Ensure that the input and output are integer multiples of 64 bits.
230 * Type conversion is performed only when the address is 8-byte aligned.
231 *
232 * @param a [IN] Input data a
233 * @param b [IN] Input data b
234 * @param r [out] Output the result data.
235 * @param len [IN] Output result data length
236 */
237 #define DATA64_XOR(a, b, r, len) \
238 do { \
239 uint32_t ii; \
240 uintptr_t aPtr = (uintptr_t)(a); \
241 uintptr_t bPtr = (uintptr_t)(b); \
242 uintptr_t rPtr = (uintptr_t)(r); \
243 if (((aPtr & 0x7) != 0) || ((bPtr & 0x7) != 0) || ((rPtr & 0x7) != 0)) { \
244 for (ii = 0; ii < (len); ii++) { \
245 (r)[ii] = (a)[ii] ^ (b)[ii]; \
246 } \
247 } else { \
248 for (ii = 0; ii < (len); ii += 8) { \
249 *(uint64_t *)((r) + ii) = (*(const uint64_t *)((a) + ii)) ^ (*(const uint64_t *)((b) + ii)); \
250 } \
251 } \
252 } while (0)
253
254 /**
255 * @brief Calculate the hash value of the input data.
256 *
257 * @param hashMethod [IN] Hash method
258 * @param hashData [IN] Hash data
259 * @param size [IN] Size of hash data
260 * @param out [OUT] Output hash value
261 */
262 int32_t CRYPT_CalcHash(const EAL_MdMethod *hashMethod, const CRYPT_ConstData *hashData, uint32_t size,
263 uint8_t *out, uint32_t *outlen);
264
265 /**
266 * @ingroup rsa
267 * @brief mgf1 of PKCS1
268 *
269 * @param hashMethod [IN] Hash method
270 * @param seed [IN] Seed
271 * @param seedLen [IN] Seed length
272 * @param mask [OUT] Mask
273 * @param maskLen [IN] Mask length
274 *
275 * @retval CRYPT_SUCCESS on success
276 */
277 int32_t CRYPT_Mgf1(const EAL_MdMethod *hashMethod, const uint8_t *seed, const uint32_t seedLen,
278 uint8_t *mask, uint32_t maskLen);
279
280 /**
281 * @brief Retrieves the process function callback and its arguments from a parameter list.
282 *
283 * @param params A pointer to the BSL_Param list containing the parameters.
284 * @param processCb A pointer to a pointer to the process function callback.
285 * @param args A pointer to a pointer to the process function arguments.
286 * @return int32_t Returns CRYPT_SUCCESS if the operation is successful, otherwise an error code.
287 */
288 int32_t CRYPT_GetPkeyProcessParams(BSL_Param *params, CRYPT_EAL_ProcessFuncCb *processCb, void **args);
289
290 /* Assumes that x is uint32_t and 0 < n < 32 */
291 #define ROTL32(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
292
293 #define ROTR64(x, n) (((x) << (64 - (n))) | ((x) >> (n))) // Assumes that x is uint64_t and 0 < n < 64
294
295 #define IS_BUF_NON_ZERO(out, outLen) (((out) != NULL) && ((outLen) > 0))
296 #define CRYPT_IS_BUF_NON_ZERO(out, outLen) (((out) != NULL) && ((outLen) > 0))
297 #define CRYPT_CHECK_DATA_INVALID(d) (((d)->data == NULL && (d)->len != 0))
298 #define CRYPT_IsDataNull(d) ((d) == NULL || (d)->data == NULL || (d)->len == 0)
299 #define CRYPT_IN_RANGE(x, range) ((x) >= (range)->min && (x) <= (range)->max)
300 #define CRYPT_CHECK_BUF_INVALID(buf, len) (((buf) == NULL && (len) != 0))
301 #define CRYPT_SWAP32(x) ((((x) & 0xff000000) >> 24) | \
302 (((x) & 0x00ff0000) >> 8) | \
303 (((x) & 0x0000ff00) << 8) | \
304 (((x) & 0x000000ff) << 24))
305 #ifdef HITLS_BIG_ENDIAN
306
307 #define CRYPT_HTONL(x) (x)
308
309 // Interpret p + i as little endian order. The type of p must be uint8_t *.
310 #define GET_UINT32_LE(p, i) \
311 ( \
312 ((uint32_t)((const uint8_t *)(p))[(i) + 3] << 24) | \
313 ((uint32_t)((const uint8_t *)(p))[(i) + 2] << 16) | \
314 ((uint32_t)((const uint8_t *)(p))[(i) + 1] << 8) | \
315 ((uint32_t)((const uint8_t *)(p))[(i) + 0] << 0) \
316 )
317
318 // Convert little-endian order to host order
319 #define CRYPT_LE32TOH(x) CRYPT_SWAP32(x)
320 // Convert host order to little-endian order
321 #define CRYPT_HTOLE32(x) CRYPT_SWAP32(x)
322
323 #else
324
325 #define CRYPT_HTONL(x) CRYPT_SWAP32(x)
326
327 // Interpret p + i as little endian.
328 #define GET_UINT32_LE(p, i) \
329 ( \
330 (((uintptr_t)(p) & 0x7) != 0) ? ((uint32_t)((const uint8_t *)(p))[(i) + 3] << 24) | \
331 ((uint32_t)((const uint8_t *)(p))[(i) + 2] << 16) | \
332 ((uint32_t)((const uint8_t *)(p))[(i) + 1] << 8) | \
333 ((uint32_t)((const uint8_t *)(p))[(i) + 0] << 0) \
334 : (*(uint32_t *)((uint8_t *)(uintptr_t)(p) + (i))) \
335 )
336 // Convert little-endian order to host order
337 #define CRYPT_LE32TOH(x) (x)
338 // Convert host order to little-endian order
339 #define CRYPT_HTOLE32(x) (x)
340
341 #endif
342
343 #ifdef HITLS_BIG_ENDIAN
344
345 // Interpret p + i as little endian. The type of p must be uint8_t *.
346 #define GET_UINT16_LE(p, i) \
347 ( \
348 ((uint16_t)((const uint8_t *)(p))[(i) + 1] << 8) | \
349 ((uint16_t)((const uint8_t *)(p))[(i) + 0] << 0) \
350 )
351 #else
352 // Interpret p + i as little endian.
353 #define GET_UINT16_LE(p, i) \
354 ( \
355 (((uintptr_t)(p) & 0x7) != 0) ? ((uint16_t)((const uint8_t *)(p))[(i) + 1] << 8) | \
356 ((uint16_t)((const uint8_t *)(p))[(i) + 0] << 0) \
357 : (*(uint16_t *)((uint8_t *)(uintptr_t)(p) + (i))) \
358 )
359 #endif
360
361 #define PUT_UINT16_LE(v, p, i) \
362 do \
363 { \
364 (p)[(i) + 1] = (uint8_t)((v) >> 8); \
365 (p)[(i) + 0] = (uint8_t)((v) >> 0); \
366 } while (0)
367
368 /**
369 * 64-bit integer manipulation functions (big endian)
370 */
Uint64FromBeBytes(const uint8_t * bytes)371 static inline uint64_t Uint64FromBeBytes(const uint8_t *bytes)
372 {
373 return (((uint64_t)bytes[0] << 56) |
374 ((uint64_t)bytes[1] << 48) |
375 ((uint64_t)bytes[2] << 40) |
376 ((uint64_t)bytes[3] << 32) |
377 ((uint64_t)bytes[4] << 24) |
378 ((uint64_t)bytes[5] << 16) |
379 ((uint64_t)bytes[6] << 8) |
380 (uint64_t)bytes[7]);
381 }
382
Uint64ToBeBytes(uint64_t v,uint8_t * bytes)383 static inline void Uint64ToBeBytes(uint64_t v, uint8_t *bytes)
384 {
385 bytes[0] = (uint8_t)(v >> 56);
386 bytes[1] = (uint8_t)(v >> 48);
387 bytes[2] = (uint8_t)(v >> 40);
388 bytes[3] = (uint8_t)(v >> 32);
389 bytes[4] = (uint8_t)(v >> 24);
390 bytes[5] = (uint8_t)(v >> 16);
391 bytes[6] = (uint8_t)(v >> 8);
392 bytes[7] = (uint8_t)(v & 0xffu);
393 }
394
395 #if defined(HITLS_CRYPTO_RSA_SIGN) || defined(HITLS_CRYPTO_RSA_VERIFY)
396 uint32_t CRYPT_GetMdSizeById(CRYPT_MD_AlgId id);
397 #endif
398
ParamIdIsValid(uint32_t id,const uint32_t * list,uint32_t num)399 static inline bool ParamIdIsValid(uint32_t id, const uint32_t *list, uint32_t num)
400 {
401 for (uint32_t i = 0; i < num; i++) {
402 if (id == list[i]) {
403 return true;
404 }
405 }
406 return false;
407 }
408
409 typedef uint32_t (*GetUintCallBack)(const void *key);
GetUintCtrl(const void * ctx,void * val,uint32_t len,GetUintCallBack getUint)410 static inline int32_t GetUintCtrl(const void *ctx, void *val, uint32_t len, GetUintCallBack getUint)
411 {
412 if (val == NULL) {
413 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
414 return CRYPT_NULL_INPUT;
415 }
416 if (len != sizeof(uint32_t)) {
417 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
418 return CRYPT_INVALID_ARG;
419 }
420 *(uint32_t *)val = getUint(ctx);
421 return CRYPT_SUCCESS;
422 }
423
424 void GetCpuInstrSupportState(void);
425
426 #ifdef __x86_64__
427 #define CPU_ID_OUT_U32_CNT 4
428 #define EAX_OUT_IDX 0
429 #define EBX_OUT_IDX 1
430 #define ECX_OUT_IDX 2
431 #define EDX_OUT_IDX 3
432
433 /* %eax */
434 #define XCR0_BIT_SSE (1ULL << 1)
435 #define XCR0_BIT_AVX (1ULL << 2)
436 #define XCR0_BIT_OPMASK (1ULL << 5)
437 #define XCR0_BIT_ZMM_LOW (1ULL << 6)
438 #define XCR0_BIT_ZMM_HIGH (1ULL << 7)
439
440 typedef struct {
441 uint32_t code1Out[CPU_ID_OUT_U32_CNT];
442 uint32_t code7Out[CPU_ID_OUT_U32_CNT];
443 bool osSupportAVX; /* input ecx = 0, output edx:eax bit 2 */
444 bool osSupportAVX512; /* input ecx = 0, output edx:eax bit 6 */
445 } CpuInstrSupportState;
446
447 bool IsSupportAES(void);
448 bool IsSupportBMI1(void);
449 bool IsSupportBMI2(void);
450 bool IsSupportADX(void);
451 bool IsSupportAVX(void);
452 bool IsSupportAVX2(void);
453 bool IsSupportSSE(void);
454 bool IsSupportSSE2(void);
455 bool IsSupportSSE3(void);
456 bool IsSupportMOVBE(void);
457 bool IsSupportAVX512F(void);
458 bool IsSupportAVX512VL(void);
459 bool IsSupportAVX512BW(void);
460 bool IsSupportAVX512DQ(void);
461 bool IsSupportXSAVE(void);
462 bool IsSupportOSXSAVE(void);
463 bool IsOSSupportAVX(void);
464 bool IsOSSupportAVX512(void);
465
466 void GetCpuId(uint32_t eax, uint32_t ecx, uint32_t cpuId[CPU_ID_OUT_U32_CNT]);
467
468 #elif defined(__arm__) || defined(__arm) || defined(__aarch64__)
469
470 bool IsSupportAES(void);
471 bool IsSupportPMULL(void);
472 bool IsSupportSHA1(void);
473 bool IsSupportSHA256(void);
474 bool IsSupportNEON(void);
475
476 #if defined(__aarch64__)
477 bool IsSupportSHA512(void);
478 #endif // __aarch64__
479
480 #endif // __arm__ || __arm || __aarch64__
481
482 #ifdef __cplusplus
483 }
484 #endif // __cplusplus
485
486 #endif // CRYPT_UTILS_H
487