diff options
author | Tom Rini <trini@konsulko.com> | 2021-11-30 08:03:21 -0500 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2021-11-30 08:03:21 -0500 |
commit | ce29c52891d2265f854119c9cc6defcc70b54c07 (patch) | |
tree | a6d0c08733eb50431342d440152754baf19fba2e | |
parent | ade37460a944aed36ae6ee634c4d4a9a22690461 (diff) | |
parent | c0d9bb0b4a747a7ec481b2369391ca8f53e50bc9 (diff) | |
download | u-boot-ce29c52891d2265f854119c9cc6defcc70b54c07.zip u-boot-ce29c52891d2265f854119c9cc6defcc70b54c07.tar.gz u-boot-ce29c52891d2265f854119c9cc6defcc70b54c07.tar.bz2 |
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
-rw-r--r-- | cmd/tpm-v2.c | 3 | ||||
-rw-r--r-- | configs/qemu_arm64_defconfig | 1 | ||||
-rw-r--r-- | configs/qemu_arm_defconfig | 1 | ||||
-rw-r--r-- | doc/board/emulation/qemu-arm.rst | 9 | ||||
-rw-r--r-- | drivers/tpm/tpm2_tis_mmio.c | 5 | ||||
-rw-r--r-- | include/efi_loader.h | 2 | ||||
-rw-r--r-- | include/tpm-v2.h | 5 | ||||
-rw-r--r-- | lib/efi_loader/efi_tcg2.c | 545 | ||||
-rw-r--r-- | lib/tpm-v2.c | 12 | ||||
-rw-r--r-- | test/py/tests/test_efi_selftest.py | 20 | ||||
-rw-r--r-- | test/py/tests/test_tpm2.py | 1 |
11 files changed, 526 insertions, 78 deletions
diff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c index daae911..4ea5f9f 100644 --- a/cmd/tpm-v2.c +++ b/cmd/tpm-v2.c @@ -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); - 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) { printf("PCR #%u content (%u known updates):\n", index, updates); print_byte_string(data, TPM2_DIGEST_LEN); diff --git a/configs/qemu_arm64_defconfig b/configs/qemu_arm64_defconfig index 83d7ae5..e8a6f75 100644 --- a/configs/qemu_arm64_defconfig +++ b/configs/qemu_arm64_defconfig @@ -23,6 +23,7 @@ CONFIG_CMD_DFU=y CONFIG_CMD_MTD=y CONFIG_CMD_PCI=y CONFIG_CMD_USB=y +CONFIG_CMD_TPM=y CONFIG_CMD_MTDPARTS=y CONFIG_OF_BOARD=y CONFIG_ENV_IS_IN_FLASH=y diff --git a/configs/qemu_arm_defconfig b/configs/qemu_arm_defconfig index ab55748..b459305 100644 --- a/configs/qemu_arm_defconfig +++ b/configs/qemu_arm_defconfig @@ -25,6 +25,7 @@ CONFIG_CMD_DFU=y CONFIG_CMD_MTD=y CONFIG_CMD_PCI=y CONFIG_CMD_USB=y +CONFIG_CMD_TPM=y CONFIG_CMD_MTDPARTS=y CONFIG_OF_BOARD=y CONFIG_ENV_IS_IN_FLASH=y diff --git a/doc/board/emulation/qemu-arm.rst b/doc/board/emulation/qemu-arm.rst index 584ef0a..7c24e29 100644 --- a/doc/board/emulation/qemu-arm.rst +++ b/doc/board/emulation/qemu-arm.rst @@ -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.:: - -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.:: @@ -75,10 +76,14 @@ can be enabled with the following command line parameters: -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 +- 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. Enabling TPMv2 support diff --git a/drivers/tpm/tpm2_tis_mmio.c b/drivers/tpm/tpm2_tis_mmio.c index 9cedff2..f04aab2 100644 --- a/drivers/tpm/tpm2_tis_mmio.c +++ b/drivers/tpm/tpm2_tis_mmio.c @@ -118,10 +118,13 @@ iounmap: static int tpm_tis_remove(struct udevice *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); - return tpm_tis_cleanup(dev); + return ret; } static const struct tpm_ops tpm_tis_ops = { diff --git a/include/efi_loader.h b/include/efi_loader.h index d52e399..67c40ca 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -988,4 +988,6 @@ efi_status_t efi_esrt_register(void); */ efi_status_t efi_esrt_populate(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 */ diff --git a/include/tpm-v2.h b/include/tpm-v2.h index ceff7d2..4e9dd52 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -512,13 +512,16 @@ u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data, * @dev TPM device * @idx Index of the PCR * @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 + * @digest_len len of the data * @updates Optional out parameter: number of updates for this PCR * * @return code of the operation */ 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 diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 8c1f22e..5f71b18 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -199,6 +199,44 @@ static efi_status_t tcg2_pcr_extend(struct udevice *dev, u32 pcr_index, 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 * * @pcr_index: PCR index @@ -325,6 +363,45 @@ __weak efi_status_t platform_get_tpm2_device(struct udevice **dev) } /** + * 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 * * @dev: TPM device @@ -1182,6 +1259,318 @@ static const struct efi_tcg2_protocol efi_tcg2_protocol = { }; /** + * 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 * * @dev: tpm device @@ -1313,69 +1702,6 @@ out: } /** - * 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 * * @dev: TPM device @@ -1428,6 +1754,93 @@ static efi_status_t efi_append_scrtm_version(struct udevice *dev) } /** + * 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 * * @dev: TPM device @@ -1963,12 +2376,6 @@ efi_status_t efi_tcg2_register(void) if (ret != EFI_SUCCESS) 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, (void *)&efi_tcg2_protocol); if (ret != EFI_SUCCESS) { diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c index 2e7b27b..1bf6278 100644 --- a/lib/tpm-v2.c +++ b/lib/tpm-v2.c @@ -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, - 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 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 */ 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 */ /* 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) return ret; + if (digest_len > response_len) + return TPM_LIB_ERROR; + if (unpack_byte_string(response, response_len, "ds", 10, &counter, - response_len - TPM2_DIGEST_LEN, data, - TPM2_DIGEST_LEN)) + response_len - digest_len, data, + digest_len)) return TPM_LIB_ERROR; if (updates) diff --git a/test/py/tests/test_efi_selftest.py b/test/py/tests/test_efi_selftest.py index 0161a6e..a48cd32 100644 --- a/test/py/tests/test_efi_selftest.py +++ b/test/py/tests/test_efi_selftest.py @@ -210,3 +210,23 @@ def test_efi_selftest_text_input_ex(u_boot_console): if m != 0: raise Exception('Failures occurred during the EFI selftest') 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() diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py index 7c89f5f..d2ad6f9 100644 --- a/test/py/tests/test_tpm2.py +++ b/test/py/tests/test_tpm2.py @@ -186,6 +186,7 @@ def test_tpm2_change_auth(u_boot_console): u_boot_console.run_command('tpm2 clear TPM2_RH_PLATFORM') assert output.endswith('0') +@pytest.mark.buildconfigspec('sandbox') @pytest.mark.buildconfigspec('cmd_tpm_v2') def test_tpm2_get_capability(u_boot_console): """Execute a TPM_GetCapability command. |