From patchwork Fri Oct 16 12:01:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Hu X-Patchwork-Id: 1383309 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=fwts-devel-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CCPrZ2WTmz9sTD for ; Fri, 16 Oct 2020 23:01:32 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1kTOQF-0000wf-E1; Fri, 16 Oct 2020 12:01:23 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1kTOQC-0000un-1P for fwts-devel@lists.ubuntu.com; Fri, 16 Oct 2020 12:01:20 +0000 Received: from [106.104.70.34] (helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1kTOQA-0002Dh-Ro for fwts-devel@lists.ubuntu.com; Fri, 16 Oct 2020 12:01:19 +0000 From: Ivan Hu To: fwts-devel@lists.ubuntu.com Subject: [PATCH 1/2] lib: fwts_tpm: move some tpm funcitons to lib Date: Fri, 16 Oct 2020 20:01:12 +0800 Message-Id: <20201016120113.29486-1-ivan.hu@canonical.com> X-Mailer: git-send-email 2.17.1 X-BeenThere: fwts-devel@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Firmware Test Suite Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: fwts-devel-bounces@lists.ubuntu.com Sender: "fwts-devel" No function changed.`` Signed-off-by: Ivan Hu Acked-by: Colin Ian King Acked-by: Alex Hung --- src/lib/include/fwts_tpm.h | 3 ++ src/lib/src/Makefile.am | 1 + src/lib/src/fwts_tpm.c | 68 +++++++++++++++++++++++++++++ src/tpm/tpmevlogdump/tpmevlogdump.c | 57 ++++-------------------- 4 files changed, 80 insertions(+), 49 deletions(-) create mode 100644 src/lib/src/fwts_tpm.c diff --git a/src/lib/include/fwts_tpm.h b/src/lib/include/fwts_tpm.h index 6e32e334..07fdb40b 100644 --- a/src/lib/include/fwts_tpm.h +++ b/src/lib/include/fwts_tpm.h @@ -167,6 +167,9 @@ typedef struct { */ } __attribute__ ((packed)) fwts_tcg_pcr_event2; +void fwts_tpm_data_hexdump(fwts_framework *fw, uint8_t *data, size_t size, char *str); +uint8_t fwts_tpm_get_hash_size(TPM2_ALG_ID hash); + PRAGMA_POP #endif diff --git a/src/lib/src/Makefile.am b/src/lib/src/Makefile.am index 4593bb82..2c3c1cb7 100644 --- a/src/lib/src/Makefile.am +++ b/src/lib/src/Makefile.am @@ -107,6 +107,7 @@ libfwts_la_SOURCES = \ fwts_stringextras.c \ fwts_summary.c \ fwts_text_list.c \ + fwts_tpm.c \ fwts_tty.c \ fwts_uefi.c \ fwts_wakealarm.c \ diff --git a/src/lib/src/fwts_tpm.c b/src/lib/src/fwts_tpm.c new file mode 100644 index 00000000..f196ff8c --- /dev/null +++ b/src/lib/src/fwts_tpm.c @@ -0,0 +1,68 @@ +/* + * 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 "fwts_tpm.h" + +/* + * fwts_tpm_data_hexdump + * hex dump of a tpm event log data + */ +void fwts_tpm_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); + } +} + +/* + * fwts_tpm_evlog_type_to_string + * get hash size + */ +uint8_t fwts_tpm_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; +} diff --git a/src/tpm/tpmevlogdump/tpmevlogdump.c b/src/tpm/tpmevlogdump/tpmevlogdump.c index 94bb5cc1..8254554f 100644 --- a/src/tpm/tpmevlogdump/tpmevlogdump.c +++ b/src/tpm/tpmevlogdump/tpmevlogdump.c @@ -26,22 +26,7 @@ #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); - } -} +#define FWTS_TPM_LOG_DIR_PATH "/sys/kernel/security" static char *tpmevlogdump_evtype_to_string (fwts_tpmlog_event_type event_type) { @@ -172,32 +157,6 @@ static char *tpmevlogdump_hash_to_string (TPM2_ALG_ID hash) 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 char *tpmevlogdump_pcrindex_to_string (uint32_t pcr) { @@ -270,7 +229,7 @@ static size_t tpmevlogdump_specid_event_dump(fwts_framework *fw, uint8_t *data, fwts_log_info_verbatim(fw, "PCRIndex: 0x%8.8" PRIx32 "(%s)", pc_event->pcr_index, str_info); 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_tpm_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); @@ -318,7 +277,7 @@ static size_t tpmevlogdump_specid_event_dump(fwts_framework *fw, uint8_t *data, fwts_log_info(fw, "Cannot get enough length for dumping data."); return 0; } - tpmevlogdump_data_hexdump(fw, pdata, vendor_info_size, " vendorInfo"); + fwts_tpm_data_hexdump(fw, pdata, vendor_info_size, " vendorInfo"); len_remain -= vendor_info_size; } @@ -357,7 +316,7 @@ static size_t tpmevlogdump_event_v2_dump(fwts_framework *fw, uint8_t *data, size } 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); + hash_size = fwts_tpm_get_hash_size(alg_id); if (!hash_size) { fwts_log_info(fw, "Unknown hash algorithm. Aborted."); return 0; @@ -369,7 +328,7 @@ static size_t tpmevlogdump_event_v2_dump(fwts_framework *fw, uint8_t *data, size fwts_log_info(fw, "Cannot get enough length for dumping data."); return 0; } - tpmevlogdump_data_hexdump(fw, pdata, hash_size, " Digest"); + fwts_tpm_data_hexdump(fw, pdata, hash_size, " Digest"); pdata += hash_size; len_remain -= hash_size; } @@ -386,7 +345,7 @@ static size_t tpmevlogdump_event_v2_dump(fwts_framework *fw, uint8_t *data, size fwts_log_info_verbatim(fw, " EventSize: %" PRIu32, event_size); if (event_size > 0) { - tpmevlogdump_data_hexdump(fw, pdata, event_size, " Event"); + fwts_tpm_data_hexdump(fw, pdata, event_size, " Event"); len_remain -= event_size; } @@ -435,10 +394,10 @@ static void tpmevlogdump_event_dump(fwts_framework *fw, uint8_t *data, size_t le fwts_log_info_verbatim(fw, "PCRIndex: 0x%8.8" PRIx32 "(%s)", pc_event->pcr_index, str_info); 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_tpm_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); if (pc_event->event_data_size > 0) - tpmevlogdump_data_hexdump(fw, pc_event->event, pc_event->event_data_size, "Event"); + fwts_tpm_data_hexdump(fw, pc_event->event, pc_event->event_data_size, "Event"); pdata += (sizeof(fwts_pc_client_pcr_event) + pc_event->event_data_size); len -= (sizeof(fwts_pc_client_pcr_event) + pc_event->event_data_size); } From patchwork Fri Oct 16 12:01:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Hu X-Patchwork-Id: 1383308 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=fwts-devel-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CCPrZ3QGxz9sTK for ; Fri, 16 Oct 2020 23:01:33 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1kTOQI-0000y2-Hs; Fri, 16 Oct 2020 12:01:26 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1kTOQF-0000x9-Vt for fwts-devel@lists.ubuntu.com; Fri, 16 Oct 2020 12:01:23 +0000 Received: from [106.104.70.34] (helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1kTOQF-0002EN-3S for fwts-devel@lists.ubuntu.com; Fri, 16 Oct 2020 12:01:23 +0000 From: Ivan Hu To: fwts-devel@lists.ubuntu.com Subject: [PATCH 2/2] tpmevlog: add tests for snatic check of the Tpm event log Date: Fri, 16 Oct 2020 20:01:13 +0800 Message-Id: <20201016120113.29486-2-ivan.hu@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201016120113.29486-1-ivan.hu@canonical.com> References: <20201016120113.29486-1-ivan.hu@canonical.com> X-BeenThere: fwts-devel@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Firmware Test Suite Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: fwts-devel-bounces@lists.ubuntu.com Sender: "fwts-devel" Signed-off-by: Ivan Hu --- src/Makefile.am | 1 + src/tpm/tpmevlog/tpmevlog.c | 441 ++++++++++++++++++++++++++++++++++++ 2 files changed, 442 insertions(+) create mode 100644 src/tpm/tpmevlog/tpmevlog.c diff --git a/src/Makefile.am b/src/Makefile.am index 5d78411b..b7f3f7db 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -184,6 +184,7 @@ fwts_SOURCES = main.c \ pci/aspm/aspm.c \ pci/crs/crs.c \ pci/maxreadreq/maxreadreq.c \ + tpm/tpmevlog/tpmevlog.c \ tpm/tpmevlogdump/tpmevlogdump.c \ uefi/csm/csm.c \ uefi/uefidump/uefidump.c \ diff --git a/src/tpm/tpmevlog/tpmevlog.c b/src/tpm/tpmevlog/tpmevlog.c new file mode 100644 index 00000000..1d184fd0 --- /dev/null +++ b/src/tpm/tpmevlog/tpmevlog.c @@ -0,0 +1,441 @@ +/* + * 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 +#include +#include +#include +#include + +#include "fwts_tpm.h" + +#define FWTS_TPM_LOG_DIR_PATH "/sys/kernel/security" + +static int tpmevlog_pcrindex_value_check(fwts_framework *fw, uint32_t pcr) +{ + + if ((pcr > 16) && (pcr != 23)) { + fwts_failed(fw, LOG_LEVEL_HIGH, "PCRIndexValue", + "The PCR Index value is undefined, 0x%8.8" PRIx32 ".", + pcr); + return FWTS_ERROR; + } + + return FWTS_OK; +} + +static int tpmevlog_eventtype_check(fwts_framework *fw, fwts_tpmlog_event_type event_type) +{ + + switch (event_type) { + case EV_PREBOOT_CERT: + case EV_POST_CODE: + case EV_UNUSED: + case EV_NO_ACTION: + case EV_SEPARATOR: + case EV_ACTION: + case EV_EVENT_TAG: + case EV_S_CRTM_CONTENTS: + case EV_S_CRTM_VERSION: + case EV_CPU_MICROCODE: + case EV_PLATFORM_CONFIG_FLAGS: + case EV_TABLE_OF_DEVICES: + case EV_IPL: + case EV_IPL_PARTITION_DATA: + case EV_NONHOST_CODE: + case EV_NONHOST_CONFIG: + case EV_NONHOST_INFO: + case EV_OMIT_BOOT_DEVICE_EVENTS: + case EV_EFI_EVENT_BASE: + case EV_EFI_VARIABLE_DRIVER_CONFIG: + case EV_EFI_VARIABLE_BOOT: + case EV_EFI_BOOT_SERVICES_APPLICATION: + case EV_EFI_BOOT_SERVICES_DRIVER: + case EV_EFI_RUNTIME_SERVICES_DRIVER: + case EV_EFI_GPT_EVENT: + case EV_EFI_ACTION: + case EV_EFI_PLATFORM_FIRMWARE_BLOB: + case EV_EFI_HANDOFF_TABLES: + case EV_EFI_HCRTM_EVENT: + case EV_EFI_VARIABLE_AUTHORITY: + return FWTS_OK; + default: + fwts_failed(fw, LOG_LEVEL_HIGH, "PCREventType", + "The Event Type is undefined, 0x%8.8" PRIx32 ".", + event_type); + return FWTS_ERROR; + } + + return FWTS_OK; +} + +static int tpmevlog_algid_check(fwts_framework *fw, TPM2_ALG_ID hash) +{ + + switch (hash) { + case TPM2_ALG_RSA: + case TPM2_ALG_TDES: + case TPM2_ALG_SHA1: + case TPM2_ALG_HMAC: + case TPM2_ALG_AES: + case TPM2_ALG_MGF1: + case TPM2_ALG_KEYEDHASH: + case TPM2_ALG_XOR: + case TPM2_ALG_SHA256: + case TPM2_ALG_SHA384: + case TPM2_ALG_SHA512: + case TPM2_ALG_NULL: + case TPM2_ALG_SM3_256: + case TPM2_ALG_SM4: + case TPM2_ALG_RSASSA: + case TPM2_ALG_RSAES: + case TPM2_ALG_RSAPSS: + case TPM2_ALG_OAEP: + case TPM2_ALG_ECDSA: + case TPM2_ALG_ECDH: + case TPM2_ALG_ECDAA: + case TPM2_ALG_SM2: + case TPM2_ALG_ECSCHNORR: + case TPM2_ALG_ECMQV: + case TPM2_ALG_KDF1_SP800_56A: + case TPM2_ALG_KDF2: + case TPM2_ALG_KDF1_SP800_108: + case TPM2_ALG_ECC: + case TPM2_ALG_SYMCIPHER: + case TPM2_ALG_CAMELLIA: + case TPM2_ALG_CMAC: + case TPM2_ALG_CTR: + case TPM2_ALG_SHA3_256: + case TPM2_ALG_SHA3_384: + case TPM2_ALG_SHA3_512: + case TPM2_ALG_OFB: + case TPM2_ALG_CBC: + case TPM2_ALG_CFB: + case TPM2_ALG_ECB: + return FWTS_OK; + default: + fwts_failed(fw, LOG_LEVEL_HIGH, "AlgorithmID", + "The AlgorithmID is undefined, 0x%4.4" PRIx16 ".", + hash); + return FWTS_ERROR; + } + + return FWTS_OK; +} + +static int tpmevlog_v2_check(fwts_framework *fw, uint8_t *data, size_t len) +{ + int ret = FWTS_OK; + size_t len_remain = len; + uint8_t *pdata = data; + int i = 0; + uint8_t vendor_info_size = 0; + uint8_t hash_size = 0; + uint32_t event_size = 0; + + /* specid_event_check */ + if (len < sizeof(fwts_pc_client_pcr_event)) { + fwts_failed(fw, LOG_LEVEL_MEDIUM, "SpecidEventLength", + "The length of the Specid event is %zd bytes " + "is smaller than the PCClientPCREvent %zd bytes.", + len_remain, + sizeof(fwts_pc_client_pcr_event)); + return FWTS_ERROR; + } + + fwts_pc_client_pcr_event *pc_event = (fwts_pc_client_pcr_event *)pdata; + ret = tpmevlog_pcrindex_value_check(fw, pc_event->pcr_index); + if (ret != FWTS_OK) + return ret; + ret = tpmevlog_eventtype_check(fw, pc_event->event_type); + if (ret != FWTS_OK) + return ret; + for (i = 0; i < TPM2_SHA1_DIGEST_SIZE; i++) { + if (pc_event->digest[i] != 0) { + fwts_failed(fw, LOG_LEVEL_HIGH, "SpecIdEvDigest", + "The digest filed of SpecId event should be all zero."); + fwts_tpm_data_hexdump(fw, pc_event->digest, sizeof(pc_event->digest), "Digest"); + } + } + + pdata += sizeof(fwts_pc_client_pcr_event); + len_remain -= sizeof(fwts_pc_client_pcr_event); + + /* check the data length specid event */ + if (len_remain < sizeof(fwts_efi_spec_id_event)) { + fwts_failed(fw, LOG_LEVEL_MEDIUM, "SpecidEventLength", + "The length of the Specid event is %zd bytes " + "is smaller than the SpecId event %zd bytes.", + len_remain, + sizeof(fwts_efi_spec_id_event)); + return FWTS_ERROR; + } + + fwts_efi_spec_id_event *specid_evcent = (fwts_efi_spec_id_event *)pdata; + if (strcmp((char *)specid_evcent->signature, FWTS_TPM_EVENTLOG_V2_SIGNATURE) != 0) { + fwts_failed(fw, LOG_LEVEL_HIGH, "SpecIdEvSignature", + "The signature of SpecId event is not the same as expected " + "Spec ID Event03, got %s.", + (char *)specid_evcent->signature); + return FWTS_ERROR; + } + + /* + * Check the platform class value which defined in TCG ACPI Specification, + * 0 for client platforms, 1 for server platforms. + */ + if (specid_evcent->platform_class > 1) { + fwts_failed(fw, LOG_LEVEL_HIGH, "SpecIdEvPlatformClass", + "The PlatformClass value of SpecId event is unexpected " + "0 for client platforms, 1 for server platforms, " + "got 0x%8.8" PRIx32 ".", specid_evcent->platform_class); + return FWTS_ERROR; + } + + if (specid_evcent->uintn_size < 1 || specid_evcent->uintn_size > 2) { + fwts_failed(fw, LOG_LEVEL_HIGH, "SpecIdEvUINTNFields", + "The size of the UINTN fieldsof SpecId event is unexpected " + "0x01 indicates UINT32 and 0x02 indicates UINT64, " + "got 0x%" PRIx8 ".", specid_evcent->uintn_size); + return FWTS_ERROR; + } + + if (specid_evcent->number_of_alg < 1) { + fwts_failed(fw, LOG_LEVEL_HIGH, "SpecIdEvAlgNumber", + "The number of Hash algorithms of SpecId event must " + "be set to a value of 0x01 or greater " + "got 0x%" PRIx8 ".", specid_evcent->number_of_alg); + return FWTS_ERROR; + } + + 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++) { + if (len_remain < sizeof(fwts_spec_id_event_alg_sz)) { + fwts_failed(fw, LOG_LEVEL_MEDIUM, "SpecidEventLength", + "The length of the Specid event is %zd bytes " + "is smaller than AlgorithmSize %zd bytes.", + len_remain, + sizeof(fwts_spec_id_event_alg_sz)); + return FWTS_ERROR; + } + + ret = tpmevlog_algid_check(fw, alg_sz->algorithm_id); + if (ret != FWTS_OK) + return ret; + + 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; + } + + vendor_info_size = *(uint8_t *)pdata; + pdata += sizeof(vendor_info_size); + len_remain -= sizeof(vendor_info_size); + if (vendor_info_size > 0) { + if (len_remain < vendor_info_size) { + fwts_failed(fw, LOG_LEVEL_MEDIUM, "SpecidEventLength", + "The remain length of the Specid event is " + "is too small (%zd bytes) for " + "vendor info size.", + len_remain); + return FWTS_ERROR; + } + len_remain -= vendor_info_size; + pdata += vendor_info_size; + } + + /* Check the Crypto agile log format event */ + while (len_remain > 0) { + if (len_remain < sizeof(fwts_tcg_pcr_event2)) { + fwts_failed(fw, LOG_LEVEL_MEDIUM, "EventV2Length", + "The length of the event2 is %zd bytes " + "is smaller than the tcg pcr event2 %zd bytes.", + len_remain, + sizeof(fwts_tcg_pcr_event2)); + return FWTS_ERROR; + } + + fwts_tcg_pcr_event2 *pcr_event2 = (fwts_tcg_pcr_event2 *)pdata; + ret = tpmevlog_pcrindex_value_check(fw, pcr_event2->pcr_index); + if (ret != FWTS_OK) + return ret; + ret = tpmevlog_eventtype_check(fw, pcr_event2->event_type); + if (ret != FWTS_OK) + return ret; + + pdata += sizeof(fwts_tcg_pcr_event2); + len_remain -= sizeof(fwts_tcg_pcr_event2); + for (i = 0; i < pcr_event2->digests_count; i++) { + + hash_size = 0; + TPM2_ALG_ID alg_id = *(TPM2_ALG_ID *)pdata; + + ret = tpmevlog_algid_check(fw, alg_id); + if (ret != FWTS_OK) + return ret; + + pdata += sizeof(TPM2_ALG_ID); + len_remain -= sizeof(TPM2_ALG_ID); + + hash_size = fwts_tpm_get_hash_size(alg_id); + if (!hash_size) { + fwts_failed(fw, LOG_LEVEL_MEDIUM, "EventV2HashSize", + "The hash sie of the event2 is %zd bytes " + "is smaller than the tcg pcr event2 %zd bytes.", + len_remain, + sizeof(fwts_tcg_pcr_event2)); + return FWTS_ERROR; + } + + pdata += hash_size; + len_remain -= hash_size; + } + + event_size = *(uint32_t *)pdata; + + if (len_remain < event_size) { + fwts_failed(fw, LOG_LEVEL_MEDIUM, "EventV2Length", + "The remain length of the event2 is %zd bytes " + "is smaller than required event2 length %zd bytes.", + len_remain, + sizeof(event_size)); + return FWTS_ERROR; + } + pdata += (event_size + sizeof(event_size)); + len_remain -= (event_size + sizeof(event_size)); + + } + fwts_passed(fw, "Check Tpm crypto agile event log test passed."); + return FWTS_OK; +} + +static uint8_t *tpmevlog_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 tpmevlog_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 = tpmevlog_load_file(fd, &length); + tpm_logfile_found = true; + if (data == NULL) { + fwts_log_info(fw, "Cannot load the tpm event logs. Aborted."); + (void)closedir(dir); + (void)close(fd); + return FWTS_ABORTED; + } else { + /* check if the TPM2 eventlog */ + if (strstr((char *)(data + sizeof(fwts_pc_client_pcr_event)), FWTS_TPM_EVENTLOG_V2_SIGNATURE)) + tpmevlog_v2_check(fw, data, length); + + free(data); + } + (void)close(fd); + } + } + } while (tpmdir); + + (void)closedir(dir); + + if (!tpm_logfile_found) { + fwts_log_info(fw, "Cannot find the tpm event log. Aborted."); + return FWTS_ABORTED; + } + return FWTS_OK; +} + +static fwts_framework_minor_test tpmevlog_tests[] = { + { tpmevlog_test1, "Sanity check Tpm event log." }, + { NULL, NULL } +}; + +static fwts_framework_ops tpmevlog_ops = { + .description = "Sanity check Tpm event log.", + .minor_tests = tpmevlog_tests +}; + +FWTS_REGISTER("tpmevlog", &tpmevlog_ops, FWTS_TEST_ANYTIME, FWTS_FLAG_ROOT_PRIV)