Merged PR 3264: SPDM 1.0 support for review

SPDM 1.0 support for review

Related work items: #3740
This commit is contained in:
Paul Rhea 2024-05-09 04:37:51 +00:00
Родитель 274dcd9ebf
Коммит 58d1a086c6
10 изменённых файлов: 870 добавлений и 143 удалений

Просмотреть файл

@ -37,6 +37,14 @@ enum {
*/
enum attestation_protocol {
ATTESTATION_PROTOCOL_CERBERUS = 0, /**< Cerberus challenge protocol */
ATTESTATION_PROTOCOL_DMTF_SPDM, /**< DMTF SPDM protocol */
};
/**
* Attestation protocols spdm minor version numbers
*/
enum attestation_spdm_minor_version {
ATTESTATION_PROTOCOL_DMTF_SPDM_1_0 = 0, /**< DMTF SPDM protocol 1.0 */
ATTESTATION_PROTOCOL_DMTF_SPDM_1_1, /**< DMTF SPDM protocol 1.1 */
ATTESTATION_PROTOCOL_DMTF_SPDM_1_2, /**< DMTF SPDM protocol 1.2 */
};

Просмотреть файл

@ -54,7 +54,7 @@
* @param command Command expected
*/
#define attestation_requester_check_spdm_unexpected_rsp(attestation, command) \
((attestation->state->txn.protocol < ATTESTATION_PROTOCOL_DMTF_SPDM_1_1) || \
((attestation->state->txn.protocol != ATTESTATION_PROTOCOL_DMTF_SPDM) || \
(attestation->state->txn.requested_command != command))
/**
@ -65,7 +65,6 @@
#define attestation_requester_is_version_set_selected(attestation) \
(attestation->state->txn.device_version_set != 0)
#if defined (ATTESTATION_SUPPORT_SPDM) || defined (ATTESTATION_SUPPORT_CERBERUS_CHALLENGE)
/**
* Function to send Cerberus protocol or SPDM request and wait for a response. This function
@ -149,7 +148,7 @@ static int attestation_requester_send_request_and_get_response (
request_len =
spdm_generate_respond_if_ready_request (attestation->state->spdm_msg_buffer,
ATTESTATION_REQUESTER_MAX_SPDM_REQUEST, attestation->state->txn.requested_command,
attestation->state->txn.respond_if_ready_token, attestation->state->txn.protocol);
attestation->state->txn.respond_if_ready_token, attestation->state->txn.spdm_minor_version);
if (ROT_IS_ERROR ((int) request_len)) {
return request_len;
}
@ -273,7 +272,7 @@ static int attestation_requester_verify_and_load_leaf_key (
int leaf_key_type;
int status;
if (attestation->state->txn.protocol >= ATTESTATION_PROTOCOL_DMTF_SPDM_1_1) {
if (attestation->state->txn.protocol == ATTESTATION_PROTOCOL_DMTF_SPDM) {
cert_offset = sizeof (struct spdm_certificate_chain) + transcript_hash_len;
}
@ -425,6 +424,55 @@ release_cert_buffer:
return status;
}
/**
* Verify provided ECDSA signature using cached alias key of target device.
*
* @param attestation Attestation requester instance to utilize.
* @param signature Buffer with signature sent by target device to verify.
* @param signature_len Length of signature.
* @param digest Hash to be verified against the signature.
* @param transcript_hash_len Length of the digest.
* @param alias_key Key used to verify the signature.
*
* @return 0 if completed successfully, or an error code
*/
static int attestation_requester_verify_ecdsa_signature (const struct attestation_requester *attestation,
uint8_t* signature, size_t signature_len, uint8_t *digest, size_t transcript_hash_len,
const struct device_manager_key *alias_key)
{
struct ecc_public_key ecc_key;
int signature_der_len;
uint8_t signature_der[ECC_DER_ECDSA_MAX_LENGTH];
int status;
// SPDM signatures are not DER encoded, encode before processing
if (attestation->state->txn.protocol != ATTESTATION_PROTOCOL_CERBERUS) {
signature_der_len = ecc_der_encode_ecdsa_signature (signature,
&signature[attestation->state->txn.alias_signature_len],
attestation->state->txn.alias_signature_len, signature_der, sizeof (signature_der));
if (ROT_IS_ERROR (signature_der_len)) {
return signature_der_len;
}
}
else {
memcpy (signature_der, signature, signature_len);
signature_der_len = signature_len;
}
status = attestation->ecc->init_public_key (attestation->ecc, alias_key->key,
alias_key->key_len, &ecc_key);
if (status != 0) {
return status;
}
status = attestation->ecc->verify (attestation->ecc, &ecc_key, digest, transcript_hash_len,
signature_der, signature_der_len);
attestation->ecc->release_key_pair (attestation->ecc, NULL, &ecc_key);
return status;
}
/**
* Finalize current hash operation, then verify provided signature using cached alias key of
* target device using provided EID.
@ -442,12 +490,10 @@ static int attestation_requester_verify_signature (const struct attestation_requ
struct hash_engine *hash, uint8_t eid, uint8_t *signature, size_t signature_len,
char *spdm_context)
{
uint8_t signature_der[ECC_DER_ECDSA_MAX_LENGTH];
uint8_t digest[HASH_MAX_HASH_LEN];
const struct device_manager_key *alias_key;
size_t transcript_hash_len =
hash_get_hash_length (attestation->state->txn.transcript_hash_type);
int signature_der_len;
int status;
status = hash->finish (hash, digest, sizeof (digest));
@ -464,9 +510,10 @@ static int attestation_requester_verify_signature (const struct attestation_requ
}
#ifdef ATTESTATION_SUPPORT_SPDM
if (attestation->state->txn.protocol >= ATTESTATION_PROTOCOL_DMTF_SPDM_1_2) {
if ((attestation->state->txn.protocol != ATTESTATION_PROTOCOL_CERBERUS) &&
(attestation->state->txn.spdm_minor_version >= ATTESTATION_PROTOCOL_DMTF_SPDM_1_2)) {
status = spdm_format_signature_digest (hash, attestation->state->txn.transcript_hash_type,
attestation->state->txn.protocol, spdm_context, digest);
attestation->state->txn.spdm_minor_version, spdm_context, digest);
if (status != 0) {
return status;
}
@ -479,32 +526,23 @@ static int attestation_requester_verify_signature (const struct attestation_requ
}
if (alias_key->key_type == X509_PUBLIC_KEY_ECC) {
struct ecc_public_key ecc_key;
status = attestation_requester_verify_ecdsa_signature (attestation,
signature, signature_len, digest, transcript_hash_len, alias_key);
// SPDM signatures are not DER encoded, encode before processing
if (attestation->state->txn.protocol != ATTESTATION_PROTOCOL_CERBERUS) {
signature_der_len = ecc_der_encode_ecdsa_signature (signature,
&signature[attestation->state->txn.alias_signature_len],
attestation->state->txn.alias_signature_len, signature_der, sizeof (signature_der));
if (ROT_IS_ERROR (signature_der_len)) {
return signature_der_len;
}
/* The endianess of the signature is not clearly declared in the SPDM 1.0 and 1.1
* specification. It's not possible to programatically identify the endianess used.
* To cover the case where the siguature fails due to the endianess,
* this code swaps the signature endianess, and retries the verification. */
if ((status == ECC_ENGINE_BAD_SIGNATURE) &&
(attestation->state->txn.spdm_minor_version < ATTESTATION_PROTOCOL_DMTF_SPDM_1_2) &&
(attestation->state->txn.protocol != ATTESTATION_PROTOCOL_CERBERUS)) {
buffer_reverse (signature, signature_len / 2);
buffer_reverse (signature + (signature_len / 2), signature_len / 2);
status = attestation_requester_verify_ecdsa_signature (attestation,
signature, signature_len, digest, transcript_hash_len, alias_key);
}
else {
memcpy (signature_der, signature, signature_len);
signature_der_len = signature_len;
}
status = attestation->ecc->init_public_key (attestation->ecc, alias_key->key,
alias_key->key_len, &ecc_key);
if (status != 0) {
return status;
}
status = attestation->ecc->verify (attestation->ecc, &ecc_key, digest, transcript_hash_len,
signature_der, signature_der_len);
attestation->ecc->release_key_pair (attestation->ecc, NULL, &ecc_key);
}
#ifdef ATTESTATION_SUPPORT_RSA_CHALLENGE
else if ((alias_key->key_type == X509_PUBLIC_KEY_RSA) && (attestation->rsa != NULL)) {
@ -563,7 +601,8 @@ static int attestation_requester_get_version_rsp_post_processing (
}
if (found) {
attestation->state->txn.protocol = (enum attestation_protocol) minor_version;
attestation->state->txn.spdm_minor_version = (enum attestation_spdm_minor_version) minor_version;
attestation->state->txn.protocol = (enum attestation_protocol) ATTESTATION_PROTOCOL_DMTF_SPDM;
return 0;
}
@ -658,7 +697,7 @@ static int attestation_requester_get_capabilities_rsp_post_processing (
* than that, we will fail attestation at 25.5s even if device thinks it has more time to
* respond. */
ct_exponent = (rsp->base_capabilities.ct_exponent > 24) ? 24 :
rsp->base_capabilities.ct_exponent;
rsp->base_capabilities.ct_exponent;
capabilities.max_timeout = device_manager_set_timeout_ms (SPDM_MAX_RESPONSE_TIMEOUT_MS);
capabilities.max_sig =
@ -1150,8 +1189,8 @@ static void attestation_requester_copy_spdm_response (const struct spdm_protocol
debug_log_create_entry (DEBUG_LOG_SEVERITY_ERROR, DEBUG_LOG_COMPONENT_ATTESTATION,
ATTESTATION_LOGGING_UNEXPECTED_RESPONSE_RECEIVED, response->source_eid,
((attestation->state->txn.protocol << 24) |
(attestation->state->txn.requested_command << 16) |
(ATTESTATION_PROTOCOL_DMTF_SPDM_1_1 << 8) | command));
(attestation->state->txn.requested_command << 16) |
(ATTESTATION_PROTOCOL_DMTF_SPDM << 8) | command));
attestation->state->txn.request_status = ATTESTATION_REQUESTER_REQUEST_RSP_FAIL;
@ -1257,12 +1296,12 @@ void attestation_requester_on_spdm_response_not_ready (
(struct spdm_error_response_not_ready*) spdm_get_spdm_error_rsp_optional_data (rsp);
uint8_t rdt_exponent;
if (attestation->state->txn.protocol < ATTESTATION_PROTOCOL_DMTF_SPDM_1_1) {
if (attestation->state->txn.protocol != ATTESTATION_PROTOCOL_DMTF_SPDM) {
debug_log_create_entry (DEBUG_LOG_SEVERITY_ERROR, DEBUG_LOG_COMPONENT_ATTESTATION,
ATTESTATION_LOGGING_UNEXPECTED_RESPONSE_RECEIVED, response->source_eid,
((attestation->state->txn.protocol << 24) |
(attestation->state->txn.requested_command << 16) |
(ATTESTATION_PROTOCOL_DMTF_SPDM_1_1 << 8) | SPDM_RESPONSE_ERROR));
(ATTESTATION_PROTOCOL_DMTF_SPDM << 8) | SPDM_RESPONSE_ERROR));
goto fail;
}
@ -1933,7 +1972,7 @@ static int attestation_requester_setup_spdm_device (const struct attestation_req
}
rq_len = spdm_generate_get_capabilities_request (attestation->state->spdm_msg_buffer,
ATTESTATION_REQUESTER_MAX_SPDM_REQUEST, attestation->state->txn.protocol);
ATTESTATION_REQUESTER_MAX_SPDM_REQUEST, attestation->state->txn.spdm_minor_version);
if (ROT_IS_ERROR (rq_len)) {
return rq_len;
}
@ -2011,7 +2050,7 @@ static int attestation_requester_setup_spdm_device (const struct attestation_req
rq_len = spdm_generate_negotiate_algorithms_request (attestation->state->spdm_msg_buffer,
ATTESTATION_REQUESTER_MAX_SPDM_REQUEST, base_asym_algo, base_hash_algo,
attestation->state->txn.protocol);
attestation->state->txn.spdm_minor_version);
if (ROT_IS_ERROR (rq_len)) {
return rq_len;
}
@ -2155,7 +2194,8 @@ static int attestation_requester_send_and_receive_spdm_get_measurements (
/* In 1.2+, every Get Measurement transaction with a signature requested in response requires a
* a transcript that includes VDM. */
if ((attestation->state->txn.protocol > ATTESTATION_PROTOCOL_DMTF_SPDM_1_1) ||
if (((attestation->state->txn.protocol != ATTESTATION_PROTOCOL_CERBERUS) &&
(attestation->state->txn.spdm_minor_version > ATTESTATION_PROTOCOL_DMTF_SPDM_1_1)) ||
attestation->state->txn.device_discovery) {
status = attestation_requester_setup_spdm_device (attestation, eid, device_addr);
if (status != 0) {
@ -2177,7 +2217,7 @@ static int attestation_requester_send_and_receive_spdm_get_measurements (
ATTESTATION_REQUESTER_MAX_SPDM_REQUEST, attestation->state->txn.slot_num,
measurement_operation, attestation->state->txn.cert_supported ? true : false,
raw_bitstream_requested, attestation->state->txn.cert_supported ? nonce : NULL,
attestation->state->txn.protocol);
attestation->state->txn.spdm_minor_version);
if (ROT_IS_ERROR (rq_len)) {
return rq_len;
}
@ -2190,11 +2230,12 @@ static int attestation_requester_send_and_receive_spdm_get_measurements (
* the last measurement block on the device. Starting from SPDM 1.2.x, measurement blocks
* no longer have the contiguity requirement so instead use index 0xEF which is dedicated to
* device IDs. */
if (attestation->state->txn.protocol == ATTESTATION_PROTOCOL_DMTF_SPDM_1_1) {
if ((attestation->state->txn.protocol != ATTESTATION_PROTOCOL_CERBERUS) &&
(attestation->state->txn.spdm_minor_version <= ATTESTATION_PROTOCOL_DMTF_SPDM_1_1)) {
rq_len = spdm_generate_get_measurements_request (attestation->state->spdm_msg_buffer,
ATTESTATION_REQUESTER_MAX_SPDM_REQUEST, attestation->state->txn.slot_num,
SPDM_MEASUREMENT_OPERATION_GET_NUM_BLOCKS, false, raw_bitstream_requested, NULL,
attestation->state->txn.protocol);
attestation->state->txn.spdm_minor_version);
if (ROT_IS_ERROR (rq_len)) {
return rq_len;
}
@ -2221,7 +2262,7 @@ static int attestation_requester_send_and_receive_spdm_get_measurements (
rq_len = spdm_generate_get_measurements_request (attestation->state->spdm_msg_buffer,
ATTESTATION_REQUESTER_MAX_SPDM_REQUEST, attestation->state->txn.slot_num,
measurement_operation, false, raw_bitstream_requested, NULL,
attestation->state->txn.protocol);
attestation->state->txn.spdm_minor_version);
if (ROT_IS_ERROR (rq_len)) {
return rq_len;
}
@ -2687,8 +2728,9 @@ static int attestation_requester_attest_device_spdm (
return status;
}
// Start off assuming 1.1 then update based on response from device to the Get Version request
attestation->state->txn.protocol = ATTESTATION_PROTOCOL_DMTF_SPDM_1_1;
// Start off assuming 1.0 then update based on response from device to the Get Version request
attestation->state->txn.protocol = ATTESTATION_PROTOCOL_DMTF_SPDM;
attestation->state->txn.spdm_minor_version = ATTESTATION_PROTOCOL_DMTF_SPDM_1_0;
status = attestation_requester_setup_spdm_device (attestation, eid, device_addr);
if (status != 0) {
@ -2697,7 +2739,7 @@ static int attestation_requester_attest_device_spdm (
if (attestation->state->txn.cert_supported) {
rq_len = spdm_generate_get_digests_request (attestation->state->spdm_msg_buffer,
ATTESTATION_REQUESTER_MAX_SPDM_REQUEST, attestation->state->txn.protocol);
ATTESTATION_REQUESTER_MAX_SPDM_REQUEST, attestation->state->txn.spdm_minor_version);
if (ROT_IS_ERROR (rq_len)) {
status = rq_len;
goto hash_cancel;
@ -2721,7 +2763,8 @@ static int attestation_requester_attest_device_spdm (
ATTESTATION_REQUESTER_MAX_SPDM_REQUEST, attestation->state->txn.slot_num,
attestation->state->txn.cert_buffer_len,
attestation->state->txn.cert_total_len -
attestation->state->txn.cert_buffer_len, attestation->state->txn.protocol);
attestation->state->txn.cert_buffer_len,
attestation->state->txn.spdm_minor_version);
if (ROT_IS_ERROR (rq_len)) {
status = rq_len;
goto clear_cert_chain;
@ -2753,7 +2796,8 @@ static int attestation_requester_attest_device_spdm (
rq_len = spdm_generate_challenge_request (attestation->state->spdm_msg_buffer,
ATTESTATION_REQUESTER_MAX_SPDM_REQUEST, attestation->state->txn.slot_num,
SPDM_MEASUREMENT_SUMMARY_HASH_ALL, nonce, attestation->state->txn.protocol);
SPDM_MEASUREMENT_SUMMARY_HASH_ALL, nonce,
attestation->state->txn.spdm_minor_version);
if (ROT_IS_ERROR (rq_len)) {
status = rq_len;
goto hash_cancel;
@ -2970,7 +3014,8 @@ static int attestation_requester_discover_device_spdm_protocol (
int device_num;
int status;
attestation->state->txn.protocol = ATTESTATION_PROTOCOL_DMTF_SPDM_1_1;
attestation->state->txn.protocol = ATTESTATION_PROTOCOL_DMTF_SPDM;
attestation->state->txn.spdm_minor_version = ATTESTATION_PROTOCOL_DMTF_SPDM_1_0;
attestation->state->txn.transcript_hash_type = HASH_TYPE_SHA256;
attestation->state->txn.measurement_hash_type = HASH_TYPE_SHA256;
@ -2983,7 +3028,7 @@ static int attestation_requester_discover_device_spdm_protocol (
if (block->completion_code != SPDM_DISCOVERY_DEVICE_ID_BLOCK_CC_SUCCESS) {
debug_log_create_entry (DEBUG_LOG_SEVERITY_ERROR, DEBUG_LOG_COMPONENT_ATTESTATION,
ATTESTATION_LOGGING_GET_DEVICE_ID_FAILED,
((eid << 8) | attestation->state->txn.protocol), block->completion_code);
((eid << 8) | attestation->state->txn.spdm_minor_version), block->completion_code);
return ATTESTATION_GET_DEVICE_ID_FAIL;
}
@ -2991,7 +3036,7 @@ static int attestation_requester_discover_device_spdm_protocol (
// Only PCI descriptors are supported, so ensure the 4 PCI descriptors are included in response
if ((block->descriptor_count < 4) ||
(block->device_id_len <
((sizeof (struct spdm_discovery_device_id_descriptor) + sizeof (uint16_t)) * 4))) {
((sizeof (struct spdm_discovery_device_id_descriptor) + sizeof (uint16_t)) * 4))) {
return 0;
}

Просмотреть файл

@ -39,6 +39,7 @@ struct attestation_requester_transaction_state {
size_t msg_buffer_len; /**< Length of data in message buffer */
enum attestation_requester_request_state request_status; /**< Response processing status. */
enum attestation_protocol protocol; /**< Attestation protocol utilized with this device. */
enum attestation_spdm_minor_version spdm_minor_version; /**< Attestation spdm minor version utilized with this device. */
uint32_t sleep_duration_ms; /**< Duration in milliseconds to sleep while waiting for response. */
uint16_t device_version_set; /**< Version set selected for device. */
uint8_t *cert_buffer; /**< A temporary dynamically allocated buffer for aggregating and verifying certificate chain. */

Просмотреть файл

@ -49,9 +49,11 @@ enum {
CMD_HANDLER_SPDM_UNSUPPORTED_MSG = CMD_HANDLER_SPDM_ERROR (0x06), /**< Message type not supported. */
CMD_HANDLER_SPDM_UNSUPPORTED_OPERATION = CMD_HANDLER_SPDM_ERROR (0x07), /**< The requested operation is not supported. */
CMD_HANDLER_SPDM_NOT_INTEROPERABLE = CMD_HANDLER_SPDM_ERROR (0x08), /**< Received message using different specification major version */
CMD_HANDLER_SPDM_UNSUPPORTED_MEAS_SPEC = CMD_HANDLER_SPDM_ERROR (0x09), /**< Requested measurement specification unsupported */
CMD_HANDLER_SPDM_UNSUPPORTED_ASYM_ALGO = CMD_HANDLER_SPDM_ERROR (0x0a), /**< Requested asymmetric cryptographic algorithm unsupported */
CMD_HANDLER_SPDM_UNSUPPORTED_HASH_ALGO = CMD_HANDLER_SPDM_ERROR (0x0b), /**< Requested hashing algorithm unsupported */
CMD_HANDLER_SPDM_UNSUPPORTED_MEAS_SPEC = CMD_HANDLER_SPDM_ERROR (0x09), /**< Requested measurement specification unsupported */
CMD_HANDLER_SPDM_UNSUPPORTED_ASYM_ALGO = CMD_HANDLER_SPDM_ERROR (0x0a), /**< Requested asymmetric cryptographic algorithm unsupported */
CMD_HANDLER_SPDM_UNSUPPORTED_HASH_ALGO = CMD_HANDLER_SPDM_ERROR (0x0b), /**< Requested hashing algorithm unsupported */
CMD_HANDLER_SPDM_UNSUPPORTED_SLOT_ID = CMD_HANDLER_SPDM_ERROR (0x0c), /**< Requested slot id unsupported */
CMD_HANDLER_SPDM_BAD_RESPONSE = CMD_HANDLER_SPDM_ERROR (0x0d), /**< Received bad response to request */
};

Просмотреть файл

@ -1799,44 +1799,55 @@ int spdm_generate_get_capabilities_request (uint8_t *buf, size_t buf_len,
return CMD_HANDLER_SPDM_INVALID_ARGUMENT;
}
if (spdm_minor_version < 2) {
if (spdm_minor_version < 1) {
if (buf_len < sizeof (struct spdm_get_capabilities_1_0)) {
return CMD_HANDLER_SPDM_BUF_TOO_SMALL;
}
memset (rq, 0, sizeof (struct spdm_get_capabilities_1_0));
}
else if (spdm_minor_version < 2) {
if (buf_len < sizeof (struct spdm_get_capabilities_1_1)) {
return CMD_HANDLER_SPDM_BUF_TOO_SMALL;
}
memset (rq, 0, sizeof (struct spdm_get_capabilities_1_1));
}
else {
if (buf_len < sizeof (struct spdm_get_capabilities)) {
return CMD_HANDLER_SPDM_BUF_TOO_SMALL;
}
memset (rq, 0, sizeof (struct spdm_get_capabilities));
}
memset (rq, 0, sizeof (struct spdm_get_capabilities));
spdm_populate_header (&rq->base_capabilities.header, SPDM_REQUEST_GET_CAPABILITIES,
spdm_minor_version);
rq->base_capabilities.ct_exponent = SPDM_MAX_CT_EXPONENT;
if (spdm_minor_version > 0) {
rq->base_capabilities.ct_exponent = SPDM_MAX_CT_EXPONENT;
rq->base_capabilities.flags.cache_cap = SPDM_REQUESTER_CACHE_CAP;
rq->base_capabilities.flags.cert_cap = SPDM_REQUESTER_CERT_CAP;
rq->base_capabilities.flags.chal_cap = SPDM_REQUESTER_CHAL_CAP;
rq->base_capabilities.flags.meas_cap = SPDM_REQUESTER_MEAS_CAP;
rq->base_capabilities.flags.meas_fresh_cap = SPDM_REQUESTER_MEAS_FRESH_CAP;
rq->base_capabilities.flags.encrypt_cap = SPDM_REQUESTER_ENCRYPT_CAP;
rq->base_capabilities.flags.mac_cap = SPDM_REQUESTER_MAC_CAP;
rq->base_capabilities.flags.mut_auth_cap = SPDM_REQUESTER_MUT_AUTH_CAP;
rq->base_capabilities.flags.key_ex_cap = SPDM_REQUESTER_KEY_EX_CAP;
rq->base_capabilities.flags.psk_cap = SPDM_REQUESTER_PSK_CAP;
rq->base_capabilities.flags.encap_cap = SPDM_REQUESTER_ENCAP_CAP;
rq->base_capabilities.flags.hbeat_cap = SPDM_REQUESTER_HBEAT_CAP;
rq->base_capabilities.flags.key_upd_cap = SPDM_REQUESTER_KEY_UPD_CAP;
rq->base_capabilities.flags.handshake_in_the_clear_cap =
SPDM_REQUESTER_HANDSHAKE_IN_THE_CLEAR_CAP;
rq->base_capabilities.flags.pub_key_id_cap = SPDM_REQUESTER_PUB_KEY_ID_CAP;
rq->base_capabilities.flags.chunk_cap = SPDM_REQUESTER_CHUNK_CAP;
rq->base_capabilities.flags.alias_cert_cap = SPDM_REQUESTER_ALIAS_CERT_CAP;
if (spdm_minor_version < 2) {
rq->base_capabilities.flags.cache_cap = SPDM_REQUESTER_CACHE_CAP;
rq->base_capabilities.flags.cert_cap = SPDM_REQUESTER_CERT_CAP;
rq->base_capabilities.flags.chal_cap = SPDM_REQUESTER_CHAL_CAP;
rq->base_capabilities.flags.meas_cap = SPDM_REQUESTER_MEAS_CAP;
rq->base_capabilities.flags.meas_fresh_cap = SPDM_REQUESTER_MEAS_FRESH_CAP;
rq->base_capabilities.flags.encrypt_cap = SPDM_REQUESTER_ENCRYPT_CAP;
rq->base_capabilities.flags.mac_cap = SPDM_REQUESTER_MAC_CAP;
rq->base_capabilities.flags.mut_auth_cap = SPDM_REQUESTER_MUT_AUTH_CAP;
rq->base_capabilities.flags.key_ex_cap = SPDM_REQUESTER_KEY_EX_CAP;
rq->base_capabilities.flags.psk_cap = SPDM_REQUESTER_PSK_CAP;
rq->base_capabilities.flags.encap_cap = SPDM_REQUESTER_ENCAP_CAP;
rq->base_capabilities.flags.hbeat_cap = SPDM_REQUESTER_HBEAT_CAP;
rq->base_capabilities.flags.key_upd_cap = SPDM_REQUESTER_KEY_UPD_CAP;
rq->base_capabilities.flags.handshake_in_the_clear_cap =
SPDM_REQUESTER_HANDSHAKE_IN_THE_CLEAR_CAP;
rq->base_capabilities.flags.pub_key_id_cap = SPDM_REQUESTER_PUB_KEY_ID_CAP;
rq->base_capabilities.flags.chunk_cap = SPDM_REQUESTER_CHUNK_CAP;
rq->base_capabilities.flags.alias_cert_cap = SPDM_REQUESTER_ALIAS_CERT_CAP;
}
if (spdm_minor_version < 1) {
return sizeof (struct spdm_get_capabilities_1_0);
}
else if (spdm_minor_version < 2) {
return sizeof (struct spdm_get_capabilities_1_1);
}
else {
@ -2326,6 +2337,11 @@ int spdm_process_negotiate_algorithms_response (struct cmd_interface_msg *respon
}
resp = (struct spdm_negotiate_algorithms_response*) response->payload;
if (resp->header.spdm_minor_version < 1) {
if (resp->num_alg_structure_tables != 0) {
return CMD_HANDLER_SPDM_BAD_RESPONSE;
}
}
if ((response->payload_length < sizeof (struct spdm_negotiate_algorithms_response)) ||
(response->payload_length != resp->length) ||
@ -3183,13 +3199,21 @@ int spdm_generate_get_measurements_request (uint8_t *buf, size_t buf_len, uint8_
{
struct spdm_get_measurements_request *rq = (struct spdm_get_measurements_request*) buf;
size_t rq_length = sizeof (struct spdm_get_measurements_request) +
((1 + SPDM_NONCE_LEN) * sig_required);
((SPDM_NONCE_LEN) * sig_required);
uint8_t *slot_id;
if ((buf == NULL) || ((nonce == NULL) && sig_required)) {
return CMD_HANDLER_SPDM_INVALID_ARGUMENT;
}
if ((spdm_minor_version == 0) && (slot_num != 0)) {
return CMD_HANDLER_SPDM_UNSUPPORTED_SLOT_ID;
}
if (spdm_minor_version > 0) {
rq_length += sig_required;
}
if (buf_len < rq_length) {
return CMD_HANDLER_SPDM_BUF_TOO_SMALL;
}
@ -3206,8 +3230,10 @@ int spdm_generate_get_measurements_request (uint8_t *buf, size_t buf_len, uint8_
}
if (sig_required) {
slot_id = spdm_get_measurements_rq_slot_id_ptr (rq);
*slot_id = slot_num;
if (spdm_minor_version > 0) {
slot_id = spdm_get_measurements_rq_slot_id_ptr (rq);
*slot_id = slot_num;
}
memcpy (spdm_get_measurements_rq_nonce (rq), nonce, SPDM_NONCE_LEN);
}

Просмотреть файл

@ -173,6 +173,15 @@ enum spdm_pre_shared_key_capability_options {
SPDM_PSK_RESERVED, /**< Reserved.*/
};
/**
* SPDM get capabilities request format for SPDM 1.0
*/
struct spdm_get_capabilities_1_0 {
struct spdm_protocol_header header; /**< Message header */
uint8_t reserved; /**< Reserved */
uint8_t reserved2; /**< Reserved */
};
/**
* SPDM get capabilities request/response format for SPDM 1.1
*/
@ -853,6 +862,14 @@ struct spdm_get_measurements_request {
#define spdm_get_measurements_rq_length(rq) (sizeof (struct spdm_get_measurements_request) + \
((rq)->sig_required * (sizeof (uint8_t) + SPDM_NONCE_LEN)))
/**
* Get the total length of a SPDM 1.0 get measurements request message
*
* @param rq Buffer containing struct spdm_get_measurements_request
*/
#define spdm_get_measurements_rq_length_1_0(rq) (sizeof (struct spdm_get_measurements_request) + \
((rq)->sig_required * SPDM_NONCE_LEN))
/**
* Get the buffer containing the nonce in SPDM get measurements request. This is only valid when
* the signature required flag is set.

Просмотреть файл

@ -22,7 +22,7 @@
#define SPDM_NONCE_LEN 32
#define SPDM_MAJOR_VERSION 1
#define SPDM_MIN_MINOR_VERSION 1
#define SPDM_MIN_MINOR_VERSION 0
#define SPDM_MAX_MINOR_VERSION 2
#define SPDM_MAX_RESPONSE_TIMEOUT_MS 100
@ -38,15 +38,10 @@
/**
* Supported SPDM versions.
*/
#define SPDM_VERSION_1_0 SPDM_MAKE_VERSION (1, 0)
#define SPDM_VERSION_1_1 SPDM_MAKE_VERSION (1, 1)
#define SPDM_VERSION_1_2 SPDM_MAKE_VERSION (1, 2)
/**
* GET_VERSION/VERSION SPDM message version.
*/
#define SPDM_VERSION_1_0 SPDM_MAKE_VERSION (1, 0)
/**
* Get SPDM major version.
*

Просмотреть файл

@ -159,7 +159,6 @@ struct attestation_requester_testing {
size_t max_cert_buffer_portion; /**< Maximum certificate buffer portion length */
};
/**
* Helper function to add an intermediate and root CA to RIoT key manager cert chain
*
@ -3028,7 +3027,16 @@ static void attestation_requester_testing_send_and_receive_spdm_get_capabilities
header = (struct mctp_base_protocol_transport_header*) tx_packet.data;
header->cmd_code = SMBUS_CMD_CODE_MCTP;
header->byte_count = (testing->spdm_version >= 2)? 0x1A : 0x12;
if ( testing->spdm_version >= 2 ) {
header->byte_count = 0x1A;
}
else if (testing->spdm_version == 1 ) {
header->byte_count = 0x12;
}
else {
header->byte_count = 0x0A;
}
header->source_addr = (0x41 << 1) | 1;
header->rsvd = 0;
header->header_version = 1;
@ -3052,31 +3060,36 @@ static void attestation_requester_testing_send_and_receive_spdm_get_capabilities
request->base_capabilities.header.spdm_major_version = SPDM_MAJOR_VERSION;
request->base_capabilities.header.req_rsp_code = SPDM_REQUEST_GET_CAPABILITIES;
request->base_capabilities.ct_exponent = SPDM_MAX_CT_EXPONENT;
request->base_capabilities.flags.cache_cap = 0;
request->base_capabilities.flags.cert_cap = 0;
request->base_capabilities.flags.chal_cap = 0;
request->base_capabilities.flags.meas_cap = 0;
request->base_capabilities.flags.meas_fresh_cap = 0;
request->base_capabilities.flags.encrypt_cap = 0;
request->base_capabilities.flags.mac_cap = 0;
request->base_capabilities.flags.mut_auth_cap = 0;
request->base_capabilities.flags.key_ex_cap = 0;
request->base_capabilities.flags.psk_cap = 0;
request->base_capabilities.flags.encap_cap = 0;
request->base_capabilities.flags.hbeat_cap = 0;
request->base_capabilities.flags.key_upd_cap = 0;
request->base_capabilities.flags.handshake_in_the_clear_cap = 0;
request->base_capabilities.flags.pub_key_id_cap = 0;
if (testing->spdm_version >= 1) {
request->base_capabilities.ct_exponent = SPDM_MAX_CT_EXPONENT;
request->base_capabilities.flags.cache_cap = 0;
request->base_capabilities.flags.cert_cap = 0;
request->base_capabilities.flags.chal_cap = 0;
request->base_capabilities.flags.meas_cap = 0;
request->base_capabilities.flags.meas_fresh_cap = 0;
request->base_capabilities.flags.encrypt_cap = 0;
request->base_capabilities.flags.mac_cap = 0;
request->base_capabilities.flags.mut_auth_cap = 0;
request->base_capabilities.flags.key_ex_cap = 0;
request->base_capabilities.flags.psk_cap = 0;
request->base_capabilities.flags.encap_cap = 0;
request->base_capabilities.flags.hbeat_cap = 0;
request->base_capabilities.flags.key_upd_cap = 0;
request->base_capabilities.flags.handshake_in_the_clear_cap = 0;
request->base_capabilities.flags.pub_key_id_cap = 0;
}
if (testing->spdm_version >= 2) {
request->data_transfer_size = MCTP_BASE_PROTOCOL_MAX_MESSAGE_BODY;
request->max_spdm_msg_size = MCTP_BASE_PROTOCOL_MAX_MESSAGE_BODY;
offset += sizeof (struct spdm_get_capabilities);
}
else {
else if (testing->spdm_version == 1) {
offset += sizeof (struct spdm_get_capabilities_1_1);
}
else {
offset += sizeof (struct spdm_get_capabilities_1_0);
}
tx_packet.data[offset] = checksum_crc8 (0x20 << 1, tx_packet.data, offset);
@ -3132,8 +3145,10 @@ static void attestation_requester_testing_send_and_receive_spdm_get_capabilities
{
struct spdm_get_capabilities req;
struct spdm_get_capabilities rsp;
size_t capabilities_len = (testing->spdm_version >= 2) ?
size_t capabilities_len_rsp = (testing->spdm_version >= 2) ?
(sizeof (struct spdm_get_capabilities)) : (sizeof (struct spdm_get_capabilities_1_1));
size_t capabilities_len_req = (testing->spdm_version >= 1) ? capabilities_len_rsp :
(sizeof (struct spdm_get_capabilities_1_0));
int status;
memset (&req, 0, sizeof (struct spdm_get_capabilities));
@ -3143,22 +3158,24 @@ static void attestation_requester_testing_send_and_receive_spdm_get_capabilities
req.base_capabilities.header.spdm_major_version = SPDM_MAJOR_VERSION;
req.base_capabilities.header.req_rsp_code = SPDM_REQUEST_GET_CAPABILITIES;
req.base_capabilities.ct_exponent = SPDM_MAX_CT_EXPONENT;
req.base_capabilities.flags.cache_cap = 0;
req.base_capabilities.flags.cert_cap = 0;
req.base_capabilities.flags.chal_cap = 0;
req.base_capabilities.flags.meas_cap = 0;
req.base_capabilities.flags.meas_fresh_cap = 0;
req.base_capabilities.flags.encrypt_cap = 0;
req.base_capabilities.flags.mac_cap = 0;
req.base_capabilities.flags.mut_auth_cap = 0;
req.base_capabilities.flags.key_ex_cap = 0;
req.base_capabilities.flags.psk_cap = 0;
req.base_capabilities.flags.encap_cap = 0;
req.base_capabilities.flags.hbeat_cap = 0;
req.base_capabilities.flags.key_upd_cap = 0;
req.base_capabilities.flags.handshake_in_the_clear_cap = 0;
req.base_capabilities.flags.pub_key_id_cap = 0;
if (testing->spdm_version >= 1) {
req.base_capabilities.ct_exponent = SPDM_MAX_CT_EXPONENT;
req.base_capabilities.flags.cache_cap = 0;
req.base_capabilities.flags.cert_cap = 0;
req.base_capabilities.flags.chal_cap = 0;
req.base_capabilities.flags.meas_cap = 0;
req.base_capabilities.flags.meas_fresh_cap = 0;
req.base_capabilities.flags.encrypt_cap = 0;
req.base_capabilities.flags.mac_cap = 0;
req.base_capabilities.flags.mut_auth_cap = 0;
req.base_capabilities.flags.key_ex_cap = 0;
req.base_capabilities.flags.psk_cap = 0;
req.base_capabilities.flags.encap_cap = 0;
req.base_capabilities.flags.hbeat_cap = 0;
req.base_capabilities.flags.key_upd_cap = 0;
req.base_capabilities.flags.handshake_in_the_clear_cap = 0;
req.base_capabilities.flags.pub_key_id_cap = 0;
}
if (testing->spdm_version >= 2) {
req.data_transfer_size = MCTP_BASE_PROTOCOL_MAX_MESSAGE_BODY;
@ -3196,19 +3213,20 @@ static void attestation_requester_testing_send_and_receive_spdm_get_capabilities
starting_msg_tag, false, testing);
status = mock_expect (&testing->secondary_hash.mock, testing->secondary_hash.base.update,
&testing->secondary_hash, 0, MOCK_ARG_PTR_CONTAINS_TMP (&req, capabilities_len),
MOCK_ARG (capabilities_len));
&testing->secondary_hash, 0, MOCK_ARG_PTR_CONTAINS_TMP (&req, capabilities_len_req),
MOCK_ARG (capabilities_len_req));
if (hash_update_fail) {
status = mock_expect (&testing->secondary_hash.mock, testing->secondary_hash.base.update,
&testing->secondary_hash, HASH_ENGINE_NO_MEMORY,
MOCK_ARG_PTR_CONTAINS_TMP (&rsp, capabilities_len), MOCK_ARG (capabilities_len));
MOCK_ARG_PTR_CONTAINS_TMP (&rsp, capabilities_len_rsp), MOCK_ARG (capabilities_len_rsp));
status |= mock_expect (&testing->secondary_hash.mock, testing->secondary_hash.base.cancel,
&testing->secondary_hash, 0);
}
else {
status = mock_expect (&testing->secondary_hash.mock, testing->secondary_hash.base.update,
&testing->secondary_hash, 0, MOCK_ARG_PTR_CONTAINS_TMP (&rsp, capabilities_len),
MOCK_ARG (capabilities_len));
&testing->secondary_hash, 0, MOCK_ARG_PTR_CONTAINS_TMP (&rsp, capabilities_len_rsp),
MOCK_ARG (capabilities_len_rsp));
}
CuAssertIntEquals (test, 0, status);
@ -4158,7 +4176,8 @@ static void attestation_requester_testing_send_and_receive_spdm_get_measurements
header = (struct mctp_base_protocol_transport_header*) tx_packet.data;
header->cmd_code = SMBUS_CMD_CODE_MCTP;
header->byte_count = (testing->spdm_discovery || testing->get_cert_unsupported) ? 0x0A : 0x2B;
header->byte_count = (testing->spdm_discovery || testing->get_cert_unsupported) ? 0x0A :
(testing->spdm_version == 0) ? 0x2A : 0x2B;
header->source_addr = (0x41 << 1) | 1;
header->rsvd = 0;
header->header_version = 1;
@ -4184,7 +4203,7 @@ static void attestation_requester_testing_send_and_receive_spdm_get_measurements
request->measurement_operation = measurement_operation;
request->sig_required = !testing->spdm_discovery && !testing->get_cert_unsupported;
request->raw_bit_stream_requested = testing->spdm_version == 1 ? 0 : raw_request;
request->raw_bit_stream_requested = testing->spdm_version <= 1 ? 0 : raw_request;
offset += sizeof (struct spdm_get_measurements_request);
@ -4197,10 +4216,12 @@ static void attestation_requester_testing_send_and_receive_spdm_get_measurements
offset += SPDM_NONCE_LEN;
slot_id = spdm_get_measurements_rq_slot_id_ptr (request);
*slot_id = ATTESTATION_RIOT_SLOT_NUM;
if (testing->spdm_version != 0) {
slot_id = spdm_get_measurements_rq_slot_id_ptr (request);
*slot_id = ATTESTATION_RIOT_SLOT_NUM;
++offset;
++offset;
}
}
tx_packet.data[offset] = checksum_crc8 (0x20 << 1, tx_packet.data, offset);
@ -4273,6 +4294,7 @@ static void attestation_requester_testing_send_and_receive_spdm_get_measurements
size_t offset;
int status;
size_t i;
size_t rq_len;
if (testing->meas_hashing_alg_supported == SPDM_MEAS_RSP_TPM_ALG_SHA_256) {
hash_len = SHA256_HASH_LENGTH;
@ -4392,10 +4414,11 @@ static void attestation_requester_testing_send_and_receive_spdm_get_measurements
CuAssertIntEquals (test, 0, status);
}
rq_len = ( testing->spdm_version == 0 ) ? spdm_get_measurements_rq_length_1_0 (req) : spdm_get_measurements_rq_length (req);
status = mock_expect (&testing->secondary_hash.mock, testing->secondary_hash.base.update,
&testing->secondary_hash, 0,
MOCK_ARG_PTR_CONTAINS_TMP (req, spdm_get_measurements_rq_length (req)),
MOCK_ARG (spdm_get_measurements_rq_length (req)));
MOCK_ARG_PTR_CONTAINS_TMP (req, rq_len),
MOCK_ARG (rq_len));
if (hash_update_fail) {
status |= mock_expect (&testing->secondary_hash.mock, testing->secondary_hash.base.update,
&testing->secondary_hash, HASH_ENGINE_NO_MEMORY,
@ -8643,6 +8666,412 @@ static void attestation_requester_test_attest_device_spdm_sha512_1_1_only_pmr0 (
complete_attestation_requester_mock_test (test, &testing, true);
}
static void attestation_requester_test_attest_device_spdm_only_little_endian_signature (
CuTest *test)
{
struct attestation_requester_testing testing;
struct cfm_measurement_container container;
struct cfm_allowable_data data;
struct cfm_allowable_data_entry data_entry;
uint32_t component_id = 101;
uint8_t digest[SHA256_HASH_LENGTH];
uint8_t measurement[SHA256_HASH_LENGTH];
uint8_t signature[ECC_KEY_LENGTH_256 * 2];
uint8_t sig_der[ECC_DER_P256_ECDSA_MAX_LENGTH];
uint8_t sig_der2[ECC_DER_P256_ECDSA_MAX_LENGTH];
int status;
size_t i;
data.allowable_data = &data_entry;
data.bitmask = NULL;
data.bitmask_length = 0;
data.check = CFM_CHECK_EQUAL;
data.big_endian = false;
data.data_count = 1;
data.allowable_data[0].data_len = sizeof (measurement);
data.allowable_data[0].data = measurement;
data.allowable_data[0].version_set = 1;
container.measurement_type = CFM_MEASUREMENT_TYPE_DATA;
container.measurement.data.pmr_id = 0;
container.measurement.data.measurement_id = 1;
container.measurement.data.data_checks = &data;
container.measurement.data.data_checks_count = 1;
for (i = 0; i < sizeof (digest); ++i) {
digest[i] = i * 3;
measurement[i] = 51 + i;
}
for (i = 0; i < (ECC_KEY_LENGTH_256 * 2); ++i) {
signature[i] = i * 10;
}
TEST_START;
buffer_reverse(signature, ECC_KEY_LENGTH_256);
buffer_reverse(signature + ECC_KEY_LENGTH_256, ECC_KEY_LENGTH_256);
status = ecc_der_encode_ecdsa_signature (signature,
&signature[ECC_KEY_LENGTH_256], ECC_KEY_LENGTH_256, sig_der, sizeof (sig_der));
CuAssertIntEquals (test, 70, status);
buffer_reverse(signature, ECC_KEY_LENGTH_256);
buffer_reverse(signature + ECC_KEY_LENGTH_256, ECC_KEY_LENGTH_256);
status = ecc_der_encode_ecdsa_signature (signature,
&signature[ECC_KEY_LENGTH_256], ECC_KEY_LENGTH_256, sig_der2, sizeof (sig_der2));
CuAssertIntEquals (test, 69, status);
setup_attestation_requester_mock_attestation_test (test, &testing, true, true, true, true,
HASH_TYPE_SHA256, HASH_TYPE_SHA256, CFM_ATTESTATION_DMTF_SPDM, ATTESTATION_RIOT_SLOT_NUM,
component_id);
testing.challenge_unsupported = true;
testing.get_all_blocks = false;
testing.raw_rsp[0] = true;
testing.spdm_max_version = 1;
testing.spdm_min_version = 1;
testing.spdm_version = 1;
status = mock_expect (&testing.secondary_hash.mock, testing.secondary_hash.base.start_sha256,
&testing.secondary_hash, 0);
CuAssertIntEquals (test, 0, status);
attestation_requester_testing_send_and_receive_spdm_negotiate_algorithms_with_mocks (test, 0,
false, &testing);
attestation_requester_testing_send_and_receive_spdm_get_digests_with_mocks (test, false, true,
false, &testing, 3);
attestation_requester_testing_send_and_receive_spdm_get_certificate_with_mocks_and_verify (test,
&testing, HASH_TYPE_SHA256, 4, true, false, false, false, NULL, component_id);
status = mock_expect (&testing.secondary_hash.mock, testing.secondary_hash.base.cancel,
&testing.secondary_hash, 0);
status = mock_expect (&testing.secondary_hash.mock, testing.secondary_hash.base.start_sha256,
&testing.secondary_hash, 0);
CuAssertIntEquals (test, 0, status);
attestation_requester_testing_send_and_receive_spdm_get_measurements_with_mocks (test, false,
false, &testing, 5, 1);
status = mock_expect (&testing.secondary_hash.mock, testing.secondary_hash.base.finish,
&testing.secondary_hash, 0, MOCK_ARG_NOT_NULL, MOCK_ARG (HASH_MAX_HASH_LEN));
status |= mock_expect_output_tmp (&testing.secondary_hash.mock, 0, digest, sizeof (digest), -1);
CuAssertIntEquals (test, 0, status);
status = mock_expect (&testing.ecc.mock, testing.ecc.base.init_public_key, &testing.ecc,
0, MOCK_ARG_PTR_CONTAINS (RIOT_CORE_ALIAS_PUBLIC_KEY,
RIOT_CORE_ALIAS_PUBLIC_KEY_LEN),
MOCK_ARG (RIOT_CORE_ALIAS_PUBLIC_KEY_LEN), MOCK_ARG_NOT_NULL);
status |= mock_expect_save_arg (&testing.ecc.mock, 2, 0);
status |= mock_expect (&testing.ecc.mock, testing.ecc.base.verify, &testing.ecc,
ECC_ENGINE_BAD_SIGNATURE, MOCK_ARG_SAVED_ARG (0), MOCK_ARG_PTR_CONTAINS_TMP (digest, sizeof (digest)),
MOCK_ARG (sizeof (digest)), MOCK_ARG_PTR_CONTAINS_TMP (sig_der2, 69),
MOCK_ARG (69));
status |= mock_expect (&testing.ecc.mock, testing.ecc.base.release_key_pair, &testing.ecc, 0,
MOCK_ARG_ANY, MOCK_ARG_SAVED_ARG (0));
CuAssertIntEquals (test, 0, status);
status = mock_expect (&testing.ecc.mock, testing.ecc.base.init_public_key, &testing.ecc,
0, MOCK_ARG_PTR_CONTAINS (RIOT_CORE_ALIAS_PUBLIC_KEY,
RIOT_CORE_ALIAS_PUBLIC_KEY_LEN),
MOCK_ARG (RIOT_CORE_ALIAS_PUBLIC_KEY_LEN), MOCK_ARG_NOT_NULL);
status |= mock_expect_save_arg (&testing.ecc.mock, 2, 1);
status |= mock_expect (&testing.ecc.mock, testing.ecc.base.verify, &testing.ecc,
0, MOCK_ARG_SAVED_ARG (0), MOCK_ARG_PTR_CONTAINS_TMP (digest, sizeof (digest)),
MOCK_ARG (sizeof (digest)), MOCK_ARG_PTR_CONTAINS_TMP (sig_der, 70),
MOCK_ARG (70));
status |= mock_expect (&testing.ecc.mock, testing.ecc.base.release_key_pair, &testing.ecc, 0,
MOCK_ARG_ANY, MOCK_ARG_SAVED_ARG (0));
CuAssertIntEquals (test, 0, status);
status = mock_expect (&testing.cfm.mock, testing.cfm.base.get_component_pmr_digest,
&testing.cfm, CFM_PMR_DIGEST_NOT_FOUND, MOCK_ARG (component_id), MOCK_ARG (0),
MOCK_ARG_NOT_NULL);
status |= mock_expect (&testing.cfm.mock,
testing.cfm.base.get_next_measurement_or_measurement_data, &testing.cfm, 0,
MOCK_ARG (component_id), MOCK_ARG_NOT_NULL, MOCK_ARG (1));
status |= mock_expect_output_tmp (&testing.cfm.mock, 1, &container,
sizeof (struct cfm_measurement_container), -1);
status |= mock_expect (&testing.cfm.mock,
testing.cfm.base.get_next_measurement_or_measurement_data, &testing.cfm,
CFM_ENTRY_NOT_FOUND, MOCK_ARG (component_id), MOCK_ARG_NOT_NULL, MOCK_ARG (0));
status |= mock_expect (&testing.cfm.mock, testing.cfm.base.free_measurement_container,
&testing.cfm, 0, MOCK_ARG_NOT_NULL);
CuAssertIntEquals (test, 0, status);
status = attestation_requester_attest_device (&testing.test, 0x0A);
CuAssertIntEquals (test, 0, status);
status = device_manager_get_device_state_by_eid (&testing.device_mgr, 0x0A);
CuAssertIntEquals (test, DEVICE_MANAGER_AUTHENTICATED, status);
complete_attestation_requester_mock_test (test, &testing, true);
}
static void attestation_requester_test_attest_device_spdm_only_little_endian_signature_spdm_1_0 (
CuTest *test)
{
struct attestation_requester_testing testing;
struct cfm_measurement_container container;
struct cfm_allowable_data data;
struct cfm_allowable_data_entry data_entry;
uint32_t component_id = 101;
uint8_t digest[SHA256_HASH_LENGTH];
uint8_t measurement[SHA256_HASH_LENGTH];
uint8_t signature[ECC_KEY_LENGTH_256 * 2];
uint8_t sig_der[ECC_DER_P256_ECDSA_MAX_LENGTH];
uint8_t sig_der2[ECC_DER_P256_ECDSA_MAX_LENGTH];
int status;
size_t i;
data.allowable_data = &data_entry;
data.bitmask = NULL;
data.bitmask_length = 0;
data.check = CFM_CHECK_EQUAL;
data.big_endian = false;
data.data_count = 1;
data.allowable_data[0].data_len = sizeof (measurement);
data.allowable_data[0].data = measurement;
data.allowable_data[0].version_set = 1;
container.measurement_type = CFM_MEASUREMENT_TYPE_DATA;
container.measurement.data.pmr_id = 0;
container.measurement.data.measurement_id = 1;
container.measurement.data.data_checks = &data;
container.measurement.data.data_checks_count = 1;
for (i = 0; i < sizeof (digest); ++i) {
digest[i] = i * 3;
measurement[i] = 51 + i;
}
for (i = 0; i < (ECC_KEY_LENGTH_256 * 2); ++i) {
signature[i] = i * 10;
}
TEST_START;
buffer_reverse(signature, ECC_KEY_LENGTH_256);
buffer_reverse(signature + ECC_KEY_LENGTH_256, ECC_KEY_LENGTH_256);
status = ecc_der_encode_ecdsa_signature (signature,
&signature[ECC_KEY_LENGTH_256], ECC_KEY_LENGTH_256, sig_der, sizeof (sig_der));
CuAssertIntEquals (test, 70, status);
buffer_reverse(signature, ECC_KEY_LENGTH_256);
buffer_reverse(signature + ECC_KEY_LENGTH_256, ECC_KEY_LENGTH_256);
status = ecc_der_encode_ecdsa_signature (signature,
&signature[ECC_KEY_LENGTH_256], ECC_KEY_LENGTH_256, sig_der2, sizeof (sig_der2));
CuAssertIntEquals (test, 69, status);
setup_attestation_requester_mock_attestation_test (test, &testing, true, true, true, true,
HASH_TYPE_SHA256, HASH_TYPE_SHA256, CFM_ATTESTATION_DMTF_SPDM, ATTESTATION_RIOT_SLOT_NUM,
component_id);
testing.challenge_unsupported = true;
testing.get_all_blocks = false;
testing.raw_rsp[0] = true;
testing.spdm_max_version = 0;
testing.spdm_min_version = 0;
testing.spdm_version = 0;
status = mock_expect (&testing.secondary_hash.mock, testing.secondary_hash.base.start_sha256,
&testing.secondary_hash, 0);
CuAssertIntEquals (test, 0, status);
attestation_requester_testing_send_and_receive_spdm_negotiate_algorithms_with_mocks (test, 0,
false, &testing);
attestation_requester_testing_send_and_receive_spdm_get_digests_with_mocks (test, false, true,
false, &testing, 3);
attestation_requester_testing_send_and_receive_spdm_get_certificate_with_mocks_and_verify (test,
&testing, HASH_TYPE_SHA256, 4, true, false, false, false, NULL, component_id);
status = mock_expect (&testing.secondary_hash.mock, testing.secondary_hash.base.cancel,
&testing.secondary_hash, 0);
status = mock_expect (&testing.secondary_hash.mock, testing.secondary_hash.base.start_sha256,
&testing.secondary_hash, 0);
CuAssertIntEquals (test, 0, status);
attestation_requester_testing_send_and_receive_spdm_get_measurements_with_mocks (test, false,
false, &testing, 5, 1);
status = mock_expect (&testing.secondary_hash.mock, testing.secondary_hash.base.finish,
&testing.secondary_hash, 0, MOCK_ARG_NOT_NULL, MOCK_ARG (HASH_MAX_HASH_LEN));
status |= mock_expect_output_tmp (&testing.secondary_hash.mock, 0, digest, sizeof (digest), -1);
CuAssertIntEquals (test, 0, status);
status = mock_expect (&testing.ecc.mock, testing.ecc.base.init_public_key, &testing.ecc,
0, MOCK_ARG_PTR_CONTAINS (RIOT_CORE_ALIAS_PUBLIC_KEY,
RIOT_CORE_ALIAS_PUBLIC_KEY_LEN),
MOCK_ARG (RIOT_CORE_ALIAS_PUBLIC_KEY_LEN), MOCK_ARG_NOT_NULL);
status |= mock_expect_save_arg (&testing.ecc.mock, 2, 0);
status |= mock_expect (&testing.ecc.mock, testing.ecc.base.verify, &testing.ecc,
ECC_ENGINE_BAD_SIGNATURE, MOCK_ARG_SAVED_ARG (0), MOCK_ARG_PTR_CONTAINS_TMP (digest,
sizeof (digest)), MOCK_ARG (sizeof (digest)), MOCK_ARG_PTR_CONTAINS_TMP (sig_der2, 69),
MOCK_ARG (69));
status |= mock_expect (&testing.ecc.mock, testing.ecc.base.release_key_pair, &testing.ecc, 0,
MOCK_ARG_ANY, MOCK_ARG_SAVED_ARG (0));
CuAssertIntEquals (test, 0, status);
status = mock_expect (&testing.ecc.mock, testing.ecc.base.init_public_key, &testing.ecc,
0, MOCK_ARG_PTR_CONTAINS (RIOT_CORE_ALIAS_PUBLIC_KEY,
RIOT_CORE_ALIAS_PUBLIC_KEY_LEN),
MOCK_ARG (RIOT_CORE_ALIAS_PUBLIC_KEY_LEN), MOCK_ARG_NOT_NULL);
status |= mock_expect_save_arg (&testing.ecc.mock, 2, 1);
status |= mock_expect (&testing.ecc.mock, testing.ecc.base.verify, &testing.ecc,
0, MOCK_ARG_SAVED_ARG (0), MOCK_ARG_PTR_CONTAINS_TMP (digest, sizeof (digest)),
MOCK_ARG (sizeof (digest)), MOCK_ARG_PTR_CONTAINS_TMP (sig_der, 70),
MOCK_ARG (70));
status |= mock_expect (&testing.ecc.mock, testing.ecc.base.release_key_pair, &testing.ecc, 0,
MOCK_ARG_ANY, MOCK_ARG_SAVED_ARG (0));
CuAssertIntEquals (test, 0, status);
status = mock_expect (&testing.cfm.mock, testing.cfm.base.get_component_pmr_digest,
&testing.cfm, CFM_PMR_DIGEST_NOT_FOUND, MOCK_ARG (component_id), MOCK_ARG (0),
MOCK_ARG_NOT_NULL);
status |= mock_expect (&testing.cfm.mock,
testing.cfm.base.get_next_measurement_or_measurement_data, &testing.cfm, 0,
MOCK_ARG (component_id), MOCK_ARG_NOT_NULL, MOCK_ARG (1));
status |= mock_expect_output_tmp (&testing.cfm.mock, 1, &container,
sizeof (struct cfm_measurement_container), -1);
status |= mock_expect (&testing.cfm.mock,
testing.cfm.base.get_next_measurement_or_measurement_data, &testing.cfm,
CFM_ENTRY_NOT_FOUND, MOCK_ARG (component_id), MOCK_ARG_NOT_NULL, MOCK_ARG (0));
status |= mock_expect (&testing.cfm.mock, testing.cfm.base.free_measurement_container,
&testing.cfm, 0, MOCK_ARG_NOT_NULL);
CuAssertIntEquals (test, 0, status);
status = attestation_requester_attest_device (&testing.test, 0x0A);
CuAssertIntEquals (test, 0, status);
status = device_manager_get_device_state_by_eid (&testing.device_mgr, 0x0A);
CuAssertIntEquals (test, DEVICE_MANAGER_AUTHENTICATED, status);
complete_attestation_requester_mock_test (test, &testing, true);
}
static void attestation_requester_test_attest_device_spdm_only_little_endian_signature_spdm_1_2 (
CuTest *test)
{
struct attestation_requester_testing testing;
struct cfm_measurement_container container;
struct cfm_allowable_data data;
struct cfm_allowable_data_entry data_entry;
uint32_t component_id = 101;
uint8_t digest[SHA256_HASH_LENGTH];
uint8_t measurement[SHA256_HASH_LENGTH];
uint8_t signature[ECC_KEY_LENGTH_256 * 2];
uint8_t sig_der[ECC_DER_P256_ECDSA_MAX_LENGTH];
uint8_t sig_der2[ECC_DER_P256_ECDSA_MAX_LENGTH];
int status;
size_t i;
data.allowable_data = &data_entry;
data.bitmask = NULL;
data.bitmask_length = 0;
data.check = CFM_CHECK_EQUAL;
data.big_endian = false;
data.data_count = 1;
data.allowable_data[0].data_len = sizeof (measurement);
data.allowable_data[0].data = measurement;
data.allowable_data[0].version_set = 1;
container.measurement_type = CFM_MEASUREMENT_TYPE_DATA;
container.measurement.data.pmr_id = 0;
container.measurement.data.measurement_id = 1;
container.measurement.data.data_checks = &data;
container.measurement.data.data_checks_count = 1;
for (i = 0; i < sizeof (digest); ++i) {
digest[i] = i * 3;
measurement[i] = 51 + i;
}
for (i = 0; i < (ECC_KEY_LENGTH_256 * 2); ++i) {
signature[i] = i * 10;
}
TEST_START;
buffer_reverse(signature, ECC_KEY_LENGTH_256);
buffer_reverse(signature + ECC_KEY_LENGTH_256, ECC_KEY_LENGTH_256);
status = ecc_der_encode_ecdsa_signature (signature,
&signature[ECC_KEY_LENGTH_256], ECC_KEY_LENGTH_256, sig_der, sizeof (sig_der));
CuAssertIntEquals (test, 70, status);
buffer_reverse(signature, ECC_KEY_LENGTH_256);
buffer_reverse(signature + ECC_KEY_LENGTH_256, ECC_KEY_LENGTH_256);
status = ecc_der_encode_ecdsa_signature (signature,
&signature[ECC_KEY_LENGTH_256], ECC_KEY_LENGTH_256, sig_der2, sizeof (sig_der2));
CuAssertIntEquals (test, 69, status);
setup_attestation_requester_mock_attestation_test (test, &testing, true, true, true, true,
HASH_TYPE_SHA256, HASH_TYPE_SHA256, CFM_ATTESTATION_DMTF_SPDM, ATTESTATION_RIOT_SLOT_NUM,
component_id);
status = mock_expect (&testing.secondary_hash.mock, testing.secondary_hash.base.start_sha256,
&testing.secondary_hash, 0);
CuAssertIntEquals (test, 0, status);
attestation_requester_testing_send_and_receive_spdm_negotiate_algorithms_with_mocks (test, 0,
false, &testing);
attestation_requester_testing_send_and_receive_spdm_get_digests_with_mocks (test, false, true,
false, &testing, 3);
attestation_requester_testing_send_and_receive_spdm_get_certificate_with_mocks_and_verify (test,
&testing, HASH_TYPE_SHA256, 4, true, false, false, false, NULL, component_id);
attestation_requester_testing_send_and_receive_spdm_challenge_with_mocks (test, false, false,
&testing, 5);
status = mock_expect (&testing.secondary_hash.mock, testing.secondary_hash.base.cancel,
&testing.secondary_hash, 0);
status = mock_expect (&testing.secondary_hash.mock, testing.secondary_hash.base.start_sha256,
&testing.secondary_hash, 0);
CuAssertIntEquals (test, 0, status);
status = mock_expect (&testing.secondary_hash.mock, testing.secondary_hash.base.finish,
&testing.secondary_hash, 0, MOCK_ARG_NOT_NULL, MOCK_ARG (HASH_MAX_HASH_LEN));
status |= mock_expect_output_tmp (&testing.secondary_hash.mock, 0, digest, sizeof (digest), -1);
CuAssertIntEquals (test, 0, status);
status = mock_expect (&testing.ecc.mock, testing.ecc.base.init_public_key, &testing.ecc,
0, MOCK_ARG_PTR_CONTAINS (RIOT_CORE_ALIAS_PUBLIC_KEY,
RIOT_CORE_ALIAS_PUBLIC_KEY_LEN),
MOCK_ARG (RIOT_CORE_ALIAS_PUBLIC_KEY_LEN), MOCK_ARG_NOT_NULL);
status |= mock_expect_save_arg (&testing.ecc.mock, 2, 0);
status |= mock_expect (&testing.ecc.mock, testing.ecc.base.verify, &testing.ecc,
ECC_ENGINE_BAD_SIGNATURE, MOCK_ARG_SAVED_ARG (0), MOCK_ARG_PTR_CONTAINS_TMP (digest, sizeof (digest)),
MOCK_ARG (sizeof (digest)), MOCK_ARG_PTR_CONTAINS_TMP (sig_der2, 69),
MOCK_ARG (69));
status |= mock_expect (&testing.ecc.mock, testing.ecc.base.release_key_pair, &testing.ecc, 0,
MOCK_ARG_ANY, MOCK_ARG_SAVED_ARG (0));
CuAssertIntEquals (test, 0, status);
status = mock_expect (&testing.cfm.mock, testing.cfm.base.get_component_pmr_digest,
&testing.cfm, CFM_PMR_DIGEST_NOT_FOUND, MOCK_ARG (component_id), MOCK_ARG (0),
MOCK_ARG_NOT_NULL);
status |= mock_expect (&testing.cfm.mock,
testing.cfm.base.get_next_measurement_or_measurement_data, &testing.cfm, 0,
MOCK_ARG (component_id), MOCK_ARG_NOT_NULL, MOCK_ARG (1));
status |= mock_expect_output_tmp (&testing.cfm.mock, 1, &container,
sizeof (struct cfm_measurement_container), -1);
status |= mock_expect (&testing.cfm.mock,
testing.cfm.base.get_next_measurement_or_measurement_data, &testing.cfm,
CFM_ENTRY_NOT_FOUND, MOCK_ARG (component_id), MOCK_ARG_NOT_NULL, MOCK_ARG (0));
status |= mock_expect (&testing.cfm.mock, testing.cfm.base.free_measurement_container,
&testing.cfm, 0, MOCK_ARG_NOT_NULL);
CuAssertIntEquals (test, 0, status);
status = attestation_requester_attest_device (&testing.test, 0x0A);
CuAssertIntEquals (test, ECC_ENGINE_BAD_SIGNATURE, status);
}
static void attestation_requester_test_attest_device_spdm_only_pmr0_multiple_pmr0_options (
CuTest *test)
{
@ -31293,6 +31722,9 @@ TEST (attestation_requester_test_attest_device_spdm_sha384_only_pmr0);
TEST (attestation_requester_test_attest_device_spdm_sha384_1_1_only_pmr0);
TEST (attestation_requester_test_attest_device_spdm_sha512_only_pmr0);
TEST (attestation_requester_test_attest_device_spdm_sha512_1_1_only_pmr0);
TEST (attestation_requester_test_attest_device_spdm_only_little_endian_signature);
TEST (attestation_requester_test_attest_device_spdm_only_little_endian_signature_spdm_1_0);
TEST (attestation_requester_test_attest_device_spdm_only_little_endian_signature_spdm_1_2);
TEST (attestation_requester_test_attest_device_spdm_only_pmr0_multiple_pmr0_options);
TEST (attestation_requester_test_attest_device_spdm_sha256_only_measurement);
TEST (attestation_requester_test_attest_device_spdm_sha256_1_1_only_measurement);

Просмотреть файл

@ -80,7 +80,7 @@ struct cmd_interface_spdm_responder_testing {
struct spdm_secure_session_manager_state session_manager_state; /**< The session manager state. */
struct hash_engine_mock hash_engine_mock[SPDM_RESPONDER_HASH_ENGINE_REQUIRED_COUNT]; /**< Mock hash engine for the responder. */
struct hash_engine *hash_engine[SPDM_RESPONDER_HASH_ENGINE_REQUIRED_COUNT]; /**< Hash engines. */
struct spdm_version_num_entry version_num[SPDM_MAX_MINOR_VERSION]; /**< Version number entries. */
struct spdm_version_num_entry version_num[2]; /**< Version number entries. */
struct spdm_version_num_entry secure_message_version_num[SECURED_MESSAGE_VERSION_COUNT]; /**< Secured version number entries. */
struct spdm_device_capability local_capabilities; /**< Local capabilities. */
struct spdm_local_device_algorithms local_algorithms; /**< Local algorithms. */
@ -103,7 +103,7 @@ void cmd_interface_spdm_responder_testing_init_dependencies (CuTest *test,
struct cmd_interface_spdm_responder_testing *testing)
{
int status;
struct spdm_version_num_entry version_num[SPDM_MAX_MINOR_VERSION] =
struct spdm_version_num_entry version_num[2] =
{ {0, 0, 1, 1}, {0, 0, 2, 1} };
struct spdm_version_number secure_message_version_num[SECURED_MESSAGE_VERSION_COUNT] =
{ {0, 0, 0, 1}, {0, 0, 1, 1} };
@ -1092,7 +1092,7 @@ static void cmd_interface_spdm_responder_test_process_request_get_version (CuTes
struct spdm_get_version_response *expected_rsp =
(struct spdm_get_version_response*) expected_buf;
struct cmd_interface_msg request;
size_t version_count = SPDM_MAX_MINOR_VERSION - SPDM_MIN_MINOR_VERSION + 1;
size_t version_count = 2;
size_t version_length = version_count * sizeof (struct spdm_version_num_entry);
struct spdm_version_num_entry *version_num =
spdm_get_version_resp_version_table (expected_rsp);

Просмотреть файл

@ -94,7 +94,7 @@ struct spdm_command_testing {
struct spdm_secure_session_manager_state session_manager_state; /**< The session manager state. */
struct hash_engine_mock hash_engine_mock[SPDM_RESPONDER_HASH_ENGINE_REQUIRED_COUNT]; /**< Mock hash engine for the responder. */
struct hash_engine *hash_engine[SPDM_RESPONDER_HASH_ENGINE_REQUIRED_COUNT]; /**< Hash engines. */
struct spdm_version_num_entry version_num[SPDM_MAX_MINOR_VERSION]; /**< Version number entries. */
struct spdm_version_num_entry version_num[2]; /**< Version number entries. */
struct spdm_version_num_entry secured_message_version_num[SECURED_MESSAGE_VERSION_COUNT]; /**< Secured version number entries. */
struct spdm_device_capability local_capabilities; /**< Local capabilities. */
struct spdm_local_device_algorithms local_algorithms; /**< Local algorithms. */
@ -117,7 +117,7 @@ static void spdm_command_testing_init_dependencies (CuTest *test,
struct spdm_command_testing *testing)
{
int status;
struct spdm_version_num_entry version_num[SPDM_MAX_MINOR_VERSION] =
struct spdm_version_num_entry version_num[SPDM_MAX_MINOR_VERSION - SPDM_MIN_MINOR_VERSION + 1] =
{ {0, 0, 1, 1}, {0, 0, 2, 1} };
struct spdm_version_number secured_message_version_num[SECURED_MESSAGE_VERSION_COUNT] =
{ {0, 0, 0, 1}, {0, 0, 1, 1} };
@ -500,6 +500,26 @@ static void spdm_test_get_capabilities_1_1_format (CuTest *test)
CuAssertIntEquals (test, 0, msg->flags.reserved2);
}
static void spdm_test_get_capabilities_1_0_format (CuTest *test)
{
uint8_t raw_buffer_msg[] = {
0x10,0xe1,
0x01,0x02
};
struct spdm_get_capabilities_1_0 *msg = (struct spdm_get_capabilities_1_0*) raw_buffer_msg;
TEST_START;
CuAssertIntEquals (test, sizeof (raw_buffer_msg), sizeof (struct spdm_get_capabilities_1_0));
CuAssertIntEquals (test, 0x00, msg->header.spdm_minor_version);
CuAssertIntEquals (test, 0x01, msg->header.spdm_major_version);
CuAssertIntEquals (test, SPDM_REQUEST_GET_CAPABILITIES, msg->header.req_rsp_code);
CuAssertIntEquals (test, 1, msg->reserved);
CuAssertIntEquals (test, 2, msg->reserved2);
}
static void spdm_test_negotiate_algorithms_request_format (CuTest *test)
{
uint8_t raw_buffer_req[] = {
@ -3612,6 +3632,25 @@ static void spdm_test_generate_get_capabilities_request_1_1 (CuTest *test)
CuAssertIntEquals (test, 0, rq->flags.reserved2);
}
static void spdm_test_generate_get_capabilities_request_1_0 (CuTest *test)
{
uint8_t buf[CERBERUS_PROTOCOL_MAX_PAYLOAD_PER_MSG] = {0};
struct spdm_get_capabilities_1_0 *rq = (struct spdm_get_capabilities_1_0*) buf;
int status;
TEST_START;
memset (buf, 0x55, sizeof (buf));
status = spdm_generate_get_capabilities_request (buf, sizeof (buf), 0);
CuAssertIntEquals (test, sizeof (struct spdm_get_capabilities_1_0), status);
CuAssertIntEquals (test, 0, rq->header.spdm_minor_version);
CuAssertIntEquals (test, 1, rq->header.spdm_major_version);
CuAssertIntEquals (test, SPDM_REQUEST_GET_CAPABILITIES, rq->header.req_rsp_code);
CuAssertIntEquals (test, 0, rq->reserved);
CuAssertIntEquals (test, 0, rq->reserved2);
}
static void spdm_test_generate_get_capabilities_request_null (CuTest *test)
{
uint8_t buf[sizeof (struct spdm_get_capabilities)];
@ -3645,6 +3684,17 @@ static void spdm_test_generate_get_capabilities_request_1_1_buf_too_small (CuTes
CuAssertIntEquals (test, CMD_HANDLER_SPDM_BUF_TOO_SMALL, status);
}
static void spdm_test_generate_get_capabilities_request_1_0_buf_too_small (CuTest *test)
{
uint8_t buf[sizeof (struct spdm_get_capabilities_1_0) - 1];
int status;
TEST_START;
status = spdm_generate_get_capabilities_request (buf, sizeof (buf), 0);
CuAssertIntEquals (test, CMD_HANDLER_SPDM_BUF_TOO_SMALL, status);
}
static void spdm_test_process_get_capabilities_response (CuTest *test)
{
uint8_t buf[MCTP_BASE_PROTOCOL_MAX_MESSAGE_BODY] = {0};
@ -3756,6 +3806,48 @@ static void spdm_test_process_get_capabilities_1_1_response (CuTest *test)
CuAssertPtrEquals (test, resp, msg.payload);
}
static void spdm_test_process_get_capabilities_1_0_response (CuTest *test)
{
uint8_t buf[MCTP_BASE_PROTOCOL_MAX_MESSAGE_BODY] = {0};
struct spdm_get_capabilities_1_1 *resp = (struct spdm_get_capabilities_1_1*) &buf[16];
struct cmd_interface_msg msg;
int status;
TEST_START;
memset (&msg, 0, sizeof (msg));
msg.data = buf;
msg.payload = (uint8_t*) resp;
msg.max_response = MCTP_BASE_PROTOCOL_MAX_MESSAGE_BODY;
msg.payload_length = sizeof (struct spdm_get_capabilities_1_1);
msg.length = msg.payload_length + 16;
resp->header.spdm_minor_version = 0;
resp->header.spdm_major_version = SPDM_MAJOR_VERSION;
resp->header.req_rsp_code = SPDM_RESPONSE_GET_CAPABILITIES;
resp->reserved = 0;
resp->reserved2 = 0;
resp->reserved3 = 0;
resp->ct_exponent = 1;
resp->reserved4 = 0;
resp->flags.cache_cap = 1;
resp->flags.cert_cap = 1;
resp->flags.chal_cap = 1;
resp->flags.meas_cap = 1;
resp->flags.meas_fresh_cap = 1;
resp->flags.encrypt_cap = 1;
resp->flags.mac_cap = 1;
status = spdm_process_get_capabilities_response (&msg);
CuAssertIntEquals (test, 0, status);
CuAssertIntEquals (test, 16 + sizeof (struct spdm_get_capabilities_1_1), msg.length);
CuAssertIntEquals (test, sizeof (struct spdm_get_capabilities_1_1), msg.payload_length);
CuAssertPtrEquals (test, buf, msg.data);
CuAssertPtrEquals (test, resp, msg.payload);
}
static void spdm_test_process_get_capabilities_response_null (CuTest *test)
{
int status;
@ -3836,6 +3928,41 @@ static void spdm_test_process_get_capabilities_response_1_1_bad_length (CuTest *
CuAssertPtrEquals (test, resp, msg.payload);
}
static void spdm_test_process_get_capabilities_response_1_0_bad_length (CuTest *test)
{
uint8_t buf[CERBERUS_PROTOCOL_MAX_PAYLOAD_PER_MSG] = {0};
struct spdm_get_capabilities_1_1 *resp = (struct spdm_get_capabilities_1_1*) &buf[8];
struct cmd_interface_msg msg;
int status;
TEST_START;
memset (&msg, 0, sizeof (msg));
msg.data = buf;
msg.payload = (uint8_t*) resp;
msg.max_response = MCTP_BASE_PROTOCOL_MAX_MESSAGE_BODY;
msg.payload_length = sizeof (struct spdm_get_capabilities_1_1) - 1;
msg.length = msg.payload_length + 8;
resp->header.spdm_minor_version = 0;
resp->header.spdm_major_version = SPDM_MAJOR_VERSION;
resp->header.req_rsp_code = SPDM_RESPONSE_GET_CAPABILITIES;
status = spdm_process_get_capabilities_response (&msg);
CuAssertIntEquals (test, CMD_HANDLER_SPDM_BAD_LENGTH, status);
msg.payload_length = sizeof (struct spdm_get_capabilities_1_1) + 1;
msg.length = msg.payload_length + 8;
status = spdm_process_get_capabilities_response (&msg);
CuAssertIntEquals (test, CMD_HANDLER_SPDM_BAD_LENGTH, status);
CuAssertIntEquals (test, 8 + sizeof (struct spdm_get_capabilities_1_1) + 1, msg.length);
CuAssertIntEquals (test, sizeof (struct spdm_get_capabilities_1_1) + 1, msg.payload_length);
CuAssertPtrEquals (test, buf, msg.data);
CuAssertPtrEquals (test, resp, msg.payload);
}
static void spdm_test_negotiate_algorithms (CuTest *test)
{
uint8_t buf[MCTP_BASE_PROTOCOL_MAX_MESSAGE_BODY] = {0};
@ -8031,6 +8158,28 @@ static void spdm_test_process_negotiate_algorithms_response (CuTest *test)
CuAssertPtrEquals (test, resp, msg.payload);
}
static void spdm_test_process_negotiate_algorithms_response_1_0_non_zero_alg_tables (CuTest *test)
{
uint8_t buf[MCTP_BASE_PROTOCOL_MAX_MESSAGE_BODY] = {0};
struct spdm_negotiate_algorithms_response *resp =
(struct spdm_negotiate_algorithms_response*) &buf[8];
struct cmd_interface_msg msg;
int status;
TEST_START;
memset (&msg, 0, sizeof (msg));
msg.data = buf;
msg.payload = (uint8_t*) resp;
resp->header.spdm_minor_version = 0;
resp->num_alg_structure_tables = 1;
status = spdm_process_negotiate_algorithms_response (&msg);
CuAssertIntEquals (test, CMD_HANDLER_SPDM_BAD_RESPONSE, status);
}
static void spdm_test_process_negotiate_algorithms_response_null (CuTest *test)
{
int status;
@ -22158,6 +22307,38 @@ static void spdm_test_generate_get_measurements_request (CuTest *test)
CuAssertIntEquals (test, 0, status);
}
static void spdm_test_generate_get_measurements_request_1_0 (CuTest *test)
{
uint8_t buf[CERBERUS_PROTOCOL_MAX_PAYLOAD_PER_MSG] = {0};
struct spdm_get_measurements_request *rq = (struct spdm_get_measurements_request*) buf;
uint8_t nonce[SPDM_NONCE_LEN] = {0};
int status;
TEST_START;
memset (buf, 0x55, sizeof (buf));
nonce[0] = 0xaa;
nonce[10] = 0xbb;
nonce[20] = 0xcc;
nonce[30] = 0xdd;
nonce[31] = 0xee;
status = spdm_generate_get_measurements_request (buf, sizeof (buf), 0, 4, 1, 0, nonce, 0);
CuAssertIntEquals (test, sizeof (struct spdm_get_measurements_request) + SPDM_NONCE_LEN,
status);
CuAssertIntEquals (test, 0, rq->header.spdm_minor_version);
CuAssertIntEquals (test, 1, rq->header.spdm_major_version);
CuAssertIntEquals (test, SPDM_REQUEST_GET_MEASUREMENTS, rq->header.req_rsp_code);
CuAssertIntEquals (test, 1, rq->sig_required);
CuAssertIntEquals (test, 0, rq->raw_bit_stream_requested);
CuAssertIntEquals (test, 0, rq->reserved);
CuAssertIntEquals (test, 4, rq->measurement_operation);
status = testing_validate_array (nonce, spdm_get_measurements_rq_nonce (rq), sizeof (nonce));
CuAssertIntEquals (test, 0, status);
}
static void spdm_test_generate_get_measurements_request_no_sig_required (CuTest *test)
{
uint8_t buf[CERBERUS_PROTOCOL_MAX_PAYLOAD_PER_MSG] = {0};
@ -22215,6 +22396,18 @@ static void spdm_test_generate_get_measurements_request_raw_bitstream_requested
CuAssertIntEquals (test, 0, status);
}
static void spdm_test_generate_get_measurements_request_SPDM_1_0_invalid_slotid (CuTest *test)
{
uint8_t buf[sizeof (struct spdm_get_measurements_request)];
uint8_t nonce[SPDM_NONCE_LEN];
int status;
TEST_START;
status = spdm_generate_get_measurements_request (buf, sizeof (buf), 2, 4, 1, 0, nonce, 0);
CuAssertIntEquals (test, CMD_HANDLER_SPDM_UNSUPPORTED_SLOT_ID, status);
}
static void spdm_test_generate_get_measurements_request_null (CuTest *test)
{
uint8_t buf[sizeof (struct spdm_get_measurements_request)];
@ -22397,6 +22590,7 @@ TEST (spdm_test_get_version_request_format);
TEST (spdm_test_get_version_response_format);
TEST (spdm_test_get_capabilities_format);
TEST (spdm_test_get_capabilities_1_1_format);
TEST (spdm_test_get_capabilities_1_0_format);
TEST (spdm_test_negotiate_algorithms_request_format);
TEST (spdm_test_negotiate_algorithms_response_format);
TEST (spdm_test_get_digests_request_format);
@ -22450,14 +22644,18 @@ TEST (spdm_test_get_capabilities_append_request_fail);
TEST (spdm_test_get_capabilities_append_response_fail);
TEST (spdm_test_generate_get_capabilities_request);
TEST (spdm_test_generate_get_capabilities_request_1_1);
TEST (spdm_test_generate_get_capabilities_request_1_0);
TEST (spdm_test_generate_get_capabilities_request_null);
TEST (spdm_test_generate_get_capabilities_request_buf_too_small);
TEST (spdm_test_generate_get_capabilities_request_1_1_buf_too_small);
TEST (spdm_test_generate_get_capabilities_request_1_0_buf_too_small);
TEST (spdm_test_process_get_capabilities_response);
TEST (spdm_test_process_get_capabilities_1_1_response);
TEST (spdm_test_process_get_capabilities_1_0_response);
TEST (spdm_test_process_get_capabilities_response_null);
TEST (spdm_test_process_get_capabilities_response_bad_length);
TEST (spdm_test_process_get_capabilities_response_1_1_bad_length);
TEST (spdm_test_process_get_capabilities_response_1_0_bad_length);
TEST (spdm_test_negotiate_algorithms);
TEST (spdm_test_negotiate_algorithms_highest_pri_hash_algo);
TEST (spdm_test_negotiate_algorithms_lowest_pri_hash_algo);
@ -22500,6 +22698,7 @@ TEST (spdm_test_generate_negotiate_algorithms_request);
TEST (spdm_test_generate_negotiate_algorithms_request_null);
TEST (spdm_test_generate_negotiate_algorithms_request_buf_too_small);
TEST (spdm_test_process_negotiate_algorithms_response);
TEST (spdm_test_process_negotiate_algorithms_response_1_0_non_zero_alg_tables);
TEST (spdm_test_process_negotiate_algorithms_response_null);
TEST (spdm_test_process_negotiate_algorithms_response_bad_length);
TEST (spdm_test_get_digests_sha256);
@ -22664,8 +22863,10 @@ TEST (spdm_test_process_challenge_response);
TEST (spdm_test_process_challenge_response_null);
TEST (spdm_test_process_challenge_response_bad_length);
TEST (spdm_test_generate_get_measurements_request);
TEST (spdm_test_generate_get_measurements_request_1_0);
TEST (spdm_test_generate_get_measurements_request_no_sig_required);
TEST (spdm_test_generate_get_measurements_request_raw_bitstream_requested);
TEST (spdm_test_generate_get_measurements_request_SPDM_1_0_invalid_slotid);
TEST (spdm_test_generate_get_measurements_request_null);
TEST (spdm_test_generate_get_measurements_request_buf_too_small);
TEST (spdm_test_process_get_measurements_response);