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