ACK: [PATCH][V2] tpmevlogdump: add function for dumping tpm event log
Alex Hung
alex.hung at canonical.com
Tue Jul 7 03:41:02 UTC 2020
On 2020-07-06 12:14 a.m., Ivan Hu wrote:
> The tpm event log define in "TCG PC Client Specific Platform Firmware Profile
> Specification" chapter 9.
> https://trustedcomputinggroup.org/resource/pc-client-specific-platform-firmware-profile-specification/
>
> Signed-off-by: Ivan Hu <ivan.hu at canonical.com>
> ---
> src/Makefile.am | 1 +
> src/lib/include/fwts_tpm.h | 172 ++++++++++
> src/tpm/tpmevlogdump/tpmevlogdump.c | 473 ++++++++++++++++++++++++++++
> 3 files changed, 646 insertions(+)
> create mode 100644 src/lib/include/fwts_tpm.h
> create mode 100644 src/tpm/tpmevlogdump/tpmevlogdump.c
>
> diff --git a/src/Makefile.am b/src/Makefile.am
> index b0e51dd8..19ae7a05 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -183,6 +183,7 @@ fwts_SOURCES = main.c \
> pci/aspm/aspm.c \
> pci/crs/crs.c \
> pci/maxreadreq/maxreadreq.c \
> + tpm/tpmevlogdump/tpmevlogdump.c \
> uefi/csm/csm.c \
> uefi/uefidump/uefidump.c \
> uefi/uefirttime/uefirttime.c \
> diff --git a/src/lib/include/fwts_tpm.h b/src/lib/include/fwts_tpm.h
> new file mode 100644
> index 00000000..6e32e334
> --- /dev/null
> +++ b/src/lib/include/fwts_tpm.h
> @@ -0,0 +1,172 @@
> +/*
> + * Copyright (C) 2020 Canonical
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
> + *
> + */
> +
> +#ifndef __FWTS_TPM_H__
> +#define __FWTS_TPM_H__
> +
> +PRAGMA_PUSH
> +PRAGMA_PACK_WARN_OFF
> +
> +#define FWTS_TPM_EVENTLOG_V2_SIGNATURE "Spec ID Event03"
> +
> +/* define from tpm2-tss */
> +#define TPM2_SHA_DIGEST_SIZE 20
> +#define TPM2_SHA1_DIGEST_SIZE 20
> +#define TPM2_SHA256_DIGEST_SIZE 32
> +#define TPM2_SHA384_DIGEST_SIZE 48
> +#define TPM2_SHA512_DIGEST_SIZE 64
> +
> +typedef uint16_t TPM2_ALG_ID;
> +#define TPM2_ALG_ERROR ((TPM2_ALG_ID) 0x0000)
> +#define TPM2_ALG_RSA ((TPM2_ALG_ID) 0x0001)
> +#define TPM2_ALG_TDES ((TPM2_ALG_ID) 0x0003)
> +#define TPM2_ALG_SHA ((TPM2_ALG_ID) 0x0004)
> +#define TPM2_ALG_SHA1 ((TPM2_ALG_ID) 0x0004)
> +#define TPM2_ALG_HMAC ((TPM2_ALG_ID) 0x0005)
> +#define TPM2_ALG_AES ((TPM2_ALG_ID) 0x0006)
> +#define TPM2_ALG_MGF1 ((TPM2_ALG_ID) 0x0007)
> +#define TPM2_ALG_KEYEDHASH ((TPM2_ALG_ID) 0x0008)
> +#define TPM2_ALG_XOR ((TPM2_ALG_ID) 0x000A)
> +#define TPM2_ALG_SHA256 ((TPM2_ALG_ID) 0x000B)
> +#define TPM2_ALG_SHA384 ((TPM2_ALG_ID) 0x000C)
> +#define TPM2_ALG_SHA512 ((TPM2_ALG_ID) 0x000D)
> +#define TPM2_ALG_NULL ((TPM2_ALG_ID) 0x0010)
> +#define TPM2_ALG_SM3_256 ((TPM2_ALG_ID) 0x0012)
> +#define TPM2_ALG_SM4 ((TPM2_ALG_ID) 0x0013)
> +#define TPM2_ALG_RSASSA ((TPM2_ALG_ID) 0x0014)
> +#define TPM2_ALG_RSAES ((TPM2_ALG_ID) 0x0015)
> +#define TPM2_ALG_RSAPSS ((TPM2_ALG_ID) 0x0016)
> +#define TPM2_ALG_OAEP ((TPM2_ALG_ID) 0x0017)
> +#define TPM2_ALG_ECDSA ((TPM2_ALG_ID) 0x0018)
> +#define TPM2_ALG_ECDH ((TPM2_ALG_ID) 0x0019)
> +#define TPM2_ALG_ECDAA ((TPM2_ALG_ID) 0x001A)
> +#define TPM2_ALG_SM2 ((TPM2_ALG_ID) 0x001B)
> +#define TPM2_ALG_ECSCHNORR ((TPM2_ALG_ID) 0x001C)
> +#define TPM2_ALG_ECMQV ((TPM2_ALG_ID) 0x001D)
> +#define TPM2_ALG_KDF1_SP800_56A ((TPM2_ALG_ID) 0x0020)
> +#define TPM2_ALG_KDF2 ((TPM2_ALG_ID) 0x0021)
> +#define TPM2_ALG_KDF1_SP800_108 ((TPM2_ALG_ID) 0x0022)
> +#define TPM2_ALG_ECC ((TPM2_ALG_ID) 0x0023)
> +#define TPM2_ALG_SYMCIPHER ((TPM2_ALG_ID) 0x0025)
> +#define TPM2_ALG_CAMELLIA ((TPM2_ALG_ID) 0x0026)
> +#define TPM2_ALG_CMAC ((TPM2_ALG_ID) 0x003F)
> +#define TPM2_ALG_CTR ((TPM2_ALG_ID) 0x0040)
> +#define TPM2_ALG_SHA3_256 ((TPM2_ALG_ID) 0x0027)
> +#define TPM2_ALG_SHA3_384 ((TPM2_ALG_ID) 0x0028)
> +#define TPM2_ALG_SHA3_512 ((TPM2_ALG_ID) 0x0029)
> +#define TPM2_ALG_OFB ((TPM2_ALG_ID) 0x0041)
> +#define TPM2_ALG_CBC ((TPM2_ALG_ID) 0x0042)
> +#define TPM2_ALG_CFB ((TPM2_ALG_ID) 0x0043)
> +#define TPM2_ALG_ECB ((TPM2_ALG_ID) 0x0044)
> +
> +/*
> + * define from TCG PC Client Platform Firmware Profile Specification
> + * https://trustedcomputinggroup.org/resource/pc-client-specific-platform-firmware-profile-specification/
> + */
> +
> +typedef enum {
> + EV_PREBOOT_CERT = 0x00000000,
> + EV_POST_CODE = 0x00000001,
> + EV_UNUSED = 0x00000002,
> + EV_NO_ACTION = 0x00000003,
> + EV_SEPARATOR = 0x00000004,
> + EV_ACTION = 0x00000005,
> + EV_EVENT_TAG = 0x00000006,
> + EV_S_CRTM_CONTENTS = 0x00000007,
> + EV_S_CRTM_VERSION = 0x00000008,
> + EV_CPU_MICROCODE = 0x00000009,
> + EV_PLATFORM_CONFIG_FLAGS = 0x0000000a,
> + EV_TABLE_OF_DEVICES = 0x0000000b,
> + EV_COMPACT_HASH = 0x0000000c,
> + EV_IPL = 0x0000000d,
> + EV_IPL_PARTITION_DATA = 0x0000000e,
> + EV_NONHOST_CODE = 0x0000000f,
> + EV_NONHOST_CONFIG = 0x00000010,
> + EV_NONHOST_INFO = 0x00000011,
> + EV_OMIT_BOOT_DEVICE_EVENTS = 0x00000012,
> + EV_EFI_EVENT_BASE = 0x80000000,
> + EV_EFI_VARIABLE_DRIVER_CONFIG = 0x80000001,
> + EV_EFI_VARIABLE_BOOT = 0x80000002,
> + EV_EFI_BOOT_SERVICES_APPLICATION = 0x80000003,
> + EV_EFI_BOOT_SERVICES_DRIVER = 0x80000004,
> + EV_EFI_RUNTIME_SERVICES_DRIVER = 0x80000005,
> + EV_EFI_GPT_EVENT = 0x80000006,
> + EV_EFI_ACTION = 0x80000007,
> + EV_EFI_PLATFORM_FIRMWARE_BLOB = 0x80000008,
> + EV_EFI_HANDOFF_TABLES = 0x80000009,
> + EV_EFI_HCRTM_EVENT = 0x80000010,
> + EV_EFI_VARIABLE_AUTHORITY = 0x800000e0
> +} fwts_tpmlog_event_type;
> +
> +
> +typedef struct {
> + uint32_t pcr_index;
> + uint32_t event_type;
> + uint8_t digest[20];
> + uint32_t event_data_size;
> + uint8_t event[0];
> +} __attribute__ ((packed)) fwts_pc_client_pcr_event;
> +
> +typedef struct {
> +uint16_t algorithm_id;
> +uint16_t digest_size;
> +} __attribute__ ((packed)) fwts_spec_id_event_alg_sz;
> +
> +typedef struct {
> + uint8_t signature[16];
> + uint32_t platform_class;
> + uint8_t spec_version_minor;
> + uint8_t spec_version_major;
> + uint8_t spec_errata;
> + uint8_t uintn_size;
> + uint32_t number_of_alg;
> +/*
> + * Below items are not fix sizes, skip to define them
> + * but it should be calculated when evaluate the
> + * struct size.
> + */
> +
> +/*
> + fwts_spec_id_event_alg_sz digest_sizes[0];
> + uint8_t vendor_info_size;
> + uint8_t vendor_info[0];
> +*/
> +} __attribute__ ((packed)) fwts_efi_spec_id_event;
> +
> +
> +typedef struct {
> + uint32_t pcr_index;
> + uint32_t event_type;
> + uint32_t digests_count;
> +/*
> + * Below items are not fix size, skip to define them
> + * but it should be calculated when evaluate the
> + * struct size.
> + */
> +
> +/*
> + uint8_t digests[0];
> + uint32_t event_size;
> + uint8_t event[eventSize];
> +*/
> +} __attribute__ ((packed)) fwts_tcg_pcr_event2;
> +
> +PRAGMA_POP
> +
> +#endif
> diff --git a/src/tpm/tpmevlogdump/tpmevlogdump.c b/src/tpm/tpmevlogdump/tpmevlogdump.c
> new file mode 100644
> index 00000000..4a6276b3
> --- /dev/null
> +++ b/src/tpm/tpmevlogdump/tpmevlogdump.c
> @@ -0,0 +1,473 @@
> +/*
> + * Copyright (C) 2020 Canonical
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
> + *
> + */
> +#include "fwts.h"
> +
> +#include <sys/types.h>
> +#include <dirent.h>
> +#include <errno.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +
> +#include "fwts_tpm.h"
> +
> +#define FWTS_TPM_LOG_DIR_PATH "/sys/kernel/security"
> +
> +
> +static void tpmevlogdump_data_hexdump(fwts_framework *fw, uint8_t *data, size_t size, char *str)
> +{
> + size_t i;
> +
> + fwts_log_info_verbatim(fw, "%s: ", str);
> + for (i = 0; i < size; i += 16) {
> + char buffer[128];
> + size_t left = size - i;
> +
> + fwts_dump_raw_data(buffer, sizeof(buffer), data + i, i, left > 16 ? 16 : left);
> + fwts_log_info_verbatim(fw, "%s", buffer + 2);
> + }
> +}
> +
> +static char *tpmevlogdump_evtype_to_string (fwts_tpmlog_event_type event_type)
> +{
> +
> + char *str;
> +
> + switch (event_type) {
> + case EV_PREBOOT_CERT:
> + str = "EV_PREBOOT_CERT";
> + break;
> + case EV_POST_CODE:
> + str = "EV_POST_CODE";
> + break;
> + case EV_UNUSED:
> + str = "EV_UNUSED";
> + break;
> + case EV_NO_ACTION:
> + str = "EV_NO_ACTION";
> + break;
> + case EV_SEPARATOR:
> + str = "EV_SEPARATOR";
> + break;
> + case EV_ACTION:
> + str = "EV_ACTION";
> + break;
> + case EV_EVENT_TAG:
> + str = "EV_EVENT_TAG";
> + break;
> + case EV_S_CRTM_CONTENTS:
> + str = "EV_S_CRTM_CONTENTS";
> + break;
> + case EV_S_CRTM_VERSION:
> + str = "EV_S_CRTM_VERSION";
> + break;
> + case EV_CPU_MICROCODE:
> + str = "EV_CPU_MICROCODE";
> + break;
> + case EV_PLATFORM_CONFIG_FLAGS:
> + str = "EV_PLATFORM_CONFIG_FLAGS";
> + break;
> + case EV_TABLE_OF_DEVICES:
> + str = "EV_TABLE_OF_DEVICES";
> + break;
> + case EV_IPL:
> + str = "EV_IPL";
> + break;
> + case EV_IPL_PARTITION_DATA:
> + str = "EV_IPL_PARTITION_DATA";
> + break;
> + case EV_NONHOST_CODE:
> + str = "EV_NONHOST_CODE";
> + break;
> + case EV_NONHOST_CONFIG:
> + str = "EV_NONHOST_CONFIG";
> + break;
> + case EV_NONHOST_INFO:
> + str = "EV_NONHOST_INFO";
> + break;
> + case EV_OMIT_BOOT_DEVICE_EVENTS:
> + str = "EV_OMIT_BOOT_DEVICE_EVENTS";
> + break;
> + case EV_EFI_EVENT_BASE:
> + str = "EV_EFI_EVENT_BASE";
> + break;
> + case EV_EFI_VARIABLE_DRIVER_CONFIG:
> + str = "EV_EFI_VARIABLE_DRIVER_CONFIG";
> + break;
> + case EV_EFI_VARIABLE_BOOT:
> + str = "EV_EFI_VARIABLE_BOOT";
> + break;
> + case EV_EFI_BOOT_SERVICES_APPLICATION:
> + str = "EV_EFI_BOOT_SERVICES_APPLICATION";
> + break;
> + case EV_EFI_BOOT_SERVICES_DRIVER:
> + str = "EV_EFI_BOOT_SERVICES_DRIVER";
> + break;
> + case EV_EFI_RUNTIME_SERVICES_DRIVER:
> + str = "EV_EFI_RUNTIME_SERVICES_DRIVER";
> + break;
> + case EV_EFI_GPT_EVENT:
> + str = "EV_EFI_GPT_EVENT";
> + break;
> + case EV_EFI_ACTION:
> + str = "EV_EFI_ACTION";
> + break;
> + case EV_EFI_PLATFORM_FIRMWARE_BLOB:
> + str = "EV_EFI_PLATFORM_FIRMWARE_BLOB";
> + break;
> + case EV_EFI_HANDOFF_TABLES:
> + str = "EV_EFI_HANDOFF_TABLES";
> + break;
> + case EV_EFI_HCRTM_EVENT:
> + str = "EV_EFI_HCRTM_EVENT";
> + break;
> + case EV_EFI_VARIABLE_AUTHORITY:
> + str = "EV_EFI_VARIABLE_AUTHORITY";
> + break;
> + default:
> + str = "Unknown";
> + break;
> + }
> +
> + return str;
> +}
> +
> +static char *tpmevlogdump_hash_to_string (TPM2_ALG_ID hash)
> +{
> +
> + char *str;
> +
> + switch (hash) {
> + case TPM2_ALG_SHA1:
> + str = "SHA1";
> + break;
> + case TPM2_ALG_SHA256:
> + str = "SHA256";
> + break;
> + case TPM2_ALG_SHA384:
> + str = "SHA384";
> + break;
> + case TPM2_ALG_SHA512:
> + str = "SHA512";
> + break;
> + default:
> + str = "Unknown";
> + break;
> + }
> +
> + return str;
> +}
> +
> +static uint8_t tpmevlogdump_get_hash_size (TPM2_ALG_ID hash)
> +{
> + uint8_t sz;
> +
> + switch (hash) {
> + case TPM2_ALG_SHA1:
> + sz = TPM2_SHA1_DIGEST_SIZE;
> + break;
> + case TPM2_ALG_SHA256:
> + sz = TPM2_SHA256_DIGEST_SIZE;
> + break;
> + case TPM2_ALG_SHA384:
> + sz = TPM2_SHA384_DIGEST_SIZE;
> + break;
> + case TPM2_ALG_SHA512:
> + sz = TPM2_SHA512_DIGEST_SIZE;
> + break;
> + default:
> + sz = 0;
> + break;
> + }
> +
> + return sz;
> +}
> +
> +static size_t tpmevlogdump_specid_event_dump(fwts_framework *fw, uint8_t *data, size_t len)
> +{
> +
> + uint32_t i;
> + size_t len_remain = len;
> + uint8_t *pdata = data;
> + char *str_info;
> +
> + /* check the data length for dumping */
> + if (len_remain < sizeof(fwts_pc_client_pcr_event)) {
> + fwts_log_info(fw, "Cannot get enough length for dumping data.");
> + return 0;
> + }
> + fwts_pc_client_pcr_event *pc_event = (fwts_pc_client_pcr_event *)pdata;
> + fwts_log_info_verbatim(fw, "PCRIndex: 0x%8.8" PRIx32, pc_event->pcr_index);
> + str_info = tpmevlogdump_evtype_to_string(pc_event->event_type);
> + fwts_log_info_verbatim(fw, "EventType: 0x%8.8" PRIx32 "(%s)", pc_event->event_type, str_info);
> + tpmevlogdump_data_hexdump(fw, pc_event->digest, sizeof(pc_event->digest), "Digest");
> + fwts_log_info_verbatim(fw, "EventSize: 0x%8.8" PRIx32, pc_event->event_data_size);
> +
> + pdata += sizeof(fwts_pc_client_pcr_event);
> + len_remain -= sizeof(fwts_pc_client_pcr_event);
> +
> + /* check the data length for dumping */
> + if (len_remain < sizeof(fwts_efi_spec_id_event)) {
> + fwts_log_info(fw, "Cannot get enough length for dumping data.");
> + return 0;
> + }
> + fwts_efi_spec_id_event *specid_evcent = (fwts_efi_spec_id_event *)pdata;
> + fwts_log_info_verbatim(fw, "EfiSpecIdEvent:");
> + fwts_log_info_verbatim(fw, " Signature: %s", (char *)specid_evcent->signature);
> + fwts_log_info_verbatim(fw, " platformClass: 0x%8.8" PRIx32, specid_evcent->platform_class);
> + fwts_log_info_verbatim(fw, " specVersionMinor: 0x%" PRIx8, specid_evcent->spec_version_minor);
> + fwts_log_info_verbatim(fw, " specVersionMajor: 0x%" PRIx8, specid_evcent->platform_class);
> + fwts_log_info_verbatim(fw, " specErrata: 0x%" PRIx8, specid_evcent->spec_errata);
> + fwts_log_info_verbatim(fw, " uintnSize: 0x%" PRIx8, specid_evcent->uintn_size);
> + fwts_log_info_verbatim(fw, " NumberOfAlgorithms: 0x%8.8" PRIx32, specid_evcent->number_of_alg);
> +
> + pdata += sizeof(fwts_efi_spec_id_event);
> + len_remain -= sizeof(fwts_efi_spec_id_event);
> + fwts_spec_id_event_alg_sz *alg_sz = (fwts_spec_id_event_alg_sz *)pdata;
> + for (i = 0; i < specid_evcent->number_of_alg; i++) {
> + /* check the data length for dumping */
> + if (len_remain < sizeof(fwts_spec_id_event_alg_sz)) {
> + fwts_log_info(fw, "Cannot get enough length for dumping data.");
> + return 0;
> + }
> + str_info = tpmevlogdump_hash_to_string(alg_sz->algorithm_id);
> + fwts_log_info_verbatim(fw, " digestSizes[%d].AlgId: 0x%4.4" PRIx16 "(%s)", i, alg_sz->algorithm_id, str_info);
> + fwts_log_info_verbatim(fw, " digestSizes[%d].DigestSize: %" PRIu16, i, alg_sz->digest_size);
> + pdata += sizeof(fwts_spec_id_event_alg_sz);
> + len_remain -= sizeof(fwts_spec_id_event_alg_sz);
> + alg_sz = (fwts_spec_id_event_alg_sz *)pdata;
> + }
> +
> + uint8_t vendor_info_size = *(uint8_t *)pdata;
> + fwts_log_info_verbatim(fw, " vendorInfoSize: 0x%" PRIx8, vendor_info_size);
> + pdata += sizeof(vendor_info_size);
> + len_remain -= sizeof(vendor_info_size);
> + if (vendor_info_size > 0) {
> + /* check the data length for dumping */
> + if (len_remain < vendor_info_size) {
> + fwts_log_info(fw, "Cannot get enough length for dumping data.");
> + return 0;
> + }
> + tpmevlogdump_data_hexdump(fw, pdata, vendor_info_size, " vendorInfo");
> + len_remain -= vendor_info_size;
> + }
> +
> + return len_remain;
> +}
> +
> +static size_t tpmevlogdump_event_v2_dump(fwts_framework *fw, uint8_t *data, size_t len)
> +{
> + uint32_t i;
> + uint8_t *pdata = data;
> + size_t len_remain = len;
> + char *str_info;
> +
> + /* check the data length for dumping */
> + if (len_remain < sizeof(fwts_tcg_pcr_event2)) {
> + fwts_log_info(fw, "Cannot get enough length for dumping data.");
> + return 0;
> + }
> + fwts_tcg_pcr_event2 *pcr_event2 = (fwts_tcg_pcr_event2 *)pdata;
> + fwts_log_info_verbatim(fw, "PCRIndex: 0x%8.8" PRIx32, pcr_event2->pcr_index);
> + str_info = tpmevlogdump_evtype_to_string(pcr_event2->event_type);
> + fwts_log_info_verbatim(fw, "EventType: 0x%8.8" PRIx32 "(%s)", pcr_event2->event_type, str_info);
> + fwts_log_info_verbatim(fw, "Digests Count : 0x%8.8" PRIx32, pcr_event2->digests_count);
> + pdata += sizeof(fwts_tcg_pcr_event2);
> + len_remain -= sizeof(fwts_tcg_pcr_event2);
> + for (i = 0; i < pcr_event2->digests_count; i++) {
> +
> + uint8_t hash_size = 0;
> + TPM2_ALG_ID alg_id = *(TPM2_ALG_ID *)pdata;
> +
> + /* check the data length for dumping */
> + if (len_remain < sizeof(TPM2_ALG_ID)) {
> + fwts_log_info(fw, "Cannot get enough length for dumping data.");
> + return 0;
> + }
> + str_info = tpmevlogdump_hash_to_string(alg_id);
> + fwts_log_info_verbatim(fw, " Digests[%d].AlgId: 0x%4.4" PRIx16 "(%s)", i, alg_id, str_info);
> + hash_size = tpmevlogdump_get_hash_size(alg_id);
> + if (!hash_size) {
> + fwts_log_info(fw, "Unknown hash algorithm. Aborted.");
> + return 0;
> + }
> + pdata += sizeof(TPM2_ALG_ID);
> + len_remain -= sizeof(TPM2_ALG_ID);
> + /* check the data length for dumping */
> + if (len_remain < sizeof(TPM2_ALG_ID)) {
> + fwts_log_info(fw, "Cannot get enough length for dumping data.");
> + return 0;
> + }
> + tpmevlogdump_data_hexdump(fw, pdata, hash_size, " Digest");
> + pdata += hash_size;
> + len_remain -= hash_size;
> + }
> +
> + uint32_t event_size = *(uint32_t *)pdata;
> +
> + /* check the data length for dumping */
> + if (len_remain < event_size + sizeof(event_size)) {
> + fwts_log_info(fw, "Cannot get enough length for dumping data.");
> + return 0;
> + }
> + pdata += sizeof(event_size);
> + len_remain -= sizeof(event_size);
> +
> + fwts_log_info_verbatim(fw, " EventSize: %" PRIu32, event_size);
> + if (event_size > 0) {
> + tpmevlogdump_data_hexdump(fw, pdata, event_size, " Event");
> + len_remain -= event_size;
> + }
> +
> + return len_remain;
> +}
> +
> +static void tpmevlogdump_parser(fwts_framework *fw, uint8_t *data, size_t len)
> +{
> + size_t t_len = len;
> + size_t len_remain = 0;
> + uint8_t *pdata = data;
> +
> + len_remain = tpmevlogdump_specid_event_dump(fw, pdata, t_len);
> + fwts_log_nl(fw);
> + pdata += (t_len - len_remain);
> + while (len_remain > 0) {
> + t_len = len_remain;
> + len_remain = tpmevlogdump_event_v2_dump(fw, pdata, t_len);
> + pdata += (t_len - len_remain);
> + fwts_log_nl(fw);
> + }
> + return;
> +}
> +
> +static uint8_t *tpmevlogdump_load_file(const int fd, size_t *length)
> +{
> + uint8_t *ptr = NULL, *tmp;
> + size_t size = 0;
> + char buffer[4096];
> +
> + *length = 0;
> +
> + for (;;) {
> + ssize_t n = read(fd, buffer, sizeof(buffer));
> +
> + if (n == 0)
> + break;
> + if (n < 0) {
> + if (errno != EINTR && errno != EAGAIN) {
> + free(ptr);
> + return NULL;
> + }
> + continue;
> + }
> + if (n > (ssize_t)sizeof(buffer))
> + goto err;
> + if (size + n > 0xffffffff)
> + goto err;
> +
> + if ((tmp = (uint8_t*)realloc(ptr, size + n + 1)) == NULL) {
> + free(ptr);
> + return NULL;
> + }
> + ptr = tmp;
> + memcpy(ptr + size, buffer, n);
> + size += n;
> + }
> +
> + if (!ptr || !size)
> + goto err_no_data;
> +
> + *length = size;
> + return ptr;
> +
> +err:
> + free(ptr);
> +err_no_data:
> + *length = 0;
> + return NULL;
> +}
> +
> +static int tpmevlogdump_test1(fwts_framework *fw)
> +{
> + DIR *dir;
> + struct dirent *tpmdir;
> + bool tpm_logfile_found = false;
> +
> + if (!(dir = opendir(FWTS_TPM_LOG_DIR_PATH))) {
> + fwts_log_info(fw, "Cannot find the tpm event log. Aborted.");
> + return FWTS_ABORTED;
> + }
> +
> + do {
> + tpmdir = readdir(dir);
> + if (tpmdir && strstr(tpmdir->d_name, "tpm")) {
> + char path[PATH_MAX];
> + uint8_t *data;
> + int fd;
> + size_t length;
> +
> + fwts_log_nl(fw);
> + fwts_log_info_verbatim(fw, "%s", tpmdir->d_name);
> +
> + snprintf(path, sizeof(path), FWTS_TPM_LOG_DIR_PATH "/%s/binary_bios_measurements", tpmdir->d_name);
> +
> + if ((fd = open(path, O_RDONLY)) >= 0) {
> + data = tpmevlogdump_load_file(fd, &length);
> + tpm_logfile_found = true;
> + if (data == NULL) {
> + fwts_log_info(fw, "Cannot load the tpm event logs. Aborted.");
> + closedir(dir);
> + return FWTS_ABORTED;
> + } else {
> + /* check if the TPM2 eventlog */
> + if (strstr((char *)(data + sizeof(fwts_pc_client_pcr_event)), FWTS_TPM_EVENTLOG_V2_SIGNATURE))
> + tpmevlogdump_parser(fw, data, length);
> + else {
> + fwts_log_info(fw, "Cannot find the tpm2 event log. Aborted.");
> + free(data);
> + closedir(dir);
> + return FWTS_ABORTED;
> + }
> + free(data);
> + }
> + close(fd);
> + }
> + }
> + } while (tpmdir);
> +
> + if (!tpm_logfile_found) {
> + fwts_log_info(fw, "Cannot find the tpm event log. Aborted.");
> + closedir(dir);
> + return FWTS_ABORTED;
> + }
> +
> + closedir(dir);
> + return FWTS_OK;
> +}
> +
> +static fwts_framework_minor_test tpmevlogdump_tests[] = {
> + { tpmevlogdump_test1, "Dump Tpm2 Event Log." },
> + { NULL, NULL }
> +};
> +
> +static fwts_framework_ops tpmevlogdump_ops = {
> + .description = "Dump Tpm2 Event Log.",
> + .minor_tests = tpmevlogdump_tests
> +};
> +
> +FWTS_REGISTER("tpmevlogdump", &tpmevlogdump_ops, FWTS_TEST_ANYTIME, FWTS_FLAG_UTILS | FWTS_FLAG_ROOT_PRIV)
>
Acked-by: Alex Hung <alex.hung at canonical.com>
More information about the fwts-devel
mailing list