Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2021-2025 DMTF. All rights reserved.
4 : * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
5 : **/
6 :
7 : #include "internal/libspdm_crypt_lib.h"
8 : #include "library/spdm_common_lib.h"
9 :
10 : typedef struct {
11 : bool is_requester;
12 : uint8_t op_code;
13 : const void *context;
14 : size_t context_size;
15 : size_t zero_pad_size;
16 : } libspdm_signing_context_str_t;
17 :
18 : static const libspdm_signing_context_str_t m_libspdm_signing_context_str_table[] = {
19 : {false, SPDM_CHALLENGE_AUTH, SPDM_CHALLENGE_AUTH_SIGN_CONTEXT,
20 : SPDM_CHALLENGE_AUTH_SIGN_CONTEXT_SIZE, 36 - SPDM_CHALLENGE_AUTH_SIGN_CONTEXT_SIZE},
21 : {true, SPDM_CHALLENGE_AUTH, SPDM_MUT_CHALLENGE_AUTH_SIGN_CONTEXT,
22 : SPDM_MUT_CHALLENGE_AUTH_SIGN_CONTEXT_SIZE, 36 - SPDM_MUT_CHALLENGE_AUTH_SIGN_CONTEXT_SIZE},
23 : {false, SPDM_MEASUREMENTS, SPDM_MEASUREMENTS_SIGN_CONTEXT, SPDM_MEASUREMENTS_SIGN_CONTEXT_SIZE,
24 : 36 - SPDM_MEASUREMENTS_SIGN_CONTEXT_SIZE},
25 : {false, SPDM_KEY_EXCHANGE_RSP, SPDM_KEY_EXCHANGE_RESPONSE_SIGN_CONTEXT,
26 : SPDM_KEY_EXCHANGE_RESPONSE_SIGN_CONTEXT_SIZE,
27 : 36 - SPDM_KEY_EXCHANGE_RESPONSE_SIGN_CONTEXT_SIZE},
28 : {true, SPDM_FINISH, SPDM_FINISH_SIGN_CONTEXT, SPDM_FINISH_SIGN_CONTEXT_SIZE,
29 : 36 - SPDM_FINISH_SIGN_CONTEXT_SIZE},
30 : {false, SPDM_ENDPOINT_INFO, SPDM_ENDPOINT_INFO_SIGN_CONTEXT,
31 : SPDM_ENDPOINT_INFO_SIGN_CONTEXT_SIZE,
32 : 36 - SPDM_ENDPOINT_INFO_SIGN_CONTEXT_SIZE},
33 : {true, SPDM_ENDPOINT_INFO, SPDM_MUT_ENDPOINT_INFO_SIGN_CONTEXT,
34 : SPDM_MUT_ENDPOINT_INFO_SIGN_CONTEXT_SIZE, 36 - SPDM_MUT_ENDPOINT_INFO_SIGN_CONTEXT_SIZE},
35 : };
36 :
37 : #if LIBSPDM_RSA_SSA_SUPPORT
38 36 : static bool libspdm_rsa_pkcs1_sign_with_nid_wrap (void *context, size_t hash_nid,
39 : const uint8_t *param, size_t param_size,
40 : const uint8_t *message,
41 : size_t message_size, uint8_t *signature,
42 : size_t *sig_size)
43 : {
44 36 : return libspdm_rsa_pkcs1_sign_with_nid (context, hash_nid,
45 : message, message_size, signature, sig_size);
46 : }
47 : #endif
48 :
49 : #if LIBSPDM_RSA_PSS_SUPPORT
50 0 : static bool libspdm_rsa_pss_sign_wrap (void *context, size_t hash_nid,
51 : const uint8_t *param, size_t param_size,
52 : const uint8_t *message,
53 : size_t message_size, uint8_t *signature,
54 : size_t *sig_size)
55 : {
56 0 : return libspdm_rsa_pss_sign (context, hash_nid,
57 : message, message_size, signature, sig_size);
58 : }
59 : #endif
60 :
61 : #if LIBSPDM_ECDSA_SUPPORT
62 140 : static bool libspdm_ecdsa_sign_wrap (void *context, size_t hash_nid,
63 : const uint8_t *param, size_t param_size,
64 : const uint8_t *message,
65 : size_t message_size, uint8_t *signature,
66 : size_t *sig_size)
67 : {
68 140 : return libspdm_ecdsa_sign (context, hash_nid,
69 : message, message_size, signature, sig_size);
70 : }
71 : #endif
72 :
73 : #if (LIBSPDM_EDDSA_ED25519_SUPPORT) || (LIBSPDM_EDDSA_ED448_SUPPORT)
74 : static bool libspdm_eddsa_sign_wrap (void *context, size_t hash_nid,
75 : const uint8_t *param, size_t param_size,
76 : const uint8_t *message,
77 : size_t message_size, uint8_t *signature,
78 : size_t *sig_size)
79 : {
80 : return libspdm_eddsa_sign (context, hash_nid, param, param_size,
81 : message, message_size, signature, sig_size);
82 : }
83 : #endif
84 :
85 : #if LIBSPDM_SM2_DSA_SUPPORT
86 : static bool libspdm_sm2_dsa_sign_wrap (void *context, size_t hash_nid,
87 : const uint8_t *param, size_t param_size,
88 : const uint8_t *message,
89 : size_t message_size, uint8_t *signature,
90 : size_t *sig_size)
91 : {
92 : return libspdm_sm2_dsa_sign (context, hash_nid, param, param_size,
93 : message, message_size, signature, sig_size);
94 : }
95 : #endif
96 :
97 : /**
98 : * Get the SPDM signing context string, which is required since SPDM 1.2.
99 : *
100 : * @param spdm_version negotiated SPDM version
101 : * @param op_code the SPDM opcode which requires the signing
102 : * @param is_requester indicate if the signing is from a requester
103 : * @param context_size SPDM signing context size
104 : **/
105 0 : static const void *libspdm_get_signing_context_string (
106 : spdm_version_number_t spdm_version,
107 : uint8_t op_code,
108 : bool is_requester,
109 : size_t *context_size)
110 : {
111 : size_t index;
112 :
113 : /* It is introduced in SPDM 1.2*/
114 0 : LIBSPDM_ASSERT((spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT) > SPDM_MESSAGE_VERSION_11);
115 :
116 0 : for (index = 0; index < LIBSPDM_ARRAY_SIZE(m_libspdm_signing_context_str_table); index++) {
117 0 : if (m_libspdm_signing_context_str_table[index].is_requester == is_requester &&
118 0 : m_libspdm_signing_context_str_table[index].op_code == op_code) {
119 0 : *context_size = m_libspdm_signing_context_str_table[index].context_size;
120 0 : return m_libspdm_signing_context_str_table[index].context;
121 : }
122 : }
123 0 : LIBSPDM_ASSERT(false);
124 0 : return NULL;
125 : }
126 :
127 : /**
128 : * Create SPDM signing context, which is required since SPDM 1.2.
129 : *
130 : * @param spdm_version negotiated SPDM version
131 : * @param op_code the SPDM opcode which requires the signing
132 : * @param is_requester indicate if the signing is from a requester
133 : * @param spdm_signing_context SPDM signing context
134 : **/
135 81 : static void libspdm_create_signing_context (
136 : spdm_version_number_t spdm_version,
137 : uint8_t op_code,
138 : bool is_requester,
139 : void *spdm_signing_context)
140 : {
141 : size_t index;
142 : char *context_str;
143 :
144 : /* It is introduced in SPDM 1.2*/
145 81 : LIBSPDM_ASSERT((spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT) > SPDM_MESSAGE_VERSION_11);
146 :
147 : /* So far, it only leaves 1 bytes for version*/
148 81 : LIBSPDM_ASSERT((((spdm_version >> 12) & 0xF) < 10) &&
149 : (((spdm_version >> 8) & 0xF) < 10));
150 :
151 81 : context_str = spdm_signing_context;
152 405 : for (index = 0; index < 4; index++) {
153 324 : libspdm_copy_mem(context_str,
154 : SPDM_VERSION_1_2_SIGNING_PREFIX_CONTEXT_SIZE,
155 : SPDM_VERSION_1_2_SIGNING_PREFIX_CONTEXT,
156 : SPDM_VERSION_1_2_SIGNING_PREFIX_CONTEXT_SIZE);
157 : /* patch the version*/
158 324 : context_str[11] = (char)('0' + ((spdm_version >> 12) & 0xF));
159 324 : context_str[13] = (char)('0' + ((spdm_version >> 8) & 0xF));
160 324 : context_str[15] = (char)('*');
161 324 : context_str += SPDM_VERSION_1_2_SIGNING_PREFIX_CONTEXT_SIZE;
162 : }
163 400 : for (index = 0; index < LIBSPDM_ARRAY_SIZE(m_libspdm_signing_context_str_table); index++) {
164 400 : if (m_libspdm_signing_context_str_table[index].is_requester == is_requester &&
165 238 : m_libspdm_signing_context_str_table[index].op_code == op_code) {
166 81 : libspdm_zero_mem (
167 : context_str,
168 81 : m_libspdm_signing_context_str_table[index].zero_pad_size);
169 81 : libspdm_copy_mem(context_str + m_libspdm_signing_context_str_table[index].zero_pad_size,
170 81 : m_libspdm_signing_context_str_table[index].context_size,
171 81 : m_libspdm_signing_context_str_table[index].context,
172 81 : m_libspdm_signing_context_str_table[index].context_size);
173 81 : return;
174 : }
175 : }
176 0 : LIBSPDM_ASSERT(false);
177 : }
178 :
179 615 : uint32_t libspdm_get_asym_signature_size(uint32_t base_asym_algo)
180 : {
181 615 : switch (base_asym_algo) {
182 106 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
183 : #if LIBSPDM_RSA_SSA_2048_SUPPORT
184 106 : return 256;
185 : #else
186 : return 0;
187 : #endif
188 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048:
189 : #if LIBSPDM_RSA_PSS_2048_SUPPORT
190 0 : return 256;
191 : #else
192 : return 0;
193 : #endif
194 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
195 : #if LIBSPDM_RSA_SSA_3072_SUPPORT
196 0 : return 384;
197 : #else
198 : return 0;
199 : #endif
200 1 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072:
201 : #if LIBSPDM_RSA_PSS_3072_SUPPORT
202 1 : return 384;
203 : #else
204 : return 0;
205 : #endif
206 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
207 : #if LIBSPDM_RSA_SSA_4096_SUPPORT
208 0 : return 512;
209 : #else
210 : return 0;
211 : #endif
212 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096:
213 : #if LIBSPDM_RSA_PSS_4096_SUPPORT
214 0 : return 512;
215 : #else
216 : return 0;
217 : #endif
218 498 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
219 : #if LIBSPDM_ECDSA_P256_SUPPORT
220 498 : return 32 * 2;
221 : #else
222 : return 0;
223 : #endif
224 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384:
225 : #if LIBSPDM_ECDSA_P384_SUPPORT
226 0 : return 48 * 2;
227 : #else
228 : return 0;
229 : #endif
230 2 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521:
231 : #if LIBSPDM_ECDSA_P521_SUPPORT
232 2 : return 66 * 2;
233 : #else
234 : return 0;
235 : #endif
236 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
237 : #if LIBSPDM_SM2_DSA_P256_SUPPORT
238 : return 32 * 2;
239 : #else
240 0 : return 0;
241 : #endif
242 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
243 : #if LIBSPDM_EDDSA_ED25519_SUPPORT
244 : return 32 * 2;
245 : #else
246 0 : return 0;
247 : #endif
248 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
249 : #if LIBSPDM_EDDSA_ED448_SUPPORT
250 : return 57 * 2;
251 : #else
252 0 : return 0;
253 : #endif
254 8 : default:
255 8 : return 0;
256 : }
257 : }
258 :
259 176 : static bool libspdm_asym_sign_wrap (void *context, size_t hash_nid, uint32_t base_asym_algo,
260 : const uint8_t *param, size_t param_size,
261 : const uint8_t *message, size_t message_size,
262 : uint8_t *signature, size_t *sig_size)
263 : {
264 176 : switch (base_asym_algo) {
265 36 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
266 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
267 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
268 : #if LIBSPDM_RSA_SSA_SUPPORT
269 : #if !LIBSPDM_RSA_SSA_2048_SUPPORT
270 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048);
271 : #endif
272 : #if !LIBSPDM_RSA_SSA_3072_SUPPORT
273 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072);
274 : #endif
275 : #if !LIBSPDM_RSA_SSA_4096_SUPPORT
276 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096);
277 : #endif
278 36 : return libspdm_rsa_pkcs1_sign_with_nid_wrap(context, hash_nid,
279 : param, param_size,
280 : message, message_size,
281 : signature, sig_size);
282 : #else
283 : LIBSPDM_ASSERT(false);
284 : return false;
285 : #endif
286 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048:
287 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072:
288 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096:
289 : #if LIBSPDM_RSA_PSS_SUPPORT
290 : #if !LIBSPDM_RSA_PSS_2048_SUPPORT
291 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048);
292 : #endif
293 : #if !LIBSPDM_RSA_PSS_3072_SUPPORT
294 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072);
295 : #endif
296 : #if !LIBSPDM_RSA_PSS_4096_SUPPORT
297 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096);
298 : #endif
299 0 : return libspdm_rsa_pss_sign_wrap(context, hash_nid,
300 : param, param_size,
301 : message, message_size,
302 : signature, sig_size);
303 : #else
304 : LIBSPDM_ASSERT(false);
305 : return false;
306 : #endif
307 140 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
308 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384:
309 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521:
310 : #if LIBSPDM_ECDSA_SUPPORT
311 : #if !LIBSPDM_ECDSA_P256_SUPPORT
312 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256);
313 : #endif
314 : #if !LIBSPDM_ECDSA_P384_SUPPORT
315 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384);
316 : #endif
317 : #if !LIBSPDM_ECDSA_P521_SUPPORT
318 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521);
319 : #endif
320 140 : return libspdm_ecdsa_sign_wrap(context, hash_nid,
321 : param, param_size,
322 : message, message_size,
323 : signature, sig_size);
324 : #else
325 : LIBSPDM_ASSERT(false);
326 : return false;
327 : #endif
328 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
329 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
330 : #if (LIBSPDM_EDDSA_ED25519_SUPPORT) || (LIBSPDM_EDDSA_ED448_SUPPORT)
331 : #if !LIBSPDM_EDDSA_ED25519_SUPPORT
332 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519);
333 : #endif
334 : #if !LIBSPDM_EDDSA_ED448_SUPPORT
335 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448);
336 : #endif
337 : return libspdm_eddsa_sign_wrap(context, hash_nid,
338 : param, param_size,
339 : message, message_size,
340 : signature, sig_size);
341 : #else
342 0 : LIBSPDM_ASSERT(false);
343 0 : return false;
344 : #endif
345 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
346 : #if LIBSPDM_SM2_DSA_SUPPORT
347 : return libspdm_sm2_dsa_sign_wrap(context, hash_nid,
348 : param, param_size,
349 : message, message_size,
350 : signature, sig_size);
351 : #else
352 0 : LIBSPDM_ASSERT(false);
353 0 : return false;
354 : #endif
355 0 : default:
356 0 : LIBSPDM_ASSERT(false);
357 0 : return false;
358 : }
359 : }
360 :
361 961 : void libspdm_asym_free(uint32_t base_asym_algo, void *context)
362 : {
363 961 : if (context == NULL) {
364 2 : return;
365 : }
366 959 : switch (base_asym_algo) {
367 102 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
368 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
369 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
370 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048:
371 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072:
372 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096:
373 : #if (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT)
374 102 : libspdm_rsa_free(context);
375 : #else
376 : LIBSPDM_ASSERT(false);
377 : #endif
378 102 : break;
379 857 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
380 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384:
381 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521:
382 : #if LIBSPDM_ECDSA_SUPPORT
383 857 : libspdm_ec_free(context);
384 : #else
385 : LIBSPDM_ASSERT(false);
386 : #endif
387 857 : break;
388 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
389 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
390 : #if (LIBSPDM_EDDSA_ED25519_SUPPORT) || (LIBSPDM_EDDSA_ED448_SUPPORT)
391 : libspdm_ecd_free(context);
392 : #else
393 0 : LIBSPDM_ASSERT(false);
394 : #endif
395 0 : break;
396 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
397 : #if LIBSPDM_SM2_DSA_SUPPORT
398 : libspdm_sm2_dsa_free(context);
399 : #else
400 0 : LIBSPDM_ASSERT(false);
401 : #endif
402 0 : break;
403 0 : default:
404 0 : LIBSPDM_ASSERT(false);
405 0 : break;
406 : }
407 : }
408 :
409 10 : static bool libspdm_asym_get_public_key_from_der_wrap(uint32_t base_asym_algo,
410 : const uint8_t *der_data,
411 : size_t der_size,
412 : void **context)
413 : {
414 10 : switch (base_asym_algo) {
415 5 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
416 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
417 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
418 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048:
419 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072:
420 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096:
421 : #if (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT)
422 : #if !LIBSPDM_RSA_SSA_2048_SUPPORT
423 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048);
424 : #endif
425 : #if !LIBSPDM_RSA_SSA_3072_SUPPORT
426 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072);
427 : #endif
428 : #if !LIBSPDM_RSA_SSA_4096_SUPPORT
429 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096);
430 : #endif
431 : #if !LIBSPDM_RSA_PSS_2048_SUPPORT
432 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048);
433 : #endif
434 : #if !LIBSPDM_RSA_PSS_3072_SUPPORT
435 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072);
436 : #endif
437 : #if !LIBSPDM_RSA_PSS_4096_SUPPORT
438 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096);
439 : #endif
440 5 : return libspdm_rsa_get_public_key_from_der(der_data, der_size, context);
441 : #else
442 : LIBSPDM_ASSERT(false);
443 : return false;
444 : #endif
445 5 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
446 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384:
447 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521:
448 : #if LIBSPDM_ECDSA_SUPPORT
449 : #if !LIBSPDM_ECDSA_P256_SUPPORT
450 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256);
451 : #endif
452 : #if !LIBSPDM_ECDSA_P384_SUPPORT
453 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384);
454 : #endif
455 : #if !LIBSPDM_ECDSA_P521_SUPPORT
456 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521);
457 : #endif
458 5 : return libspdm_ec_get_public_key_from_der(der_data, der_size, context);
459 : #else
460 : LIBSPDM_ASSERT(false);
461 : return false;
462 : #endif
463 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
464 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
465 : #if (LIBSPDM_EDDSA_ED25519_SUPPORT) || (LIBSPDM_EDDSA_ED448_SUPPORT)
466 : return libspdm_ecd_get_public_key_from_der(der_data, der_size, context);
467 : #else
468 0 : LIBSPDM_ASSERT(false);
469 0 : return false;
470 : #endif
471 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
472 : #if LIBSPDM_SM2_DSA_SUPPORT
473 : #if !LIBSPDM_EDDSA_ED25519_SUPPORT
474 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519);
475 : #endif
476 : #if !LIBSPDM_EDDSA_ED448_SUPPORT
477 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448);
478 : #endif
479 : return libspdm_sm2_get_public_key_from_der(der_data, der_size, context);
480 : #else
481 0 : LIBSPDM_ASSERT(false);
482 0 : return false;
483 : #endif
484 0 : default:
485 0 : LIBSPDM_ASSERT(false);
486 0 : return false;
487 : }
488 : }
489 :
490 5 : bool libspdm_asym_get_public_key_from_der(uint32_t base_asym_algo,
491 : const uint8_t *der_data,
492 : size_t der_size,
493 : void **context)
494 : {
495 5 : return libspdm_asym_get_public_key_from_der_wrap(base_asym_algo,
496 : der_data,
497 : der_size,
498 : context);
499 : }
500 :
501 : /**
502 : * Return if asymmetric function need message hash.
503 : *
504 : * @param base_asym_algo SPDM base_asym_algo
505 : *
506 : * @retval true asymmetric function need message hash
507 : * @retval false asymmetric function need raw message
508 : **/
509 285 : static bool libspdm_asym_func_need_hash(uint32_t base_asym_algo)
510 : {
511 285 : switch (base_asym_algo) {
512 65 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
513 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
514 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
515 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048:
516 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072:
517 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096:
518 65 : return true;
519 220 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
520 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384:
521 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521:
522 220 : return true;
523 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
524 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
525 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
526 0 : return false;
527 0 : default:
528 0 : LIBSPDM_ASSERT(false);
529 0 : break;
530 : }
531 :
532 0 : return false;
533 : }
534 :
535 : /**
536 : * libspdm_copy_signature_swap_endian_rsa
537 : * Swaps the endianness of a RSA signature buffer. The ECDSA signature buffer is
538 : * actually single internal buffer and can be swapped as a single whole buffer.
539 : *
540 : * There are two known usage models for buffers for this function.
541 : * 1) Source and dest are the same (and their sizes). This would be an in-place swap.
542 : * 2) Source and dest are completely different (and dest size >= src size). No overlap.
543 : *
544 : * The case where source and dest are overlapped (and not the exact same buffer)
545 : * is not allowed and guarded against with an assert.
546 : **/
547 10 : static void libspdm_copy_signature_swap_endian_rsa(
548 : uint8_t* dst,
549 : size_t dst_size,
550 : const uint8_t* src,
551 : size_t src_size)
552 : {
553 : /* RSA signature is a single buffer to be swapped */
554 : size_t i;
555 :
556 10 : if (src == dst) {
557 4 : LIBSPDM_ASSERT(dst_size == src_size);
558 :
559 : /* src and dst are same buffer. Swap in place. */
560 :
561 : uint8_t byte;
562 516 : for (i = 0; i < dst_size / 2; i++) {
563 512 : byte = dst[i];
564 512 : dst[i] = dst[dst_size - i - 1];
565 512 : dst[dst_size - i - 1] = byte;
566 : }
567 : } else {
568 : /* src and dst are different buffers.
569 : * Guard against overlap case with assert.
570 : * Overlap case is not an expected usage model. */
571 6 : LIBSPDM_ASSERT(dst_size >= src_size);
572 6 : LIBSPDM_ASSERT((src < dst && src + src_size <= dst) ||
573 : (dst < src && dst + dst_size <= src));
574 :
575 1542 : for (i = 0; i < src_size; i++) {
576 1536 : dst[i] = src[src_size - i - 1];
577 : }
578 : }
579 10 : }
580 :
581 : /**
582 : * libspdm_copy_signature_swap_endian_ecdsa
583 : * Swaps the endianness of a ECDSA signature buffer. The ECDSA signature buffer is
584 : * actually two internal buffers, and each internal buffer must be swapped individually.
585 : *
586 : * There are two known usage models for buffers for this function.
587 : * 1) Source and dest are the same (and their sizes). This would be an in-place swap.
588 : * 2) Source and dest are completely different (and dest size >= src size). No overlap.
589 : *
590 : * The case where source and dest are overlapped (and not the exact same buffer)
591 : * is not allowed and guarded against with an assert.
592 : **/
593 10 : static void libspdm_copy_signature_swap_endian_ecdsa(
594 : uint8_t* dst,
595 : size_t dst_size,
596 : const uint8_t* src,
597 : size_t src_size)
598 : {
599 : /* ECDSA signature is actually 2 buffers (x & y)
600 : * and each must be swapped individually */
601 : size_t i;
602 :
603 10 : if (src == dst) {
604 4 : LIBSPDM_ASSERT(dst_size == src_size);
605 :
606 : /* src and dst are same buffer. Swap ecdsa 2 internal buffers in place. */
607 :
608 : size_t x_size;
609 : size_t y_size;
610 : uint8_t* x;
611 : uint8_t* y;
612 : uint8_t byte;
613 :
614 4 : x_size = dst_size / 2;
615 4 : y_size = x_size;
616 :
617 4 : x = dst;
618 4 : y = x + x_size;
619 :
620 68 : for (i = 0; i < x_size / 2; i++) {
621 64 : byte = x[i];
622 64 : x[i] = x[x_size - i - 1];
623 64 : x[x_size - i - 1] = byte;
624 : }
625 :
626 68 : for (i = 0; i < y_size / 2; i++) {
627 64 : byte = y[i];
628 64 : y[i] = y[y_size - i - 1];
629 64 : y[y_size - i - 1] = byte;
630 : }
631 : } else {
632 : /* src and dst are different buffers.
633 : * Guard against overlap case with assert.
634 : * Overlap case is not an expected usage model. */
635 6 : LIBSPDM_ASSERT(dst_size >= src_size);
636 6 : LIBSPDM_ASSERT((src < dst && src + src_size <= dst) ||
637 : (dst < src && dst + dst_size <= src));
638 :
639 : size_t x_size;
640 : size_t y_size;
641 :
642 : const uint8_t* src_x;
643 : const uint8_t* src_y;
644 :
645 : uint8_t* dst_x;
646 : uint8_t* dst_y;
647 :
648 6 : x_size = src_size / 2;
649 6 : y_size = x_size;
650 :
651 6 : src_x = src;
652 6 : src_y = src_x + x_size;
653 :
654 6 : dst_x = dst;
655 6 : dst_y = dst_x + x_size;
656 :
657 198 : for (i = 0; i < x_size; i++) {
658 192 : dst_x[i] = src_x[x_size - i - 1];
659 : }
660 :
661 198 : for (i = 0; i < y_size; i++) {
662 192 : dst_y[i] = src_y[y_size - i - 1];
663 : }
664 : }
665 10 : }
666 :
667 20 : void libspdm_copy_signature_swap_endian(
668 : uint32_t base_asym_algo,
669 : uint8_t* dst,
670 : size_t dst_size,
671 : const uint8_t* src,
672 : size_t src_size)
673 : {
674 20 : const uint32_t spdm_10_11_rsa_algos =
675 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048 |
676 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048 |
677 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072 |
678 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072 |
679 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096 |
680 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096;
681 :
682 20 : const uint32_t spdm_10_11_ecdsa_algos =
683 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256 |
684 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384 |
685 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521;
686 :
687 20 : if (base_asym_algo & spdm_10_11_rsa_algos) {
688 10 : libspdm_copy_signature_swap_endian_rsa(dst, dst_size, src, src_size);
689 10 : } else if (base_asym_algo & spdm_10_11_ecdsa_algos) {
690 10 : libspdm_copy_signature_swap_endian_ecdsa(dst, dst_size, src, src_size);
691 : } else {
692 : /* Currently do not expect asymmetric algorithms other than RSA and ECDSA */
693 0 : LIBSPDM_ASSERT(0);
694 : }
695 20 : }
696 :
697 : /**
698 : * libspdm_is_palindrome
699 : * Checks to see if a buffer is a palindrome.
700 : * If the buffer is a palindrone, it is the same for both endians,
701 : * and therefore endianness cannot be determined.
702 : **/
703 69 : bool libspdm_is_palindrome(const uint8_t* buf, size_t buf_size)
704 : {
705 : size_t head;
706 : size_t tail;
707 :
708 69 : head = 0;
709 69 : tail = buf_size - 1;
710 :
711 290 : while (head < tail) {
712 267 : if (buf[head] != buf[tail]) {
713 46 : return false;
714 : }
715 221 : head++;
716 221 : tail--;
717 : }
718 :
719 23 : return true;
720 : }
721 :
722 52 : bool libspdm_is_signature_buffer_palindrome(
723 : uint32_t base_asym_algo, const uint8_t *buf, size_t buf_size)
724 : {
725 52 : const uint32_t spdm_10_11_rsa_algos =
726 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048 |
727 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048 |
728 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072 |
729 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072 |
730 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096 |
731 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096;
732 :
733 52 : const uint32_t spdm_10_11_ecdsa_algos =
734 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256 |
735 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384 |
736 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521;
737 :
738 52 : if (base_asym_algo & spdm_10_11_rsa_algos) {
739 27 : return libspdm_is_palindrome(buf, buf_size);
740 25 : } else if (base_asym_algo & spdm_10_11_ecdsa_algos) {
741 25 : const size_t x_size = buf_size / 2;
742 25 : const size_t y_size = x_size;
743 :
744 25 : const uint8_t *x = buf;
745 25 : const uint8_t *y = buf + x_size;
746 :
747 25 : return libspdm_is_palindrome(x, x_size) && libspdm_is_palindrome(y, y_size);
748 : } else {
749 : /* Currently do not expect asymmetric algorithms other than RSA and ECDSA */
750 0 : LIBSPDM_ASSERT(0);
751 0 : return false;
752 : }
753 : }
754 :
755 : #if LIBSPDM_RSA_SSA_SUPPORT
756 30 : static bool libspdm_rsa_pkcs1_verify_with_nid_wrap (void *context, size_t hash_nid,
757 : const uint8_t *param, size_t param_size,
758 : const uint8_t *message,
759 : size_t message_size,
760 : const uint8_t *signature,
761 : size_t sig_size)
762 : {
763 30 : return libspdm_rsa_pkcs1_verify_with_nid (context, hash_nid,
764 : message, message_size, signature, sig_size);
765 : }
766 : #endif
767 :
768 : #if LIBSPDM_RSA_PSS_SUPPORT
769 0 : static bool libspdm_rsa_pss_verify_wrap (void *context, size_t hash_nid,
770 : const uint8_t *param, size_t param_size,
771 : const uint8_t *message,
772 : size_t message_size,
773 : const uint8_t *signature,
774 : size_t sig_size)
775 : {
776 0 : return libspdm_rsa_pss_verify (context, hash_nid, message, message_size, signature, sig_size);
777 : }
778 : #endif
779 :
780 : #if LIBSPDM_ECDSA_SUPPORT
781 82 : bool libspdm_ecdsa_verify_wrap (void *context, size_t hash_nid,
782 : const uint8_t *param, size_t param_size,
783 : const uint8_t *message,
784 : size_t message_size,
785 : const uint8_t *signature,
786 : size_t sig_size)
787 : {
788 82 : return libspdm_ecdsa_verify (context, hash_nid, message, message_size, signature, sig_size);
789 : }
790 : #endif
791 :
792 : #if (LIBSPDM_EDDSA_ED25519_SUPPORT) || (LIBSPDM_EDDSA_ED448_SUPPORT)
793 : bool libspdm_eddsa_verify_wrap (void *context, size_t hash_nid,
794 : const uint8_t *param, size_t param_size,
795 : const uint8_t *message,
796 : size_t message_size,
797 : const uint8_t *signature,
798 : size_t sig_size)
799 : {
800 : return libspdm_eddsa_verify (context, hash_nid, param, param_size,
801 : message, message_size, signature, sig_size);
802 : }
803 : #endif
804 :
805 : #if LIBSPDM_SM2_DSA_SUPPORT
806 : bool libspdm_sm2_dsa_verify_wrap (void *context, size_t hash_nid,
807 : const uint8_t *param, size_t param_size,
808 : const uint8_t *message,
809 : size_t message_size,
810 : const uint8_t *signature,
811 : size_t sig_size)
812 : {
813 : return libspdm_sm2_dsa_verify (context, hash_nid, param, param_size,
814 : message, message_size, signature, sig_size);
815 : }
816 : #endif
817 :
818 112 : static bool libspdm_asym_verify_wrap(
819 : void *context, size_t hash_nid, uint32_t base_asym_algo,
820 : const uint8_t *param, size_t param_size,
821 : const uint8_t *message, size_t message_size,
822 : const uint8_t *signature, size_t sig_size)
823 : {
824 112 : switch (base_asym_algo) {
825 30 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048:
826 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072:
827 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096:
828 : #if LIBSPDM_RSA_SSA_SUPPORT
829 : #if !LIBSPDM_RSA_SSA_2048_SUPPORT
830 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048);
831 : #endif
832 : #if !LIBSPDM_RSA_SSA_3072_SUPPORT
833 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072);
834 : #endif
835 : #if !LIBSPDM_RSA_SSA_4096_SUPPORT
836 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096);
837 : #endif
838 30 : return libspdm_rsa_pkcs1_verify_with_nid_wrap(context, hash_nid,
839 : param, param_size,
840 : message, message_size,
841 : signature, sig_size);
842 : #else
843 : LIBSPDM_ASSERT(false);
844 : return false;
845 : #endif
846 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048:
847 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072:
848 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096:
849 : #if LIBSPDM_RSA_PSS_SUPPORT
850 : #if !LIBSPDM_RSA_PSS_2048_SUPPORT
851 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048);
852 : #endif
853 : #if !LIBSPDM_RSA_PSS_3072_SUPPORT
854 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072);
855 : #endif
856 : #if !LIBSPDM_RSA_PSS_4096_SUPPORT
857 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096);
858 : #endif
859 0 : return libspdm_rsa_pss_verify_wrap(context, hash_nid,
860 : param, param_size,
861 : message, message_size,
862 : signature, sig_size);
863 : #else
864 : LIBSPDM_ASSERT(false);
865 : return false;
866 : #endif
867 82 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256:
868 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384:
869 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521:
870 : #if LIBSPDM_ECDSA_SUPPORT
871 : #if !LIBSPDM_ECDSA_P256_SUPPORT
872 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256);
873 : #endif
874 : #if !LIBSPDM_ECDSA_P384_SUPPORT
875 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384);
876 : #endif
877 : #if !LIBSPDM_ECDSA_P521_SUPPORT
878 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521);
879 : #endif
880 82 : return libspdm_ecdsa_verify_wrap(context, hash_nid,
881 : param, param_size,
882 : message, message_size,
883 : signature, sig_size);
884 : #else
885 : LIBSPDM_ASSERT(false);
886 : return false;
887 : #endif
888 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
889 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
890 : #if (LIBSPDM_EDDSA_ED25519_SUPPORT) || (LIBSPDM_EDDSA_ED448_SUPPORT)
891 : #if !LIBSPDM_EDDSA_ED25519_SUPPORT
892 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519);
893 : #endif
894 : #if !LIBSPDM_EDDSA_ED448_SUPPORT
895 : LIBSPDM_ASSERT(base_asym_algo!= SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448);
896 : #endif
897 : return libspdm_eddsa_verify_wrap(context, hash_nid,
898 : param, param_size,
899 : message, message_size,
900 : signature, sig_size);
901 : #else
902 0 : LIBSPDM_ASSERT(false);
903 0 : return false;
904 : #endif
905 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
906 : #if LIBSPDM_SM2_DSA_SUPPORT
907 : return libspdm_sm2_dsa_verify_wrap(context, hash_nid,
908 : param, param_size,
909 : message, message_size,
910 : signature, sig_size);
911 : #else
912 0 : LIBSPDM_ASSERT(false);
913 0 : return false;
914 : #endif
915 0 : default:
916 0 : LIBSPDM_ASSERT(false);
917 0 : return false;
918 : }
919 : }
920 :
921 0 : bool libspdm_asym_verify_ex(
922 : spdm_version_number_t spdm_version, uint8_t op_code,
923 : uint32_t base_asym_algo, uint32_t base_hash_algo,
924 : void *context,
925 : const uint8_t *message, size_t message_size,
926 : const uint8_t *signature, size_t sig_size,
927 : uint8_t *endian)
928 : {
929 : bool need_hash;
930 : uint8_t message_hash[LIBSPDM_MAX_HASH_SIZE];
931 : size_t hash_size;
932 : bool result;
933 : size_t hash_nid;
934 : uint8_t spdm12_signing_context_with_hash[SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE +
935 : LIBSPDM_MAX_HASH_SIZE];
936 : const void *param;
937 : size_t param_size;
938 :
939 : bool try_big_endian;
940 : bool try_little_endian;
941 : bool little_endian_succeeded;
942 : uint8_t endian_swapped_signature[LIBSPDM_MAX_ASYM_SIG_SIZE];
943 :
944 0 : hash_nid = libspdm_get_hash_nid(base_hash_algo);
945 0 : need_hash = libspdm_asym_func_need_hash(base_asym_algo);
946 :
947 0 : param = NULL;
948 0 : param_size = 0;
949 :
950 0 : if ((spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT) > SPDM_MESSAGE_VERSION_11) {
951 : /* Need use SPDM 1.2 signing. */
952 0 : switch (base_asym_algo) {
953 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
954 0 : param = "";
955 0 : param_size = 0;
956 0 : break;
957 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
958 0 : hash_nid = LIBSPDM_CRYPTO_NID_NULL;
959 0 : break;
960 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
961 0 : hash_nid = LIBSPDM_CRYPTO_NID_NULL;
962 0 : param = libspdm_get_signing_context_string (spdm_version, op_code, false, ¶m_size);
963 0 : break;
964 0 : default:
965 : /* pass thru for rest algorithm */
966 0 : break;
967 : }
968 :
969 0 : libspdm_create_signing_context (spdm_version, op_code, false,
970 : spdm12_signing_context_with_hash);
971 0 : hash_size = libspdm_get_hash_size(base_hash_algo);
972 0 : result = libspdm_hash_all(base_hash_algo, message, message_size,
973 : &spdm12_signing_context_with_hash[
974 : SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE]);
975 0 : if (!result) {
976 0 : return false;
977 : }
978 :
979 : /* re-assign message and message_size for signing */
980 0 : message = spdm12_signing_context_with_hash;
981 0 : message_size = SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE + hash_size;
982 0 : try_big_endian = true;
983 0 : try_little_endian = false;
984 0 : little_endian_succeeded = false;
985 : /* Passthru */
986 : } else {
987 0 : try_big_endian =
988 0 : (*endian == LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_ONLY
989 0 : || *endian == LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_OR_LITTLE);
990 :
991 0 : try_little_endian =
992 0 : (*endian == LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_LITTLE_ONLY
993 0 : || *endian == LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_OR_LITTLE);
994 :
995 0 : little_endian_succeeded = false;
996 : }
997 :
998 0 : if (need_hash) {
999 0 : hash_size = libspdm_get_hash_size(base_hash_algo);
1000 0 : result = libspdm_hash_all(base_hash_algo, message, message_size, message_hash);
1001 0 : if (!result) {
1002 0 : return false;
1003 : }
1004 0 : result = false;
1005 0 : if (try_big_endian) {
1006 0 : result = libspdm_asym_verify_wrap(context, hash_nid, base_asym_algo,
1007 : param, param_size,
1008 : message_hash, hash_size,
1009 : signature, sig_size);
1010 : }
1011 0 : if (!result && try_little_endian) {
1012 0 : libspdm_copy_signature_swap_endian(
1013 : base_asym_algo,
1014 : endian_swapped_signature, sizeof(endian_swapped_signature),
1015 : signature, sig_size);
1016 :
1017 0 : result = libspdm_asym_verify_wrap(context, hash_nid, base_asym_algo,
1018 : param, param_size,
1019 : message_hash, hash_size,
1020 : endian_swapped_signature, sig_size);
1021 0 : little_endian_succeeded = result;
1022 : }
1023 : } else {
1024 0 : result = false;
1025 0 : if (try_big_endian) {
1026 0 : result = libspdm_asym_verify_wrap(context, hash_nid, base_asym_algo,
1027 : param, param_size,
1028 : message, message_size,
1029 : signature, sig_size);
1030 : }
1031 0 : if (!result && try_little_endian) {
1032 0 : libspdm_copy_signature_swap_endian(
1033 : base_asym_algo,
1034 : endian_swapped_signature, sizeof(endian_swapped_signature),
1035 : signature, sig_size);
1036 :
1037 0 : result = libspdm_asym_verify_wrap(context, hash_nid, base_asym_algo,
1038 : param, param_size,
1039 : message, message_size,
1040 : endian_swapped_signature, sig_size);
1041 0 : little_endian_succeeded = result;
1042 : }
1043 : }
1044 0 : if (try_big_endian && try_little_endian && result) {
1045 0 : if (!libspdm_is_signature_buffer_palindrome(base_asym_algo, signature, sig_size)) {
1046 0 : if (little_endian_succeeded) {
1047 0 : *endian = LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_LITTLE_ONLY;
1048 : } else {
1049 0 : *endian = LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_ONLY;
1050 : }
1051 : }
1052 : }
1053 0 : return result;
1054 : }
1055 :
1056 :
1057 80 : bool libspdm_asym_verify_hash_ex(
1058 : spdm_version_number_t spdm_version, uint8_t op_code,
1059 : uint32_t base_asym_algo, uint32_t base_hash_algo,
1060 : void *context, const uint8_t *message_hash,
1061 : size_t hash_size, const uint8_t *signature,
1062 : size_t sig_size, uint8_t *endian)
1063 : {
1064 : bool need_hash;
1065 : uint8_t *message;
1066 : size_t message_size;
1067 : uint8_t full_message_hash[LIBSPDM_MAX_HASH_SIZE];
1068 : bool result;
1069 : size_t hash_nid;
1070 : uint8_t spdm12_signing_context_with_hash[SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE +
1071 : LIBSPDM_MAX_HASH_SIZE];
1072 : const void *param;
1073 : size_t param_size;
1074 :
1075 : bool try_big_endian;
1076 : bool try_little_endian;
1077 : bool little_endian_succeeded;
1078 : uint8_t endian_swapped_signature[LIBSPDM_MAX_ASYM_SIG_SIZE];
1079 :
1080 80 : hash_nid = libspdm_get_hash_nid(base_hash_algo);
1081 80 : need_hash = libspdm_asym_func_need_hash(base_asym_algo);
1082 80 : LIBSPDM_ASSERT (hash_size == libspdm_get_hash_size(base_hash_algo));
1083 :
1084 80 : param = NULL;
1085 80 : param_size = 0;
1086 80 : try_big_endian = true;
1087 80 : try_little_endian = false;
1088 80 : little_endian_succeeded = false;
1089 :
1090 80 : if ((spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT) > SPDM_MESSAGE_VERSION_11) {
1091 : /* Need use SPDM 1.2 signing */
1092 22 : switch (base_asym_algo) {
1093 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
1094 0 : param = "";
1095 0 : param_size = 0;
1096 0 : break;
1097 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
1098 0 : hash_nid = LIBSPDM_CRYPTO_NID_NULL;
1099 0 : break;
1100 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
1101 0 : hash_nid = LIBSPDM_CRYPTO_NID_NULL;
1102 0 : param = libspdm_get_signing_context_string (spdm_version, op_code, false, ¶m_size);
1103 0 : break;
1104 22 : default:
1105 : /* pass thru for rest algorithm */
1106 22 : break;
1107 : }
1108 :
1109 22 : libspdm_create_signing_context (spdm_version, op_code, false,
1110 : spdm12_signing_context_with_hash);
1111 22 : libspdm_copy_mem(&spdm12_signing_context_with_hash[SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE],
1112 : sizeof(spdm12_signing_context_with_hash)
1113 : - (&spdm12_signing_context_with_hash[SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE]
1114 : - spdm12_signing_context_with_hash),
1115 : message_hash, hash_size);
1116 :
1117 : /* assign message and message_size for signing */
1118 22 : message = spdm12_signing_context_with_hash;
1119 22 : message_size = SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE + hash_size;
1120 :
1121 22 : if (need_hash) {
1122 22 : result = libspdm_hash_all(base_hash_algo, message, message_size, full_message_hash);
1123 22 : if (!result) {
1124 0 : return false;
1125 : }
1126 22 : return libspdm_asym_verify_wrap(context, hash_nid, base_asym_algo,
1127 : param, param_size,
1128 : full_message_hash, hash_size,
1129 : signature, sig_size);
1130 : } else {
1131 0 : return libspdm_asym_verify_wrap(context, hash_nid, base_asym_algo,
1132 : param, param_size,
1133 : message, message_size,
1134 : signature, sig_size);
1135 : }
1136 : /* SPDM 1.2 signing done. */
1137 : } else {
1138 58 : try_big_endian =
1139 58 : (*endian == LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_ONLY
1140 58 : || *endian == LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_OR_LITTLE);
1141 :
1142 58 : try_little_endian =
1143 58 : (*endian == LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_LITTLE_ONLY
1144 58 : || *endian == LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_OR_LITTLE);
1145 :
1146 58 : little_endian_succeeded = false;
1147 : }
1148 :
1149 58 : if (need_hash) {
1150 58 : result = false;
1151 58 : if (try_big_endian) {
1152 54 : result = libspdm_asym_verify_wrap(context, hash_nid, base_asym_algo,
1153 : param, param_size,
1154 : message_hash, hash_size,
1155 : signature, sig_size);
1156 : }
1157 58 : if (!result && try_little_endian) {
1158 6 : libspdm_copy_signature_swap_endian(
1159 : base_asym_algo,
1160 : endian_swapped_signature, sizeof(endian_swapped_signature),
1161 : signature, sig_size);
1162 :
1163 6 : result = libspdm_asym_verify_wrap(context, hash_nid, base_asym_algo,
1164 : param, param_size,
1165 : message_hash, hash_size,
1166 : endian_swapped_signature, sig_size);
1167 6 : little_endian_succeeded = result;
1168 : }
1169 58 : if (try_big_endian && try_little_endian && result) {
1170 4 : if (!libspdm_is_signature_buffer_palindrome(base_asym_algo, signature, sig_size)) {
1171 4 : if (little_endian_succeeded) {
1172 2 : *endian = LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_LITTLE_ONLY;
1173 : } else {
1174 2 : *endian = LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_ONLY;
1175 : }
1176 : }
1177 : }
1178 58 : return result;
1179 :
1180 : } else {
1181 0 : LIBSPDM_ASSERT(false);
1182 0 : return false;
1183 : }
1184 : }
1185 :
1186 0 : bool libspdm_asym_verify(
1187 : spdm_version_number_t spdm_version, uint8_t op_code,
1188 : uint32_t base_asym_algo, uint32_t base_hash_algo,
1189 : void* context, const uint8_t* message,
1190 : size_t message_size, const uint8_t* signature,
1191 : size_t sig_size)
1192 : {
1193 0 : uint8_t endian = LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_ONLY;
1194 0 : return libspdm_asym_verify_ex(
1195 : spdm_version, op_code, base_asym_algo, base_hash_algo,
1196 : context, message, message_size, signature, sig_size, &endian);
1197 : }
1198 :
1199 0 : bool libspdm_asym_verify_hash(
1200 : spdm_version_number_t spdm_version, uint8_t op_code,
1201 : uint32_t base_asym_algo, uint32_t base_hash_algo,
1202 : void* context, const uint8_t* message_hash,
1203 : size_t hash_size, const uint8_t* signature,
1204 : size_t sig_size)
1205 : {
1206 0 : uint8_t endian = LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_ONLY;
1207 0 : return libspdm_asym_verify_hash_ex(
1208 : spdm_version, op_code, base_asym_algo, base_hash_algo,
1209 : context, message_hash, hash_size, signature, sig_size, &endian);
1210 : }
1211 :
1212 99 : bool libspdm_asym_sign(
1213 : spdm_version_number_t spdm_version, uint8_t op_code,
1214 : uint32_t base_asym_algo, uint32_t base_hash_algo,
1215 : void *context, const uint8_t *message,
1216 : size_t message_size, uint8_t *signature,
1217 : size_t *sig_size)
1218 : {
1219 : bool need_hash;
1220 : uint8_t message_hash[LIBSPDM_MAX_HASH_SIZE];
1221 : size_t hash_size;
1222 : bool result;
1223 : size_t hash_nid;
1224 : uint8_t spdm12_signing_context_with_hash[SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE +
1225 : LIBSPDM_MAX_HASH_SIZE];
1226 : const void *param;
1227 : size_t param_size;
1228 :
1229 99 : hash_nid = libspdm_get_hash_nid(base_hash_algo);
1230 99 : need_hash = libspdm_asym_func_need_hash(base_asym_algo);
1231 :
1232 99 : param = NULL;
1233 99 : param_size = 0;
1234 :
1235 99 : if ((spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT) > SPDM_MESSAGE_VERSION_11) {
1236 : /* Need use SPDM 1.2 signing */
1237 23 : switch (base_asym_algo) {
1238 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
1239 0 : param = "";
1240 0 : param_size = 0;
1241 0 : break;
1242 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
1243 0 : hash_nid = LIBSPDM_CRYPTO_NID_NULL;
1244 0 : break;
1245 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
1246 0 : hash_nid = LIBSPDM_CRYPTO_NID_NULL;
1247 0 : param = libspdm_get_signing_context_string (spdm_version, op_code, false, ¶m_size);
1248 0 : break;
1249 23 : default:
1250 : /* pass thru for rest algorithm */
1251 23 : break;
1252 : }
1253 :
1254 23 : libspdm_create_signing_context (spdm_version, op_code, false,
1255 : spdm12_signing_context_with_hash);
1256 23 : hash_size = libspdm_get_hash_size(base_hash_algo);
1257 23 : result = libspdm_hash_all(base_hash_algo, message, message_size,
1258 : &spdm12_signing_context_with_hash[
1259 : SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE]);
1260 23 : if (!result) {
1261 0 : return false;
1262 : }
1263 :
1264 : /* re-assign message and message_size for signing */
1265 23 : message = spdm12_signing_context_with_hash;
1266 23 : message_size = SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE + hash_size;
1267 :
1268 : /* Passthru*/
1269 : }
1270 :
1271 99 : if (need_hash) {
1272 99 : hash_size = libspdm_get_hash_size(base_hash_algo);
1273 99 : result = libspdm_hash_all(base_hash_algo, message, message_size, message_hash);
1274 99 : if (!result) {
1275 0 : return false;
1276 : }
1277 99 : return libspdm_asym_sign_wrap(context, hash_nid, base_asym_algo,
1278 : param, param_size,
1279 : message_hash, hash_size,
1280 : signature, sig_size);
1281 : } else {
1282 0 : return libspdm_asym_sign_wrap(context, hash_nid, base_asym_algo,
1283 : param, param_size,
1284 : message, message_size,
1285 : signature, sig_size);
1286 : }
1287 : }
1288 :
1289 41 : bool libspdm_asym_sign_hash(
1290 : spdm_version_number_t spdm_version, uint8_t op_code,
1291 : uint32_t base_asym_algo, uint32_t base_hash_algo,
1292 : void *context, const uint8_t *message_hash,
1293 : size_t hash_size, uint8_t *signature,
1294 : size_t *sig_size)
1295 : {
1296 : bool need_hash;
1297 : uint8_t *message;
1298 : size_t message_size;
1299 : uint8_t full_message_hash[LIBSPDM_MAX_HASH_SIZE];
1300 : bool result;
1301 : size_t hash_nid;
1302 : uint8_t spdm12_signing_context_with_hash[SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE +
1303 : LIBSPDM_MAX_HASH_SIZE];
1304 : const void *param;
1305 : size_t param_size;
1306 :
1307 41 : hash_nid = libspdm_get_hash_nid(base_hash_algo);
1308 41 : need_hash = libspdm_asym_func_need_hash(base_asym_algo);
1309 41 : LIBSPDM_ASSERT (hash_size == libspdm_get_hash_size(base_hash_algo));
1310 :
1311 41 : param = NULL;
1312 41 : param_size = 0;
1313 :
1314 41 : if ((spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT) > SPDM_MESSAGE_VERSION_11) {
1315 : /* Need use SPDM 1.2 signing */
1316 13 : switch (base_asym_algo) {
1317 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
1318 0 : param = "";
1319 0 : param_size = 0;
1320 0 : break;
1321 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
1322 0 : hash_nid = LIBSPDM_CRYPTO_NID_NULL;
1323 0 : break;
1324 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
1325 0 : hash_nid = LIBSPDM_CRYPTO_NID_NULL;
1326 0 : param = libspdm_get_signing_context_string (spdm_version, op_code, false, ¶m_size);
1327 0 : break;
1328 13 : default:
1329 : /* pass thru for rest algorithm */
1330 13 : break;
1331 : }
1332 :
1333 13 : libspdm_create_signing_context (spdm_version, op_code, false,
1334 : spdm12_signing_context_with_hash);
1335 13 : libspdm_copy_mem(&spdm12_signing_context_with_hash[SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE],
1336 : sizeof(spdm12_signing_context_with_hash)
1337 : - (&spdm12_signing_context_with_hash[SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE]
1338 : - spdm12_signing_context_with_hash),
1339 : message_hash, hash_size);
1340 :
1341 : /* assign message and message_size for signing */
1342 13 : message = spdm12_signing_context_with_hash;
1343 13 : message_size = SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE + hash_size;
1344 :
1345 13 : if (need_hash) {
1346 13 : result = libspdm_hash_all(base_hash_algo, message, message_size, full_message_hash);
1347 13 : if (!result) {
1348 0 : return false;
1349 : }
1350 13 : return libspdm_asym_sign_wrap(context, hash_nid, base_asym_algo,
1351 : param, param_size,
1352 : full_message_hash, hash_size,
1353 : signature, sig_size);
1354 : } else {
1355 0 : return libspdm_asym_sign_wrap(context, hash_nid, base_asym_algo,
1356 : param, param_size,
1357 : message, message_size,
1358 : signature, sig_size);
1359 : }
1360 :
1361 : /* SPDM 1.2 signing done. */
1362 : }
1363 :
1364 28 : if (need_hash) {
1365 28 : return libspdm_asym_sign_wrap(context, hash_nid, base_asym_algo,
1366 : param, param_size,
1367 : message_hash, hash_size,
1368 : signature, sig_size);
1369 : } else {
1370 0 : LIBSPDM_ASSERT (false);
1371 0 : return false;
1372 : }
1373 : }
1374 :
1375 97 : uint32_t libspdm_get_req_asym_signature_size(uint16_t req_base_asym_alg)
1376 : {
1377 97 : return libspdm_get_asym_signature_size(req_base_asym_alg);
1378 : }
1379 :
1380 40 : void libspdm_req_asym_free(uint16_t req_base_asym_alg, void *context)
1381 : {
1382 40 : libspdm_asym_free(req_base_asym_alg, context);
1383 40 : }
1384 :
1385 5 : bool libspdm_req_asym_get_public_key_from_der(uint16_t req_base_asym_alg,
1386 : const uint8_t *der_data,
1387 : size_t der_size,
1388 : void **context)
1389 : {
1390 5 : return libspdm_asym_get_public_key_from_der_wrap(req_base_asym_alg,
1391 : der_data,
1392 : der_size,
1393 : context);
1394 : }
1395 :
1396 65 : bool libspdm_req_asym_func_need_hash(uint16_t req_base_asym_alg)
1397 : {
1398 65 : return libspdm_asym_func_need_hash(req_base_asym_alg);
1399 : }
1400 :
1401 0 : bool libspdm_req_asym_verify_ex(
1402 : spdm_version_number_t spdm_version, uint8_t op_code,
1403 : uint16_t req_base_asym_alg,
1404 : uint32_t base_hash_algo, void *context,
1405 : const uint8_t *message, size_t message_size,
1406 : const uint8_t *signature, size_t sig_size, uint8_t *endian)
1407 : {
1408 : bool need_hash;
1409 : uint8_t message_hash[LIBSPDM_MAX_HASH_SIZE];
1410 : size_t hash_size;
1411 : bool result;
1412 : size_t hash_nid;
1413 : uint8_t spdm12_signing_context_with_hash[SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE +
1414 : LIBSPDM_MAX_HASH_SIZE];
1415 : const void *param;
1416 : size_t param_size;
1417 :
1418 : bool try_big_endian;
1419 : bool try_little_endian;
1420 : bool little_endian_succeeded;
1421 : uint8_t endian_swapped_signature[LIBSPDM_MAX_ASYM_SIG_SIZE];
1422 :
1423 0 : hash_nid = libspdm_get_hash_nid(base_hash_algo);
1424 0 : need_hash = libspdm_req_asym_func_need_hash(req_base_asym_alg);
1425 :
1426 0 : param = NULL;
1427 0 : param_size = 0;
1428 :
1429 0 : if ((spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT) > SPDM_MESSAGE_VERSION_11) {
1430 : /* Need use SPDM 1.2 signing */
1431 0 : switch (req_base_asym_alg) {
1432 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
1433 0 : param = "";
1434 0 : param_size = 0;
1435 0 : break;
1436 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
1437 0 : hash_nid = LIBSPDM_CRYPTO_NID_NULL;
1438 0 : break;
1439 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
1440 0 : hash_nid = LIBSPDM_CRYPTO_NID_NULL;
1441 0 : param = libspdm_get_signing_context_string (spdm_version, op_code, true, ¶m_size);
1442 0 : break;
1443 0 : default:
1444 : /* pass thru for rest algorithm */
1445 0 : break;
1446 : }
1447 :
1448 0 : libspdm_create_signing_context (spdm_version, op_code, true,
1449 : spdm12_signing_context_with_hash);
1450 0 : hash_size = libspdm_get_hash_size(base_hash_algo);
1451 0 : result = libspdm_hash_all(base_hash_algo, message, message_size,
1452 : &spdm12_signing_context_with_hash[
1453 : SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE]);
1454 0 : if (!result) {
1455 0 : return false;
1456 : }
1457 :
1458 : /* re-assign message and message_size for signing */
1459 0 : message = spdm12_signing_context_with_hash;
1460 0 : message_size = SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE + hash_size;
1461 0 : try_big_endian = true;
1462 0 : try_little_endian = false;
1463 0 : little_endian_succeeded = false;
1464 : /* Passthru */
1465 : } else {
1466 0 : try_big_endian =
1467 0 : (*endian == LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_ONLY
1468 0 : || *endian == LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_OR_LITTLE);
1469 :
1470 0 : try_little_endian =
1471 0 : (*endian == LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_LITTLE_ONLY
1472 0 : || *endian == LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_OR_LITTLE);
1473 :
1474 0 : little_endian_succeeded = false;
1475 : }
1476 :
1477 0 : if (need_hash) {
1478 0 : hash_size = libspdm_get_hash_size(base_hash_algo);
1479 0 : result = libspdm_hash_all(base_hash_algo, message, message_size, message_hash);
1480 0 : if (!result) {
1481 0 : return false;
1482 : }
1483 0 : result = false;
1484 0 : if (try_big_endian) {
1485 0 : result = libspdm_asym_verify_wrap(context, hash_nid, req_base_asym_alg,
1486 : param, param_size,
1487 : message_hash, hash_size,
1488 : signature, sig_size);
1489 : }
1490 0 : if (!result && try_little_endian) {
1491 0 : libspdm_copy_signature_swap_endian(
1492 : req_base_asym_alg,
1493 : endian_swapped_signature, sizeof(endian_swapped_signature),
1494 : signature, sig_size);
1495 :
1496 0 : result = libspdm_asym_verify_wrap(context, hash_nid, req_base_asym_alg,
1497 : param, param_size,
1498 : message_hash, hash_size,
1499 : endian_swapped_signature, sig_size);
1500 0 : little_endian_succeeded = result;
1501 : }
1502 : } else {
1503 0 : result = false;
1504 0 : if (try_big_endian) {
1505 0 : result = libspdm_asym_verify_wrap(context, hash_nid, req_base_asym_alg,
1506 : param, param_size,
1507 : message, message_size,
1508 : signature, sig_size);
1509 : }
1510 0 : if (!result && try_little_endian) {
1511 0 : libspdm_copy_signature_swap_endian(
1512 : req_base_asym_alg,
1513 : endian_swapped_signature, sizeof(endian_swapped_signature),
1514 : signature, sig_size);
1515 :
1516 0 : result = libspdm_asym_verify_wrap(context, hash_nid, req_base_asym_alg,
1517 : param, param_size,
1518 : message, message_size,
1519 : endian_swapped_signature, sig_size);
1520 0 : little_endian_succeeded = result;
1521 : }
1522 : }
1523 0 : if (try_big_endian && try_little_endian && result) {
1524 0 : if (!libspdm_is_signature_buffer_palindrome(req_base_asym_alg, signature, sig_size)) {
1525 0 : if (little_endian_succeeded) {
1526 0 : *endian = LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_LITTLE_ONLY;
1527 : } else {
1528 0 : *endian = LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_ONLY;
1529 : }
1530 : }
1531 : }
1532 0 : return result;
1533 : }
1534 :
1535 29 : bool libspdm_req_asym_verify_hash_ex(
1536 : spdm_version_number_t spdm_version, uint8_t op_code,
1537 : uint16_t req_base_asym_alg,
1538 : uint32_t base_hash_algo, void *context,
1539 : const uint8_t *message_hash, size_t hash_size,
1540 : const uint8_t *signature, size_t sig_size, uint8_t *endian)
1541 : {
1542 : bool need_hash;
1543 : uint8_t *message;
1544 : size_t message_size;
1545 : uint8_t full_message_hash[LIBSPDM_MAX_HASH_SIZE];
1546 : bool result;
1547 : size_t hash_nid;
1548 : uint8_t spdm12_signing_context_with_hash[SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE +
1549 : LIBSPDM_MAX_HASH_SIZE];
1550 : const void *param;
1551 : size_t param_size;
1552 :
1553 : bool try_big_endian;
1554 : bool try_little_endian;
1555 : bool little_endian_succeeded;
1556 : uint8_t endian_swapped_signature[LIBSPDM_MAX_ASYM_SIG_SIZE];
1557 :
1558 29 : hash_nid = libspdm_get_hash_nid(base_hash_algo);
1559 29 : need_hash = libspdm_req_asym_func_need_hash(req_base_asym_alg);
1560 29 : LIBSPDM_ASSERT (hash_size == libspdm_get_hash_size(base_hash_algo));
1561 :
1562 29 : param = NULL;
1563 29 : param_size = 0;
1564 :
1565 29 : if ((spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT) > SPDM_MESSAGE_VERSION_11) {
1566 : /* Need use SPDM 1.2 signing */
1567 10 : switch (req_base_asym_alg) {
1568 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
1569 0 : param = "";
1570 0 : param_size = 0;
1571 0 : break;
1572 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
1573 0 : hash_nid = LIBSPDM_CRYPTO_NID_NULL;
1574 0 : break;
1575 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
1576 0 : hash_nid = LIBSPDM_CRYPTO_NID_NULL;
1577 0 : param = libspdm_get_signing_context_string (spdm_version, op_code, true, ¶m_size);
1578 0 : break;
1579 10 : default:
1580 : /* pass thru for rest algorithm */
1581 10 : break;
1582 : }
1583 :
1584 10 : libspdm_create_signing_context (spdm_version, op_code, true,
1585 : spdm12_signing_context_with_hash);
1586 10 : libspdm_copy_mem(&spdm12_signing_context_with_hash[SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE],
1587 : sizeof(spdm12_signing_context_with_hash)
1588 : - (&spdm12_signing_context_with_hash[SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE]
1589 : - spdm12_signing_context_with_hash),
1590 : message_hash, hash_size);
1591 :
1592 : /* assign message and message_size for signing */
1593 10 : message = spdm12_signing_context_with_hash;
1594 10 : message_size = SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE + hash_size;
1595 :
1596 10 : if (need_hash) {
1597 10 : result = libspdm_hash_all(base_hash_algo, message, message_size,
1598 : full_message_hash);
1599 10 : if (!result) {
1600 0 : return false;
1601 : }
1602 10 : return libspdm_asym_verify_wrap(context, hash_nid, req_base_asym_alg,
1603 : param, param_size,
1604 : full_message_hash, hash_size,
1605 : signature, sig_size);
1606 : } else {
1607 0 : return libspdm_asym_verify_wrap(context, hash_nid, req_base_asym_alg,
1608 : param, param_size,
1609 : message, message_size,
1610 : signature, sig_size);
1611 : }
1612 : /* SPDM 1.2 signing done. */
1613 : } else {
1614 19 : try_big_endian =
1615 19 : (*endian == LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_ONLY
1616 19 : || *endian == LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_OR_LITTLE);
1617 :
1618 19 : try_little_endian =
1619 19 : (*endian == LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_LITTLE_ONLY
1620 19 : || *endian == LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_OR_LITTLE);
1621 :
1622 19 : little_endian_succeeded = false;
1623 : }
1624 :
1625 19 : if (need_hash) {
1626 19 : result = false;
1627 19 : if (try_big_endian) {
1628 14 : result = libspdm_asym_verify_wrap(context, hash_nid, req_base_asym_alg,
1629 : param, param_size,
1630 : message_hash, hash_size,
1631 : signature, sig_size);
1632 : }
1633 19 : if (!result && try_little_endian) {
1634 6 : libspdm_copy_signature_swap_endian(
1635 : req_base_asym_alg,
1636 : endian_swapped_signature, sizeof(endian_swapped_signature),
1637 : signature, sig_size);
1638 :
1639 6 : result = libspdm_asym_verify_wrap(context, hash_nid, req_base_asym_alg,
1640 : param, param_size,
1641 : message_hash, hash_size,
1642 : endian_swapped_signature, sig_size);
1643 6 : little_endian_succeeded = result;
1644 : }
1645 19 : if (try_big_endian && try_little_endian && result) {
1646 3 : if (!libspdm_is_signature_buffer_palindrome(req_base_asym_alg, signature, sig_size)) {
1647 3 : if (little_endian_succeeded) {
1648 1 : *endian = LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_LITTLE_ONLY;
1649 : } else {
1650 2 : *endian = LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_ONLY;
1651 : }
1652 : }
1653 : }
1654 19 : return result;
1655 : } else {
1656 0 : LIBSPDM_ASSERT (false);
1657 0 : return false;
1658 : }
1659 : }
1660 :
1661 0 : bool libspdm_req_asym_verify(
1662 : spdm_version_number_t spdm_version, uint8_t op_code,
1663 : uint16_t req_base_asym_alg,
1664 : uint32_t base_hash_algo, void* context,
1665 : const uint8_t* message, size_t message_size,
1666 : const uint8_t* signature, size_t sig_size)
1667 : {
1668 0 : uint8_t endian = LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_ONLY;
1669 0 : return libspdm_req_asym_verify_ex(
1670 : spdm_version, op_code, req_base_asym_alg, base_hash_algo, context,
1671 : message, message_size, signature, sig_size, &endian);
1672 : }
1673 :
1674 0 : bool libspdm_req_asym_verify_hash(
1675 : spdm_version_number_t spdm_version, uint8_t op_code,
1676 : uint16_t req_base_asym_alg,
1677 : uint32_t base_hash_algo, void* context,
1678 : const uint8_t* message_hash, size_t hash_size,
1679 : const uint8_t* signature, size_t sig_size)
1680 : {
1681 0 : uint8_t endian = LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_ONLY;
1682 0 : return libspdm_req_asym_verify_hash_ex(
1683 : spdm_version, op_code, req_base_asym_alg, base_hash_algo, context,
1684 : message_hash, hash_size, signature, sig_size, &endian);
1685 : }
1686 :
1687 22 : bool libspdm_req_asym_sign(
1688 : spdm_version_number_t spdm_version, uint8_t op_code,
1689 : uint16_t req_base_asym_alg,
1690 : uint32_t base_hash_algo, void *context,
1691 : const uint8_t *message, size_t message_size,
1692 : uint8_t *signature, size_t *sig_size)
1693 : {
1694 : bool need_hash;
1695 : uint8_t message_hash[LIBSPDM_MAX_HASH_SIZE];
1696 : size_t hash_size;
1697 : bool result;
1698 : size_t hash_nid;
1699 : uint8_t spdm12_signing_context_with_hash[SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE +
1700 : LIBSPDM_MAX_HASH_SIZE];
1701 : const void *param;
1702 : size_t param_size;
1703 :
1704 22 : hash_nid = libspdm_get_hash_nid(base_hash_algo);
1705 22 : need_hash = libspdm_req_asym_func_need_hash(req_base_asym_alg);
1706 :
1707 22 : param = NULL;
1708 22 : param_size = 0;
1709 :
1710 22 : if ((spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT) > SPDM_MESSAGE_VERSION_11) {
1711 : /* Need use SPDM 1.2 signing */
1712 7 : switch (req_base_asym_alg) {
1713 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
1714 0 : param = "";
1715 0 : param_size = 0;
1716 0 : break;
1717 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
1718 0 : hash_nid = LIBSPDM_CRYPTO_NID_NULL;
1719 0 : break;
1720 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
1721 0 : hash_nid = LIBSPDM_CRYPTO_NID_NULL;
1722 0 : param = libspdm_get_signing_context_string (spdm_version, op_code, true, ¶m_size);
1723 0 : break;
1724 7 : default:
1725 : /* pass thru for rest algorithm */
1726 7 : break;
1727 : }
1728 :
1729 7 : libspdm_create_signing_context (spdm_version, op_code, true,
1730 : spdm12_signing_context_with_hash);
1731 7 : hash_size = libspdm_get_hash_size(base_hash_algo);
1732 7 : result = libspdm_hash_all(base_hash_algo, message, message_size,
1733 : &spdm12_signing_context_with_hash[
1734 : SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE]);
1735 7 : if (!result) {
1736 0 : return false;
1737 : }
1738 :
1739 : /* re-assign message and message_size for signing */
1740 7 : message = spdm12_signing_context_with_hash;
1741 7 : message_size = SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE + hash_size;
1742 :
1743 : /* Passthru */
1744 : }
1745 :
1746 22 : if (need_hash) {
1747 22 : hash_size = libspdm_get_hash_size(base_hash_algo);
1748 22 : result = libspdm_hash_all(base_hash_algo, message, message_size,
1749 : message_hash);
1750 22 : if (!result) {
1751 0 : return false;
1752 : }
1753 22 : return libspdm_asym_sign_wrap(context, hash_nid, req_base_asym_alg,
1754 : param, param_size,
1755 : message_hash, hash_size,
1756 : signature, sig_size);
1757 : } else {
1758 0 : return libspdm_asym_sign_wrap(context, hash_nid, req_base_asym_alg,
1759 : param, param_size,
1760 : message, message_size,
1761 : signature, sig_size);
1762 : }
1763 : }
1764 :
1765 14 : bool libspdm_req_asym_sign_hash(
1766 : spdm_version_number_t spdm_version, uint8_t op_code,
1767 : uint16_t req_base_asym_alg,
1768 : uint32_t base_hash_algo, void *context,
1769 : const uint8_t *message_hash, size_t hash_size,
1770 : uint8_t *signature, size_t *sig_size)
1771 : {
1772 : bool need_hash;
1773 : uint8_t *message;
1774 : size_t message_size;
1775 : uint8_t full_message_hash[LIBSPDM_MAX_HASH_SIZE];
1776 : bool result;
1777 : size_t hash_nid;
1778 : uint8_t spdm12_signing_context_with_hash[SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE +
1779 : LIBSPDM_MAX_HASH_SIZE];
1780 : const void *param;
1781 : size_t param_size;
1782 :
1783 14 : hash_nid = libspdm_get_hash_nid(base_hash_algo);
1784 14 : need_hash = libspdm_req_asym_func_need_hash(req_base_asym_alg);
1785 14 : LIBSPDM_ASSERT (hash_size == libspdm_get_hash_size(base_hash_algo));
1786 :
1787 14 : param = NULL;
1788 14 : param_size = 0;
1789 :
1790 14 : if ((spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT) > SPDM_MESSAGE_VERSION_11) {
1791 : /* Need use SPDM 1.2 signing */
1792 6 : switch (req_base_asym_alg) {
1793 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256:
1794 0 : param = "";
1795 0 : param_size = 0;
1796 0 : break;
1797 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519:
1798 0 : hash_nid = LIBSPDM_CRYPTO_NID_NULL;
1799 0 : break;
1800 0 : case SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448:
1801 0 : hash_nid = LIBSPDM_CRYPTO_NID_NULL;
1802 0 : param = libspdm_get_signing_context_string (spdm_version, op_code, true, ¶m_size);
1803 0 : break;
1804 6 : default:
1805 : /* pass thru for rest algorithm */
1806 6 : break;
1807 : }
1808 :
1809 6 : libspdm_create_signing_context (spdm_version, op_code, true,
1810 : spdm12_signing_context_with_hash);
1811 6 : libspdm_copy_mem(&spdm12_signing_context_with_hash[SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE],
1812 : sizeof(spdm12_signing_context_with_hash)
1813 : - (&spdm12_signing_context_with_hash[SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE]
1814 : - spdm12_signing_context_with_hash),
1815 : message_hash, hash_size);
1816 :
1817 : /* assign message and message_size for signing */
1818 6 : message = spdm12_signing_context_with_hash;
1819 6 : message_size = SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE + hash_size;
1820 :
1821 6 : if (need_hash) {
1822 6 : result = libspdm_hash_all(base_hash_algo, message, message_size,
1823 : full_message_hash);
1824 6 : if (!result) {
1825 0 : return false;
1826 : }
1827 6 : return libspdm_asym_sign_wrap(context, hash_nid, req_base_asym_alg,
1828 : param, param_size,
1829 : full_message_hash, hash_size,
1830 : signature, sig_size);
1831 : } else {
1832 0 : return libspdm_asym_sign_wrap(context, hash_nid, req_base_asym_alg,
1833 : param, param_size,
1834 : message, message_size,
1835 : signature, sig_size);
1836 : }
1837 :
1838 : /* SPDM 1.2 signing done. */
1839 : }
1840 :
1841 8 : if (need_hash) {
1842 8 : return libspdm_asym_sign_wrap(context, hash_nid, req_base_asym_alg,
1843 : param, param_size,
1844 : message_hash, hash_size,
1845 : signature, sig_size);
1846 : } else {
1847 0 : LIBSPDM_ASSERT (false);
1848 0 : return false;
1849 : }
1850 : }
|