1 /*
2 * Copyright (c) International Business Machines  Corp., 2009
3 *
4 * Authors:
5 * Mimi Zohar <zohar@us.ibm.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, version 2 of the
10 * License.
11 *
12 * File: ima_boot_aggregate.c
13 *
14 * Calculate a SHA1 boot aggregate value based on the TPM
15 * binary_bios_measurements.
16 */
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <limits.h>
25 
26 #include "config.h"
27 #include "test.h"
28 
29 char *TCID = "ima_boot_aggregate";
30 
31 #if HAVE_LIBCRYPTO
32 #include <openssl/sha.h>
33 
34 #define MAX_EVENT_SIZE (1024*1024)
35 #define EVENT_HEADER_SIZE 32
36 #define MAX_EVENT_DATA_SIZE (MAX_EVENT_SIZE - EVENT_HEADER_SIZE)
37 #define NUM_PCRS 8		/*  PCR registers 0-7 in boot aggregate */
38 
39 int TST_TOTAL = 1;
40 
display_sha1_digest(unsigned char * pcr)41 static void display_sha1_digest(unsigned char *pcr)
42 {
43 	int i;
44 
45 	for (i = 0; i < SHA_DIGEST_LENGTH; i++)
46 		printf("%02x", *(pcr + i) & 0xff);
47 	printf("\n");
48 }
49 
main(int argc,char * argv[])50 int main(int argc, char *argv[])
51 {
52 	unsigned char boot_aggregate[SHA_DIGEST_LENGTH];
53 	struct {
54 		struct {
55 			u_int32_t pcr;
56 			u_int32_t type;
57 			u_int8_t digest[SHA_DIGEST_LENGTH];
58 			u_int32_t len;
59 		} header __attribute__ ((packed));
60 		char *data;
61 	} event;
62 	struct {
63 		unsigned char digest[SHA_DIGEST_LENGTH];
64 	} pcr[NUM_PCRS];
65 	FILE *fp;
66 	int i;
67 	int debug = 0;
68 	SHA_CTX c;
69 
70 	if (argc != 2) {
71 		printf("format: %s binary_bios_measurement file\n", argv[0]);
72 		return 1;
73 	}
74 	fp = fopen(argv[1], "r");
75 	if (!fp) {
76 		perror("unable to open pcr file\n");
77 		return 1;
78 	}
79 
80 	/* Initialize psuedo PCR registers 0 - 7 */
81 	for (i = 0; i < NUM_PCRS; i++)
82 		memset(&pcr[i].digest, 0, SHA_DIGEST_LENGTH);
83 
84 	event.data = malloc(MAX_EVENT_DATA_SIZE);
85 	if (!event.data) {
86 		printf("Cannot allocate memory\n");
87 		return 1;
88 	}
89 
90 	/* Extend the pseudo PCRs with the event digest */
91 	while (fread(&event, sizeof(event.header), 1, fp)) {
92 		if (debug) {
93 			printf("%03u ", event.header.pcr);
94 			display_sha1_digest(event.header.digest);
95 		}
96 
97 		if (event.header.pcr < NUM_PCRS) {
98 			SHA1_Init(&c);
99 			SHA1_Update(&c, pcr[event.header.pcr].digest,
100 				    SHA_DIGEST_LENGTH);
101 			SHA1_Update(&c, event.header.digest,
102 				    SHA_DIGEST_LENGTH);
103 			SHA1_Final(pcr[event.header.pcr].digest, &c);
104 		}
105 
106 #if MAX_EVENT_DATA_SIZE < USHRT_MAX
107 		if (event.header.len > MAX_EVENT_DATA_SIZE) {
108 			printf("Error event too long\n");
109 			break;
110 		}
111 #endif
112 		fread(event.data, event.header.len, 1, fp);
113 	}
114 	fclose(fp);
115 	free(event.data);
116 
117 	/* Extend the boot aggregate with the pseudo PCR digest values */
118 	memset(&boot_aggregate, 0, SHA_DIGEST_LENGTH);
119 	SHA1_Init(&c);
120 	for (i = 0; i < NUM_PCRS; i++) {
121 		if (debug) {
122 			printf("PCR-%2.2x: ", i);
123 			display_sha1_digest(pcr[i].digest);
124 		}
125 		SHA1_Update(&c, pcr[i].digest, SHA_DIGEST_LENGTH);
126 	}
127 	SHA1_Final(boot_aggregate, &c);
128 
129 	printf("boot_aggregate:");
130 	display_sha1_digest(boot_aggregate);
131 	tst_exit();
132 }
133 
134 #else
main(void)135 int main(void)
136 {
137 	tst_brkm(TCONF, NULL, "test requires libcrypto and openssl development packages");
138 }
139 #endif
140