in core/attestation/pcr.c [1196:1325]
int pcr_get_tcg_log (struct pcr_bank *pcr, uint32_t pcr_num, size_t offset, uint8_t *buffer,
size_t length, size_t *total_len)
{
union {
struct pcr_tcg_event2_header header;
struct pcr_tcg_event2_sha256 sha256;
struct pcr_tcg_event2_sha384 sha384;
struct pcr_tcg_event2_sha512 sha512;
} entry;
size_t num_bytes = 0;
size_t i = 0;
uint8_t *entry_digest;
uint32_t *entry_event_size;
size_t entry_digest_len;
size_t entry_total_len;
uint8_t *entry_ptr = NULL;
size_t entry_len = 0;
size_t entry_offset = 0;
size_t event_size;
int status = 0;
if ((pcr == NULL) || (buffer == NULL) || (total_len == NULL)) {
return PCR_INVALID_ARGUMENT;
}
*total_len = 0;
if (pcr->explicit_measurement) {
return 0;
}
entry.header.pcr_index = pcr_num;
entry.header.digest_count = 1;
switch (pcr->config.measurement_algo) {
default:
/* This isn't possible, since invalid hash types would be caught during init.
* Fall-through to SHA-256. This is here mostly to keep compilers happy. */
case HASH_TYPE_SHA256:
entry.header.digest_algorithm_id = PCR_TCG_SHA256_ALG_ID;
entry_digest = entry.sha256.digest;
entry_event_size = &entry.sha256.event_size;
entry_digest_len = SHA256_HASH_LENGTH;
entry_total_len = sizeof (entry.sha256);
break;
#if PCR_MAX_DIGEST_LENGTH >= SHA384_HASH_LENGTH
case HASH_TYPE_SHA384:
entry.header.digest_algorithm_id = PCR_TCG_SHA384_ALG_ID;
entry_digest = entry.sha384.digest;
entry_event_size = &entry.sha384.event_size;
entry_digest_len = SHA384_HASH_LENGTH;
entry_total_len = sizeof (entry.sha384);
break;
#endif
#if PCR_MAX_DIGEST_LENGTH >= SHA512_HASH_LENGTH
case HASH_TYPE_SHA512:
entry.header.digest_algorithm_id = PCR_TCG_SHA512_ALG_ID;
entry_digest = entry.sha512.digest;
entry_event_size = &entry.sha512.event_size;
entry_digest_len = SHA512_HASH_LENGTH;
entry_total_len = sizeof (entry.sha512);
break;
#endif
}
platform_mutex_lock (&pcr->lock);
while ((i < pcr->config.num_measurements) && (length > 0)) {
entry.header.event_type = pcr->measurement_list[i].event_type;
memcpy (entry_digest, pcr->measurement_list[i].digest, entry_digest_len);
*total_len += entry_total_len;
if (offset >= entry_total_len) {
offset -= entry_total_len;
}
else if (length > 0) {
entry_len = min (entry_total_len - offset, length);
entry_offset = offset;
entry_ptr = buffer;
/* Do not write the entry yet because we don't know the entry size, but update the state
* as if it was written to ensure everything ends up in the right place. */
num_bytes += entry_len;
buffer += entry_len;
length -= entry_len;
offset = 0;
}
/* The entry event size is not word-aligned, so use a temp location that is aligned. */
status = pcr_get_measurement_data_internal (pcr, i, offset, buffer, length, &event_size);
if (ROT_IS_ERROR (status)) {
goto exit;
}
*entry_event_size = event_size;
if (entry_ptr != NULL) {
memcpy (entry_ptr, ((uint8_t*) &entry) + entry_offset, entry_len);
entry_ptr = NULL;
}
*total_len += event_size;
buffer += status;
length -= status;
if (status > 0) {
offset = 0;
num_bytes += status;
}
else {
offset -= event_size;
}
i++;
}
exit:
platform_mutex_unlock (&pcr->lock);
if (ROT_IS_ERROR (status)) {
return status;
}
else {
return num_bytes;
}
}