mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-19 03:15:00 +00:00
Merge tag 'tpm-master-07012025' of https://source.denx.de/u-boot/custodians/u-boot-tpm
A few changes for the TPM subsystem wrt to EventLong creation and measurements.
Generally speaking it's insecure for a TPM to not cap all the active PCRs
when performing measurements.
Up to now we had code querying the active PCR banks on the fly and reason
whether it should perform a measurement or not. Since a TPM requires a reset
to change the active PCR banks, it's easier and faster to store them in an
array in the device private data and check against that.
This relates to an interesting feature some bootloaders have. For example
TF-A can't extend a PCR since it has no TPM drivers, but can produce an
EventLog that U-Boot can replay on the hardware once that comes up.
The supported hash algorithms of the TF-A generated Eventlog are generated
at compile time. When trying to replay an EventLog the TPM active PCR banks
and the created EventLog algorithms must agree. We used to report an error
but that changed in commit 97707f12fd
("tpm: Support boot measurements").
This PR also brings up the old behavior and an error is reported now while
printing a human readable list of the mismatched algorithms.
This commit is contained in:
commit
38a3711103
5 changed files with 258 additions and 131 deletions
|
@ -42,12 +42,20 @@ enum tpm_version {
|
|||
TPM_V2,
|
||||
};
|
||||
|
||||
/**
|
||||
* define TPM2_NUM_PCR_BANKS - number of PCR banks
|
||||
* The value 16 can be found in the current standard
|
||||
* TCG TSS 2.0 Overview and Common Structures Specification 1.0, rev 10
|
||||
*/
|
||||
#define TPM2_NUM_PCR_BANKS 16
|
||||
|
||||
/**
|
||||
* struct tpm_chip_priv - Information about a TPM, stored by the uclass
|
||||
*
|
||||
* These values must be set up by the device's probe() method before
|
||||
* Some of hese values must be set up by the device's probe() method before
|
||||
* communcation is attempted. If the device has an xfer() method, this is
|
||||
* not needed. There is no need to set up @buf.
|
||||
* The active_banks is only valid for TPMv2 after the device is initialized.
|
||||
*
|
||||
* @version: TPM stack to be used
|
||||
* @duration_ms: Length of each duration type in milliseconds
|
||||
|
@ -55,6 +63,8 @@ enum tpm_version {
|
|||
* @buf: Buffer used during the exchanges with the chip
|
||||
* @pcr_count: Number of PCR per bank
|
||||
* @pcr_select_min: Minimum size in bytes of the pcrSelect array
|
||||
* @active_bank_count: Number of active PCR banks
|
||||
* @active_banks: Array of active PCRs
|
||||
* @plat_hier_disabled: Platform hierarchy has been disabled (TPM is locked
|
||||
* down until next reboot)
|
||||
*/
|
||||
|
@ -68,6 +78,10 @@ struct tpm_chip_priv {
|
|||
/* TPM v2 specific data */
|
||||
uint pcr_count;
|
||||
uint pcr_select_min;
|
||||
#if IS_ENABLED(CONFIG_TPM_V2)
|
||||
u8 active_bank_count;
|
||||
u32 active_banks[TPM2_NUM_PCR_BANKS];
|
||||
#endif
|
||||
bool plat_hier_disabled;
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
* Copyright (c) 2020 Linaro
|
||||
* Copyright (c) 2018 Bootlin
|
||||
*
|
||||
* The structures are described in
|
||||
* Trusted Platform Module Library Part 2: Structures
|
||||
* http://tcg.tjn.chef.causewaynow.com/resource/tpm-library-specification/
|
||||
*
|
||||
* C header files are listed in
|
||||
* https://trustedcomputinggroup.org/resource/tss-overview-common-structures-specification/
|
||||
*
|
||||
* Author: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
|
@ -34,16 +39,6 @@ struct udevice;
|
|||
|
||||
#define TPM2_HDR_LEN 10
|
||||
|
||||
/*
|
||||
* We deviate from this draft of the specification by increasing the value of
|
||||
* TPM2_NUM_PCR_BANKS from 3 to 16 to ensure compatibility with TPM2
|
||||
* implementations that have enabled a larger than typical number of PCR
|
||||
* banks. This larger value for TPM2_NUM_PCR_BANKS is expected to be included
|
||||
* in a future revision of the specification.
|
||||
*/
|
||||
#define TPM2_NUM_PCR_BANKS 16
|
||||
|
||||
/* Definition of (UINT32) TPM2_CAP Constants */
|
||||
#define TPM2_CAP_PCRS 0x00000005U
|
||||
#define TPM2_CAP_TPM_PROPERTIES 0x00000006U
|
||||
|
||||
|
@ -55,20 +50,43 @@ struct udevice;
|
|||
#define TPM2_PT_MAX_COMMAND_SIZE (u32)(TPM2_PT_FIXED + 30)
|
||||
#define TPM2_PT_MAX_RESPONSE_SIZE (u32)(TPM2_PT_FIXED + 31)
|
||||
|
||||
/* TPMS_TAGGED_PROPERTY Structure */
|
||||
/**
|
||||
* struct tpms_tagged_property - TPMS_TAGGED_PROPERTY structure
|
||||
*
|
||||
* This structure is returned by TPM2_GetCapability() to report
|
||||
* a u32 property value.
|
||||
*
|
||||
* @property: property identifier
|
||||
* @value: value of the property
|
||||
*/
|
||||
struct tpms_tagged_property {
|
||||
u32 property;
|
||||
u32 value;
|
||||
} __packed;
|
||||
|
||||
/* TPMS_PCR_SELECTION Structure */
|
||||
/**
|
||||
* struct tpms_pcr_selection - TPMS_PCR_SELECTION structure
|
||||
*
|
||||
* This structure allows to specify a hash algorithm and a list of
|
||||
* selected PCRs. A PCR is selected by setting the related bit in
|
||||
* @pcr_select to 1.
|
||||
*
|
||||
* @hash: hash algorithm associated with the selection
|
||||
* @size_of_select: size in bytes of the @pcr_select array
|
||||
* @pcr_select: bit map of selected PCRs
|
||||
*/
|
||||
struct tpms_pcr_selection {
|
||||
u16 hash;
|
||||
u8 size_of_select;
|
||||
u8 pcr_select[TPM2_PCR_SELECT_MAX];
|
||||
} __packed;
|
||||
|
||||
/* TPML_PCR_SELECTION Structure */
|
||||
/**
|
||||
* struct tpml_pcr_selection - TPML_PCR_SELECTION structure
|
||||
*
|
||||
* @count: number of selection structures, may be zero
|
||||
* @selection: list of selections
|
||||
*/
|
||||
struct tpml_pcr_selection {
|
||||
u32 count;
|
||||
struct tpms_pcr_selection selection[TPM2_NUM_PCR_BANKS];
|
||||
|
@ -268,6 +286,7 @@ struct digest_info {
|
|||
u16 hash_alg;
|
||||
u32 hash_mask;
|
||||
u16 hash_len;
|
||||
bool supported;
|
||||
};
|
||||
|
||||
/* Algorithm Registry */
|
||||
|
@ -278,38 +297,50 @@ struct digest_info {
|
|||
#define TCG2_BOOT_HASH_ALG_SM3_256 0x00000010
|
||||
|
||||
static const struct digest_info hash_algo_list[] = {
|
||||
#if IS_ENABLED(CONFIG_SHA1)
|
||||
{
|
||||
"sha1",
|
||||
TPM2_ALG_SHA1,
|
||||
TCG2_BOOT_HASH_ALG_SHA1,
|
||||
TPM2_SHA1_DIGEST_SIZE,
|
||||
},
|
||||
#if IS_ENABLED(CONFIG_SHA1)
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SHA256)
|
||||
},
|
||||
{
|
||||
"sha256",
|
||||
TPM2_ALG_SHA256,
|
||||
TCG2_BOOT_HASH_ALG_SHA256,
|
||||
TPM2_SHA256_DIGEST_SIZE,
|
||||
},
|
||||
#if IS_ENABLED(CONFIG_SHA256)
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SHA384)
|
||||
},
|
||||
{
|
||||
"sha384",
|
||||
TPM2_ALG_SHA384,
|
||||
TCG2_BOOT_HASH_ALG_SHA384,
|
||||
TPM2_SHA384_DIGEST_SIZE,
|
||||
},
|
||||
#if IS_ENABLED(CONFIG_SHA384)
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SHA512)
|
||||
},
|
||||
{
|
||||
"sha512",
|
||||
TPM2_ALG_SHA512,
|
||||
TCG2_BOOT_HASH_ALG_SHA512,
|
||||
TPM2_SHA512_DIGEST_SIZE,
|
||||
},
|
||||
#if IS_ENABLED(CONFIG_SHA512)
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
/* NV index attributes */
|
||||
|
@ -704,6 +735,14 @@ enum tpm2_algorithms tpm2_name_to_algorithm(const char *name);
|
|||
*/
|
||||
const char *tpm2_algorithm_name(enum tpm2_algorithms);
|
||||
|
||||
/**
|
||||
* tpm2_algorithm_supported() - Check if the algorithm supported by U-Boot
|
||||
*
|
||||
* @algorithm_id: algorithm defined in enum tpm2_algorithms
|
||||
* Return: true if supported, otherwise false
|
||||
*/
|
||||
bool tpm2_algorithm_supported(enum tpm2_algorithms algo);
|
||||
|
||||
/**
|
||||
* tpm2_algorithm_to_len() - Return an algorithm length for supported algorithm id
|
||||
*
|
||||
|
@ -732,20 +771,28 @@ u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo);
|
|||
*/
|
||||
|
||||
/**
|
||||
* tpm2_allow_extend() - Check if extending PCRs is allowed and safe
|
||||
* tpm2_check_active_banks() - Check if the active PCR banks are supported by
|
||||
* our configuration
|
||||
*
|
||||
* @dev: TPM device
|
||||
* Return: true if allowed
|
||||
*/
|
||||
bool tpm2_allow_extend(struct udevice *dev);
|
||||
bool tpm2_check_active_banks(struct udevice *dev);
|
||||
|
||||
/**
|
||||
* tpm2_is_active_pcr() - check the pcr_select. If at least one of the PCRs
|
||||
* supports the algorithm add it on the active ones
|
||||
* tpm2_is_active_bank() - check the pcr_select. If at least one of the PCRs
|
||||
* supports the algorithm add it on the active ones
|
||||
*
|
||||
* @selection: PCR selection structure
|
||||
* Return: True if the algorithm is active
|
||||
*/
|
||||
bool tpm2_is_active_pcr(struct tpms_pcr_selection *selection);
|
||||
bool tpm2_is_active_bank(struct tpms_pcr_selection *selection);
|
||||
|
||||
/**
|
||||
* tpm2_print_active_banks() - Print the active TPM PCRs
|
||||
*
|
||||
* @dev: TPM device
|
||||
*/
|
||||
void tpm2_print_active_banks(struct udevice *dev);
|
||||
|
||||
#endif /* __TPM_V2_H */
|
||||
|
|
|
@ -94,17 +94,17 @@ struct tcg_pcr_event {
|
|||
} __packed;
|
||||
|
||||
/**
|
||||
* tcg2_get_pcr_info() - get the supported, active PCRs and number of banks
|
||||
* tcg2_get_pcr_info() - get the supported, active banks and number of banks
|
||||
*
|
||||
* @dev: TPM device
|
||||
* @supported_pcr: bitmask with the algorithms supported
|
||||
* @active_pcr: bitmask with the active algorithms
|
||||
* @pcr_banks: number of PCR banks
|
||||
* @supported_bank: bitmask with the algorithms supported
|
||||
* @active_bank: bitmask with the active algorithms
|
||||
* @bank_num: number of PCR banks
|
||||
*
|
||||
* @return 0 on success, code of operation or negative errno on failure
|
||||
*/
|
||||
int tcg2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
|
||||
u32 *pcr_banks);
|
||||
int tcg2_get_pcr_info(struct udevice *dev, u32 *supported_bank, u32 *active_bank,
|
||||
u32 *bank_num);
|
||||
|
||||
/**
|
||||
* Crypto Agile Log Entry Format
|
||||
|
|
72
lib/tpm-v2.c
72
lib/tpm-v2.c
|
@ -23,6 +23,27 @@
|
|||
|
||||
#include "tpm-utils.h"
|
||||
|
||||
static int tpm2_update_active_banks(struct udevice *dev)
|
||||
{
|
||||
struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
|
||||
struct tpml_pcr_selection pcrs;
|
||||
int ret, i;
|
||||
|
||||
ret = tpm2_get_pcr_info(dev, &pcrs);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->active_bank_count = 0;
|
||||
for (i = 0; i < pcrs.count; i++) {
|
||||
if (!tpm2_is_active_bank(&pcrs.selection[i]))
|
||||
continue;
|
||||
priv->active_banks[priv->active_bank_count] = pcrs.selection[i].hash;
|
||||
priv->active_bank_count++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
|
||||
{
|
||||
const u8 command_v2[12] = {
|
||||
|
@ -41,7 +62,7 @@ u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
|
|||
if (ret && ret != TPM2_RC_INITIALIZE)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return tpm2_update_active_banks(dev);
|
||||
}
|
||||
|
||||
u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test)
|
||||
|
@ -69,8 +90,10 @@ u32 tpm2_auto_start(struct udevice *dev)
|
|||
|
||||
rc = tpm2_self_test(dev, TPMI_YES);
|
||||
}
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return rc;
|
||||
return tpm2_update_active_banks(dev);
|
||||
}
|
||||
|
||||
u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
|
||||
|
@ -197,7 +220,7 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
|
|||
if (!digest)
|
||||
return -EINVAL;
|
||||
|
||||
if (!tpm2_allow_extend(dev)) {
|
||||
if (!tpm2_check_active_banks(dev)) {
|
||||
log_err("Cannot extend PCRs if all the TPM enabled algorithms are not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -847,7 +870,7 @@ u32 tpm2_enable_nvcommits(struct udevice *dev, uint vendor_cmd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool tpm2_is_active_pcr(struct tpms_pcr_selection *selection)
|
||||
bool tpm2_is_active_bank(struct tpms_pcr_selection *selection)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -884,6 +907,18 @@ const char *tpm2_algorithm_name(enum tpm2_algorithms algo)
|
|||
return "";
|
||||
}
|
||||
|
||||
bool tpm2_algorithm_supported(enum tpm2_algorithms algo)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
|
||||
if (hash_algo_list[i].hash_alg == algo)
|
||||
return hash_algo_list[i].supported;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo)
|
||||
{
|
||||
size_t i;
|
||||
|
@ -896,7 +931,7 @@ u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool tpm2_allow_extend(struct udevice *dev)
|
||||
bool tpm2_check_active_banks(struct udevice *dev)
|
||||
{
|
||||
struct tpml_pcr_selection pcrs;
|
||||
size_t i;
|
||||
|
@ -907,10 +942,33 @@ bool tpm2_allow_extend(struct udevice *dev)
|
|||
return false;
|
||||
|
||||
for (i = 0; i < pcrs.count; i++) {
|
||||
if (tpm2_is_active_pcr(&pcrs.selection[i]) &&
|
||||
!tpm2_algorithm_to_len(pcrs.selection[i].hash))
|
||||
if (tpm2_is_active_bank(&pcrs.selection[i]) &&
|
||||
!tpm2_algorithm_supported(pcrs.selection[i].hash))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void tpm2_print_active_banks(struct udevice *dev)
|
||||
{
|
||||
struct tpml_pcr_selection pcrs;
|
||||
size_t i;
|
||||
int rc;
|
||||
|
||||
rc = tpm2_get_pcr_info(dev, &pcrs);
|
||||
if (rc) {
|
||||
log_err("Can't retrieve active PCRs\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < pcrs.count; i++) {
|
||||
if (tpm2_is_active_bank(&pcrs.selection[i])) {
|
||||
const char *str;
|
||||
|
||||
str = tpm2_algorithm_name(pcrs.selection[i].hash);
|
||||
if (str)
|
||||
log_info("%s\n", str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
190
lib/tpm_tcg2.c
190
lib/tpm_tcg2.c
|
@ -20,38 +20,36 @@
|
|||
#include <linux/unaligned/le_byteshift.h>
|
||||
#include "tpm-utils.h"
|
||||
|
||||
int tcg2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
|
||||
u32 *pcr_banks)
|
||||
int tcg2_get_pcr_info(struct udevice *dev, u32 *supported_bank, u32 *active_bank,
|
||||
u32 *bank_num)
|
||||
{
|
||||
u8 response[(sizeof(struct tpms_capability_data) -
|
||||
offsetof(struct tpms_capability_data, data))];
|
||||
struct tpml_pcr_selection pcrs;
|
||||
size_t i;
|
||||
u32 ret;
|
||||
|
||||
*supported_pcr = 0;
|
||||
*active_pcr = 0;
|
||||
*pcr_banks = 0;
|
||||
memset(response, 0, sizeof(response));
|
||||
*supported_bank = 0;
|
||||
*active_bank = 0;
|
||||
*bank_num = 0;
|
||||
|
||||
ret = tpm2_get_pcr_info(dev, &pcrs);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < pcrs.count; i++) {
|
||||
u32 hash_mask = tcg2_algorithm_to_mask(pcrs.selection[i].hash);
|
||||
struct tpms_pcr_selection *sel = &pcrs.selection[i];
|
||||
u32 hash_mask = tcg2_algorithm_to_mask(sel->hash);
|
||||
|
||||
if (hash_mask) {
|
||||
*supported_pcr |= hash_mask;
|
||||
if (tpm2_is_active_pcr(&pcrs.selection[i]))
|
||||
*active_pcr |= hash_mask;
|
||||
} else {
|
||||
printf("%s: unknown algorithm %x\n", __func__,
|
||||
pcrs.selection[i].hash);
|
||||
}
|
||||
if (tpm2_algorithm_supported(sel->hash))
|
||||
*supported_bank |= hash_mask;
|
||||
else
|
||||
log_warning("%s: unknown algorithm %x\n", __func__,
|
||||
sel->hash);
|
||||
|
||||
if (tpm2_is_active_bank(sel))
|
||||
*active_bank |= hash_mask;
|
||||
}
|
||||
|
||||
*pcr_banks = pcrs.count;
|
||||
*bank_num = pcrs.count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -95,57 +93,64 @@ u32 tcg2_event_get_size(struct tpml_digest_values *digest_list)
|
|||
int tcg2_create_digest(struct udevice *dev, const u8 *input, u32 length,
|
||||
struct tpml_digest_values *digest_list)
|
||||
{
|
||||
struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
|
||||
u8 final[sizeof(union tpmu_ha)];
|
||||
#if IS_ENABLED(CONFIG_SHA256)
|
||||
sha256_context ctx_256;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SHA512)
|
||||
sha512_context ctx_512;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SHA1)
|
||||
sha1_context ctx;
|
||||
u32 active;
|
||||
#endif
|
||||
size_t i;
|
||||
u32 len;
|
||||
int rc;
|
||||
|
||||
rc = tcg2_get_active_pcr_banks(dev, &active);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
digest_list->count = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
|
||||
if (!(active & hash_algo_list[i].hash_mask))
|
||||
continue;
|
||||
for (i = 0; i < priv->active_bank_count; i++) {
|
||||
|
||||
switch (hash_algo_list[i].hash_alg) {
|
||||
switch (priv->active_banks[i]) {
|
||||
#if IS_ENABLED(CONFIG_SHA1)
|
||||
case TPM2_ALG_SHA1:
|
||||
sha1_starts(&ctx);
|
||||
sha1_update(&ctx, input, length);
|
||||
sha1_finish(&ctx, final);
|
||||
len = TPM2_SHA1_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SHA256)
|
||||
case TPM2_ALG_SHA256:
|
||||
sha256_starts(&ctx_256);
|
||||
sha256_update(&ctx_256, input, length);
|
||||
sha256_finish(&ctx_256, final);
|
||||
len = TPM2_SHA256_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SHA384)
|
||||
case TPM2_ALG_SHA384:
|
||||
sha384_starts(&ctx_512);
|
||||
sha384_update(&ctx_512, input, length);
|
||||
sha384_finish(&ctx_512, final);
|
||||
len = TPM2_SHA384_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SHA512)
|
||||
case TPM2_ALG_SHA512:
|
||||
sha512_starts(&ctx_512);
|
||||
sha512_update(&ctx_512, input, length);
|
||||
sha512_finish(&ctx_512, final);
|
||||
len = TPM2_SHA512_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf("%s: unsupported algorithm %x\n", __func__,
|
||||
hash_algo_list[i].hash_alg);
|
||||
priv->active_banks[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
digest_list->digests[digest_list->count].hash_alg =
|
||||
hash_algo_list[i].hash_alg;
|
||||
priv->active_banks[i];
|
||||
memcpy(&digest_list->digests[digest_list->count].digest, final,
|
||||
len);
|
||||
digest_list->count++;
|
||||
|
@ -216,37 +221,17 @@ static int tcg2_log_append_check(struct tcg2_event_log *elog, u32 pcr_index,
|
|||
|
||||
static int tcg2_log_init(struct udevice *dev, struct tcg2_event_log *elog)
|
||||
{
|
||||
struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
|
||||
struct tcg_efi_spec_id_event *ev;
|
||||
struct tcg_pcr_event *log;
|
||||
u32 event_size;
|
||||
u32 count = 0;
|
||||
u32 log_size;
|
||||
u32 active;
|
||||
size_t i;
|
||||
u16 len;
|
||||
int rc;
|
||||
|
||||
rc = tcg2_get_active_pcr_banks(dev, &active);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
count = priv->active_bank_count;
|
||||
event_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes);
|
||||
for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
|
||||
if (!(active & hash_algo_list[i].hash_mask))
|
||||
continue;
|
||||
|
||||
switch (hash_algo_list[i].hash_alg) {
|
||||
case TPM2_ALG_SHA1:
|
||||
case TPM2_ALG_SHA256:
|
||||
case TPM2_ALG_SHA384:
|
||||
case TPM2_ALG_SHA512:
|
||||
count++;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
event_size += 1 +
|
||||
(sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count);
|
||||
log_size = offsetof(struct tcg_pcr_event, event) + event_size;
|
||||
|
@ -273,19 +258,11 @@ static int tcg2_log_init(struct udevice *dev, struct tcg2_event_log *elog)
|
|||
ev->uintn_size = sizeof(size_t) / sizeof(u32);
|
||||
put_unaligned_le32(count, &ev->number_of_algorithms);
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
|
||||
if (!(active & hash_algo_list[i].hash_mask))
|
||||
continue;
|
||||
|
||||
len = hash_algo_list[i].hash_len;
|
||||
if (!len)
|
||||
continue;
|
||||
|
||||
put_unaligned_le16(hash_algo_list[i].hash_alg,
|
||||
&ev->digest_sizes[count].algorithm_id);
|
||||
put_unaligned_le16(len, &ev->digest_sizes[count].digest_size);
|
||||
count++;
|
||||
for (i = 0; i < count; ++i) {
|
||||
len = tpm2_algorithm_to_len(priv->active_banks[i]);
|
||||
put_unaligned_le16(priv->active_banks[i],
|
||||
&ev->digest_sizes[i].algorithm_id);
|
||||
put_unaligned_le16(len, &ev->digest_sizes[i].digest_size);
|
||||
}
|
||||
|
||||
*((u8 *)ev + (event_size - 1)) = 0;
|
||||
|
@ -396,7 +373,6 @@ static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
|
|||
u16 len;
|
||||
int rc;
|
||||
u32 i;
|
||||
u16 j;
|
||||
|
||||
if (elog->log_size <= offsetof(struct tcg_pcr_event, event))
|
||||
return 0;
|
||||
|
@ -435,40 +411,51 @@ static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
|
|||
if (evsz != calc_size)
|
||||
return 0;
|
||||
|
||||
rc = tcg2_get_active_pcr_banks(dev, &active);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/*
|
||||
* Go through the algorithms the EventLog contains. If the EventLog
|
||||
* algorithms don't match the active TPM ones exit and report the
|
||||
* erroneous banks.
|
||||
* We've already checked that U-Boot supports all the enabled TPM
|
||||
* algorithms, so just check the EvenLog against the TPM active ones.
|
||||
*/
|
||||
digest_list.count = 0;
|
||||
log_active = 0;
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
algo = get_unaligned_le16(&event->digest_sizes[i].algorithm_id);
|
||||
mask = tcg2_algorithm_to_mask(algo);
|
||||
|
||||
if (!(active & mask))
|
||||
return 0;
|
||||
|
||||
switch (algo) {
|
||||
case TPM2_ALG_SHA1:
|
||||
case TPM2_ALG_SHA256:
|
||||
case TPM2_ALG_SHA384:
|
||||
case TPM2_ALG_SHA512:
|
||||
len = get_unaligned_le16(&event->digest_sizes[i].digest_size);
|
||||
if (tpm2_algorithm_to_len(algo) != len)
|
||||
return 0;
|
||||
if (tpm2_algorithm_to_len(algo) != len) {
|
||||
log_err("EventLog invalid algorithm length\n");
|
||||
return -1;
|
||||
}
|
||||
digest_list.digests[digest_list.count++].hash_alg = algo;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
/*
|
||||
* We can ignore this if the TPM PCRs is not extended
|
||||
* by the previous bootloader. But for now just exit
|
||||
*/
|
||||
log_err("EventLog has unsupported algorithm 0x%x\n",
|
||||
algo);
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_active |= mask;
|
||||
}
|
||||
|
||||
/* Ensure the previous firmware extended all the PCRs. */
|
||||
if (log_active != active)
|
||||
return 0;
|
||||
rc = tcg2_get_active_pcr_banks(dev, &active);
|
||||
if (rc)
|
||||
return rc;
|
||||
/* If the EventLog and active algorithms don't match exit */
|
||||
if (log_active != active) {
|
||||
log_err("EventLog doesn't contain all active PCR banks\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read PCR0 to check if previous firmware extended the PCRs or not. */
|
||||
rc = tcg2_pcr_read(dev, 0, &digest_list);
|
||||
|
@ -476,17 +463,13 @@ static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
|
|||
return rc;
|
||||
|
||||
for (i = 0; i < digest_list.count; ++i) {
|
||||
len = tpm2_algorithm_to_len(digest_list.digests[i].hash_alg);
|
||||
for (j = 0; j < len; ++j) {
|
||||
if (digest_list.digests[i].digest.sha512[j])
|
||||
break;
|
||||
}
|
||||
u8 hash_buf[TPM2_SHA512_DIGEST_SIZE] = { 0 };
|
||||
u16 hash_alg = digest_list.digests[i].hash_alg;
|
||||
|
||||
/* PCR is non-zero; it has been extended, so skip extending. */
|
||||
if (j != len) {
|
||||
if (memcmp((u8 *)&digest_list.digests[i].digest, hash_buf,
|
||||
tpm2_algorithm_to_len(hash_alg)))
|
||||
digest_list.count = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return tcg2_replay_eventlog(elog, dev, &digest_list,
|
||||
|
@ -569,11 +552,36 @@ int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog,
|
|||
bool ignore_existing_log)
|
||||
{
|
||||
struct tcg2_event_log log;
|
||||
int rc;
|
||||
int rc, i;
|
||||
|
||||
elog->log_position = 0;
|
||||
elog->found = false;
|
||||
|
||||
/*
|
||||
* Make sure U-Boot is compiled with all the active PCRs
|
||||
* since we are about to create an EventLog and we won't
|
||||
* measure anything if the PCR banks don't match
|
||||
*/
|
||||
if (!tpm2_check_active_banks(dev)) {
|
||||
log_err("Cannot create EventLog\n");
|
||||
log_err("Mismatch between U-Boot and TPM hash algos\n");
|
||||
log_info("TPM:\n");
|
||||
tpm2_print_active_banks(dev);
|
||||
log_info("U-Boot:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) {
|
||||
const struct digest_info *algo = &hash_algo_list[i];
|
||||
const char *str;
|
||||
|
||||
if (!algo->supported)
|
||||
continue;
|
||||
|
||||
str = tpm2_algorithm_name(algo->hash_alg);
|
||||
if (str)
|
||||
log_info("%s\n", str);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = tcg2_platform_get_log(dev, (void **)&log.log, &log.log_size);
|
||||
if (!rc) {
|
||||
log.log_position = 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue