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_secured_message_lib.h"
8 :
9 818 : static void generate_iv(uint64_t sequence_number, uint8_t *iv, const uint8_t *salt,
10 : size_t aead_iv_size, uint8_t endian)
11 : {
12 : uint8_t iv_temp[LIBSPDM_MAX_AEAD_IV_SIZE];
13 : size_t index;
14 :
15 : /* Form the AEAD IV from the salt and the sequence number. */
16 818 : libspdm_copy_mem(iv, LIBSPDM_MAX_AEAD_IV_SIZE, salt, aead_iv_size);
17 :
18 818 : switch (endian) {
19 818 : case LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_LITTLE:
20 : case LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_BOTH:
21 : /* If little-endian then the sequence number is zero-extended to the higher indices.
22 : * The sequence number begins at the lowest index (0). */
23 818 : libspdm_copy_mem(iv_temp, sizeof(iv_temp), &sequence_number, sizeof(sequence_number));
24 7362 : for (index = 0; index < sizeof(sequence_number); index++) {
25 6544 : iv[index] = iv[index] ^ iv_temp[index];
26 : }
27 818 : break;
28 0 : case LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_BIG_DEC_BIG:
29 : case LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_BIG_DEC_BOTH:
30 : /* If big-endian then the sequence number is zero-extended to the lower indices.
31 : * The sequence number ends at the highest index (aead_size - 1). */
32 0 : sequence_number = libspdm_byte_swap_64(sequence_number);
33 0 : libspdm_copy_mem(iv_temp + (aead_iv_size - sizeof(sequence_number)),
34 : aead_iv_size,
35 : &sequence_number,
36 : sizeof(sequence_number));
37 0 : for (index = aead_iv_size - sizeof(sequence_number); index < aead_iv_size; index++) {
38 0 : iv[index] = iv[index] ^ iv_temp[index];
39 : }
40 0 : break;
41 : }
42 818 : }
43 :
44 0 : static uint8_t swap_endian(uint8_t endian)
45 : {
46 0 : switch (endian) {
47 0 : case LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_BOTH:
48 0 : return LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_BIG_DEC_BIG;
49 0 : case LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_BIG_DEC_BOTH:
50 0 : return LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_LITTLE;
51 0 : default:
52 0 : LIBSPDM_ASSERT(0);
53 0 : return 0;
54 : }
55 : }
56 :
57 335 : static bool is_sequence_number_endian_determined(uint8_t endian)
58 : {
59 : return ((endian == LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_BIG_DEC_BIG) ||
60 335 : (endian == LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_LITTLE)) ? true : false;
61 : }
62 :
63 482 : libspdm_return_t libspdm_encode_secured_message(
64 : void *spdm_secured_message_context, uint32_t session_id,
65 : bool is_request_message, size_t app_message_size,
66 : void *app_message, size_t *secured_message_size,
67 : void *secured_message,
68 : const libspdm_secured_message_callbacks_t *spdm_secured_message_callbacks)
69 : {
70 : libspdm_secured_message_context_t *secured_message_context;
71 : size_t total_secured_message_size;
72 : size_t plain_text_size;
73 : size_t cipher_text_size;
74 : size_t aead_tag_size;
75 : size_t aead_key_size;
76 : size_t aead_iv_size;
77 : uint8_t *a_data;
78 : uint8_t *enc_msg;
79 : uint8_t *dec_msg;
80 : uint8_t *tag;
81 : spdm_secured_message_a_data_header1_t *record_header1;
82 : spdm_secured_message_a_data_header2_t *record_header2;
83 : size_t record_header_size;
84 : spdm_secured_message_cipher_header_t *enc_msg_header;
85 : bool result;
86 : const uint8_t *key;
87 : uint8_t *salt;
88 : uint8_t iv[LIBSPDM_MAX_AEAD_IV_SIZE];
89 : uint64_t sequence_number;
90 : uint64_t sequence_num_in_header;
91 : uint8_t sequence_num_in_header_size;
92 : libspdm_session_type_t session_type;
93 : uint32_t rand_count;
94 : uint32_t max_rand_count;
95 : libspdm_session_state_t session_state;
96 : spdm_version_number_t secured_spdm_version;
97 : uint8_t version;
98 :
99 482 : secured_message_context = spdm_secured_message_context;
100 482 : secured_spdm_version = spdm_secured_message_callbacks->get_secured_spdm_version(
101 482 : secured_message_context->secured_message_version);
102 482 : version = (uint8_t)(secured_spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT);
103 482 : if (version > SECURED_SPDM_VERSION_12) {
104 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
105 : }
106 :
107 482 : session_type = secured_message_context->session_type;
108 482 : LIBSPDM_ASSERT((session_type == LIBSPDM_SESSION_TYPE_MAC_ONLY) ||
109 : (session_type == LIBSPDM_SESSION_TYPE_ENC_MAC));
110 482 : session_state = secured_message_context->session_state;
111 482 : LIBSPDM_ASSERT((session_state == LIBSPDM_SESSION_STATE_HANDSHAKING) ||
112 : (session_state == LIBSPDM_SESSION_STATE_ESTABLISHED));
113 :
114 482 : aead_tag_size = secured_message_context->aead_tag_size;
115 482 : aead_key_size = secured_message_context->aead_key_size;
116 482 : aead_iv_size = secured_message_context->aead_iv_size;
117 :
118 482 : switch (session_state) {
119 71 : case LIBSPDM_SESSION_STATE_HANDSHAKING:
120 71 : if (is_request_message) {
121 36 : key = (const uint8_t *)secured_message_context->handshake_secret.
122 : request_handshake_encryption_key;
123 36 : salt = (uint8_t *)secured_message_context->handshake_secret.
124 : request_handshake_salt;
125 36 : sequence_number = secured_message_context->handshake_secret
126 : .request_handshake_sequence_number;
127 : } else {
128 35 : key = (const uint8_t *)secured_message_context->handshake_secret.
129 : response_handshake_encryption_key;
130 35 : salt = (uint8_t *)secured_message_context->handshake_secret.
131 : response_handshake_salt;
132 35 : sequence_number = secured_message_context->handshake_secret
133 : .response_handshake_sequence_number;
134 : }
135 71 : break;
136 411 : case LIBSPDM_SESSION_STATE_ESTABLISHED:
137 411 : if (is_request_message) {
138 208 : key = (const uint8_t *)secured_message_context->application_secret.
139 : request_data_encryption_key;
140 208 : salt = (uint8_t *)secured_message_context->application_secret.
141 : request_data_salt;
142 208 : sequence_number = secured_message_context->application_secret
143 : .request_data_sequence_number;
144 : } else {
145 203 : key = (const uint8_t *)secured_message_context->application_secret.
146 : response_data_encryption_key;
147 203 : salt = (uint8_t *)secured_message_context->application_secret.
148 : response_data_salt;
149 203 : sequence_number = secured_message_context->application_secret
150 : .response_data_sequence_number;
151 : }
152 411 : break;
153 0 : default:
154 0 : LIBSPDM_ASSERT(false);
155 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
156 : break;
157 : }
158 :
159 482 : if (sequence_number >= secured_message_context->max_spdm_session_sequence_number) {
160 0 : return LIBSPDM_STATUS_SEQUENCE_NUMBER_OVERFLOW;
161 : }
162 :
163 482 : generate_iv(sequence_number, iv, salt, aead_iv_size,
164 482 : secured_message_context->sequence_number_endian);
165 :
166 482 : sequence_num_in_header = 0;
167 482 : sequence_num_in_header_size = spdm_secured_message_callbacks->get_sequence_number(
168 : sequence_number, (uint8_t *)&sequence_num_in_header);
169 482 : LIBSPDM_ASSERT(sequence_num_in_header_size <= sizeof(sequence_num_in_header));
170 :
171 482 : if (session_state == LIBSPDM_SESSION_STATE_HANDSHAKING) {
172 71 : if (is_request_message) {
173 36 : secured_message_context->handshake_secret.request_handshake_sequence_number++;
174 : } else {
175 35 : secured_message_context->handshake_secret.response_handshake_sequence_number++;
176 : }
177 : } else {
178 411 : if (is_request_message) {
179 208 : secured_message_context->application_secret.request_data_sequence_number++;
180 : } else {
181 203 : secured_message_context->application_secret.response_data_sequence_number++;
182 : }
183 : }
184 :
185 482 : record_header_size = sizeof(spdm_secured_message_a_data_header1_t) +
186 482 : sequence_num_in_header_size +
187 : sizeof(spdm_secured_message_a_data_header2_t);
188 :
189 482 : switch (session_type) {
190 482 : case LIBSPDM_SESSION_TYPE_ENC_MAC:
191 482 : max_rand_count = spdm_secured_message_callbacks->get_max_random_number_count();
192 482 : if (max_rand_count != 0) {
193 482 : rand_count = 0;
194 482 : result = libspdm_get_random_number(sizeof(rand_count), (uint8_t *)&rand_count);
195 482 : if (!result) {
196 0 : return LIBSPDM_STATUS_LOW_ENTROPY;
197 : }
198 482 : rand_count = (uint8_t)((rand_count % max_rand_count) + 1);
199 : } else {
200 0 : rand_count = 0;
201 : }
202 :
203 482 : plain_text_size = sizeof(spdm_secured_message_cipher_header_t) + app_message_size +
204 : rand_count;
205 482 : cipher_text_size = plain_text_size;
206 482 : total_secured_message_size = record_header_size + cipher_text_size + aead_tag_size;
207 :
208 482 : LIBSPDM_ASSERT(*secured_message_size >= total_secured_message_size);
209 482 : if (*secured_message_size < total_secured_message_size) {
210 0 : *secured_message_size = total_secured_message_size;
211 0 : return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
212 : }
213 482 : *secured_message_size = total_secured_message_size;
214 482 : record_header1 = (void *)secured_message;
215 482 : record_header2 = (void *)((uint8_t *)record_header1 +
216 482 : sizeof(spdm_secured_message_a_data_header1_t) +
217 : sequence_num_in_header_size);
218 482 : record_header1->session_id = session_id;
219 482 : libspdm_copy_mem(record_header1 + 1,
220 482 : *secured_message_size
221 482 : - ((uint8_t*)(record_header1 + 1) - (uint8_t*)secured_message),
222 : &sequence_num_in_header,
223 : sequence_num_in_header_size);
224 482 : record_header2->length = (uint16_t)(cipher_text_size + aead_tag_size);
225 :
226 482 : enc_msg_header =
227 : (void *)((uint8_t *)app_message - sizeof(spdm_secured_message_cipher_header_t));
228 482 : enc_msg_header->application_data_length = (uint16_t)app_message_size;
229 482 : result = libspdm_get_random_number(rand_count,
230 : (uint8_t *)enc_msg_header +
231 482 : sizeof(spdm_secured_message_cipher_header_t) +
232 : app_message_size);
233 482 : if (!result) {
234 0 : return LIBSPDM_STATUS_LOW_ENTROPY;
235 : }
236 :
237 482 : a_data = (uint8_t *)record_header1;
238 482 : enc_msg = (uint8_t *)(record_header2 + 1);
239 482 : dec_msg = (uint8_t *)enc_msg_header;
240 482 : tag = (uint8_t *)record_header1 + record_header_size +
241 : cipher_text_size;
242 :
243 482 : result = libspdm_aead_encryption(
244 482 : secured_message_context->secured_message_version,
245 482 : secured_message_context->aead_cipher_suite, key,
246 : aead_key_size, iv, aead_iv_size, (uint8_t *)a_data,
247 : record_header_size, dec_msg, cipher_text_size, tag,
248 : aead_tag_size, enc_msg, &cipher_text_size);
249 482 : break;
250 :
251 0 : case LIBSPDM_SESSION_TYPE_MAC_ONLY:
252 0 : total_secured_message_size =
253 0 : record_header_size + app_message_size + aead_tag_size;
254 :
255 0 : LIBSPDM_ASSERT(*secured_message_size >= total_secured_message_size);
256 0 : if (*secured_message_size < total_secured_message_size) {
257 0 : *secured_message_size = total_secured_message_size;
258 0 : return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
259 : }
260 0 : *secured_message_size = total_secured_message_size;
261 0 : record_header1 = (void *)secured_message;
262 0 : record_header2 =
263 : (void *)((uint8_t *)record_header1 +
264 0 : sizeof(spdm_secured_message_a_data_header1_t) +
265 : sequence_num_in_header_size);
266 0 : record_header1->session_id = session_id;
267 0 : libspdm_copy_mem(record_header1 + 1,
268 0 : *secured_message_size
269 0 : - ((uint8_t*)(record_header1 + 1) - (uint8_t*)secured_message),
270 : &sequence_num_in_header,
271 : sequence_num_in_header_size);
272 0 : record_header2->length =
273 0 : (uint16_t)(app_message_size + aead_tag_size);
274 0 : libspdm_copy_mem(record_header2 + 1,
275 0 : *secured_message_size
276 0 : - ((uint8_t*)(record_header2 + 1) - (uint8_t*)secured_message),
277 : app_message, app_message_size);
278 0 : a_data = (uint8_t *)record_header1;
279 0 : tag = (uint8_t *)record_header1 + record_header_size + app_message_size;
280 :
281 0 : result = libspdm_aead_encryption(
282 0 : secured_message_context->secured_message_version,
283 0 : secured_message_context->aead_cipher_suite, key,
284 : aead_key_size, iv, aead_iv_size, (uint8_t *)a_data,
285 : record_header_size + app_message_size, NULL, 0, tag,
286 : aead_tag_size, NULL, NULL);
287 0 : break;
288 :
289 0 : default:
290 0 : LIBSPDM_ASSERT(false);
291 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
292 : }
293 482 : if (!result) {
294 0 : return LIBSPDM_STATUS_CRYPTO_ERROR;
295 : }
296 482 : return LIBSPDM_STATUS_SUCCESS;
297 : }
298 :
299 336 : libspdm_return_t libspdm_decode_secured_message(
300 : void *spdm_secured_message_context, uint32_t session_id,
301 : bool is_request_message, size_t secured_message_size,
302 : void *secured_message, size_t *app_message_size,
303 : void **app_message,
304 : const libspdm_secured_message_callbacks_t *spdm_secured_message_callbacks)
305 : {
306 : libspdm_secured_message_context_t *secured_message_context;
307 : size_t plain_text_size;
308 : size_t cipher_text_size;
309 : size_t aead_tag_size;
310 : size_t aead_key_size;
311 : size_t aead_iv_size;
312 : const uint8_t *a_data;
313 : const uint8_t *enc_msg;
314 : uint8_t *dec_msg;
315 : const uint8_t *tag;
316 : spdm_secured_message_a_data_header1_t *record_header1;
317 : spdm_secured_message_a_data_header2_t *record_header2;
318 : size_t record_header_size;
319 : spdm_secured_message_cipher_header_t *enc_msg_header;
320 : bool result;
321 : const uint8_t *key;
322 : uint8_t *salt;
323 : uint8_t iv[LIBSPDM_MAX_AEAD_IV_SIZE];
324 : uint64_t sequence_number;
325 : uint64_t sequence_num_in_header;
326 : uint8_t sequence_num_in_header_size;
327 : libspdm_session_type_t session_type;
328 : libspdm_session_state_t session_state;
329 : libspdm_error_struct_t spdm_error;
330 : spdm_version_number_t secured_spdm_version;
331 : uint8_t version;
332 :
333 336 : spdm_error.error_code = 0;
334 336 : spdm_error.session_id = 0;
335 336 : libspdm_secured_message_set_last_spdm_error_struct(spdm_secured_message_context, &spdm_error);
336 :
337 336 : spdm_error.error_code = SPDM_ERROR_CODE_DECRYPT_ERROR;
338 336 : spdm_error.session_id = session_id;
339 :
340 336 : secured_message_context = spdm_secured_message_context;
341 336 : secured_spdm_version = spdm_secured_message_callbacks->get_secured_spdm_version(
342 336 : secured_message_context->secured_message_version);
343 336 : version = (uint8_t)(secured_spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT);
344 336 : if (version > SECURED_SPDM_VERSION_12) {
345 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
346 : }
347 :
348 336 : session_type = secured_message_context->session_type;
349 336 : LIBSPDM_ASSERT((session_type == LIBSPDM_SESSION_TYPE_MAC_ONLY) ||
350 : (session_type == LIBSPDM_SESSION_TYPE_ENC_MAC));
351 336 : session_state = secured_message_context->session_state;
352 336 : LIBSPDM_ASSERT((session_state == LIBSPDM_SESSION_STATE_HANDSHAKING) ||
353 : (session_state == LIBSPDM_SESSION_STATE_ESTABLISHED));
354 :
355 336 : aead_tag_size = secured_message_context->aead_tag_size;
356 336 : aead_key_size = secured_message_context->aead_key_size;
357 336 : aead_iv_size = secured_message_context->aead_iv_size;
358 :
359 336 : switch (session_state) {
360 37 : case LIBSPDM_SESSION_STATE_HANDSHAKING:
361 37 : if (is_request_message) {
362 2 : key = (const uint8_t *)secured_message_context->handshake_secret.
363 : request_handshake_encryption_key;
364 2 : salt = (uint8_t *)secured_message_context->handshake_secret.
365 : request_handshake_salt;
366 2 : sequence_number =
367 : secured_message_context->handshake_secret.request_handshake_sequence_number;
368 : } else {
369 35 : key = (const uint8_t *)secured_message_context->handshake_secret.
370 : response_handshake_encryption_key;
371 35 : salt = (uint8_t *)secured_message_context->handshake_secret.
372 : response_handshake_salt;
373 35 : sequence_number =
374 : secured_message_context->handshake_secret.response_handshake_sequence_number;
375 : }
376 37 : break;
377 299 : case LIBSPDM_SESSION_STATE_ESTABLISHED:
378 299 : if (is_request_message) {
379 67 : key = (const uint8_t *)secured_message_context->application_secret.
380 : request_data_encryption_key;
381 67 : salt = (uint8_t *)secured_message_context->application_secret.
382 : request_data_salt;
383 67 : sequence_number =
384 : secured_message_context->application_secret.request_data_sequence_number;
385 : } else {
386 232 : key = (const uint8_t *)secured_message_context->application_secret.
387 : response_data_encryption_key;
388 232 : salt = (uint8_t *)secured_message_context->application_secret.
389 : response_data_salt;
390 232 : sequence_number =
391 : secured_message_context->application_secret.response_data_sequence_number;
392 : }
393 299 : break;
394 0 : default:
395 0 : LIBSPDM_ASSERT(false);
396 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
397 : }
398 :
399 336 : if (sequence_number >= secured_message_context->max_spdm_session_sequence_number) {
400 0 : libspdm_secured_message_set_last_spdm_error_struct(
401 : spdm_secured_message_context, &spdm_error);
402 0 : return LIBSPDM_STATUS_SEQUENCE_NUMBER_OVERFLOW;
403 : }
404 :
405 336 : generate_iv(sequence_number, iv, salt, aead_iv_size,
406 336 : secured_message_context->sequence_number_endian);
407 :
408 336 : sequence_num_in_header = 0;
409 : sequence_num_in_header_size =
410 336 : spdm_secured_message_callbacks->get_sequence_number(
411 : sequence_number, (uint8_t *)&sequence_num_in_header);
412 336 : LIBSPDM_ASSERT(sequence_num_in_header_size <= sizeof(sequence_num_in_header));
413 :
414 336 : if (session_state == LIBSPDM_SESSION_STATE_HANDSHAKING) {
415 37 : if (is_request_message) {
416 2 : secured_message_context->handshake_secret.request_handshake_sequence_number++;
417 : } else {
418 35 : secured_message_context->handshake_secret.response_handshake_sequence_number++;
419 : }
420 : } else {
421 299 : if (is_request_message) {
422 67 : secured_message_context->application_secret.request_data_sequence_number++;
423 : } else {
424 232 : secured_message_context->application_secret.response_data_sequence_number++;
425 : }
426 : }
427 :
428 336 : record_header_size = sizeof(spdm_secured_message_a_data_header1_t) +
429 336 : sequence_num_in_header_size +
430 : sizeof(spdm_secured_message_a_data_header2_t);
431 :
432 336 : switch (session_type) {
433 336 : case LIBSPDM_SESSION_TYPE_ENC_MAC:
434 336 : if (secured_message_size < record_header_size + aead_tag_size) {
435 0 : libspdm_secured_message_set_last_spdm_error_struct(
436 : spdm_secured_message_context, &spdm_error);
437 0 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
438 : }
439 336 : record_header1 = secured_message;
440 336 : record_header2 =
441 : (void *)((uint8_t *)record_header1 +
442 336 : sizeof(spdm_secured_message_a_data_header1_t) +
443 : sequence_num_in_header_size);
444 336 : if (record_header1->session_id != session_id) {
445 0 : libspdm_secured_message_set_last_spdm_error_struct(
446 : spdm_secured_message_context, &spdm_error);
447 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
448 : }
449 336 : if (!libspdm_consttime_is_mem_equal(record_header1 + 1, &sequence_num_in_header,
450 : sequence_num_in_header_size)) {
451 1 : libspdm_secured_message_set_last_spdm_error_struct(
452 : spdm_secured_message_context, &spdm_error);
453 1 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
454 : }
455 335 : if (record_header2->length > secured_message_size - record_header_size) {
456 0 : libspdm_secured_message_set_last_spdm_error_struct(
457 : spdm_secured_message_context, &spdm_error);
458 0 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
459 : }
460 335 : if (record_header2->length < aead_tag_size) {
461 0 : libspdm_secured_message_set_last_spdm_error_struct(
462 : spdm_secured_message_context, &spdm_error);
463 0 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
464 : }
465 335 : cipher_text_size = (record_header2->length - aead_tag_size);
466 335 : if (cipher_text_size > *app_message_size) {
467 0 : return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
468 : }
469 335 : libspdm_zero_mem(*app_message, *app_message_size);
470 335 : enc_msg_header = (void *)(record_header2 + 1);
471 335 : a_data = (const uint8_t *)record_header1;
472 335 : enc_msg = (const uint8_t *)enc_msg_header;
473 335 : dec_msg = (uint8_t *)*app_message;
474 335 : enc_msg_header = (void *)dec_msg;
475 335 : tag = (const uint8_t *)record_header1 + record_header_size + cipher_text_size;
476 :
477 335 : result = libspdm_aead_decryption(
478 335 : secured_message_context->secured_message_version,
479 335 : secured_message_context->aead_cipher_suite, key,
480 : aead_key_size, iv, aead_iv_size, a_data,
481 : record_header_size, enc_msg, cipher_text_size, tag,
482 : aead_tag_size, dec_msg, &cipher_text_size);
483 :
484 : /* When the sequence number is 0 then it has the same encoding in both
485 : * big and little endian. The endianness can only be determined on the subsequent
486 : * decryption. */
487 335 : if (!is_sequence_number_endian_determined(
488 335 : secured_message_context->sequence_number_endian) && (sequence_number == 1)) {
489 :
490 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Sequence number endianness is not determined.\n"));
491 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Attempting to determine endianness.\n"));
492 :
493 0 : if (result) {
494 : /* Endianness is correct so set the endianness. */
495 0 : if (secured_message_context->sequence_number_endian ==
496 : LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_BOTH) {
497 0 : secured_message_context->sequence_number_endian =
498 : LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_LITTLE;
499 : } else {
500 0 : secured_message_context->sequence_number_endian =
501 : LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_BIG_DEC_BIG;
502 : }
503 : } else {
504 : /* Endianness may be incorrect so try with the opposite endianness. */
505 0 : generate_iv(sequence_number, iv, salt, aead_iv_size,
506 0 : swap_endian(secured_message_context->sequence_number_endian));
507 :
508 0 : result = libspdm_aead_decryption(
509 0 : secured_message_context->secured_message_version,
510 0 : secured_message_context->aead_cipher_suite, key,
511 : aead_key_size, iv, aead_iv_size, a_data,
512 : record_header_size, enc_msg, cipher_text_size, tag,
513 : aead_tag_size, dec_msg, &cipher_text_size);
514 :
515 0 : if (result) {
516 : /* Endianness is correct so set the endianness. */
517 0 : secured_message_context->sequence_number_endian =
518 0 : swap_endian(secured_message_context->sequence_number_endian);
519 : }
520 : }
521 : }
522 :
523 335 : if (!result) {
524 : /* Backup keys are valid, fail and alert rollback and retry is possible. */
525 27 : if ((is_request_message && secured_message_context->requester_backup_valid) ||
526 27 : ((!is_request_message) && secured_message_context->responder_backup_valid)) {
527 27 : return LIBSPDM_STATUS_SESSION_TRY_DISCARD_KEY_UPDATE;
528 : }
529 :
530 0 : libspdm_secured_message_set_last_spdm_error_struct(
531 : spdm_secured_message_context, &spdm_error);
532 0 : return LIBSPDM_STATUS_CRYPTO_ERROR;
533 : }
534 308 : plain_text_size = enc_msg_header->application_data_length;
535 308 : if (plain_text_size > cipher_text_size) {
536 0 : libspdm_secured_message_set_last_spdm_error_struct(
537 : spdm_secured_message_context, &spdm_error);
538 0 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
539 : }
540 :
541 308 : LIBSPDM_ASSERT(*app_message_size >= plain_text_size);
542 308 : *app_message = enc_msg_header + 1;
543 308 : *app_message_size = plain_text_size;
544 308 : break;
545 :
546 0 : case LIBSPDM_SESSION_TYPE_MAC_ONLY:
547 0 : if (secured_message_size < record_header_size + aead_tag_size) {
548 0 : libspdm_secured_message_set_last_spdm_error_struct(
549 : spdm_secured_message_context, &spdm_error);
550 0 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
551 : }
552 0 : record_header1 = secured_message;
553 0 : record_header2 =
554 : (void *)((uint8_t *)record_header1 +
555 0 : sizeof(spdm_secured_message_a_data_header1_t) +
556 : sequence_num_in_header_size);
557 0 : if (record_header1->session_id != session_id) {
558 0 : libspdm_secured_message_set_last_spdm_error_struct(
559 : spdm_secured_message_context, &spdm_error);
560 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
561 : }
562 0 : if (!libspdm_consttime_is_mem_equal(record_header1 + 1, &sequence_num_in_header,
563 : sequence_num_in_header_size)) {
564 0 : libspdm_secured_message_set_last_spdm_error_struct(
565 : spdm_secured_message_context, &spdm_error);
566 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
567 : }
568 0 : if (record_header2->length >
569 0 : secured_message_size - record_header_size) {
570 0 : libspdm_secured_message_set_last_spdm_error_struct(
571 : spdm_secured_message_context, &spdm_error);
572 0 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
573 : }
574 0 : if (record_header2->length < aead_tag_size) {
575 0 : libspdm_secured_message_set_last_spdm_error_struct(
576 : spdm_secured_message_context, &spdm_error);
577 0 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
578 : }
579 0 : a_data = (uint8_t *)record_header1;
580 0 : tag = (uint8_t *)record_header1 + record_header_size +
581 0 : record_header2->length - aead_tag_size;
582 :
583 0 : result = libspdm_aead_decryption(
584 0 : secured_message_context->secured_message_version,
585 0 : secured_message_context->aead_cipher_suite, key,
586 : aead_key_size, iv, aead_iv_size, a_data,
587 0 : record_header_size + record_header2->length - aead_tag_size,
588 : NULL, 0, tag, aead_tag_size, NULL, NULL);
589 :
590 : /* When the sequence number is 0 then it has the same encoding in both
591 : * big and little endian. The endianness can only be determined on the subsequent
592 : * decryption. */
593 0 : if (!is_sequence_number_endian_determined(
594 0 : secured_message_context->sequence_number_endian) && (sequence_number == 1)) {
595 0 : if (result) {
596 : /* Endianness is correct so set the endianness. */
597 0 : if (secured_message_context->sequence_number_endian ==
598 : LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_BOTH) {
599 0 : secured_message_context->sequence_number_endian =
600 : LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_LITTLE;
601 : } else {
602 0 : secured_message_context->sequence_number_endian =
603 : LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_BIG_DEC_BIG;
604 : }
605 : } else {
606 : /* Endianness may be incorrect so try with the opposite endianness. */
607 0 : generate_iv(sequence_number, iv, salt, aead_iv_size,
608 0 : swap_endian(secured_message_context->sequence_number_endian));
609 :
610 0 : result = libspdm_aead_decryption(
611 0 : secured_message_context->secured_message_version,
612 0 : secured_message_context->aead_cipher_suite, key,
613 : aead_key_size, iv, aead_iv_size, a_data,
614 0 : record_header_size + record_header2->length - aead_tag_size,
615 : NULL, 0, tag, aead_tag_size, NULL, NULL);
616 :
617 0 : if (result) {
618 : /* Endianness is correct so set the endianness. */
619 0 : secured_message_context->sequence_number_endian =
620 0 : swap_endian(secured_message_context->sequence_number_endian);
621 : }
622 : }
623 : }
624 :
625 0 : if (!result) {
626 : /* Backup keys are valid, fail and alert rollback and retry is possible. */
627 0 : if ((is_request_message && secured_message_context->requester_backup_valid) ||
628 0 : ((!is_request_message) && secured_message_context->responder_backup_valid)) {
629 0 : return LIBSPDM_STATUS_SESSION_TRY_DISCARD_KEY_UPDATE;
630 : }
631 :
632 0 : libspdm_secured_message_set_last_spdm_error_struct(
633 : spdm_secured_message_context, &spdm_error);
634 0 : return LIBSPDM_STATUS_CRYPTO_ERROR;
635 : }
636 :
637 0 : plain_text_size = record_header2->length - aead_tag_size;
638 0 : LIBSPDM_ASSERT(*app_message_size >= plain_text_size);
639 0 : *app_message = record_header2 + 1;
640 0 : *app_message_size = plain_text_size;
641 0 : break;
642 :
643 0 : default:
644 0 : LIBSPDM_ASSERT(false);
645 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
646 : }
647 :
648 308 : return LIBSPDM_STATUS_SUCCESS;
649 : }
|