[PATCH v3 3/6] tpm: add wrapper and helper APIs for PCR allocate
Raymond Mao
raymond.mao at linaro.org
Mon Jan 27 15:58:48 CET 2025
Add PCR allocate wrapper APIs for using in tcg2 protocol.
The wrapper proceeds a PCR allocate command, followed by a
shutdown command.
A system boot is required after two commands since TPM device needs
a HW reset to activate the new algorithms config.
Also, a helper function is included to determine the new bank mask
for PCR allocation by combining the status of current active,
supported and eventlog bank masks.
A new kconfig is created. PCR allocate and system reboot only
happens when the kconfig is selected, otherwise just exit with
errors.
Signed-off-by: Raymond Mao <raymond.mao at linaro.org>
---
changes in v2
- Rename the newly added APIs.
changes in v3
- Rename tpm2_set_algorithm_mask to tpm2_scan_masks.
include/tpm-v2.h | 21 ++++++++
lib/Kconfig | 12 +++++
lib/tpm-v2.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 154 insertions(+)
diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index af3158f6e4..ece422df0c 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -703,6 +703,18 @@ u32 tpm2_report_state(struct udevice *dev, uint vendor_cmd, uint vendor_subcmd,
u32 tpm2_enable_nvcommits(struct udevice *dev, uint vendor_cmd,
uint vendor_subcmd);
+/**
+ * tpm2_scan_masks - Scan the bitmask of algorithms based on the
+ * active/supported banks and the one from eventlog.
+ *
+ * @dev TPM device
+ * @log_active Active algorithm bitmask
+ * @mask Bitmask to set
+ *
+ * Return: zero on success, negative errno otherwise
+ */
+int tpm2_scan_masks(struct udevice *dev, u32 log_active, u32 *mask);
+
/**
* tpm2_pcr_config_algo() - Allocate the active PCRs. Requires reboot
*
@@ -730,6 +742,15 @@ u32 tpm2_pcr_config_algo(struct udevice *dev, u32 algo_mask,
u32 tpm2_send_pcr_allocate(struct udevice *dev, const char *pw,
const ssize_t pw_sz, struct tpml_pcr_selection *pcr,
u32 pcr_len);
+/**
+ * tpm2_activate_banks() - Activate PCR banks
+ *
+ * @param dev TPM device
+ * @log_active Bitmask of eventlog algorithms
+ *
+ * Return: code of the operation
+ */
+int tpm2_activate_banks(struct udevice *dev, u32 log_active);
/**
* tpm2_auto_start() - start up the TPM and perform selftests.
diff --git a/lib/Kconfig b/lib/Kconfig
index baeb615626..0732333849 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -514,6 +514,18 @@ config VPL_TPM
for the low-level TPM interface, but only one TPM is supported at
a time by the TPM library.
+config TPM_PCR_ALLOCATE
+ bool "Re-configurate TPM algorithms in run-time (PCR allocate)"
+ depends on TPM_V2 && (MEASURED_BOOT || EFI_TCG2_PROTOCOL)
+ help
+ This enables a detection for the dismatches of algorithms among TPM
+ device, eventlog from previous boot stage and U-Boot support.
+ A PCR allocate command will be sent to reconfigurate the TPM device
+ in run-time to make sure algorithms in TPM device, eventlog and
+ U-Boot are aligned with each other.
+ A system reboot will be proceeded after then to activate the new
+ algorithms.
+
endmenu
menu "Android Verified Boot"
diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index 045b5dd9eb..aa02a9e961 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -44,6 +44,127 @@ static int tpm2_update_active_banks(struct udevice *dev)
return 0;
}
+static void tpm2_print_selected_algorithm_name(u32 selected)
+{
+ size_t i;
+ const char *str;
+
+ for (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) {
+ const struct digest_info *algo = &hash_algo_list[i];
+
+ if (!(selected & algo->hash_mask))
+ continue;
+
+ str = tpm2_algorithm_name(algo->hash_alg);
+ if (str)
+ log_info("%s\n", str);
+ }
+}
+
+int tpm2_scan_masks(struct udevice *dev, u32 log_active, u32 *mask)
+{
+ struct tpml_pcr_selection pcrs;
+ u32 active = 0;
+ u32 supported = 0;
+ int rc, i;
+
+ *mask = 0;
+
+ rc = tpm2_get_pcr_info(dev, &pcrs);
+ if (rc)
+ return rc;
+
+ for (i = 0; i < pcrs.count; i++) {
+ struct tpms_pcr_selection *sel = &pcrs.selection[i];
+ size_t j;
+ u32 hash_mask = 0;
+
+ for (j = 0; j < ARRAY_SIZE(hash_algo_list); j++) {
+ if (hash_algo_list[j].hash_alg == sel->hash)
+ hash_mask = hash_algo_list[j].hash_mask;
+ }
+
+ if (tpm2_algorithm_supported(sel->hash))
+ supported |= hash_mask;
+
+ if (tpm2_is_active_bank(sel))
+ active |= hash_mask;
+ }
+
+ /* All eventlog algorithm(s) must be supported */
+ if (log_active & ~supported) {
+ log_err("EventLog contains U-Boot unsupported algorithm(s)\n");
+ tpm2_print_selected_algorithm_name(log_active & ~supported);
+ rc = -1;
+ }
+ if (log_active && active & ~log_active) {
+ log_warning("TPM active algorithm(s) not exist in eventlog\n");
+ tpm2_print_selected_algorithm_name(active & ~log_active);
+ *mask = log_active;
+ }
+
+ /* Any active algorithm(s) which are not supported must be removed */
+ if (active & ~supported) {
+ log_warning("TPM active algorithm(s) unsupported by u-boot\n");
+ tpm2_print_selected_algorithm_name(active & ~supported);
+ if (*mask)
+ *mask = active & supported & *mask;
+ else
+ *mask = active & supported;
+ }
+
+ return rc;
+}
+
+static int tpm2_pcr_allocate(struct udevice *dev, u32 algo_mask)
+{
+ struct tpml_pcr_selection pcr = { 0 };
+ u32 pcr_len = 0;
+ int rc;
+
+ rc = tpm2_get_pcr_info(dev, &pcr);
+ if (rc)
+ return rc;
+
+ rc = tpm2_pcr_config_algo(dev, algo_mask, &pcr, &pcr_len);
+ if (rc)
+ return rc;
+
+ /* Assume no password */
+ rc = tpm2_send_pcr_allocate(dev, NULL, 0, &pcr, pcr_len);
+ if (rc)
+ return rc;
+
+ /* Send TPM2_Shutdown, assume mode = TPM2_SU_CLEAR */
+ return tpm2_startup(dev, false, TPM2_SU_CLEAR);
+}
+
+int tpm2_activate_banks(struct udevice *dev, u32 log_active)
+{
+ u32 algo_mask = 0;
+ int rc;
+
+ rc = tpm2_scan_masks(dev, log_active, &algo_mask);
+ if (rc)
+ return rc;
+
+ if (algo_mask) {
+ if (!IS_ENABLED(CONFIG_TPM_PCR_ALLOCATE))
+ return -1;
+
+ rc = tpm2_pcr_allocate(dev, algo_mask);
+ if (rc)
+ return rc;
+
+ log_info("PCR allocate done, shutdown TPM and reboot\n");
+ do_reset(NULL, 0, 0, NULL);
+ log_err("reset does not work!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
u32 tpm2_startup(struct udevice *dev, bool bon, enum tpm2_startup_types mode)
{
int op = bon ? TPM2_CC_STARTUP : TPM2_CC_SHUTDOWN;
--
2.25.1
More information about the U-Boot
mailing list