in core/attestation/attestation_requester.c [2333:2452]
static int attestation_requester_send_and_receive_spdm_get_measurements (
const struct attestation_requester *attestation, uint8_t eid, int device_addr,
uint8_t measurement_operation, bool raw_bitstream_requested)
{
uint8_t nonce[SPDM_NONCE_LEN];
int rq_len;
int status;
if (!attestation->state->txn.device_discovery) {
if (!attestation->state->txn.hash_finish) {
attestation->secondary_hash->cancel (attestation->secondary_hash);
}
attestation->state->txn.hash_finish = true;
status = hash_start_new_hash (attestation->secondary_hash,
attestation->state->txn.transcript_hash_type);
if (status != 0) {
return status;
}
attestation->state->txn.hash_finish = false;
}
/* 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_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) {
return status;
}
}
// No signature or nonce needed when getting device ID measurement block in device discovery
if (!attestation->state->txn.device_discovery) {
if (attestation->state->txn.cert_supported) {
status = attestation->rng->generate_random_buffer (attestation->rng, SPDM_NONCE_LEN,
nonce);
if (status != 0) {
return status;
}
}
rq_len = spdm_generate_get_measurements_request (attestation->state->spdm_msg_buffer,
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.spdm_minor_version);
if (ROT_IS_ERROR (rq_len)) {
return rq_len;
}
}
else {
/* SPDM 1.1.x requires all measurement blocks to be contiguous. This means that device
* might not be able to support the dedicated 0xEF block and be compliant, so instead
* device IDs are placed in the last measurement block on the device. Cerberus will first
* get the number of measurement blocks, then update measurement_operation to the index of
* 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_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.spdm_minor_version);
if (ROT_IS_ERROR (rq_len)) {
return rq_len;
}
attestation->state->txn.raw_bitstream_requested = raw_bitstream_requested;
attestation->state->txn.measurement_operation_requested =
SPDM_MEASUREMENT_OPERATION_GET_NUM_BLOCKS;
status = attestation_requester_send_spdm_request_and_get_response (attestation, rq_len,
device_addr, eid, true, SPDM_REQUEST_GET_MEASUREMENTS);
if (status != 0) {
return status;
}
status =
attestation_requester_spdm_process_get_measurements_response (attestation, eid);
if (status != 0) {
device_manager_update_device_state_by_eid (attestation->device_mgr, eid,
DEVICE_MANAGER_ATTESTATION_INVALID_MEASUREMENT);
return status;
}
measurement_operation = attestation->state->txn.msg_buffer[0];
}
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.spdm_minor_version);
if (ROT_IS_ERROR (rq_len)) {
return rq_len;
}
}
attestation->state->txn.raw_bitstream_requested = raw_bitstream_requested;
attestation->state->txn.measurement_operation_requested = measurement_operation;
status = attestation_requester_send_spdm_request_and_get_response (attestation, rq_len,
device_addr, eid, true, SPDM_REQUEST_GET_MEASUREMENTS);
if (status != 0) {
return status;
}
status = attestation_requester_spdm_process_get_measurements_response (attestation, eid);
if (status != 0) {
device_manager_update_device_state_by_eid (attestation->device_mgr, eid,
DEVICE_MANAGER_ATTESTATION_INVALID_MEASUREMENT);
}
return status;
}