Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add 1.3 support for challenge #2420

Merged
merged 1 commit into from
Nov 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
steven-bellock marked this conversation as resolved.
Show resolved Hide resolved

/* 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.
steven-bellock marked this conversation as resolved.
Show resolved Hide resolved
* 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