summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2025-01-29 08:12:21 -0600
committerTom Rini <trini@konsulko.com>2025-01-29 08:12:21 -0600
commit021baf7b08cceb58bb850859dba1614424e16a83 (patch)
tree9f53a40366eea064bcafbe5b82a3f1245b2671bc /cmd
parent75125f392de4e672127fe0b092d481e78ff8bdd0 (diff)
parent8895ff8ae2186b53b4a073966ef16b09c12a69b8 (diff)
Merge tag 'tpm-master-28012025' of https://source.denx.de/u-boot/custodians/u-boot-tpm
CI: https://source.denx.de/u-boot/custodians/u-boot-tpm/-/pipelines/24375 We have use cases where a previous stage boot loader doesn't have any TPM drivers. Instead of extending the hardware PCRs it produces an EventLog that U-Boot later replays on the hardware. The only real example we have is TF-A, which produces the EventLog using hashing algorithms created at compile time. This creates a problem to the TPM since measurements need to extend all active PCR banks. Up to now we were exiting refusing the extend measurements. TPMs can be instructed to change their active PCR banks, as long as the device resets immediately after a reconfiguration. This PR is adding that functionality. U-Boot can now scan the currently active TPM PCR banks, the ones it was compiled to support and the ones present in an EventLog. It the reconfigures the TPM on the fly with the correct algorithms.
Diffstat (limited to 'cmd')
-rw-r--r--cmd/tpm-v2.c128
1 files changed, 125 insertions, 3 deletions
diff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c
index 8517833f861..a62862e94f9 100644
--- a/cmd/tpm-v2.c
+++ b/cmd/tpm-v2.c
@@ -18,11 +18,14 @@ static int do_tpm2_startup(struct cmd_tbl *cmdtp, int flag, int argc,
enum tpm2_startup_types mode;
struct udevice *dev;
int ret;
+ bool bon = true;
ret = get_tpm(&dev);
if (ret)
return ret;
- if (argc != 2)
+
+ /* argv[2] is optional to perform a TPM2_CC_SHUTDOWN */
+ if (argc > 3 || (argc == 3 && strcasecmp("off", argv[2])))
return CMD_RET_USAGE;
if (!strcasecmp("TPM2_SU_CLEAR", argv[1])) {
@@ -34,7 +37,10 @@ static int do_tpm2_startup(struct cmd_tbl *cmdtp, int flag, int argc,
return CMD_RET_FAILURE;
}
- return report_return_code(tpm2_startup(dev, mode));
+ if (argv[2])
+ bon = false;
+
+ return report_return_code(tpm2_startup(dev, bon, mode));
}
static int do_tpm2_self_test(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -226,6 +232,106 @@ unmap_data:
return report_return_code(rc);
}
+static u32 select_mask(u32 mask, enum tpm2_algorithms algo, bool select)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) {
+ if (hash_algo_list[i].hash_alg != algo)
+ continue;
+
+ if (select)
+ mask |= hash_algo_list[i].hash_mask;
+ else
+ mask &= ~hash_algo_list[i].hash_mask;
+
+ break;
+ }
+
+ return mask;
+}
+
+static bool
+is_algo_in_pcrs(enum tpm2_algorithms algo, struct tpml_pcr_selection *pcrs)
+{
+ size_t i;
+
+ for (i = 0; i < pcrs->count; i++) {
+ if (algo == pcrs->selection[i].hash)
+ return true;
+ }
+
+ return false;
+}
+
+static int do_tpm2_pcrallocate(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ int ret;
+ enum tpm2_algorithms algo;
+ const char *pw = (argc < 4) ? NULL : argv[3];
+ const ssize_t pw_sz = pw ? strlen(pw) : 0;
+ static struct tpml_pcr_selection pcr = { 0 };
+ u32 pcr_len = 0;
+ bool bon = false;
+ static u32 mask;
+ int i;
+
+ /* argv[1]: algorithm (bank), argv[2]: on/off */
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+
+ if (!strcasecmp("on", argv[2]))
+ bon = true;
+ else if (strcasecmp("off", argv[2]))
+ return CMD_RET_USAGE;
+
+ algo = tpm2_name_to_algorithm(argv[1]);
+ if (algo == -EINVAL)
+ return CMD_RET_USAGE;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ if (!pcr.count) {
+ /*
+ * Get current active algorithms (banks), PCRs and mask via the
+ * first call
+ */
+ ret = tpm2_get_pcr_info(dev, &pcr);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < pcr.count; i++) {
+ struct tpms_pcr_selection *sel = &pcr.selection[i];
+ const char *name;
+
+ if (!tpm2_is_active_bank(sel))
+ continue;
+
+ mask = select_mask(mask, sel->hash, true);
+ name = tpm2_algorithm_name(sel->hash);
+ if (name)
+ printf("Active bank[%d]: %s\n", i, name);
+ }
+ }
+
+ if (!is_algo_in_pcrs(algo, &pcr)) {
+ printf("%s is not supported by the tpm device\n", argv[1]);
+ return CMD_RET_USAGE;
+ }
+
+ mask = select_mask(mask, algo, bon);
+ ret = tpm2_pcr_config_algo(dev, mask, &pcr, &pcr_len);
+ if (ret)
+ return ret;
+
+ return report_return_code(tpm2_send_pcr_allocate(dev, pw, pw_sz, &pcr,
+ pcr_len));
+}
+
static int do_tpm_dam_reset(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
@@ -395,6 +501,7 @@ static struct cmd_tbl tpm2_commands[] = {
do_tpm_pcr_setauthpolicy, "", ""),
U_BOOT_CMD_MKENT(pcr_setauthvalue, 0, 1,
do_tpm_pcr_setauthvalue, "", ""),
+ U_BOOT_CMD_MKENT(pcr_allocate, 0, 1, do_tpm2_pcrallocate, "", ""),
};
struct cmd_tbl *get_tpm2_commands(unsigned int *size)
@@ -420,11 +527,13 @@ U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command",
" Initialize the software stack. Always the first command to issue.\n"
" 'tpm startup' is the only acceptable command after a 'tpm init' has been\n"
" issued\n"
-"startup <mode>\n"
+"startup <mode> [<op>]\n"
" Issue a TPM2_Startup command.\n"
" <mode> is one of:\n"
" * TPM2_SU_CLEAR (reset state)\n"
" * TPM2_SU_STATE (preserved state)\n"
+" <op>:\n"
+" * off - To shutdown the TPM\n"
"self_test <type>\n"
" Test the TPM capabilities.\n"
" <type> is one of:\n"
@@ -473,4 +582,17 @@ U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command",
" <pcr>: index of the PCR\n"
" <key>: secret to protect the access of PCR #<pcr>\n"
" <password>: optional password of the PLATFORM hierarchy\n"
+"pcr_allocate <algorithm> <on/off> [<password>]\n"
+" Issue a TPM2_PCR_Allocate Command to reconfig PCR bank algorithm.\n"
+" <algorithm> is one of:\n"
+" * sha1\n"
+" * sha256\n"
+" * sha384\n"
+" * sha512\n"
+" <on|off> is one of:\n"
+" * on - Select all available PCRs associated with the specified\n"
+" algorithm (bank)\n"
+" * off - Clear all available PCRs associated with the specified\n"
+" algorithm (bank)\n"
+" <password>: optional password\n"
);