
On Wed, 15 Jan 2025 at 22:02, Raymond Mao raymond.mao@linaro.org wrote:
Add PCR allocate wrapper APIs for using in tcg2 protocol. The wrapper proceeds a PCR allocate command, followed by a shutdown command.
We have lib/tpm_tcg2.c does any of the functions belong to that file? Unless we expect the non-TCG version to do something similar....
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@linaro.org
include/tpm-v2.h | 20 ++++++++ lib/Kconfig | 12 +++++ lib/tpm-v2.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+)
diff --git a/include/tpm-v2.h b/include/tpm-v2.h index af3158f6e4..79dc4a34e2 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -703,6 +703,17 @@ 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_pcr_allocate_get_mask - Get algorithm bitmask for PCR allocate
Naming nit. This is comparing the EventLog, U-Boot supported, and active algorithms. Can we rename it to tpm2_scan_masks() or something similar and update the description with that?
- @dev TPM device
- @log_active Active algorithm bitmask
- @mask Bitmask for PCR allocate
- Return: zero on success, negative errno otherwise
- */
+int tpm2_pcr_allocate_get_mask(struct udevice *dev, u32 log_active, u32 *mask);
/**
- tpm2_pcr_config_algo() - Allocate the active PCRs. Requires reboot
@@ -730,6 +741,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_pcr_allocate() - Allocate the PCRs
- @param dev TPM device
- @log_active Bitmask of eventlog algorithms
- Return: code of the operation
- */
+int tpm2_pcr_allocate(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..71abf070de 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_pcr_allocate_get_mask(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;
We duplicate this in the tcg functions for getting active pcr banks, but I can live with it now and refactor it later.
}
/* 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)
if (rc) is clearer here I think
*mask = active & supported & *mask;
else
*mask = active & supported;
}
return rc;
+}
+static int tpm2_proceed_pcr_allocate(struct udevice *dev, u32 algo_mask)
Naming this tpm2_pcr_allocate() is better
+{
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_pcr_allocate(struct udevice *dev, u32 log_active)
This assumes there's a log involved. So let's find a better name and keep the current one for the function above.
+{
u32 algo_mask = 0;
int rc;
rc = tpm2_pcr_allocate_get_mask(dev, log_active, &algo_mask);
if (rc)
return rc;
if (algo_mask) {
if (!IS_ENABLED(CONFIG_TPM_PCR_ALLOCATE))
return -1;
rc = tpm2_proceed_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
Thanks /Ilias