core/spdm/spdm_commands.h (675 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. #ifndef SPDM_COMMANDS_H_ #define SPDM_COMMANDS_H_ #include "cmd_interface_spdm.h" #include "cmd_interface_spdm_responder.h" #include "platform_config.h" #include "spdm_protocol.h" #include "spdm_transcript_manager.h" #include "attestation/attestation_responder.h" #include "cmd_interface/cmd_interface.h" #include "cmd_interface/device_manager.h" #include "common/common_math.h" #include "crypto/hash.h" /* Configurable parameters. Defaults can be overridden in platform_config.h. */ /** * Maximum exponent for cryptographic processing time as described in section 10.3 of the DSP0274 * SPDM spec. */ #ifndef SPDM_MAX_CT_EXPONENT #define SPDM_MAX_CT_EXPONENT 31 #endif /** * Capabilities of SPDM requester. Capabilities described in section 10.3 in DSP0274 SPDM spec. */ #define SPDM_REQUESTER_CACHE_CAP 0 #define SPDM_REQUESTER_CERT_CAP 0 #define SPDM_REQUESTER_CHAL_CAP 0 #define SPDM_REQUESTER_MEAS_CAP 0 #define SPDM_REQUESTER_MEAS_FRESH_CAP 0 #define SPDM_REQUESTER_ENCRYPT_CAP 0 #define SPDM_REQUESTER_MAC_CAP 0 #define SPDM_REQUESTER_MUT_AUTH_CAP 0 #define SPDM_REQUESTER_KEY_EX_CAP 0 #define SPDM_REQUESTER_PSK_CAP 0 #define SPDM_REQUESTER_ENCAP_CAP 0 #define SPDM_REQUESTER_HBEAT_CAP 0 #define SPDM_REQUESTER_KEY_UPD_CAP 0 #define SPDM_REQUESTER_HANDSHAKE_IN_THE_CLEAR_CAP 0 #define SPDM_REQUESTER_PUB_KEY_ID_CAP 0 #define SPDM_REQUESTER_CHUNK_CAP 0 #define SPDM_REQUESTER_ALIAS_CERT_CAP 0 /** * SPDM measurement response capabilities values for the Get Capabilities command, from section 10.3 * in DSP0274 SPDM spec. */ #define SPDM_MEASUREMENT_RSP_CAP_MEASUREMENTS_WITHOUT_SIG (0x01) #define SPDM_MEASUREMENT_RSP_CAP_MEASUREMENTS_WITH_SIG (0x02) /** * SPDM combined prefix length as described in section 15 of DSP0274 SPDM spec. */ #define SPDM_COMBINED_PREFIX_LEN 100 /** * SPDM signature context string data structure. */ struct spdm_signing_context_str { bool is_requester; /**< Flag indicating if the context is for the requester. */ uint8_t op_code; /**< SPDM operation code. */ const void *context; /**< Context data. */ size_t context_size; /**< Size of the context data. */ size_t zero_pad_size; /**< Size of the zero padding. */ }; #pragma pack(push, 1) /** * SPDM get version request format */ struct spdm_get_version_request { struct spdm_protocol_header header; /**< Message header */ uint8_t reserved; /**< Reserved */ uint8_t reserved2; /**< Reserved */ }; /** * SPDM get version response format */ struct spdm_get_version_response { struct spdm_protocol_header header; /**< Message header */ uint8_t reserved; /**< Reserved */ uint8_t reserved2; /**< Reserved */ uint8_t reserved3; /**< Reserved */ uint8_t version_num_entry_count; /**< Number of version entries present in response */ }; /** * SPDM version entry format */ struct spdm_version_num_entry { uint8_t alpha:4; /**< Pre-release WIP version of the specification */ uint8_t update_version:4; /**< Specification update version */ uint8_t minor_version:4; /**< Specification minor version */ uint8_t major_version:4; /**< Specification major version */ }; /** * Get the total length of a SPDM get version response message * * @param resp Buffer with struct spdm_get_version_response */ #define spdm_get_version_resp_length(resp) \ ((resp->version_num_entry_count * sizeof (struct spdm_version_num_entry)) + \ sizeof (struct spdm_get_version_response)) /** * Get the buffer containing the version table from a SPDM get version response * * @param resp Buffer with struct spdm_get_version_response */ #define spdm_get_version_resp_version_table(resp) \ ((struct spdm_version_num_entry*) (((uint8_t*) resp) + sizeof (*resp))) /** * Convert SPDM CT base 2 exponent to timeout in milliseconds * * @param ct Exponent of base 2 used to calculate CT defined in section 9.2 in DSP0274 SPDM spec */ #define spdm_capabilities_rsp_ct_to_ms(ct) ((1 << (ct)) / 1000) /** * Minimum data transfer size for 1.2 per SPDM spec section 10.3 */ #define SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_1_2 42 /** * SPDM get capabilities flags format */ struct spdm_get_capabilities_flags_format { uint8_t cache_cap:1; /**< Supports ability to cache negotiated state across reset. Only set in response messages */ uint8_t cert_cap:1; /**< Supports Get Digests and Get Certificate commands */ uint8_t chal_cap:1; /**< Supports Challenge command */ uint8_t meas_cap:2; /**< Measurement response capabilities. Only set in response messages */ uint8_t meas_fresh_cap:1; /**< Measurement response capabilities. Only set in response messages */ uint8_t encrypt_cap:1; /**< Supports message encryption */ uint8_t mac_cap:1; /**< Supports message authentication */ uint8_t mut_auth_cap:1; /**< Supports mutual authentication */ uint8_t key_ex_cap:1; /**< Supports Key Exchange command */ uint8_t psk_cap:2; /**< Pre-shared key capabilities */ uint8_t encap_cap:1; /**< Supports encapsulated requests */ uint8_t hbeat_cap:1; /**< Supports heartbeat command */ uint8_t key_upd_cap:1; /**< Supports Key Update command */ uint8_t handshake_in_the_clear_cap:1; /**< Supports communication with messages exchanged during the Session Handshake Phase in the clear */ uint8_t pub_key_id_cap:1; /**< Public key of device was provisioned to target */ uint8_t chunk_cap:1; /**< Supports large SPDM message transfer mechanism */ uint8_t alias_cert_cap:1; /**< Uses the AliasCert model */ uint8_t reserved:5; /**< Reserved */ uint8_t reserved2; /**< Reserved */ }; /** * SPDM measurement capability flag values. */ enum spm_measurement_capability_options { SPDM_MEAS_CAP_NO_SIG = 1, /**< Measurement response without signature */ SPDM_MEAS_CAP_WITH_SIG = 2, /**< Measurement response with signature */ }; /** * SPDM pre-shared key capabilities flag values. */ enum spdm_pre_shared_key_capability_options { SPDM_PSK_NOT_SUPPORTED, /**< Pre-shared key capabilities not supported.*/ SPDM_PSK_SUPPORTED_NO_CONTEXT, /** <Pre-shared key supported without session key derviation context.*/ SPDM_PSK_SUPPORTED_WITH_CONTEXT, /** <Pre-shared key supported with session key derviation context.*/ 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 */ struct spdm_get_capabilities_1_1 { struct spdm_protocol_header header; /**< Message header */ uint8_t reserved; /**< Reserved */ uint8_t reserved2; /**< Reserved */ uint8_t reserved3; /**< Reserved */ uint8_t ct_exponent; /**< Exponent of base 2 used to calculate CT from timing specification table */ uint16_t reserved4; /**< Reserved */ struct spdm_get_capabilities_flags_format flags; /**< Capabilities flags */ }; /** * SPDM get capabilities request/response format */ struct spdm_get_capabilities { struct spdm_get_capabilities_1_1 base_capabilities; /**< Common capabilities segment with v1.1 get capabilities format*/ uint32_t data_transfer_size; /**< Maximum buffer size in bytes of the device for receiving a single SPDM message */ uint32_t max_spdm_msg_size; /**< Maximum size in bytes of the internal buffer for processing a single large SPDM message */ }; /** * SPDM measurement specification values for Negotiate Algorithm command, from section 10.4 in * DSP0274 SPDM spec. */ #define SPDM_MEASUREMENT_SPEC_DMTF (1 << 0) /** * SPDM asymmetric key signature algorithm bitmask selection for Negotiate Algorithm command, from * section 10.4 in DSP0274 SPDM spec. */ #define SPDM_TPM_ALG_RSASSA_2048 (1 << 0) #define SPDM_TPM_ALG_RSAPSS_2048 (1 << 1) #define SPDM_TPM_ALG_RSASSA_3072 (1 << 2) #define SPDM_TPM_ALG_RSAPSS_3072 (1 << 3) #define SPDM_TPM_ALG_ECDSA_ECC_NIST_P256 (1 << 4) #define SPDM_TPM_ALG_RSASSA_4096 (1 << 5) #define SPDM_TPM_ALG_RSAPSS_4096 (1 << 6) #define SPDM_TPM_ALG_ECDSA_ECC_NIST_P384 (1 << 7) #define SPDM_TPM_ALG_ECDSA_ECC_NIST_P521 (1 << 8) /** * SPDM cryptographic hashing algorithm bitmask selection for Negotiate Algorithm command, from * section 10.4 in DSP0274 SPDM spec. */ #define SPDM_TPM_ALG_SHA_256 (1 << 0) #define SPDM_TPM_ALG_SHA_384 (1 << 1) #define SPDM_TPM_ALG_SHA_512 (1 << 2) #define SPDM_TPM_ALG_SHA3_256 (1 << 3) #define SPDM_TPM_ALG_SHA3_384 (1 << 4) #define SPDM_TPM_ALG_SHA3_512 (1 << 5) /** * SPDM cryptographic hashing algorithm bitmask selection for measurements in Negotiate Algorithm * response, from section 10.4 in DSP0274 SPDM spec. */ #define SPDM_MEAS_RSP_ALG_RAW_BIT_STREAM_ONLY (1 << 0) #define SPDM_MEAS_RSP_TPM_ALG_SHA_256 (1 << 1) #define SPDM_MEAS_RSP_TPM_ALG_SHA_384 (1 << 2) #define SPDM_MEAS_RSP_TPM_ALG_SHA_512 (1 << 3) #define SPDM_MEAS_RSP_TPM_ALG_SHA3_256 (1 << 4) #define SPDM_MEAS_RSP_TPM_ALG_SHA3_384 (1 << 5) #define SPDM_MEAS_RSP_TPM_ALG_SHA3_512 (1 << 6) /** * SPDM algorithm type for an algorithm request structure, from section 10.4 in DSP0274 SPDM spec. */ #define SPDM_ALG_REQ_STRUCT_MAX_NUM_STRUCT_TABLE_ALG 4 #define SPDM_ALG_REQ_STRUCT_ALG_TYPE_DHE 2 #define SPDM_ALG_REQ_STRUCT_ALG_TYPE_AEAD 3 #define SPDM_ALG_REQ_STRUCT_ALG_TYPE_REQ_BASE_ASYM_ALG 4 #define SPDM_ALG_REQ_STRUCT_ALG_TYPE_KEY_SCHEDULE 5 /** * SPDM negotiate algorithms maximum request size, from section 10.4 in DSP0274 SPDM spec. */ #define SPDM_NEGOTIATE_ALGORITHMS_REQUEST_MAX_LENGTH 0x80 /** * SPDM negotiate algorithms maximum extension algorithm count, from section 10.4 in DSP0274 SPDM * spec. */ #define SPDM_NEGOTIATE_ALGORITHMS_REQUEST_MAX_EXT_ALG_COUNT_VERSION 0x14 /** * SPDM Opaque Data Format (v1.2). */ #define SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_NONE 0x0 #define SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_0 0x1 #define SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1 0x2 /** * SPDM Opaque Data Format 1 (v1.2) table header */ struct spdm_general_opaque_data_table_header { uint8_t total_elements; /**< Total number of elements in the table */ uint8_t reserved[3]; /**< Reserved */ }; /** * SPDM Opaque Data element table header. */ struct spdm_opaque_element_table_header { uint8_t id; /**< Registry or standards body ID */ uint8_t vendor_len; /**< Length of the vendor Id */ }; /* SPDM registry_id */ #define SPDM_REGISTRY_ID_DMTF 0x0 #define SPDM_REGISTRY_ID_TCG 0x1 #define SPDM_REGISTRY_ID_USB 0x2 #define SPDM_REGISTRY_ID_PCISIG 0x3 #define SPDM_REGISTRY_ID_IANA 0x4 #define SPDM_REGISTRY_ID_HDBASET 0x5 #define SPDM_REGISTRY_ID_MIPI 0x6 #define SPDM_REGISTRY_ID_CXL 0x7 #define SPDM_REGISTRY_ID_JEDEC 0x8 #define SPDM_REGISTRY_ID_VESA 0x9 #define SPDM_REGISTRY_ID_IANA_CBOR 0xa #define SPDM_REGISTRY_ID_MAX 0xa /** * SPDM Negotiate Algorithm request KEY_SCHEDULE algorithm. */ #define SPDM_ALG_KEY_SCHEDULE_HMAC_HASH 0x00000001 /** * SPDM Negotiate Algorithm request AEAD algorithms. */ #define SPDM_ALG_AEAD_CIPHER_SUITE_AES_128_GCM 0x00000001 #define SPDM_ALG_AEAD_CIPHER_SUITE_AES_256_GCM 0x00000002 #define SPDM_ALG_AEAD_CIPHER_SUITE_CHACHA20_POLY1305 0x00000004 #define SPDM_ALG_AEAD_CIPHER_SUITE_AEAD_SM4_GCM 0x00000008 /** * SPDM Negotiate Algorithm request DHE algorithms. */ #define SPDM_ALG_DHE_NAMED_GROUP_FFDHE_2048 0x00000001 #define SPDM_ALG_DHE_NAMED_GROUP_FFDHE_3072 0x00000002 #define SPDM_ALG_DHE_NAMED_GROUP_FFDHE_4096 0x00000004 #define SPDM_ALG_DHE_NAMED_GROUP_SECP_256_R1 0x00000008 #define SPDM_ALG_DHE_NAMED_GROUP_SECP_384_R1 0x00000010 #define SPDM_ALG_DHE_NAMED_GROUP_SECP_521_R1 0x00000020 /** * SPDM Negotiate Algorithm request algorithm structure types. */ #define SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE 2 #define SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_AEAD 3 #define SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_BASE_ASYM_ALG 4 #define SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEY_SCHEDULE 5 /** * SPDM Negotiate Algorithm 'OtherParamsSupport' format. */ struct spdm_other_params_support { uint8_t opaque_data_format:4; /**< Opaque Data Format Support and Selection */ uint8_t reserved:4; /**< Reserved */ }; /** * SPDM negotiate algorithms request format */ struct spdm_negotiate_algorithms_request { struct spdm_protocol_header header; /**< Message header */ uint8_t num_alg_structure_tables; /**< Number of algorithm structure tables in request */ uint8_t reserved; /**< Reserved */ uint16_t length; /**< Length of the entire message in bytes */ uint8_t measurement_specification; /**< Measurement specification bitmask */ struct spdm_other_params_support other_params_support; /**< Additional params supported */ uint32_t base_asym_algo; /**< Supported asymmetric key signature algorithms */ uint32_t base_hash_algo; /**< Supported cryptographic hashing algorithms */ uint8_t reserved3[12]; /**< Reserved */ uint8_t ext_asym_count; /**< Number of supported extended asymmetric key signature algorithms */ uint8_t ext_hash_count; /**< Number of supported extended cryptographic hashing algorithms */ uint16_t reserved4; /**< Reserved */ }; /** * SPDM extended algorithm format */ struct spdm_extended_algorithm { uint8_t registry_id; /**< Registry or standards body */ uint8_t reserved; /**< Reserved */ uint16_t algorithm_id; /**< Algorithm ID */ }; /** * SPDM algorithm request structure format */ struct spdm_algorithm_request { uint8_t alg_type; /**< Type of algorithm */ uint8_t ext_alg_count:4; /**< Number of supported extended algorithms */ uint8_t fixed_alg_count:4; /**< Number of supported SPDM-enumerated fixed algorithms */ uint16_t alg_supported; /**< Bitmask for supported SPDM-enumerated algorithms */ }; /** * Get the minimum length of a SPDM negotiate algorithms request message * * @param req Buffer containing struct spdm_negotiate_algorithms_request */ #define spdm_negotiate_algorithms_min_req_length(req) ( \ sizeof (struct spdm_negotiate_algorithms_request) + \ (sizeof (struct spdm_extended_algorithm) * (req->ext_asym_count + req->ext_hash_count)) + \ (sizeof (struct spdm_algorithm_request) * req->num_alg_structure_tables)) /** * Get the next algorithm struct table entry. * * @param curr_alg_struct_table_entry Current algorithm struct table entry. */ #define spdm_negotiate_algorithms_get_next_alg_struct_table_entry(curr_alg_struct_table_entry) ( \ (struct spdm_algorithm_request*)((size_t) curr_alg_struct_table_entry + \ sizeof (struct spdm_algorithm_request) + \ sizeof (struct spdm_extended_algorithm) * curr_alg_struct_table_entry->ext_alg_count)) /** * Get the extended asymmetric key signature algorithms table from a negotiate algorithms request * * @param req Buffer with struct spdm_negotiate_algorithms_request */ #define spdm_negotiate_algorithms_req_ext_asym_table(req) \ ((struct spdm_extended_algorithm*) (((uint8_t*) req) + sizeof (*req))) /** * Get the extended cryptographic hashing algorithms table from a negotiate algorithms request * * @param req Buffer with struct spdm_negotiate_algorithms_request */ #define spdm_negotiate_algorithms_req_ext_hash_table(req) ((struct spdm_extended_algorithm*) \ (((uint8_t*) spdm_negotiate_algorithms_req_ext_asym_table (req)) + \ req->ext_asym_count * (sizeof (struct spdm_extended_algorithm)))) /** * Get the first algorithm request structure table from a negotiate algorithms request * * @param req Buffer with struct spdm_negotiate_algorithms_request */ #define spdm_negotiate_algorithms_req_algstruct_table(req) ((struct spdm_algorithm_request*) \ ((uint8_t*) spdm_negotiate_algorithms_req_ext_hash_table (req) + \ req->ext_hash_count * (sizeof (struct spdm_extended_algorithm)))) /** * Get the expected extended algorithm structure total size. * * @param algstruct_table Algorithm structure table. */ #define spdm_negotiate_algorithms_expected_extended_algo_size(algstruct_table) ( \ sizeof (struct spdm_extended_algorithm) * algstruct_table->ext_alg_count) /** * Get the actual extended algorithm structure total size. * * @param rq Buffer containing extended algorithm structure * @param algstruct_table Algorithm structure table. */ #define spdm_negotiate_algorithms_actual_extended_algo_size(req, algstruct_table) ( \ (size_t) (req) + request->payload_length - (size_t) (algstruct_table) - \ sizeof (struct spdm_algorithm_request)) /** * SPDM negotiate algorithms response format */ struct spdm_negotiate_algorithms_response { struct spdm_protocol_header header; /**< Message header */ uint8_t num_alg_structure_tables; /**< Number of algorithm structure tables in request */ uint8_t reserved; /**< Reserved */ uint16_t length; /**< Length of the entire message in bytes */ uint8_t measurement_specification; /**< Measurement specification bitmask */ struct spdm_other_params_support other_params_selection; /**< Additional params selected */ uint32_t measurement_hash_algo; /**< SPDM-enumerated hashing algorithm selected for measurements */ uint32_t base_asym_sel; /**< Asymmetric key signature algorithm selected */ uint32_t base_hash_sel; /**< Cryptographic hashing algorithm selected */ uint8_t reserved3[12]; /**< Reserved */ uint8_t ext_asym_sel_count; /**< Number of extended asymmetric key signature algorithms selected */ uint8_t ext_hash_sel_count; /**< Number of extended cryptographic hashing algorithms selected */ uint16_t reserved4; /**< Reserved */ }; /** * Maximum algorithm structs in negotiate algorithms response. */ #define SPDM_NEGOTIATE_ALGORITHMS_MAX_NUM_STRUCT_TABLE_ALG 4 /** * SPDM negotiate algorithms response with no external algorithms. */ struct spdm_negotiate_algorithms_response_no_ext_alg { struct spdm_negotiate_algorithms_response base; struct spdm_algorithm_request algstruct_table[SPDM_NEGOTIATE_ALGORITHMS_MAX_NUM_STRUCT_TABLE_ALG]; }; /** * Get the minimum length of a SPDM negotiate algorithms response message * * @param rsp Buffer containing struct spdm_negotiate_algorithms_response */ #define spdm_negotiate_algorithms_min_rsp_length(rsp) ( \ sizeof (struct spdm_negotiate_algorithms_response) + \ (sizeof (struct spdm_extended_algorithm) * \ (rsp->ext_asym_sel_count + rsp->ext_hash_sel_count)) + \ (sizeof (struct spdm_algorithm_request) * rsp->num_alg_structure_tables)) /** * Get the extended asymmetric key signature algorithms table from a negotiate algorithms response * * @param resp Buffer with struct spdm_negotiate_algorithms_response */ #define spdm_negotiate_algorithms_rsp_ext_asym_table(resp) \ ((struct spdm_extended_algorithm*) (((uint8_t*) resp) + sizeof (*resp))) /** * Get the extended cryptographic hashing algorithms table from a negotiate algorithms response * * @param resp Buffer with struct spdm_negotiate_algorithms_response */ #define spdm_negotiate_algorithms_rsp_ext_hash_table(resp) ((struct spdm_extended_algorithm*) \ (((uint8_t*) spdm_negotiate_algorithms_rsp_ext_asym_table (resp)) + \ resp->ext_asym_sel_count * (sizeof (struct spdm_extended_algorithm)))) /** * Get the first algorithm request structure table from a negotiate algorithms response * * @param resp Buffer with struct spdm_negotiate_algorithms_response */ #define spdm_negotiate_algorithms_rsp_algstruct_table(resp) ((struct spdm_algorithm_request*) \ ((uint8_t*) spdm_negotiate_algorithms_rsp_ext_hash_table (resp) + \ (resp->ext_hash_sel_count * (sizeof (struct spdm_extended_algorithm))))) /** * Get the negotiate algorithm response size. This is based on the negotiate algorithms request. * * @param req Buffer containing the negotiate algorithms request. */ #define spdm_negotiate_algorithms_rsp_size(req) ( \ sizeof (struct spdm_negotiate_algorithms_response_no_ext_alg) - \ ((SPDM_ALG_REQ_STRUCT_MAX_NUM_STRUCT_TABLE_ALG - req->num_alg_structure_tables) * \ sizeof (struct spdm_algorithm_request))); /** * SPDM get certificate request/response slot id mask */ #define SPDM_GET_CERTIFICATE_SLOT_ID_MASK 0xF /** * SPDM certificate slot maximum count. * [TODO] This will be removed when the Certificate Manager component is available. */ #ifndef SPDM_MAX_SLOT_COUNT #define SPDM_MAX_SLOT_COUNT 1 #endif /** * SPDM max. certificates in a chain. * [TODO] This will be removed when the Certificate Manager component is available. */ #ifndef SPDM_MAX_CERT_COUNT_IN_CHAIN #define SPDM_MAX_CERT_COUNT_IN_CHAIN 4 #endif /** * SPDM get digests request format */ struct spdm_get_digests_request { struct spdm_protocol_header header; /**< Message header */ uint8_t reserved; /**< Reserved */ uint8_t reserved2; /**< Reserved */ }; /** * SPDM get digests response format */ struct spdm_get_digests_response { struct spdm_protocol_header header; /**< Message header */ uint8_t reserved; /**< Reserved */ uint8_t slot_mask; /**< Slot mask */ }; /** * SPDM cert chain header */ struct spdm_cert_chain_header { uint16_t length; /**< Length of the cert chain including this struct. */ uint16_t reserved; /**< Reserved */ }; /** * SPDM cert chain format */ struct spdm_cert_chain { struct spdm_cert_chain_header header; /**< Cert chain header */ uint8_t root_hash[HASH_MAX_HASH_LEN]; /**< Max. hash size of the root cert. */ }; /** * Get the total length of a SPDM certificate chain. * * @param hash_size Size of the cert chain hash. * @param cert_chain_length Length of the cert chain. */ #define spdm_get_digests_cert_chain_length(hash_size, cert_chain_length) \ (offsetof (struct spdm_cert_chain, root_hash) + hash_size + cert_chain_length) /** * Get the total length of a SPDM get digests response message * * @param resp Buffer containing struct spdm_get_digests_response * @param digest_len Size of each certificate chain digest */ #define spdm_get_digests_resp_length(resp, digest_len) \ (common_math_get_num_bits_set (resp->slot_mask) * digest_len + sizeof (*resp)) /** * Get the buffer containing the digests table stored in SPDM get digests response * * @param resp Buffer with struct spdm_get_digests_response */ #define spdm_get_digests_resp_digests(resp) (((uint8_t*) resp) + sizeof (*resp)) /** * Get the buffer containing a single entry from digest table stored in SPDM get digests response * * @param resp Buffer with struct spdm_get_digests_response * @param slot_num Slot number of requested certificate chain digest * @param digest_len Size of each certificate chain digest */ #define spdm_get_digests_resp_digest(resp, slot_num, digest_len) \ (spdm_get_digests_resp_digests (resp) + \ (common_math_get_num_bits_set_before_index (resp->slot_mask, slot_num) * digest_len)) /** * SPDM get certificate request format */ struct spdm_get_certificate_request { struct spdm_protocol_header header; /**< Message header */ uint8_t slot_num; /**< Slot number to read certificate chain from */ uint8_t reserved; /**< Reserved */ uint16_t offset; /**< Offset in bytes from start of certificate chain requested */ uint16_t length; /**< Length in bytes requested */ }; /** * SPDM get certificate response format */ struct spdm_get_certificate_response { struct spdm_protocol_header header; /**< Message header */ uint8_t slot_num; /**< Slot number of the certificate chain returned */ uint8_t reserved; /**< Reserved */ uint16_t portion_len; /**< Number of certificate chain bytes included in response */ uint16_t remainder_len; /**< Number of certificate chain bytes not sent yet */ }; /** * Get the total length of a SPDM get certificate response message * * @param resp Buffer containing struct spdm_get_certificate_response */ #define spdm_get_certificate_resp_length(resp) (resp->portion_len + sizeof (*resp)) /** * Maximum amount of certificate data that can be returned in the response */ #define SPDM_GET_CERTIFICATE_MAX_CERT_BUFFER (MCTP_BASE_PROTOCOL_MAX_MESSAGE_BODY - \ sizeof (struct spdm_get_certificate_response)) /** * Maximum amount of certificate data that can be returned in the response * * @param max_response Maximum response length */ #define spdm_get_certificate_max_cert_buffer(max_response) \ (max_response - sizeof (struct spdm_get_certificate_response)) /** * Get the buffer containing the certificate chain portion returned in SPDM get certificate response * * @param resp Buffer with struct spdm_get_certificate_response */ #define spdm_get_certificate_resp_cert_chain(resp) (((uint8_t*) resp) + sizeof (*resp)) /** * SPDM certificate chain format */ struct spdm_certificate_chain { uint16_t length; /**< Total length of certificate chain including all fields */ uint16_t reserved; /**< Reserved */ }; /** * SPDM measurement summary hash types for Challenge command, from section 10.9 in DSP0274 SPDM * spec. */ #define SPDM_MEASUREMENT_SUMMARY_HASH_NONE 0x0 #define SPDM_MEASUREMENT_SUMMARY_HASH_TCB 0x1 #define SPDM_MEASUREMENT_SUMMARY_HASH_ALL 0xFF /** * SPDM challenge request format */ struct spdm_challenge_request { struct spdm_protocol_header header; /**< Message header */ uint8_t slot_num; /**< Slot number selected */ uint8_t req_measurement_summary_hash_type; /**< Requested measurement summary hash type */ uint8_t nonce[SPDM_NONCE_LEN]; /**< Random nonce */ }; /** * SPDM challenge response format */ struct spdm_challenge_response { struct spdm_protocol_header header; /**< Message header */ uint8_t slot_num:4; /**< Slot number selected in request */ uint8_t reserved:3; /**< Reserved */ uint8_t basic_mutual_auth_req:1; /**< Request identity authentication of requester */ uint8_t slot_mask; /**< Slot mask indicating certificate chains supporting SPDM protocol version */ }; /** * Get the minimum length of a SPDM challenge response message, not including variable length fields * * @param cert_chain_hash_len Length of certificate chain */ #define spdm_get_challenge_resp_min_length(cert_chain_hash_len) \ (sizeof (struct spdm_challenge_response) + cert_chain_hash_len + SPDM_NONCE_LEN + \ sizeof (uint16_t)) /** * Get the total length of a SPDM challenge response message, not including signature * * @param resp Buffer containing struct spdm_get_certificate_response * @param cert_chain_hash_len Length of certificate chain * @param measurement_summary_hash Length of measurement summary hash */ #define spdm_get_challenge_resp_length(resp, cert_chain_hash_len, measurement_summary_hash) \ (spdm_get_challenge_resp_min_length (cert_chain_hash_len) + measurement_summary_hash + \ spdm_get_challenge_resp_opaque_len (resp, cert_chain_hash_len, measurement_summary_hash)) /** * Get the buffer containing the certificate chain hash in SPDM challenge response * * @param resp Buffer with struct spdm_challenge_response */ #define spdm_get_challenge_resp_cert_chain_hash(resp) (((uint8_t*) resp) + sizeof (*resp)) /** * Get the buffer containing the nonce in SPDM challenge response * * @param resp Buffer with struct spdm_challenge_response * @param cert_chain_hash_len Length of certificate chain */ #define spdm_get_challenge_resp_nonce(resp, cert_chain_hash_len) \ (spdm_get_challenge_resp_cert_chain_hash (resp) + cert_chain_hash_len) /** * Get the buffer containing the measurement summary hash in SPDM challenge response * * @param resp Buffer with struct spdm_challenge_response * @param cert_chain_hash_len Length of certificate chain */ #define spdm_get_challenge_resp_measurement_summary_hash(resp, cert_chain_hash_len) \ (spdm_get_challenge_resp_nonce (resp, cert_chain_hash_len) + SPDM_NONCE_LEN) /** * Get the max measurement summary hash length in SPDM challenge response * * @param max_response Maximum response length * @param cert_chain_hash_len Length of certificate chain * @param opaque_data_len Opaque data length * @param sig_len Signature length */ #define spdm_get_challenge_resp_measurement_summary_hash_max_len(max_response, \ cert_chain_hash_len, sig_len, opaque_data_len) \ (max_response - \ spdm_get_challenge_resp_min_length (cert_chain_hash_len) - opaque_data_len - sig_len) /** * Get the pointer holding the opaque data size from a SPDM challenge response * * @param resp Buffer with struct spdm_challenge_response * @param cert_chain_hash_len Length of certificate chain * @param measurement_summary_hash Length of measurement summary hash */ #define spdm_get_challenge_resp_opaque_len_ptr(resp, cert_chain_hash_len, \ measurement_summary_hash) \ ((uint16_t*) (spdm_get_challenge_resp_measurement_summary_hash (resp, cert_chain_hash_len) + \ measurement_summary_hash)) /** * Get the opaque data size from a SPDM challenge response * * @param resp Buffer with struct spdm_challenge_response * @param cert_chain_hash_len Length of certificate chain * @param measurement_summary_hash Length of measurement summary hash */ #define spdm_get_challenge_resp_opaque_len(resp, cert_chain_hash_len, measurement_summary_hash) \ (*spdm_get_challenge_resp_opaque_len_ptr (resp, cert_chain_hash_len, measurement_summary_hash)) /** * Get the buffer containing opaque data from a SPDM challenge response * * @param resp Buffer with struct spdm_challenge_response * @param cert_chain_hash_len Length of certificate chain * @param measurement_summary_hash Length of measurement summary hash */ #define spdm_get_challenge_resp_opaque_data(resp, cert_chain_hash_len, measurement_summary_hash) \ (spdm_get_challenge_resp_measurement_summary_hash (resp, cert_chain_hash_len) + \ measurement_summary_hash + sizeof (uint16_t)) /** * Get the buffer containing the signature from a SPDM challenge response * * @param resp Buffer with struct spdm_challenge_response * @param cert_chain_hash_len Length of certificate chain * @param measurement_summary_hash Length of measurement summary hash */ #define spdm_get_challenge_resp_signature(resp, cert_chain_hash_len, measurement_summary_hash) \ (spdm_get_challenge_resp_opaque_data (resp, cert_chain_hash_len, measurement_summary_hash) + \ spdm_get_challenge_resp_opaque_len (resp,cert_chain_hash_len, measurement_summary_hash)) /** * Get the signature length of a SPDM challenge response message * * @param resp Buffer containing struct spdm_challenge_response * @param cert_chain_hash_len Length of certificate chain * @param len Total response length * @param measurement_summary_hash Length of measurement summary hash */ #define spdm_get_challenge_resp_signature_length(resp, cert_chain_hash_len, len, \ measurement_summary_hash) \ (len - spdm_get_challenge_resp_length (resp, cert_chain_hash_len, measurement_summary_hash)) /** * SPDM measurement operation types for Get Measurements command, from section 10.11 in DSP0274 SPDM * spec. */ #define SPDM_MEASUREMENT_OPERATION_GET_NUM_BLOCKS 0x0 #define SPDM_MEASUREMENT_OPERATION_GET_ALL_BLOCKS 0xFF /** * SPDM custom device ID measurement block needed for discovery of SPDM devices by Cerberus */ #define SPDM_MEASUREMENT_OPERATION_GET_DEVICE_ID 0xEF /** * SPDM GET_MEASUREMENTS request Attributes. */ #define SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_GENERATE_SIGNATURE 0x00000001 #define SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_RAW_BIT_STREAM_REQUESTED 0x00000002 #define SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_NEW_MEASUREMENT_REQUESTED 0x00000004 /** * SPDM GET_MEASUREMENTS measurement operation request options. */ #define SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_TOTAL_NUMBER_OF_MEASUREMENTS 0 #define SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_ALL_MEASUREMENTS 0xFF /** * SPDM get measurements request format */ struct spdm_get_measurements_request { struct spdm_protocol_header header; /**< Message header */ uint8_t sig_required:1; /**< Signature required in response */ uint8_t raw_bit_stream_requested:1; /**< Raw measurement block requested */ uint8_t reserved:6; /**< Reserved */ uint8_t measurement_operation; /**< Measurement operation */ }; /** * Get the total length of a SPDM get measurements request message * * @param rq Buffer containing 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. * * @param rq Buffer containing struct spdm_get_measurements_request */ #define spdm_get_measurements_rq_nonce(rq) (((uint8_t*) rq) + sizeof (*rq)) /** * Get pointer containing slot ID buffer in SPDM get measurements request. This is only valid when * the signature required flag is set. * * @param rq Buffer with struct spdm_get_measurements_request */ #define spdm_get_measurements_rq_slot_id_ptr(rq) \ ((uint8_t*) (spdm_get_measurements_rq_nonce (rq) + (rq)->sig_required * SPDM_NONCE_LEN)) /** * Get slot ID in SPDM get measurements request * * @param rq Buffer with struct spdm_get_measurements_request */ #define spdm_get_measurements_rq_slot_id(rq) \ (*(spdm_get_measurements_rq_slot_id_ptr (rq)) & 0x0F) /** * SPDM get measurements response format */ struct spdm_get_measurements_response { struct spdm_protocol_header header; /**< Message header */ uint8_t num_measurement_indices; /**< Number of measurement indices in device */ uint8_t slot_id:4; /**< Slot ID */ uint8_t reserved:4; /**< Reserved */ uint8_t number_of_blocks; /**< Number of measurement blocks in measurement record */ uint8_t measurement_record_len[3]; /**< Length of measurement record */ }; /** * Get the minimum length of a SPDM get measurements response message, not including variable length * fields */ #define SPDM_GET_MEASUREMENTS_RESP_MIN_LENGTH \ (sizeof (struct spdm_get_measurements_response) + SPDM_NONCE_LEN + sizeof (uint16_t)) /** * Get the total length of a SPDM get measurements response message, not including signature * * @param resp Buffer containing struct spdm_get_measurements_response * @param hash_len Hashing algorithm length */ #define spdm_get_measurements_resp_length(resp) (SPDM_GET_MEASUREMENTS_RESP_MIN_LENGTH + \ spdm_get_measurements_resp_measurement_record_len (resp) + \ spdm_get_measurements_resp_opaque_len (resp)) /** * Get the buffer containing the measurement record in SPDM get measurements response * * @param resp Buffer with struct spdm_get_measurements_response */ #define spdm_get_measurements_resp_measurement_record(resp) (((uint8_t*) resp) + sizeof (*resp)) /** * Get measurement record length from measurement record length entry in * spdm_get_measurements_response * * @param resp Buffer with struct spdm_get_measurements_response */ #define spdm_get_measurements_resp_measurement_record_len(resp) \ buffer_unaligned_read24(resp->measurement_record_len) /** * Get the max measurement record length in SPDM get measurements response * * @param max_response Maximum response length * @param opaque_data_len Opaque data length */ #define spdm_get_measurements_resp_measurement_record_max_len(max_response, opaque_data_len) \ (max_response - SPDM_GET_MEASUREMENTS_RESP_MIN_LENGTH - opaque_data_len) /** * Get the buffer containing the nonce in SPDM get measurements response * * @param resp Buffer with struct spdm_get_measurements_response */ #define spdm_get_measurements_resp_nonce(resp) \ (spdm_get_measurements_resp_measurement_record (resp) + \ spdm_get_measurements_resp_measurement_record_len (resp)) /** * Get opaque data length in bytes in SPDM get measurements response * * @param resp Buffer with struct spdm_get_measurements_response */ #define spdm_get_measurements_resp_opaque_len(resp) \ buffer_unaligned_read16 ( \ (const uint16_t *)(spdm_get_measurements_resp_nonce (resp) + SPDM_NONCE_LEN)) /** * Get the buffer containing the opaque data in SPDM get measurements response * * @param resp Buffer with struct spdm_get_measurements_response */ #define spdm_get_measurements_resp_opaque_data(resp) \ (spdm_get_measurements_resp_nonce (resp) + SPDM_NONCE_LEN + sizeof (uint16_t)) /** * Get the buffer containing the signature in SPDM get measurements response * * @param resp Buffer with struct spdm_get_measurements_response */ #define spdm_get_measurements_resp_signature(resp) \ (spdm_get_measurements_resp_opaque_data (resp) + spdm_get_measurements_resp_opaque_len (resp)) /** * Get the signature length of a SPDM get measurements response message * * @param resp Buffer containing struct spdm_get_measurements_response * @param len Total response length */ #define spdm_get_measurements_resp_signature_length(resp, len) \ (len - spdm_get_measurements_resp_length (resp)) /** * SPDM error codes, from section 10.12 in DSP0274 SPDM spec. */ enum { SPDM_ERROR_RESERVED = 0x00, /**< Reserved */ SPDM_ERROR_INVALID_REQUEST = 0x01, /**< One or more request fields are invalid */ SPDM_ERROR_INVALID_SESSION = 0x02, /**< The record layer used an invalid session ID */ SPDM_ERROR_BUSY = 0x03, /**< Responder busy, try again */ SPDM_ERROR_UNEXPECTED_REQUEST = 0x04, /**< Responder received unexpected request message */ SPDM_ERROR_UNSPECIFIED = 0x05, /**< Unspecified error occurred */ SPDM_ERROR_DECRYPT_ERROR = 0x06, /**< Receiver of record cannot decrypt record or verify data */ SPDM_ERROR_UNSUPPORTED_REQUEST = 0x07, /**< RequestResponseCode in request not supported */ SPDM_ERROR_REQUEST_IN_FLIGHT = 0x08, /**< Responder has delivered request to which it is still waiting for response */ SPDM_ERROR_INVALID_RESPONSE_CODE = 0x09, /**< Requester delivered an invalid response for an encapsulated response */ SPDM_ERROR_SESSION_LIMIT_EXCEEDED = 0x0A, /**< Maximum number of concurrent sessions reached */ SPDM_ERROR_SESSION_REQUIRED = 0x0B, /**< Request received only allowed within a session */ SPDM_ERROR_RESET_REQUIRED = 0x0C, /**< Device requires a reset to complete requested operation */ SPDM_ERROR_RESP_TOO_LARGE = 0x0D, /**< Response is greater than requester maximum message size */ SPDM_ERROR_REQ_TOO_LARGE = 0x0E, /**< Request is greater than responder maximum message size */ SPDM_ERROR_LARGE_RESPONSE = 0x0F, /**< Response is greater than DataTransferSize of requesting SPDM endpoint */ SPDM_ERROR_MSG_LOST = 0x10, /**< SPDM message lost */ SPDM_ERROR_VERSION_MISMATCH = 0x41, /**< Requested SPDM version is not supported or is a different version from the selected version. */ SPDM_ERROR_RESPONSE_NOT_READY = 0x42, /**< Response not ready */ SPDM_ERROR_REQUEST_RESYNCH = 0x43, /**< Responder is requesting Requester to reissue Get Version */ SPDM_ERROR_VENDOR_OR_OTHER_STANDARDS_DEFINED = 0xFF, /**< Vendor or other standards defined */ }; /** * SPDM error response format */ struct spdm_error_response { struct spdm_protocol_header header; /**< Message header */ uint8_t error_code; /**< Error code */ uint8_t error_data; /**< Error data */ }; /** * SPDM error response not ready optional data format */ struct spdm_error_response_not_ready { uint8_t rdt_exponent; /**< Exponent for duration in microseconds after which the responder can provide response */ uint8_t request_code; /**< Request code that triggered this response */ uint8_t token; /**< Opaque handle to pass in with RESPOND_IF_READY request */ uint8_t rdtm; /**< Multiplier used to compute duration in microseconds after which the responder will stop processing initial request */ }; /** * Get the buffer containing the SPDM error response optional data * * @param resp Buffer with struct spdm_error_response */ #define spdm_get_spdm_error_rsp_optional_data(resp) (((uint8_t*) resp) + sizeof (*resp)) /** * SPDM respond if ready request format */ struct spdm_respond_if_ready_request { struct spdm_protocol_header header; /**< Message header */ uint8_t original_request_code; /**< Original request code that triggered ResponseNotReady response */ uint8_t token; /**< Token received in ResponseNotReady response */ }; /** * SPDM KEY_EXCHANGE request format. */ struct spdm_key_exchange_request { struct spdm_protocol_header header; /**< Message header */ uint8_t measurement_summary_hash_type; /**< Type of measurement summary hash requested. */ uint8_t slot_id; /**< Slot number of the Responder certificate chain that shall be used for authentication. */ uint16_t req_session_id; /**< Requester part of the session Id. */ uint8_t session_policy; /**< Session termination policy. */ uint8_t reserved; /**< Reserved */ uint8_t random_data[32]; /**< Random data. */ }; /** * SPDM KEY_EXCHANGE response format. */ struct spdm_key_exchange_response { struct spdm_protocol_header header; /**< Message header */ uint8_t heartbeat_period; /**< Heartbeat period. */ uint8_t reserved; /**< Reserved */ uint16_t rsp_session_id; /**< Responder part of the session Id. */ uint8_t mut_auth_requested; /**< Mutual authentication request. */ uint8_t req_slot_id_param; /**< Slot number of the Requester certificate chain that shall be used for authentication. */ uint8_t random_data[32]; /**< Random data. */ }; /** * SPDM FINISH request format. */ struct spdm_finish_request { struct spdm_protocol_header header; /**< Message header */ uint8_t signature_included; /**< Signature included. */ uint8_t req_slot_id; /**< Slot number of the Requester certificate chain that shall be used for authentication. */ }; /** * SPDM FINISH request signature_included */ #define SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED 0x00000001 /** * SPDM FINISH response format */ struct spdm_finish_response { struct spdm_protocol_header header; /**< Message header */ uint8_t reserved1; /**< Reserved */ uint8_t reserved2; /**< Reserved */ }; /** * Policy to either generate SPDM_ERROR_CODE_DECRYPT_ERROR response or drop the request silently. * If bit0 = 0 of handle_error_return_policy, generate SPDM_ERROR_CODE_DECRYPT_ERROR response. * If bit0 = 1, drop the request silently. */ #define SPDM_DATA_HANDLE_ERROR_RETURN_POLICY_DROP_ON_DECRYPT_ERROR 0x1 /** * SPDM END SESSION 'Negotiated State Preservation Indicator' format per DSP0274 Table 77. */ struct spdm_end_session_request_attributes { uint8_t negotiated_state_preservation_indicator:1; /**< State preservation config */ uint8_t reserved:7; /**< Reserved */ }; /** * SPDM END_SESSION request format. */ struct spdm_end_session_request { struct spdm_protocol_header header; /**< Message header */ struct spdm_end_session_request_attributes end_session_attributes; /**< Request attributes */ uint8_t reserved; /**< Reserved */ }; /* SPDM END_SESSION request Attributes */ #define SPDM_END_SESSION_REQUEST_ATTRIBUTES_PRESERVE_NEGOTIATED_STATE_CLEAR 0x00000001 /** * SPDM END_SESSION response format. */ struct spdm_end_session_response { struct spdm_protocol_header header; /**< Message header */ uint8_t reserved1; /**< Reserved */ uint8_t reserved2; /**< Reserved */ }; /** * SPDM KEY_UPDATE request format. */ struct spdm_key_update_request { struct spdm_protocol_header header; /**< Message header */ uint8_t key_operation; /**< Key update operation. */ uint8_t tag; /**< Key update tag. */ }; /** * SPDM VENDOR_DEFINED request/response format. */ struct spdm_vendor_defined_request_response { struct spdm_protocol_header header; /**< Message header. */ uint8_t reserved1; /**< Reserved. */ uint8_t reserved2; /**< Reserved. */ uint16_t standard_id; /**< Registry or standards body ID. */ uint8_t vendor_id_len; /**< Length of the Vendor ID. */ }; /** * Get the requester's DHE public key ptr. * * @param rq Buffer with struct spdm_key_exchange_request */ #define spdm_key_exchange_rq_exchange_data(\ rq) (((uint8_t*) rq) + sizeof (struct spdm_key_exchange_request)) /** * Get the responder's DHE public key ptr. * * @param resp Buffer with struct spdm_key_exchange_response */ #define spdm_key_exchange_resp_exchange_data(\ resp) (((uint8_t*) resp) + sizeof (struct spdm_key_exchange_response)) /** * Get the requester's HMAC ptr. * * @param rq Buffer with struct spdm_finish_request */ #define spdm_finish_rq_hmac(rq, sig_size) \ (((uint8_t*) rq) + sizeof (struct spdm_finish_request) + sig_size) #pragma pack(pop) /** * Identifier for an invalid session Id. */ #define SPDM_INVALID_SESSION_ID 0 /** * SPDM connection states. */ enum spdm_connection_state { SPDM_CONNECTION_STATE_NOT_STARTED, /**< Before GET_VERSION/VERSION. */ SPDM_CONNECTION_STATE_AFTER_VERSION, /**< After GET_VERSION/VERSION. */ SPDM_CONNECTION_STATE_AFTER_CAPABILITIES, /**< After GET_CAPABILITIES/CAPABILITIES. */ SPDM_CONNECTION_STATE_NEGOTIATED, /**< After NEGOTIATE_ALGORITHMS/ALGORITHMS. */ SPDM_CONNECTION_STATE_AFTER_DIGESTS, /**< After GET_DIGESTS/DIGESTS. */ SPDM_CONNECTION_STATE_AFTER_CERTIFICATE, /**< After GET_CERTIFICATE/CERTIFICATE. */ SPDM_CONNECTION_STATE_AUTHENTICATED, /**< After CHALLENGE/CHALLENGE_AUTH, and ENCAP CHALLENGE/CHALLENGE_AUTH if MUT_AUTH is enabled. */ SPDM_CONNECTION_STATE_MAX, /**< MAX */ }; /** * SPDM version info. */ struct spdm_version_number { uint16_t alpha:4; /**< Pre-release version nubmer. */ uint16_t update_version_number:4; /**< Update version number. */ uint16_t minor_version:4; /**< Major version number. */ uint16_t major_version:4; /**< Minor version number. */ }; /** * SPDM device capabilities. */ struct spdm_device_capability { /** * Maximum amount of time the endpoint has to provide any response requiring * cryptographic processing such as the GET_MEASUREMENTS or CHALLENGE request messages. */ uint8_t ct_exponent; struct spdm_get_capabilities_flags_format flags; /**< Capabilities flags */ uint32_t data_transfer_size; /**< Maximum buffer size of the device. */ uint32_t max_spdm_msg_size; /**< Maximum size for a single SPDM message */ }; /** * SPDM algorithms. */ struct spdm_device_algorithms { uint8_t measurement_spec; /**< Measurement specification */ struct spdm_other_params_support other_params_support; /**< Additional params supported */ uint32_t measurement_hash_algo; /**< Measurement hash algorithm. */ uint32_t base_asym_algo; /**< Base asymmetric algorithm. */ uint32_t base_hash_algo; /**< Base hash algorithm. */ uint16_t dhe_named_group; /**< DHE named group. */ uint16_t aead_cipher_suite; /**< AEAD cipher suite. */ uint16_t req_base_asym_alg; /**< Requested base asymmetric algorithm. */ uint16_t key_schedule; /**< Key schedule. */ }; /** * SPDM local device algorithms priority tables. */ struct spdm_local_device_algorithms_priority_table { const uint32_t *hash_priority_table; /**< Hash algorithms priority table. */ const uint32_t *asym_priority_table; /**< Asymmetric key signature algorithms priority table. */ const uint32_t *req_asym_priority_table; /**< Requested asymmetric key signature algorithms priority table. */ const uint32_t *dhe_priority_table; /**< DHE named groups priority table. */ const uint32_t *aead_priority_table; /**< AEAD cipher suites priority table. */ const uint32_t *key_schedule_priority_table; /**< Key schedule priority table. */ const uint32_t *measurement_spec_priority_table; /**< Measurement specification priority table. */ const uint32_t *other_params_support_priority_table; /**< Other params support priority table. */ uint8_t hash_priority_table_count; /**< Number of hash algorithms in priority table. */ uint8_t asym_priority_table_count; /**< Number of asymmetric key signature algorithms in priority table. */ uint8_t req_asym_priority_table_count; /**< Number of requested asymmetric key signature algorithms in priority table. */ uint8_t dhe_priority_table_count; /**< Number of DHE named groups in priority table. */ uint8_t aead_priority_table_count; /**< Number of AEAD cipher suites in priority table. */ uint8_t key_schedule_priority_table_count; /**< Number of key schedules in priority table. */ uint8_t measurement_spec_priority_table_count; /**< Number of measurement specifications in priority table. */ uint8_t other_params_support_priority_table_count; /**< Number of other params support in priority table. */ }; /** * SPDM local device algorithms and their selection priorities. */ struct spdm_local_device_algorithms { struct spdm_device_algorithms device_algorithms; /**< Local device algorithms. */ struct spdm_local_device_algorithms_priority_table algorithms_priority_table; /**< Algorithm priority tables. */ }; /** * SPDM connection info. */ struct spdm_connection_info { enum spdm_connection_state connection_state; /**< State of the SPDM connection. */ struct spdm_version_number version; /**< Negotiated version */ struct spdm_device_capability peer_capabilities; /**< Peer capabilities. */ struct spdm_device_algorithms peer_algorithms; /**< Negotiated algorithms. */ struct spdm_version_number secure_message_version; /**< Negotiated secure message version. */ /** Specifies whether the cached negotiated state should be invalidated. (responder only) * This is a sticky bit wherein if it is set to 1 then it cannot be set to 0. */ struct spdm_end_session_request_attributes end_session_attributes; }; /** * Response states of the responder. */ enum spdm_response_state { SPDM_RESPONSE_STATE_NORMAL, /**< Normal response. */ SPDM_RESPONSE_STATE_BUSY, /**< Other component is busy. */ SPDM_RESPONSE_STATE_NOT_READY, /**< Hardware is not ready. */ SPDM_RESPONSE_STATE_NEED_RESYNC, /**< Firmware Update is done. Need resync. */ SPDM_RESPONSE_STATE_PROCESSING_ENCAP, /**< Processing Encapsulated message. */ SPDM_RESPONSE_STATE_MAX, /**< MAX */ }; /** * SPDM context for a requester/responder. */ struct spdm_state { struct spdm_connection_info connection_info; /**< Connection info. */ enum spdm_response_state response_state; /**< Responder response state */ uint64_t max_spdm_session_sequence_number; /**< Max SPDM session sequence number. */ uint16_t current_local_session_id; /**< Current local session Id. */ uint8_t handle_error_return_policy; /**< Handle error return policy. */ }; /* TODO: This is a temporary work-around in the absence of a SPDM connection handler that is * currently represented by the responder cmd_interface. Delete this as part of connection * refactoring. */ struct cmd_interface_spdm_responder; int spdm_init_state (struct spdm_state *state); bool spdm_check_request_flag_compatibility (struct spdm_get_capabilities_flags_format flags, uint8_t version); int spdm_get_command_id (struct cmd_interface_msg *message, uint8_t *command_id); void spdm_populate_mctp_header (struct spdm_protocol_mctp_header *header); void spdm_generate_error_response (struct cmd_interface_msg *response, uint8_t spdm_minor_version, uint8_t error_code, uint8_t error_data, uint8_t *optional_data, size_t optional_data_len, uint8_t req_code, int status); int spdm_get_version (const struct cmd_interface_spdm_responder *spdm_responder, struct cmd_interface_msg *request); int spdm_generate_get_version_request (uint8_t *buf, size_t buf_len); int spdm_process_get_version_response (struct cmd_interface_msg *response); int spdm_get_capabilities (const struct cmd_interface_spdm_responder *spdm_responder, struct cmd_interface_msg *request); int spdm_generate_get_capabilities_request (uint8_t *buf, size_t buf_len, uint8_t spdm_minor_version); int spdm_process_get_capabilities_response (struct cmd_interface_msg *response); int spdm_negotiate_algorithms (const struct cmd_interface_spdm_responder *spdm_responder, struct cmd_interface_msg *request); int spdm_generate_negotiate_algorithms_request (uint8_t *buf, size_t buf_len, uint32_t base_asym_algo, uint32_t base_hash_algo, uint8_t spdm_minor_version); int spdm_process_negotiate_algorithms_response (struct cmd_interface_msg *response); int spdm_get_digests (const struct cmd_interface_spdm_responder *spdm_responder, struct cmd_interface_msg *request); int spdm_generate_get_digests_request (uint8_t *buf, size_t buf_len, uint8_t spdm_minor_version); int spdm_process_get_digests_response (struct cmd_interface_msg *response); int spdm_get_certificate (const struct cmd_interface_spdm_responder *spdm_responder, struct cmd_interface_msg *request); int spdm_generate_get_certificate_request (uint8_t *buf, size_t buf_len, uint8_t slot_num, uint16_t offset, uint16_t length, uint8_t spdm_minor_version); int spdm_process_get_certificate_response (struct cmd_interface_msg *response); int spdm_challenge (const struct cmd_interface_spdm_responder *spdm_responder, struct cmd_interface_msg *request); int spdm_generate_challenge_request (uint8_t *buf, size_t buf_len, uint8_t slot_num, uint8_t req_measurement_summary_hash_type, uint8_t *nonce, uint8_t spdm_minor_version); int spdm_process_challenge_response (struct cmd_interface_msg *response); int spdm_get_measurements (const struct cmd_interface_spdm_responder *spdm_responder, struct cmd_interface_msg *request); int spdm_generate_get_measurements_request (uint8_t *buf, size_t buf_len, uint8_t slot_num, uint8_t measurement_operation, bool sig_required, bool raw_bitstream_requested, uint8_t *nonce, uint8_t spdm_minor_version); int spdm_process_get_measurements_response (struct cmd_interface_msg *response); int spdm_generate_respond_if_ready_request (uint8_t *buf, size_t buf_len, uint8_t original_request_code, uint8_t token, uint8_t spdm_minor_version); int spdm_key_exchange (const struct cmd_interface_spdm_responder *spdm_responder, struct cmd_interface_msg *request); int spdm_finish (const struct cmd_interface_spdm_responder *spdm_responder, struct cmd_interface_msg *request); int spdm_end_session (const struct cmd_interface_spdm_responder *spdm_responder, struct cmd_interface_msg *request); int spdm_format_signature_digest (const struct hash_engine *hash, enum hash_type hash_type, uint8_t spdm_minor_version, char *spdm_state, uint8_t *digest); enum hash_type spdm_get_hash_type (uint32_t hash_algo); uint32_t spdm_get_dhe_pub_key_size (uint16_t dhe_named_group); uint32_t spdm_get_aead_key_size (uint16_t aead_cipher_suite); uint32_t spdm_get_aead_iv_size (uint16_t aead_cipher_suite); uint32_t spdm_get_aead_tag_size (uint16_t aead_cipher_suite); int spdm_vendor_defined_request (const struct cmd_interface_spdm_responder *spdm_responder, struct cmd_interface_msg *request); #endif /* SPDM_COMMANDS_H_ */