Output is now more similar to the Linux userspace tool "tpm2_pcrread".
The old semantics that require specifying one PCR number are retained. In addition with no arguments the command now prints contents of all PCR registers. Signed-off-by: Ludwig Nussel <[email protected]> --- (no changes since v3) Changes in v3: - fix test failure Changes in v2: - fix return value handling cmd/tpm-v2.c | 69 +++++++++++++++++++++++++++----------- test/py/tests/test_tpm2.py | 9 ++--- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c index 847b2691581..e9f4bc24e33 100644 --- a/cmd/tpm-v2.c +++ b/cmd/tpm-v2.c @@ -8,6 +8,7 @@ #include <dm.h> #include <log.h> #include <mapmem.h> +#include <malloc.h> #include <tpm-common.h> #include <tpm-v2.h> #include "tpm-user-utils.h" @@ -150,10 +151,11 @@ static int do_tpm_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc, u32 index, rc; int algo_len; unsigned int updates; - void *data; + u8 *data; int ret; + u32 pcr_start, pcr_end; - if (argc < 3 || argc > 4) + if (argc > 4) return CMD_RET_USAGE; if (argc == 4) { algo = tpm2_name_to_algorithm(argv[3]); @@ -168,25 +170,51 @@ static int do_tpm_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc, priv = dev_get_uclass_priv(dev); if (!priv) - return -EINVAL; - - index = simple_strtoul(argv[1], NULL, 0); - if (index >= priv->pcr_count) - return -EINVAL; + return CMD_RET_FAILURE; - data = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0); + if (argc >= 2) { + pcr_start = simple_strtoul(argv[1], NULL, 0); + if (pcr_start >= priv->pcr_count) { + log_err("Index %u out of range (max %u)\n", pcr_start, priv->pcr_count - 1); + return CMD_RET_FAILURE; + } + pcr_end = pcr_start + 1; + } else { + pcr_start = 0; + pcr_end = priv->pcr_count; + } - rc = tpm2_pcr_read(dev, index, priv->pcr_select_min, algo, - data, algo_len, &updates); - if (!rc) { - printf("PCR #%u %s %d byte content (%u known updates):\n", index, - tpm2_algorithm_name(algo), algo_len, updates); - print_byte_string(data, algo_len); + if (argc >= 3) { + data = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0); + } else { + data = malloc(algo_len); + if (!data) { + log_err("Failed to allocate %u bytes for PCR data\n", algo_len); + return CMD_RET_FAILURE; + } } - unmap_sysmem(data); + printf("%8s:\n", tpm2_algorithm_name(algo)); + for (index = pcr_start; index < pcr_end; ++index) { + printf("%6u: ", index); + rc = tpm2_pcr_read(dev, index, priv->pcr_select_min, algo, + data, algo_len, &updates); + if (rc == 0) { + printf("0x"); + for (int i = 0; i < algo_len; ++i) + printf("%02X", data[i]); + printf(" (%u known updates)\n", updates); + } else { + log_err("PCR #%u read failed: %d\n", index, rc); + ret = report_return_code(rc); + } + } + if (argc >= 3) + unmap_sysmem(data); + else + free(data); - return report_return_code(rc); + return ret; } static int do_tpm_get_capability(struct cmd_tbl *cmdtp, int flag, int argc, @@ -548,10 +576,13 @@ U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command", " Extend PCR #<pcr> with digest at <digest_addr> with digest_algo.\n" " <pcr>: index of the PCR\n" " <digest_addr>: address of digest of digest_algo type (defaults to SHA256)\n" -"pcr_read <pcr> <digest_addr> [<digest_algo>]\n" +"pcr_read [<pcr> [<digest_addr> [<digest_algo>]]]\n" " Read PCR #<pcr> to memory address <digest_addr> with <digest_algo>.\n" -" <pcr>: index of the PCR\n" -" <digest_addr>: address of digest of digest_algo type (defaults to SHA256)\n" +" With no arguments, print all PCR registers.\n" +" If only <pcr> is specified, a buffer is allocated internally.\n" +" <pcr>: index of the PCR (optional, defaults to all PCRs)\n" +" <digest_addr>: address of digest of digest_algo type (optional)\n" +" <digest_algo>: digest algorithm type (defaults to SHA256)\n" "get_capability <capability> <property> <addr> <count>\n" " Read and display <count> entries indexed by <capability>/<property>.\n" " Values are 4 bytes long and are written at <addr>.\n" diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py index 9be85999d46..1baf86dd065 100644 --- a/test/py/tests/test_tpm2.py +++ b/test/py/tests/test_tpm2.py @@ -198,8 +198,7 @@ def test_tpm2_pcr_read(ubman): updates = int(re.findall(r'\d+', str)[0]) # Check the output value - assert 'PCR #10 sha256 32 byte content' in read_pcr - assert '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' in read_pcr + assert 'sha256:\r\r\n 10: 0x0000000000000000000000000000000000000000000000000000000000000000' in read_pcr @pytest.mark.buildconfigspec('cmd_tpm_v2') @pytest.mark.notbuildconfigspec('target_chromebook_coral') @@ -230,8 +229,7 @@ def test_tpm2_pcr_extend(ubman): read_pcr = ubman.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20)) output = ubman.run_command('echo $?') assert output.endswith('0') - assert 'f5 a5 fd 42 d1 6a 20 30 27 98 ef 6e d3 09 97 9b' in read_pcr - assert '43 00 3d 23 20 d9 f0 e8 ea 98 31 a9 27 59 fb 4b' in read_pcr + assert 'sha256:\r\r\n 10: 0xF5A5FD42D16A20302798EF6ED309979B43003D2320D9F0E8EA9831A92759FB4B' in read_pcr str = re.findall(r'\d+ known updates', read_pcr)[0] new_updates = int(re.findall(r'\d+', str)[0]) @@ -244,8 +242,7 @@ def test_tpm2_pcr_extend(ubman): read_pcr = ubman.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20)) output = ubman.run_command('echo $?') assert output.endswith('0') - assert '7a 05 01 f5 95 7b df 9c b3 a8 ff 49 66 f0 22 65' in read_pcr - assert 'f9 68 65 8b 7a 9c 62 64 2c ba 11 65 e8 66 42 f5' in read_pcr + assert '10: 0x7A0501F5957BDF9CB3A8FF4966F02265F968658B7A9C62642CBA1165E86642F5' in read_pcr str = re.findall(r'\d+ known updates', read_pcr)[0] new_updates = int(re.findall(r'\d+', str)[0]) -- 2.43.0

