Hi Ilias, On Thu, 16 Jan 2025 at 08:01, Ilias Apalodimas <[email protected]> wrote:
> On Wed, 15 Jan 2025 at 22:02, Raymond Mao <[email protected]> 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.... > > Yes. The concept of bitmasks of algorithms is needed for PCR allocation. Currently I have to implement a few duplicated logics here to avoid moving APIs from tcg2. > > 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 <[email protected]> > > --- > > 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? > > Will do in V2. > > + * > > + * @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 > > When *mask is not 0 here, that means the TPM device activated more algorithm(s) than the ones exist in eventlog. > > + *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 > > Will do in V2. > > +{ > > + 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. > > Will do in V2. Regards, Raymond > > +{ > > + 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 >

