diff options
author | Masahisa Kojima <masahisa.kojima@linaro.org> | 2021-08-13 16:12:39 +0900 |
---|---|---|
committer | Heinrich Schuchardt <xypron.glpk@gmx.de> | 2021-08-14 20:54:41 +0200 |
commit | cfbcf054a323b692e85e73fc2a57400ee92f6b63 (patch) | |
tree | 109598db349ecabe1bb4264c3fef415ba5da33ab /lib | |
parent | 17a50bd689ab7e506c71df0856fed5935cf323d1 (diff) |
efi_loader: add secure boot variable measurement
TCG PC Client PFP spec requires to measure the secure
boot policy before validating the UEFI image.
This commit adds the secure boot variable measurement
of "SecureBoot", "PK", "KEK", "db", "dbx", "dbt", and "dbr".
Note that this implementation assumes that secure boot
variables are pre-configured and not be set/updated in runtime.
Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/efi_loader/efi_tcg2.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 1319a8b3786..db3d6d75865 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -78,6 +78,19 @@ static const struct digest_info hash_algo_list[] = { }, }; +struct variable_info { + u16 *name; + const efi_guid_t *guid; +}; + +static struct variable_info secure_variables[] = { + {L"SecureBoot", &efi_global_variable_guid}, + {L"PK", &efi_global_variable_guid}, + {L"KEK", &efi_global_variable_guid}, + {L"db", &efi_guid_image_security_database}, + {L"dbx", &efi_guid_image_security_database}, +}; + #define MAX_HASH_COUNT ARRAY_SIZE(hash_algo_list) /** @@ -1265,6 +1278,39 @@ free_pool: } /** + * tcg2_measure_event() - common function to add event log and extend PCR + * + * @dev: TPM device + * @pcr_index: PCR index + * @event_type: type of event added + * @size: event size + * @event: event data + * + * Return: status code + */ +static efi_status_t +tcg2_measure_event(struct udevice *dev, u32 pcr_index, u32 event_type, + u32 size, u8 event[]) +{ + struct tpml_digest_values digest_list; + efi_status_t ret; + + ret = tcg2_create_digest(event, size, &digest_list); + if (ret != EFI_SUCCESS) + goto out; + + ret = tcg2_pcr_extend(dev, pcr_index, &digest_list); + if (ret != EFI_SUCCESS) + goto out; + + ret = tcg2_agile_log_append(pcr_index, event_type, &digest_list, + size, event); + +out: + return ret; +} + +/** * efi_append_scrtm_version - Append an S-CRTM EV_S_CRTM_VERSION event on the * eventlog and extend the PCRs * @@ -1295,6 +1341,118 @@ out: } /** + * tcg2_measure_variable() - add variable event log and extend PCR + * + * @dev: TPM device + * @pcr_index: PCR index + * @event_type: type of event added + * @var_name: variable name + * @guid: guid + * @data_size: variable data size + * @data: variable data + * + * Return: status code + */ +static efi_status_t tcg2_measure_variable(struct udevice *dev, u32 pcr_index, + u32 event_type, u16 *var_name, + const efi_guid_t *guid, + efi_uintn_t data_size, u8 *data) +{ + u32 event_size; + efi_status_t ret; + struct efi_tcg2_uefi_variable_data *event; + + event_size = sizeof(event->variable_name) + + sizeof(event->unicode_name_length) + + sizeof(event->variable_data_length) + + (u16_strlen(var_name) * sizeof(u16)) + data_size; + event = malloc(event_size); + if (!event) + return EFI_OUT_OF_RESOURCES; + + guidcpy(&event->variable_name, guid); + event->unicode_name_length = u16_strlen(var_name); + event->variable_data_length = data_size; + memcpy(event->unicode_name, var_name, + (event->unicode_name_length * sizeof(u16))); + if (data) { + memcpy((u16 *)event->unicode_name + event->unicode_name_length, + data, data_size); + } + ret = tcg2_measure_event(dev, pcr_index, event_type, event_size, + (u8 *)event); + free(event); + return ret; +} + +/** + * tcg2_measure_secure_boot_variable() - measure secure boot variables + * + * @dev: TPM device + * + * Return: status code + */ +static efi_status_t tcg2_measure_secure_boot_variable(struct udevice *dev) +{ + u8 *data; + efi_uintn_t data_size; + u32 count, i; + efi_status_t ret; + + count = ARRAY_SIZE(secure_variables); + for (i = 0; i < count; i++) { + /* + * According to the TCG2 PC Client PFP spec, "SecureBoot", + * "PK", "KEK", "db" and "dbx" variables must be measured + * even if they are empty. + */ + data = efi_get_var(secure_variables[i].name, + secure_variables[i].guid, + &data_size); + + ret = tcg2_measure_variable(dev, 7, + EV_EFI_VARIABLE_DRIVER_CONFIG, + secure_variables[i].name, + secure_variables[i].guid, + data_size, data); + free(data); + if (ret != EFI_SUCCESS) + goto error; + } + + /* + * TCG2 PC Client PFP spec says "dbt" and "dbr" are + * measured if present and not empty. + */ + data = efi_get_var(L"dbt", + &efi_guid_image_security_database, + &data_size); + if (data) { + ret = tcg2_measure_variable(dev, 7, + EV_EFI_VARIABLE_DRIVER_CONFIG, + L"dbt", + &efi_guid_image_security_database, + data_size, data); + free(data); + } + + data = efi_get_var(L"dbr", + &efi_guid_image_security_database, + &data_size); + if (data) { + ret = tcg2_measure_variable(dev, 7, + EV_EFI_VARIABLE_DRIVER_CONFIG, + L"dbr", + &efi_guid_image_security_database, + data_size, data); + free(data); + } + +error: + return ret; +} + +/** * efi_tcg2_register() - register EFI_TCG2_PROTOCOL * * If a TPM2 device is available, the TPM TCG2 Protocol is registered @@ -1328,6 +1486,13 @@ efi_status_t efi_tcg2_register(void) tcg2_uninit(); goto fail; } + + ret = tcg2_measure_secure_boot_variable(dev); + if (ret != EFI_SUCCESS) { + tcg2_uninit(); + goto fail; + } + return ret; fail: |