// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) International Business Machines Corp., 2009 * Copyright (c) 2016-2019 Petr Vorel * * Authors: Mimi Zohar * * Calculate a SHA1 boot aggregate value based on the TPM 1.2 * binary_bios_measurements. */ #include "config.h" #include #include #include #include #include #include #include #include #include "tst_test.h" #include "tst_safe_stdio.h" #if HAVE_LIBCRYPTO #include #define MAX_EVENT_SIZE (1024*1024) #define EVENT_HEADER_SIZE 32 #define MAX_EVENT_DATA_SIZE (MAX_EVENT_SIZE - EVENT_HEADER_SIZE) #define NUM_PCRS 8 /* PCR registers 0-7 in boot aggregate */ static char *debug; static char *file; static unsigned char boot_aggregate[SHA_DIGEST_LENGTH]; static struct { struct { u_int32_t pcr; u_int32_t type; u_int8_t digest[SHA_DIGEST_LENGTH]; u_int32_t len; } header __attribute__ ((packed)); char *data; } event; static struct { unsigned char digest[SHA_DIGEST_LENGTH]; } pcr[NUM_PCRS]; static void display_sha1_digest(unsigned char *pcr) { int i; for (i = 0; i < SHA_DIGEST_LENGTH; i++) printf("%02x", *(pcr + i) & 0xff); printf("\n"); } static void do_test(void) { FILE *fp; SHA_CTX c; int i; if (!file) tst_brk(TBROK, "missing binary_bios_measurement file, specify with -f"); fp = SAFE_FOPEN(file, "r"); /* Initialize psuedo PCR registers 0 - 7 */ for (i = 0; i < NUM_PCRS; i++) memset(&pcr[i].digest, 0, SHA_DIGEST_LENGTH); event.data = malloc(MAX_EVENT_DATA_SIZE); if (!event.data) tst_brk(TBROK, "cannot allocate memory"); /* Extend the pseudo PCRs with the event digest */ while (fread(&event, sizeof(event.header), 1, fp)) { if (debug) { printf("%03u ", event.header.pcr); display_sha1_digest(event.header.digest); } if (event.header.pcr < NUM_PCRS) { SHA1_Init(&c); SHA1_Update(&c, pcr[event.header.pcr].digest, SHA_DIGEST_LENGTH); SHA1_Update(&c, event.header.digest, SHA_DIGEST_LENGTH); SHA1_Final(pcr[event.header.pcr].digest, &c); } #if MAX_EVENT_DATA_SIZE < USHRT_MAX if (event.header.len > MAX_EVENT_DATA_SIZE) { tst_res(TWARN, "error event too long"); break; } #endif fread(event.data, event.header.len, 1, fp); } SAFE_FCLOSE(fp); free(event.data); /* Extend the boot aggregate with the pseudo PCR digest values */ memset(&boot_aggregate, 0, SHA_DIGEST_LENGTH); SHA1_Init(&c); for (i = 0; i < NUM_PCRS; i++) { if (debug) { printf("PCR-%2.2x: ", i); display_sha1_digest(pcr[i].digest); } SHA1_Update(&c, pcr[i].digest, SHA_DIGEST_LENGTH); } SHA1_Final(boot_aggregate, &c); printf("sha1:"); display_sha1_digest(boot_aggregate); tst_res(TPASS, "found sha1 hash"); } static struct tst_option options[] = { {"d", &debug, "Enable debug"}, {"f:", &file, "binary_bios_measurement file (required)\n"}, {} }; static struct tst_test test = { .needs_root = 1, .test_all = do_test, .options = options, }; #else TST_TEST_TCONF("libcrypto and openssl development packages required"); #endif