From def8b316520146575321224f57c22fe7c3cc78a1 Mon Sep 17 00:00:00 2001 From: Jiewen Yao Date: Tue, 31 Oct 2023 19:32:47 +0800 Subject: [PATCH] Add 1.3 support for challenge Signed-off-by: Jiewen Yao --- include/industry_standard/spdm.h | 3 + include/library/spdm_requester_lib.h | 36 +++++ .../libspdm_req_challenge.c | 129 +++++++++++++++--- .../libspdm_rsp_challenge_auth.c | 23 +++- 4 files changed, 167 insertions(+), 24 deletions(-) diff --git a/include/industry_standard/spdm.h b/include/industry_standard/spdm.h index 65dbf8d0c78..189943c8689 100644 --- a/include/industry_standard/spdm.h +++ b/include/industry_standard/spdm.h @@ -21,6 +21,7 @@ #define SPDM_NONCE_SIZE 32 #define SPDM_RANDOM_DATA_SIZE 32 +#define SPDM_REQ_CONTEXT_SIZE 8 /* SPDM response code (1.0) */ #define SPDM_DIGESTS 0x01 @@ -480,6 +481,7 @@ typedef struct { /* param1 == slot_id * param2 == HashType*/ uint8_t nonce[32]; + /*uint8_t requester_context[SPDM_REQ_CONTEXT_SIZE]; */ } spdm_challenge_request_t; /* SPDM CHALLENGE response */ @@ -492,6 +494,7 @@ typedef struct { * uint8_t measurement_summary_hash[digest_size]; * uint16_t opaque_length; * uint8_t opaque_data[opaque_length]; + * uint8_t requester_context[SPDM_REQ_CONTEXT_SIZE]; * uint8_t signature[key_size];*/ } spdm_challenge_auth_response_t; diff --git a/include/library/spdm_requester_lib.h b/include/library/spdm_requester_lib.h index 6062ba4405c..c7af38fbcbf 100644 --- a/include/library/spdm_requester_lib.h +++ b/include/library/spdm_requester_lib.h @@ -197,6 +197,42 @@ libspdm_return_t libspdm_challenge_ex(void *spdm_context, void *reserved, void *opaque_data, size_t *opaque_data_size); +/** + * This function sends CHALLENGE to authenticate the device based upon the key in one slot. + * + * This function verifies the signature in the challenge auth. + * + * If basic mutual authentication is requested from the responder, + * this function also performs the basic mutual authentication. + * + * @param spdm_context A pointer to the SPDM context. + * @param reserved Reserved for session_id and is ignored. + * @param slot_id The number of slot for the challenge. + * @param measurement_hash_type The type of the measurement hash. + * @param measurement_hash A pointer to a destination buffer to store the measurement hash. + * @param slot_mask A pointer to a destination to store the slot mask. + * @param requester_nonce_in A buffer to hold the requester nonce (32 bytes) as input, if not NULL. + * @param requester_context A buffer to hold the requester context (8 bytes) as input, if not NULL. + * It is used only if the negotiated version >= 1.3. + * @param requester_nonce A buffer to hold the requester nonce (32 bytes), if not NULL. + * @param responder_nonce A buffer to hold the responder nonce (32 bytes), if not NULL. + * @param opaque_data A buffer to hold the responder opaque data, if not NULL. + * @param opaque_data_size On input, the size of the opaque data buffer. + * Responder opaque data should be less than 1024 bytes. + * On output, the size of the opaque data. + **/ +libspdm_return_t libspdm_challenge_ex2(void *spdm_context, void *reserved, + uint8_t slot_id, + uint8_t measurement_hash_type, + void *measurement_hash, + uint8_t *slot_mask, + const void *requester_nonce_in, + const void *requester_context, + void *requester_nonce, + void *responder_nonce, + void *opaque_data, + size_t *opaque_data_size); + /** * This function sends GET_MEASUREMENT * to get measurement from the device. diff --git a/library/spdm_requester_lib/libspdm_req_challenge.c b/library/spdm_requester_lib/libspdm_req_challenge.c index 91a132ad02c..5717ec9f472 100644 --- a/library/spdm_requester_lib/libspdm_req_challenge.c +++ b/library/spdm_requester_lib/libspdm_req_challenge.c @@ -16,6 +16,7 @@ typedef struct { uint8_t measurement_summary_hash[LIBSPDM_MAX_HASH_SIZE]; uint16_t opaque_length; uint8_t opaque_data[SPDM_MAX_OPAQUE_DATA_SIZE]; + uint8_t requester_context[SPDM_REQ_CONTEXT_SIZE]; uint8_t signature[LIBSPDM_MAX_ASYM_KEY_SIZE]; } libspdm_challenge_auth_response_max_t; #pragma pack() @@ -34,6 +35,8 @@ typedef struct { * @param measurement_hash A pointer to a destination buffer to store the measurement hash. * @param slot_mask A pointer to a destination to store the slot mask. * @param requester_nonce_in If not NULL, a buffer that holds the requester nonce (32 bytes) + * @param requester_context If not NULL, a buffer to hold the requester context (8 bytes). + * It is used only if the negotiated version >= 1.3. * @param requester_nonce If not NULL, a buffer to hold the requester nonce (32 bytes). * @param responder_nonce If not NULL, a buffer to hold the responder nonce (32 bytes). * @@ -47,6 +50,7 @@ static libspdm_return_t libspdm_try_challenge(libspdm_context_t *spdm_context, void *measurement_hash, uint8_t *slot_mask, const void *requester_nonce_in, + const void *requester_context, void *requester_nonce, void *responder_nonce, void *opaque_data, @@ -110,6 +114,9 @@ static libspdm_return_t libspdm_try_challenge(libspdm_context_t *spdm_context, spdm_request->header.param1 = slot_id; spdm_request->header.param2 = measurement_hash_type; spdm_request_size = sizeof(spdm_challenge_request_t); + if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) { + spdm_request_size = sizeof(spdm_challenge_request_t) + SPDM_REQ_CONTEXT_SIZE; + } if (requester_nonce_in == NULL) { if(!libspdm_get_random_number(SPDM_NONCE_SIZE, spdm_request->nonce)) { libspdm_release_sender_buffer (spdm_context); @@ -125,6 +132,17 @@ static libspdm_return_t libspdm_try_challenge(libspdm_context_t *spdm_context, if (requester_nonce != NULL) { libspdm_copy_mem(requester_nonce, SPDM_NONCE_SIZE, spdm_request->nonce, SPDM_NONCE_SIZE); } + if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) { + if (requester_context == NULL) { + libspdm_zero_mem(spdm_request + 1, SPDM_REQ_CONTEXT_SIZE); + } else { + libspdm_copy_mem(spdm_request + 1, SPDM_REQ_CONTEXT_SIZE, + requester_context, SPDM_REQ_CONTEXT_SIZE); + } + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterContext - ")); + LIBSPDM_INTERNAL_DUMP_DATA((uint8_t *)(spdm_request + 1), SPDM_REQ_CONTEXT_SIZE); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n")); + } /* -=[Send Request Phase]=- */ status = libspdm_send_spdm_request(spdm_context, NULL, spdm_request_size, spdm_request); @@ -274,26 +292,31 @@ static libspdm_return_t libspdm_try_challenge(libspdm_context_t *spdm_context, } } - status = libspdm_append_message_c(spdm_context, spdm_request, spdm_request_size); - if (LIBSPDM_STATUS_IS_ERROR(status)) { - goto receive_done; - } - if (spdm_response_size < - sizeof(spdm_challenge_auth_response_t) + hash_size + - SPDM_NONCE_SIZE + measurement_summary_hash_size + - sizeof(uint16_t) + opaque_length + signature_size) { - status = LIBSPDM_STATUS_INVALID_MSG_SIZE; - goto receive_done; - } - spdm_response_size = sizeof(spdm_challenge_auth_response_t) + - hash_size + SPDM_NONCE_SIZE + - measurement_summary_hash_size + sizeof(uint16_t) + - opaque_length + signature_size; - status = libspdm_append_message_c(spdm_context, spdm_response, - spdm_response_size - signature_size); - if (LIBSPDM_STATUS_IS_ERROR(status)) { - libspdm_reset_message_c(spdm_context); - goto receive_done; + if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) { + if (spdm_response_size < + sizeof(spdm_challenge_auth_response_t) + hash_size + + SPDM_NONCE_SIZE + measurement_summary_hash_size + + sizeof(uint16_t) + opaque_length + SPDM_REQ_CONTEXT_SIZE + + signature_size) { + status = LIBSPDM_STATUS_INVALID_MSG_SIZE; + goto receive_done; + } + spdm_response_size = sizeof(spdm_challenge_auth_response_t) + + hash_size + SPDM_NONCE_SIZE + + measurement_summary_hash_size + sizeof(uint16_t) + + opaque_length + SPDM_REQ_CONTEXT_SIZE + signature_size; + } else { + if (spdm_response_size < + sizeof(spdm_challenge_auth_response_t) + hash_size + + SPDM_NONCE_SIZE + measurement_summary_hash_size + + sizeof(uint16_t) + opaque_length + signature_size) { + status = LIBSPDM_STATUS_INVALID_MSG_SIZE; + goto receive_done; + } + spdm_response_size = sizeof(spdm_challenge_auth_response_t) + + hash_size + SPDM_NONCE_SIZE + + measurement_summary_hash_size + sizeof(uint16_t) + + opaque_length + signature_size; } if ((opaque_data != NULL) && (opaque_data_size != NULL)) { @@ -306,6 +329,28 @@ static libspdm_return_t libspdm_try_challenge(libspdm_context_t *spdm_context, } ptr += opaque_length; + if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) { + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterContext - ")); + LIBSPDM_INTERNAL_DUMP_DATA(ptr, SPDM_REQ_CONTEXT_SIZE); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n")); + if (!libspdm_consttime_is_mem_equal(spdm_request + 1, ptr, SPDM_REQ_CONTEXT_SIZE)) { + libspdm_reset_message_c(spdm_context); + status = LIBSPDM_STATUS_INVALID_MSG_FIELD; + goto receive_done; + } + ptr += SPDM_REQ_CONTEXT_SIZE; + } + + status = libspdm_append_message_c(spdm_context, spdm_request, spdm_request_size); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + goto receive_done; + } + status = libspdm_append_message_c(spdm_context, spdm_response, + spdm_response_size - signature_size); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + libspdm_reset_message_c(spdm_context); + goto receive_done; + } signature = ptr; LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature (0x%x):\n", signature_size)); @@ -371,7 +416,7 @@ libspdm_return_t libspdm_challenge(void *spdm_context, void *reserved, status = libspdm_try_challenge(context, slot_id, measurement_hash_type, measurement_hash, slot_mask, - NULL, NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL, NULL); if ((status != LIBSPDM_STATUS_BUSY_PEER) || (retry == 0)) { return status; } @@ -407,7 +452,47 @@ libspdm_return_t libspdm_challenge_ex(void *spdm_context, void *reserved, measurement_hash_type, measurement_hash, slot_mask, - requester_nonce_in, + requester_nonce_in, NULL, + requester_nonce, responder_nonce, + opaque_data, + opaque_data_size); + if ((status != LIBSPDM_STATUS_BUSY_PEER) || (retry == 0)) { + return status; + } + + libspdm_sleep(retry_delay_time); + } while (retry-- != 0); + + return status; +} + +libspdm_return_t libspdm_challenge_ex2(void *spdm_context, void *reserved, + uint8_t slot_id, + uint8_t measurement_hash_type, + void *measurement_hash, + uint8_t *slot_mask, + const void *requester_nonce_in, + const void *requester_context, + void *requester_nonce, + void *responder_nonce, + void *opaque_data, + size_t *opaque_data_size) +{ + libspdm_context_t *context; + size_t retry; + uint64_t retry_delay_time; + libspdm_return_t status; + + context = spdm_context; + context->crypto_request = true; + retry = context->retry_times; + retry_delay_time = context->retry_delay_time; + do { + status = libspdm_try_challenge(context, slot_id, + measurement_hash_type, + measurement_hash, + slot_mask, + requester_nonce_in, requester_context, requester_nonce, responder_nonce, opaque_data, opaque_data_size); diff --git a/library/spdm_responder_lib/libspdm_rsp_challenge_auth.c b/library/spdm_responder_lib/libspdm_rsp_challenge_auth.c index 416f64021ca..14f975a3547 100644 --- a/library/spdm_responder_lib/libspdm_rsp_challenge_auth.c +++ b/library/spdm_responder_lib/libspdm_rsp_challenge_auth.c @@ -16,6 +16,7 @@ libspdm_return_t libspdm_get_response_challenge_auth(libspdm_context_t *spdm_con void *response) { const spdm_challenge_request_t *spdm_request; + size_t spdm_request_size; spdm_challenge_auth_response_t *spdm_response; bool result; size_t signature_size; @@ -70,6 +71,15 @@ libspdm_return_t libspdm_get_response_challenge_auth(libspdm_context_t *spdm_con SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response); } + spdm_request_size = sizeof(spdm_challenge_request_t); + if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) { + if (request_size < sizeof(spdm_challenge_request_t) + SPDM_REQ_CONTEXT_SIZE) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_INVALID_REQUEST, 0, + response_size, response); + } + spdm_request_size += SPDM_REQ_CONTEXT_SIZE; + } if (spdm_request->header.param2 > 0) { if (!libspdm_is_capabilities_flag_supported( spdm_context, false, 0, @@ -118,7 +128,7 @@ libspdm_return_t libspdm_get_response_challenge_auth(libspdm_context_t *spdm_con /* response_size should be large enough to hold a challenge response without opaque data. */ LIBSPDM_ASSERT(*response_size >= sizeof(spdm_challenge_auth_response_t) + hash_size + SPDM_NONCE_SIZE + measurement_summary_hash_size + sizeof(uint16_t) + - signature_size); + SPDM_REQ_CONTEXT_SIZE + signature_size); libspdm_zero_mem(response, *response_size); spdm_response = response; @@ -251,11 +261,20 @@ libspdm_return_t libspdm_get_response_challenge_auth(libspdm_context_t *spdm_con /*the opaque_data is stored by libspdm_challenge_opaque_data*/ ptr += opaque_data_size; + if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) { + libspdm_copy_mem(ptr, SPDM_REQ_CONTEXT_SIZE, + spdm_request + 1, SPDM_REQ_CONTEXT_SIZE); + ptr += SPDM_REQ_CONTEXT_SIZE; + } + /*get actual response size*/ spdm_response_size = sizeof(spdm_challenge_auth_response_t) + hash_size + SPDM_NONCE_SIZE + measurement_summary_hash_size + sizeof(uint16_t) + opaque_data_size + signature_size; + if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) { + spdm_response_size += SPDM_REQ_CONTEXT_SIZE; + } LIBSPDM_ASSERT(*response_size >= spdm_response_size); @@ -263,7 +282,7 @@ libspdm_return_t libspdm_get_response_challenge_auth(libspdm_context_t *spdm_con /* Calc Sign*/ - status = libspdm_append_message_c(spdm_context, spdm_request, request_size); + status = libspdm_append_message_c(spdm_context, spdm_request, spdm_request_size); if (LIBSPDM_STATUS_IS_ERROR(status)) { return libspdm_generate_error_response(spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0,