1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) International Business Machines Corp., 2009
4 * Copyright (c) 2016-2019 Petr Vorel <pvorel@suse.cz>
5 *
6 * Authors: Mimi Zohar <zohar@us.ibm.com>
7 *
8 * Calculate a SHA1 boot aggregate value based on the TPM 1.2
9 * binary_bios_measurements.
10 */
11
12 #include "config.h"
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <limits.h>
21
22 #include "tst_test.h"
23 #include "tst_safe_stdio.h"
24
25 #if HAVE_LIBCRYPTO
26 #include <openssl/sha.h>
27
28 #define MAX_EVENT_SIZE (1024*1024)
29 #define EVENT_HEADER_SIZE 32
30 #define MAX_EVENT_DATA_SIZE (MAX_EVENT_SIZE - EVENT_HEADER_SIZE)
31 #define NUM_PCRS 8 /* PCR registers 0-7 in boot aggregate */
32
33 static char *debug;
34 static char *file;
35
36 static unsigned char boot_aggregate[SHA_DIGEST_LENGTH];
37
38 static struct {
39 struct {
40 u_int32_t pcr;
41 u_int32_t type;
42 u_int8_t digest[SHA_DIGEST_LENGTH];
43 u_int32_t len;
44 } header __attribute__ ((packed));
45 char *data;
46 } event;
47
48 static struct {
49 unsigned char digest[SHA_DIGEST_LENGTH];
50 } pcr[NUM_PCRS];
51
display_sha1_digest(unsigned char * pcr)52 static void display_sha1_digest(unsigned char *pcr)
53 {
54 int i;
55
56 for (i = 0; i < SHA_DIGEST_LENGTH; i++)
57 printf("%02x", *(pcr + i) & 0xff);
58 printf("\n");
59 }
60
do_test(void)61 static void do_test(void)
62 {
63 FILE *fp;
64 SHA_CTX c;
65 int i;
66
67 if (!file)
68 tst_brk(TBROK, "missing binary_bios_measurement file, specify with -f");
69
70 fp = SAFE_FOPEN(file, "r");
71
72 /* Initialize psuedo PCR registers 0 - 7 */
73 for (i = 0; i < NUM_PCRS; i++)
74 memset(&pcr[i].digest, 0, SHA_DIGEST_LENGTH);
75
76 event.data = malloc(MAX_EVENT_DATA_SIZE);
77 if (!event.data)
78 tst_brk(TBROK, "cannot allocate memory");
79
80 /* Extend the pseudo PCRs with the event digest */
81 while (fread(&event, sizeof(event.header), 1, fp)) {
82 if (debug) {
83 printf("%03u ", event.header.pcr);
84 display_sha1_digest(event.header.digest);
85 }
86
87 if (event.header.pcr < NUM_PCRS) {
88 SHA1_Init(&c);
89 SHA1_Update(&c, pcr[event.header.pcr].digest,
90 SHA_DIGEST_LENGTH);
91 SHA1_Update(&c, event.header.digest,
92 SHA_DIGEST_LENGTH);
93 SHA1_Final(pcr[event.header.pcr].digest, &c);
94 }
95
96 #if MAX_EVENT_DATA_SIZE < USHRT_MAX
97 if (event.header.len > MAX_EVENT_DATA_SIZE) {
98 tst_res(TWARN, "error event too long");
99 break;
100 }
101 #endif
102 fread(event.data, event.header.len, 1, fp);
103 }
104
105 SAFE_FCLOSE(fp);
106 free(event.data);
107
108 /* Extend the boot aggregate with the pseudo PCR digest values */
109 memset(&boot_aggregate, 0, SHA_DIGEST_LENGTH);
110 SHA1_Init(&c);
111 for (i = 0; i < NUM_PCRS; i++) {
112 if (debug) {
113 printf("PCR-%2.2x: ", i);
114 display_sha1_digest(pcr[i].digest);
115 }
116 SHA1_Update(&c, pcr[i].digest, SHA_DIGEST_LENGTH);
117 }
118 SHA1_Final(boot_aggregate, &c);
119
120 printf("sha1:");
121 display_sha1_digest(boot_aggregate);
122 tst_res(TPASS, "found sha1 hash");
123 }
124
125 static struct tst_option options[] = {
126 {"d", &debug, "Enable debug"},
127 {"f:", &file, "binary_bios_measurement file (required)\n"},
128 {NULL, NULL, NULL}
129 };
130
131 static struct tst_test test = {
132 .needs_root = 1,
133 .test_all = do_test,
134 .options = options,
135 };
136
137 #else
138 TST_TEST_TCONF("libcrypto and openssl development packages required");
139 #endif
140