Pull request for efi-2022-01-rc4

Documentation:
 
 * describe how to enable Virtio RNG on QEMU ARM
 
 UEFI:
 
 * enable testing the TCG2 protocol
 * support TPM event log passed from firmware
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAmGmDkMACgkQxIHbvCwF
 GsTJYg//eAUllDslZvhTypWezkkqJBl0PPmc7rdRGvSZJoTwN9MVPat2/Gw9oZhh
 8+YbvxaRmQApdkDqxqngvSw4BNn3XsX/AWYvWumfSCPVxROJwbhNXdVzMK3ik7xL
 LvkSLiDnhTVWKMVUTIYC+8E2GXgvgxt6Y44ywNMJ/EEaCSxgErEmWQWwPjNbEBPe
 ly+ELEGDVJj7lnkXvxxh+O3pAmVGkgHwm9b16hVdJv0/pRj6BRL+GimIykJoaaui
 Zc1UxvA66/xrNVfvdTTXV7y2msisGi6YGL/6tZfCRpJkaU03xou29H3P8mGIxNNn
 YgDLnQkMBNu9Q6bhK2xB6YV4PZsWtjCi2agHqpTw4esdHZILVfEgU71DlrnxYipK
 UmxbWkmJ7b0EuzgmWbzMmX5LNoP45qH6xR9TwAHmtHurdvLJcUH23ZyLjUOxPMR+
 Z811FpHjh4eD6HhOmRaoLeRlYIWAt1FAvpl5NNFSsKAHfJBMAHoYcHniNCbOnLrG
 ULdOgYOr0UIhJTmjCUHmmrHUaMgSctQpnbSGUeTxl2HLu574QfaJuVnDQXZ1YtEl
 akL6VYYPtNQDwBYMS4zlq0VvvRiOVr/qNcgpBV2aZgZBSuI3oIwh6B/O4VSKxf9r
 VblP+7cHx7yAd8qSjEq9qEkWMdRn4PY7TBEimG8hSLeWIKj5/SM=
 =wmUZ
 -----END PGP SIGNATURE-----

Merge tag 'efi-2022-01-rc4' of https://source.denx.de/u-boot/custodians/u-boot-efi

Pull request for efi-2022-01-rc4

Documentation:

* describe how to enable Virtio RNG on QEMU ARM

UEFI:

* enable testing the TCG2 protocol
* support TPM event log passed from firmware
This commit is contained in:
Tom Rini 2021-11-30 08:03:21 -05:00
commit ce29c52891
11 changed files with 526 additions and 78 deletions

View File

@ -151,7 +151,8 @@ static int do_tpm_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc,
data = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0); data = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);
rc = tpm2_pcr_read(dev, index, priv->pcr_select_min, data, &updates); rc = tpm2_pcr_read(dev, index, priv->pcr_select_min, TPM2_ALG_SHA256,
data, TPM2_DIGEST_LEN, &updates);
if (!rc) { if (!rc) {
printf("PCR #%u content (%u known updates):\n", index, updates); printf("PCR #%u content (%u known updates):\n", index, updates);
print_byte_string(data, TPM2_DIGEST_LEN); print_byte_string(data, TPM2_DIGEST_LEN);

View File

@ -23,6 +23,7 @@ CONFIG_CMD_DFU=y
CONFIG_CMD_MTD=y CONFIG_CMD_MTD=y
CONFIG_CMD_PCI=y CONFIG_CMD_PCI=y
CONFIG_CMD_USB=y CONFIG_CMD_USB=y
CONFIG_CMD_TPM=y
CONFIG_CMD_MTDPARTS=y CONFIG_CMD_MTDPARTS=y
CONFIG_OF_BOARD=y CONFIG_OF_BOARD=y
CONFIG_ENV_IS_IN_FLASH=y CONFIG_ENV_IS_IN_FLASH=y

View File

@ -25,6 +25,7 @@ CONFIG_CMD_DFU=y
CONFIG_CMD_MTD=y CONFIG_CMD_MTD=y
CONFIG_CMD_PCI=y CONFIG_CMD_PCI=y
CONFIG_CMD_USB=y CONFIG_CMD_USB=y
CONFIG_CMD_TPM=y
CONFIG_CMD_MTDPARTS=y CONFIG_CMD_MTDPARTS=y
CONFIG_OF_BOARD=y CONFIG_OF_BOARD=y
CONFIG_ENV_IS_IN_FLASH=y CONFIG_ENV_IS_IN_FLASH=y

View File

@ -65,7 +65,8 @@ can be enabled with the following command line parameters:
- To add a Serial ATA disk via an Intel ICH9 AHCI controller, pass e.g.:: - To add a Serial ATA disk via an Intel ICH9 AHCI controller, pass e.g.::
-drive if=none,file=disk.img,id=mydisk -device ich9-ahci,id=ahci -device ide-drive,drive=mydisk,bus=ahci.0 -drive if=none,file=disk.img,format=raw,id=mydisk \
-device ich9-ahci,id=ahci -device ide-drive,drive=mydisk,bus=ahci.0
- To add an Intel E1000 network adapter, pass e.g.:: - To add an Intel E1000 network adapter, pass e.g.::
@ -75,10 +76,14 @@ can be enabled with the following command line parameters:
-device usb-ehci,id=ehci -device usb-ehci,id=ehci
- To add a NVMe disk, pass e.g.:: - To add an NVMe disk, pass e.g.::
-drive if=none,file=disk.img,id=mydisk -device nvme,drive=mydisk,serial=foo -drive if=none,file=disk.img,id=mydisk -device nvme,drive=mydisk,serial=foo
- To add a random number generator, pass e.g.::
-device virtio-rng-pci
These have been tested in QEMU 2.9.0 but should work in at least 2.5.0 as well. These have been tested in QEMU 2.9.0 but should work in at least 2.5.0 as well.
Enabling TPMv2 support Enabling TPMv2 support

View File

@ -118,10 +118,13 @@ iounmap:
static int tpm_tis_remove(struct udevice *dev) static int tpm_tis_remove(struct udevice *dev)
{ {
struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev); struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
int ret;
ret = tpm_tis_cleanup(dev);
iounmap(drv_data->iobase); iounmap(drv_data->iobase);
return tpm_tis_cleanup(dev); return ret;
} }
static const struct tpm_ops tpm_tis_ops = { static const struct tpm_ops tpm_tis_ops = {

View File

@ -988,4 +988,6 @@ efi_status_t efi_esrt_register(void);
*/ */
efi_status_t efi_esrt_populate(void); efi_status_t efi_esrt_populate(void);
efi_status_t efi_load_capsule_drivers(void); efi_status_t efi_load_capsule_drivers(void);
efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz);
#endif /* _EFI_LOADER_H */ #endif /* _EFI_LOADER_H */

View File

@ -512,13 +512,16 @@ u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
* @dev TPM device * @dev TPM device
* @idx Index of the PCR * @idx Index of the PCR
* @idx_min_sz Minimum size in bytes of the pcrSelect array * @idx_min_sz Minimum size in bytes of the pcrSelect array
* @algorithm Algorithm used, defined in 'enum tpm2_algorithms'
* @data Output buffer for contents of the named PCR * @data Output buffer for contents of the named PCR
* @digest_len len of the data
* @updates Optional out parameter: number of updates for this PCR * @updates Optional out parameter: number of updates for this PCR
* *
* @return code of the operation * @return code of the operation
*/ */
u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz, u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
void *data, unsigned int *updates); u16 algorithm, void *data, u32 digest_len,
unsigned int *updates);
/** /**
* Issue a TPM2_GetCapability command. This implementation is limited * Issue a TPM2_GetCapability command. This implementation is limited

View File

@ -199,6 +199,44 @@ static efi_status_t tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
return EFI_SUCCESS; return EFI_SUCCESS;
} }
/* tcg2_pcr_read - Read PCRs for a TPM2 device for a given tpml_digest_values
*
* @dev: device
* @pcr_index: PCR index
* @digest_list: list of digest algorithms to extend
*
* @Return: status code
*/
static efi_status_t tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
struct tpml_digest_values *digest_list)
{
struct tpm_chip_priv *priv;
unsigned int updates, pcr_select_min;
u32 rc;
size_t i;
priv = dev_get_uclass_priv(dev);
if (!priv)
return EFI_DEVICE_ERROR;
pcr_select_min = priv->pcr_select_min;
for (i = 0; i < digest_list->count; i++) {
u16 hash_alg = digest_list->digests[i].hash_alg;
u8 *digest = (u8 *)&digest_list->digests[i].digest;
rc = tpm2_pcr_read(dev, pcr_index, pcr_select_min,
hash_alg, digest, alg_to_len(hash_alg),
&updates);
if (rc) {
EFI_PRINT("Failed to read PCR\n");
return EFI_DEVICE_ERROR;
}
}
return EFI_SUCCESS;
}
/* put_event - Append an agile event to an eventlog /* put_event - Append an agile event to an eventlog
* *
* @pcr_index: PCR index * @pcr_index: PCR index
@ -324,6 +362,45 @@ __weak efi_status_t platform_get_tpm2_device(struct udevice **dev)
return EFI_NOT_FOUND; return EFI_NOT_FOUND;
} }
/**
* platform_get_eventlog() - retrieve the eventlog address and size
*
* This function retrieves the eventlog address and size if the underlying
* firmware has done some measurements and passed them.
*
* This function may be overridden based on platform specific method of
* passing the eventlog address and size.
*
* @dev: udevice
* @addr: eventlog address
* @sz: eventlog size
* Return: status code
*/
__weak efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr,
u32 *sz)
{
const u64 *basep;
const u32 *sizep;
basep = dev_read_prop(dev, "tpm_event_log_addr", NULL);
if (!basep)
return EFI_NOT_FOUND;
*addr = be64_to_cpup((__force __be64 *)basep);
sizep = dev_read_prop(dev, "tpm_event_log_size", NULL);
if (!sizep)
return EFI_NOT_FOUND;
*sz = be32_to_cpup((__force __be32 *)sizep);
if (*sz == 0) {
log_debug("event log empty\n");
return EFI_NOT_FOUND;
}
return EFI_SUCCESS;
}
/** /**
* tpm2_get_max_command_size() - get the supported max command size * tpm2_get_max_command_size() - get the supported max command size
* *
@ -1181,6 +1258,318 @@ static const struct efi_tcg2_protocol efi_tcg2_protocol = {
.get_result_of_set_active_pcr_banks = efi_tcg2_get_result_of_set_active_pcr_banks, .get_result_of_set_active_pcr_banks = efi_tcg2_get_result_of_set_active_pcr_banks,
}; };
/**
* parse_event_log_header() - Parse and verify the event log header fields
*
* @buffer: Pointer to the start of the eventlog
* @size: Size of the eventlog
* @pos: Return offset of the next event in buffer right
* after the event header i.e specID
*
* Return: status code
*/
static efi_status_t parse_event_log_header(void *buffer, u32 size, u32 *pos)
{
struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer;
int i = 0;
if (size < sizeof(*event_header))
return EFI_COMPROMISED_DATA;
if (get_unaligned_le32(&event_header->pcr_index) != 0 ||
get_unaligned_le32(&event_header->event_type) != EV_NO_ACTION)
return EFI_COMPROMISED_DATA;
for (i = 0; i < sizeof(event_header->digest); i++) {
if (event_header->digest[i])
return EFI_COMPROMISED_DATA;
}
*pos += sizeof(*event_header);
return EFI_SUCCESS;
}
/**
* parse_specid_event() - Parse and verify the specID Event in the eventlog
*
* @dev: udevice
* @buffer: Pointer to the start of the eventlog
* @log_size: Size of the eventlog
* @pos: [in] Offset of specID event in the eventlog buffer
* [out] Return offset of the next event in the buffer
* after the specID
* @digest_list: list of digests in the event
*
* Return: status code
* @pos Offset in the eventlog where the specID event ends
* @digest_list: list of digests in the event
*/
static efi_status_t parse_specid_event(struct udevice *dev, void *buffer,
u32 log_size, u32 *pos,
struct tpml_digest_values *digest_list)
{
struct tcg_efi_spec_id_event *spec_event;
struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer;
size_t spec_event_size;
u32 active = 0, supported = 0, pcr_count = 0, alg_count = 0;
u32 spec_active = 0;
u16 hash_alg;
u8 vendor_sz;
int err, i;
if (*pos >= log_size || (*pos + sizeof(*spec_event)) > log_size)
return EFI_COMPROMISED_DATA;
/* Check specID event data */
spec_event = (struct tcg_efi_spec_id_event *)((uintptr_t)buffer + *pos);
/* Check for signature */
if (memcmp(spec_event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03))) {
log_err("specID Event: Signature mismatch\n");
return EFI_COMPROMISED_DATA;
}
if (spec_event->spec_version_minor !=
TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
spec_event->spec_version_major !=
TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
return EFI_COMPROMISED_DATA;
if (spec_event->number_of_algorithms > MAX_HASH_COUNT ||
spec_event->number_of_algorithms < 1) {
log_err("specID Event: Number of algorithms incorrect\n");
return EFI_COMPROMISED_DATA;
}
alg_count = spec_event->number_of_algorithms;
err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_count);
if (err)
return EFI_DEVICE_ERROR;
digest_list->count = 0;
/*
* We have to take care that the sequence of algorithms that we record
* in digest_list matches the sequence in eventlog.
*/
for (i = 0; i < alg_count; i++) {
hash_alg =
get_unaligned_le16(&spec_event->digest_sizes[i].algorithm_id);
if (!(supported & alg_to_mask(hash_alg))) {
log_err("specID Event: Unsupported algorithm\n");
return EFI_COMPROMISED_DATA;
}
digest_list->digests[digest_list->count++].hash_alg = hash_alg;
spec_active |= alg_to_mask(hash_alg);
}
/*
* TCG specification expects the event log to have hashes for all
* active PCR's
*/
if (spec_active != active) {
/*
* Previous stage bootloader should know all the active PCR's
* and use them in the Eventlog.
*/
log_err("specID Event: All active hash alg not present\n");
return EFI_COMPROMISED_DATA;
}
/*
* the size of the spec event and placement of vendor_info_size
* depends on supported algoriths
*/
spec_event_size =
offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
alg_count * sizeof(spec_event->digest_sizes[0]);
if (*pos + spec_event_size >= log_size)
return EFI_COMPROMISED_DATA;
vendor_sz = *(uint8_t *)((uintptr_t)buffer + *pos + spec_event_size);
spec_event_size += sizeof(vendor_sz) + vendor_sz;
*pos += spec_event_size;
if (get_unaligned_le32(&event_header->event_size) != spec_event_size) {
log_err("specID event: header event size mismatch\n");
/* Right way to handle this can be to call SetActive PCR's */
return EFI_COMPROMISED_DATA;
}
return EFI_SUCCESS;
}
/**
* tcg2_parse_event() - Parse the event in the eventlog
*
* @dev: udevice
* @buffer: Pointer to the start of the eventlog
* @log_size: Size of the eventlog
* @offset: [in] Offset of the event in the eventlog buffer
* [out] Return offset of the next event in the buffer
* @digest_list: list of digests in the event
* @pcr Index of the PCR in the event
*
* Return: status code
*/
static efi_status_t tcg2_parse_event(struct udevice *dev, void *buffer,
u32 log_size, u32 *offset,
struct tpml_digest_values *digest_list,
u32 *pcr)
{
struct tcg_pcr_event2 *event = NULL;
u32 count, size, event_size;
size_t pos;
event_size = tcg_event_final_size(digest_list);
if (*offset >= log_size || *offset + event_size > log_size) {
log_err("Event exceeds log size\n");
return EFI_COMPROMISED_DATA;
}
event = (struct tcg_pcr_event2 *)((uintptr_t)buffer + *offset);
*pcr = get_unaligned_le32(&event->pcr_index);
/* get the count */
count = get_unaligned_le32(&event->digests.count);
if (count != digest_list->count)
return EFI_COMPROMISED_DATA;
pos = offsetof(struct tcg_pcr_event2, digests);
pos += offsetof(struct tpml_digest_values, digests);
for (int i = 0; i < digest_list->count; i++) {
u16 alg;
u16 hash_alg = digest_list->digests[i].hash_alg;
u8 *digest = (u8 *)&digest_list->digests[i].digest;
alg = get_unaligned_le16((void *)((uintptr_t)event + pos));
if (alg != hash_alg)
return EFI_COMPROMISED_DATA;
pos += offsetof(struct tpmt_ha, digest);
memcpy(digest, (void *)((uintptr_t)event + pos), alg_to_len(hash_alg));
pos += alg_to_len(hash_alg);
}
size = get_unaligned_le32((void *)((uintptr_t)event + pos));
event_size += size;
pos += sizeof(u32); /* tcg_pcr_event2 event_size*/
pos += size;
/* make sure the calculated buffer is what we checked against */
if (pos != event_size)
return EFI_COMPROMISED_DATA;
if (pos > log_size)
return EFI_COMPROMISED_DATA;
*offset += pos;
return EFI_SUCCESS;
}
/**
* tcg2_get_fw_eventlog() - Get the eventlog address and size
*
* If the previous firmware has passed some eventlog, this function get it's
* location and check for it's validity.
*
* @dev: udevice
* @log_buffer: eventlog address
* @log_sz: eventlog size
*
* Return: status code
*/
static efi_status_t tcg2_get_fw_eventlog(struct udevice *dev, void *log_buffer,
size_t *log_sz)
{
struct tpml_digest_values digest_list;
void *buffer;
efi_status_t ret;
u32 pcr, pos;
u64 base;
u32 sz;
bool extend_pcr = false;
int i;
ret = platform_get_eventlog(dev, &base, &sz);
if (ret != EFI_SUCCESS)
return ret;
if (sz > TPM2_EVENT_LOG_SIZE)
return EFI_VOLUME_FULL;
buffer = (void *)(uintptr_t)base;
pos = 0;
/* Parse the eventlog to check for its validity */
ret = parse_event_log_header(buffer, sz, &pos);
if (ret)
return ret;
ret = parse_specid_event(dev, buffer, sz, &pos, &digest_list);
if (ret) {
log_err("Error parsing SPEC ID Event\n");
return ret;
}
ret = tcg2_pcr_read(dev, 0, &digest_list);
if (ret) {
log_err("Error reading PCR 0\n");
return ret;
}
/*
* If PCR0 is 0, previous firmware didn't have the capability
* to extend the PCR. In this scenario, extend the PCR as
* the eventlog is parsed.
*/
for (i = 0; i < digest_list.count; i++) {
u8 hash_buf[TPM2_SHA512_DIGEST_SIZE] = { 0 };
u16 hash_alg = digest_list.digests[i].hash_alg;
if (!memcmp((u8 *)&digest_list.digests[i].digest, hash_buf,
alg_to_len(hash_alg)))
extend_pcr = true;
}
while (pos < sz) {
ret = tcg2_parse_event(dev, buffer, sz, &pos, &digest_list,
&pcr);
if (ret) {
log_err("Error parsing event\n");
return ret;
}
if (extend_pcr) {
ret = tcg2_pcr_extend(dev, pcr, &digest_list);
if (ret != EFI_SUCCESS) {
log_err("Error in extending PCR\n");
return ret;
}
/* Clear the digest for next event */
for (i = 0; i < digest_list.count; i++) {
u16 hash_alg = digest_list.digests[i].hash_alg;
u8 *digest =
(u8 *)&digest_list.digests[i].digest;
memset(digest, 0, alg_to_len(hash_alg));
}
}
}
memcpy(log_buffer, buffer, sz);
*log_sz = sz;
return ret;
}
/** /**
* create_specid_event() - Create the first event in the eventlog * create_specid_event() - Create the first event in the eventlog
* *
@ -1312,69 +1701,6 @@ out:
return ret; return ret;
} }
/**
* efi_init_event_log() - initialize an eventlog
*/
static efi_status_t efi_init_event_log(void)
{
/*
* vendor_info_size is currently set to 0, we need to change the length
* and allocate the flexible array member if this changes
*/
struct tcg_pcr_event *event_header = NULL;
struct udevice *dev;
size_t spec_event_size;
efi_status_t ret;
ret = platform_get_tpm2_device(&dev);
if (ret != EFI_SUCCESS)
goto out;
ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, TPM2_EVENT_LOG_SIZE,
(void **)&event_log.buffer);
if (ret != EFI_SUCCESS)
goto out;
/*
* initialize log area as 0xff so the OS can easily figure out the
* last log entry
*/
memset(event_log.buffer, 0xff, TPM2_EVENT_LOG_SIZE);
event_log.pos = 0;
event_log.last_event_size = 0;
event_log.get_event_called = false;
event_log.ebs_called = false;
event_log.truncated = false;
/*
* The log header is defined to be in SHA1 event log entry format.
* Setup event header
*/
event_header = (struct tcg_pcr_event *)event_log.buffer;
put_unaligned_le32(0, &event_header->pcr_index);
put_unaligned_le32(EV_NO_ACTION, &event_header->event_type);
memset(&event_header->digest, 0, sizeof(event_header->digest));
ret = create_specid_event(dev, (void *)((uintptr_t)event_log.buffer + sizeof(*event_header)),
&spec_event_size);
if (ret != EFI_SUCCESS)
goto free_pool;
put_unaligned_le32(spec_event_size, &event_header->event_size);
event_log.pos = spec_event_size + sizeof(*event_header);
event_log.last_event_size = event_log.pos;
ret = create_final_event();
if (ret != EFI_SUCCESS)
goto free_pool;
out:
return ret;
free_pool:
efi_free_pool(event_log.buffer);
event_log.buffer = NULL;
return ret;
}
/** /**
* tcg2_measure_event() - common function to add event log and extend PCR * tcg2_measure_event() - common function to add event log and extend PCR
* *
@ -1427,6 +1753,93 @@ static efi_status_t efi_append_scrtm_version(struct udevice *dev)
return ret; return ret;
} }
/**
* efi_init_event_log() - initialize an eventlog
*
* Return: status code
*/
static efi_status_t efi_init_event_log(void)
{
/*
* vendor_info_size is currently set to 0, we need to change the length
* and allocate the flexible array member if this changes
*/
struct tcg_pcr_event *event_header = NULL;
struct udevice *dev;
size_t spec_event_size;
efi_status_t ret;
ret = platform_get_tpm2_device(&dev);
if (ret != EFI_SUCCESS)
return ret;
ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, TPM2_EVENT_LOG_SIZE,
(void **)&event_log.buffer);
if (ret != EFI_SUCCESS)
return ret;
/*
* initialize log area as 0xff so the OS can easily figure out the
* last log entry
*/
memset(event_log.buffer, 0xff, TPM2_EVENT_LOG_SIZE);
/*
* The log header is defined to be in SHA1 event log entry format.
* Setup event header
*/
event_header = (struct tcg_pcr_event *)event_log.buffer;
event_log.pos = 0;
event_log.last_event_size = 0;
event_log.get_event_called = false;
event_log.ebs_called = false;
event_log.truncated = false;
/*
* Check if earlier firmware have passed any eventlog. Different
* platforms can use different ways to do so.
*/
ret = tcg2_get_fw_eventlog(dev, event_log.buffer, &event_log.pos);
/*
* If earlier firmware hasn't passed any eventlog, go ahead and
* create the eventlog header.
*/
if (ret == EFI_NOT_FOUND) {
put_unaligned_le32(0, &event_header->pcr_index);
put_unaligned_le32(EV_NO_ACTION, &event_header->event_type);
memset(&event_header->digest, 0, sizeof(event_header->digest));
ret = create_specid_event(dev,
(void *)((uintptr_t)event_log.buffer +
sizeof(*event_header)),
&spec_event_size);
if (ret != EFI_SUCCESS)
goto free_pool;
put_unaligned_le32(spec_event_size, &event_header->event_size);
event_log.pos = spec_event_size + sizeof(*event_header);
event_log.last_event_size = event_log.pos;
/*
* Add SCRTM version to the log if previous firmmware
* doesn't pass an eventlog.
*/
ret = efi_append_scrtm_version(dev);
}
if (ret != EFI_SUCCESS)
goto free_pool;
ret = create_final_event();
if (ret != EFI_SUCCESS)
goto free_pool;
return ret;
free_pool:
efi_free_pool(event_log.buffer);
event_log.buffer = NULL;
return ret;
}
/** /**
* tcg2_measure_variable() - add variable event log and extend PCR * tcg2_measure_variable() - add variable event log and extend PCR
* *
@ -1963,12 +2376,6 @@ efi_status_t efi_tcg2_register(void)
if (ret != EFI_SUCCESS) if (ret != EFI_SUCCESS)
goto fail; goto fail;
ret = efi_append_scrtm_version(dev);
if (ret != EFI_SUCCESS) {
tcg2_uninit();
goto fail;
}
ret = efi_add_protocol(efi_root, &efi_guid_tcg2_protocol, ret = efi_add_protocol(efi_root, &efi_guid_tcg2_protocol,
(void *)&efi_tcg2_protocol); (void *)&efi_tcg2_protocol);
if (ret != EFI_SUCCESS) { if (ret != EFI_SUCCESS) {

View File

@ -254,7 +254,8 @@ u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
} }
u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz, u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
void *data, unsigned int *updates) u16 algorithm, void *data, u32 digest_len,
unsigned int *updates)
{ {
u8 idx_array_sz = max(idx_min_sz, DIV_ROUND_UP(idx, 8)); u8 idx_array_sz = max(idx_min_sz, DIV_ROUND_UP(idx, 8));
u8 command_v2[COMMAND_BUFFER_SIZE] = { u8 command_v2[COMMAND_BUFFER_SIZE] = {
@ -264,7 +265,7 @@ u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
/* TPML_PCR_SELECTION */ /* TPML_PCR_SELECTION */
tpm_u32(1), /* Number of selections */ tpm_u32(1), /* Number of selections */
tpm_u16(TPM2_ALG_SHA256), /* Algorithm of the hash */ tpm_u16(algorithm), /* Algorithm of the hash */
idx_array_sz, /* Array size for selection */ idx_array_sz, /* Array size for selection */
/* bitmap(idx) Selected PCR bitmap */ /* bitmap(idx) Selected PCR bitmap */
}; };
@ -283,10 +284,13 @@ u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
if (ret) if (ret)
return ret; return ret;
if (digest_len > response_len)
return TPM_LIB_ERROR;
if (unpack_byte_string(response, response_len, "ds", if (unpack_byte_string(response, response_len, "ds",
10, &counter, 10, &counter,
response_len - TPM2_DIGEST_LEN, data, response_len - digest_len, data,
TPM2_DIGEST_LEN)) digest_len))
return TPM_LIB_ERROR; return TPM_LIB_ERROR;
if (updates) if (updates)

View File

@ -210,3 +210,23 @@ def test_efi_selftest_text_input_ex(u_boot_console):
if m != 0: if m != 0:
raise Exception('Failures occurred during the EFI selftest') raise Exception('Failures occurred during the EFI selftest')
u_boot_console.restart_uboot() u_boot_console.restart_uboot()
@pytest.mark.buildconfigspec('cmd_bootefi_selftest')
@pytest.mark.buildconfigspec('efi_tcg2_protocol')
def test_efi_selftest_tcg2(u_boot_console):
"""Test the EFI_TCG2 PROTOCOL
:param u_boot_console: U-Boot console
This function executes the 'tcg2' unit test.
"""
u_boot_console.restart_uboot()
u_boot_console.run_command(cmd='setenv efi_selftest list')
output = u_boot_console.run_command('bootefi selftest')
assert '\'tcg2\'' in output
u_boot_console.run_command(cmd='setenv efi_selftest tcg2')
u_boot_console.run_command(cmd='bootefi selftest', wait_for_prompt=False)
m = u_boot_console.p.expect(['Summary: 0 failures', 'Press any key'])
if m != 0:
raise Exception('Failures occurred during the EFI selftest')
u_boot_console.restart_uboot()

View File

@ -186,6 +186,7 @@ def test_tpm2_change_auth(u_boot_console):
u_boot_console.run_command('tpm2 clear TPM2_RH_PLATFORM') u_boot_console.run_command('tpm2 clear TPM2_RH_PLATFORM')
assert output.endswith('0') assert output.endswith('0')
@pytest.mark.buildconfigspec('sandbox')
@pytest.mark.buildconfigspec('cmd_tpm_v2') @pytest.mark.buildconfigspec('cmd_tpm_v2')
def test_tpm2_get_capability(u_boot_console): def test_tpm2_get_capability(u_boot_console):
"""Execute a TPM_GetCapability command. """Execute a TPM_GetCapability command.