• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) International Business Machines  Corp., 2008
3  *
4  * Authors:
5  * Reiner Sailer <sailer@watson.ibm.com>
6  * Mimi Zohar <zohar@us.ibm.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation, version 2 of the
11  * License.
12  *
13  * File: ima_measure.c
14  *
15  * Calculate the SHA1 aggregate-pcr value based on the IMA runtime
16  * binary measurements.
17  */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include "config.h"
26 #include "test.h"
27 #if HAVE_OPENSSL_SHA_H
28 #include <openssl/sha.h>
29 #endif
30 
31 #define TCG_EVENT_NAME_LEN_MAX	255
32 
33 char *TCID = "ima_measure";
34 int TST_TOTAL = 1;
35 
36 static int verbose;
37 
38 #define print_info(format, arg...) \
39 	if (verbose) \
40 		printf(format, ##arg)
41 
42 #if HAVE_OPENSSL_SHA_H
43 
44 static u_int8_t zero[SHA_DIGEST_LENGTH];
45 static u_int8_t fox[SHA_DIGEST_LENGTH];
46 
47 struct event {
48 	struct {
49 		u_int32_t pcr;
50 		u_int8_t digest[SHA_DIGEST_LENGTH];
51 		u_int32_t name_len;
52 	} header;
53 	char name[TCG_EVENT_NAME_LEN_MAX + 1];
54 	struct {
55 		u_int8_t digest[SHA_DIGEST_LENGTH];
56 		char filename[TCG_EVENT_NAME_LEN_MAX + 1];
57 	} ima_data;
58 	int filename_len;
59 };
60 
display_sha1_digest(u_int8_t * digest)61 static void display_sha1_digest(u_int8_t * digest)
62 {
63 	int i;
64 
65 	for (i = 0; i < 20; i++)
66 		print_info(" %02X", (*(digest + i) & 0xff));
67 }
68 
69 /*
70  * Calculate the sha1 hash of data
71  */
calc_digest(u_int8_t * digest,int len,void * data)72 static void calc_digest(u_int8_t * digest, int len, void *data)
73 {
74 	SHA_CTX c;
75 
76 	/* Calc template hash for an ima entry */
77 	memset(digest, 0, sizeof *digest);
78 	SHA1_Init(&c);
79 	SHA1_Update(&c, data, len);
80 	SHA1_Final(digest, &c);
81 }
82 
verify_template_hash(struct event * template)83 static int verify_template_hash(struct event *template)
84 {
85 	int rc;
86 
87 	rc = memcmp(fox, template->header.digest, sizeof fox);
88 	if (rc != 0) {
89 		u_int8_t digest[SHA_DIGEST_LENGTH];
90 
91 		memset(digest, 0, sizeof digest);
92 		calc_digest(digest, sizeof template->ima_data,
93 			    &template->ima_data);
94 		rc = memcmp(digest, template->header.digest, sizeof digest);
95 		return rc != 0 ? 1 : 0;
96 	}
97 	return 0;
98 }
99 
100 #endif
101 
102 /*
103  * ima_measurements.c - calculate the SHA1 aggregate-pcr value based
104  * on the IMA runtime binary measurements.
105  *
106  * format: ima_measurement [--validate] [--verify] [--verbose]
107  *
108  * --validate: forces validation of the aggregrate pcr value
109  * 	     for an invalidated PCR. Replace all entries in the
110  * 	     runtime binary measurement list with 0x00 hash values,
111  * 	     which indicate the PCR was invalidated, either for
112  * 	     "a time of measure, time of use"(ToMToU) error, or a
113  *	     file open for read was already open for write, with
114  * 	     0xFF's hash value, when calculating the aggregate
115  *	     pcr value.
116  *
117  * --verify: for all IMA template entries in the runtime binary
118  * 	     measurement list, calculate the template hash value
119  * 	     and compare it with the actual template hash value.
120  *	     Return the number of incorrect hash measurements.
121  *
122  * --verbose: For all entries in the runtime binary measurement
123  *	     list, display the template information.
124  *
125  * template info:  list #, PCR-register #, template hash, template name
126  *	IMA info:  IMA hash, filename hint
127  *
128  * Ouput: displays the aggregate-pcr value
129  * Return code: if verification enabled, returns number of verification
130  * 		errors.
131  */
main(int argc,char * argv[])132 int main(int argc, char *argv[])
133 {
134 
135 #if HAVE_OPENSSL_SHA_H
136 	FILE *fp;
137 	struct event template;
138 	u_int8_t pcr[SHA_DIGEST_LENGTH];
139 	int i, count = 0;
140 
141 	int validate = 0;
142 	int verify = 0;
143 
144 	if (argc < 2) {
145 		printf("format: %s binary_runtime_measurements"
146 		       " [--validate] [--verbose] [--verify]\n", argv[0]);
147 		return 1;
148 	}
149 
150 	for (i = 2; i < argc; i++) {
151 		if (strncmp(argv[i], "--validate", 8) == 0)
152 			validate = 1;
153 		if (strncmp(argv[i], "--verbose", 7) == 0)
154 			verbose = 1;
155 		if (strncmp(argv[i], "--verify", 6) == 0)
156 			verify = 1;
157 	}
158 
159 	fp = fopen(argv[1], "r");
160 	if (!fp) {
161 		printf("fn: %s\n", argv[1]);
162 		perror("Unable to open file\n");
163 		return 1;
164 	}
165 	memset(pcr, 0, SHA_DIGEST_LENGTH);	/* initial PCR content 0..0 */
166 	memset(zero, 0, SHA_DIGEST_LENGTH);
167 	memset(fox, 0xff, SHA_DIGEST_LENGTH);
168 
169 	print_info("### PCR HASH                                  "
170 		   "TEMPLATE-NAME\n");
171 	while (fread(&template.header, sizeof template.header, 1, fp)) {
172 		SHA_CTX c;
173 
174 		/* Extend simulated PCR with new template digest */
175 		SHA1_Init(&c);
176 		SHA1_Update(&c, pcr, SHA_DIGEST_LENGTH);
177 		if (validate) {
178 			if (memcmp(template.header.digest, zero, 20) == 0)
179 				memset(template.header.digest, 0xFF, 20);
180 		}
181 		SHA1_Update(&c, template.header.digest, 20);
182 		SHA1_Final(pcr, &c);
183 
184 		print_info("%3d %03u ", count++, template.header.pcr);
185 		display_sha1_digest(template.header.digest);
186 		if (template.header.name_len > TCG_EVENT_NAME_LEN_MAX) {
187 			printf("%d ERROR: event name too long!\n",
188 			       template.header.name_len);
189 			exit(1);
190 		}
191 		memset(template.name, 0, sizeof template.name);
192 		fread(template.name, template.header.name_len, 1, fp);
193 		print_info(" %s ", template.name);
194 
195 		memset(&template.ima_data, 0, sizeof template.ima_data);
196 		fread(&template.ima_data.digest,
197 		      sizeof template.ima_data.digest, 1, fp);
198 		display_sha1_digest(template.ima_data.digest);
199 
200 		fread(&template.filename_len,
201 		      sizeof template.filename_len, 1, fp);
202 		fread(template.ima_data.filename, template.filename_len, 1, fp);
203 		print_info(" %s\n", template.ima_data.filename);
204 
205 		if (verify)
206 			if (verify_template_hash(&template) != 0) {
207 				tst_resm(TFAIL, "Hash failed");
208 			}
209 	}
210 	fclose(fp);
211 
212 	verbose = 1;
213 	print_info("PCRAggr (re-calculated):");
214 	display_sha1_digest(pcr);
215 #else
216 	tst_resm(TCONF, "System doesn't have openssl/sha.h");
217 #endif
218 	tst_exit();
219 }
220