Skip to content

Commit

Permalink
Add 1.3 support for challenge
Browse files Browse the repository at this point in the history
Signed-off-by: Jiewen Yao <[email protected]>
  • Loading branch information
jyao1 committed Nov 4, 2023
1 parent f029916 commit def8b31
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 24 deletions.
3 changes: 3 additions & 0 deletions include/industry_standard/spdm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */
Expand All @@ -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;

Expand Down
36 changes: 36 additions & 0 deletions include/library/spdm_requester_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
129 changes: 107 additions & 22 deletions library/spdm_requester_lib/libspdm_req_challenge.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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).
*
Expand All @@ -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,
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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)) {
Expand All @@ -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));
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down
23 changes: 21 additions & 2 deletions library/spdm_responder_lib/libspdm_rsp_challenge_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -251,19 +261,28 @@ 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);

*response_size = spdm_response_size;

/* 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,
Expand Down

0 comments on commit def8b31

Please sign in to comment.