1 /* 2 * Copyright (c) International Business Machines Corp., 2008 3 * 4 * Authors: 5 * Reiner Sailer <sailer (at) watson.ibm.com> 6 * Mimi Zohar <zohar (at) 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 26 #include "config.h" 27 #include "test.h" 28 29 char *TCID = "ima_measure"; 30 31 #if HAVE_LIBCRYPTO 32 #include <openssl/sha.h> 33 34 #define TCG_EVENT_NAME_LEN_MAX 255 35 36 int TST_TOTAL = 1; 37 38 static int verbose; 39 40 #define print_info(format, arg...) \ 41 if (verbose) \ 42 printf(format, ##arg) 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 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 */ 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 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 /* 101 * ima_measurements.c - calculate the SHA1 aggregate-pcr value based 102 * on the IMA runtime binary measurements. 103 * 104 * format: ima_measurement [--validate] [--verify] [--verbose] 105 * 106 * --validate: forces validation of the aggregrate pcr value 107 * for an invalidated PCR. Replace all entries in the 108 * runtime binary measurement list with 0x00 hash values, 109 * which indicate the PCR was invalidated, either for 110 * "a time of measure, time of use"(ToMToU) error, or a 111 * file open for read was already open for write, with 112 * 0xFF's hash value, when calculating the aggregate 113 * pcr value. 114 * 115 * --verify: for all IMA template entries in the runtime binary 116 * measurement list, calculate the template hash value 117 * and compare it with the actual template hash value. 118 * Return the number of incorrect hash measurements. 119 * 120 * --verbose: For all entries in the runtime binary measurement 121 * list, display the template information. 122 * 123 * template info: list #, PCR-register #, template hash, template name 124 * IMA info: IMA hash, filename hint 125 * 126 * Ouput: displays the aggregate-pcr value 127 * Return code: if verification enabled, returns number of verification 128 * errors. 129 */ 130 int main(int argc, char *argv[]) 131 { 132 FILE *fp; 133 struct event template; 134 u_int8_t pcr[SHA_DIGEST_LENGTH]; 135 int i, count = 0; 136 137 int validate = 0; 138 int verify = 0; 139 140 if (argc < 2) { 141 printf("format: %s binary_runtime_measurements" 142 " [--validate] [--verbose] [--verify]\n", argv[0]); 143 return 1; 144 } 145 146 for (i = 2; i < argc; i++) { 147 if (strncmp(argv[i], "--validate", 8) == 0) 148 validate = 1; 149 if (strncmp(argv[i], "--verbose", 7) == 0) 150 verbose = 1; 151 if (strncmp(argv[i], "--verify", 6) == 0) 152 verify = 1; 153 } 154 155 fp = fopen(argv[1], "r"); 156 if (!fp) { 157 printf("fn: %s\n", argv[1]); 158 perror("Unable to open file\n"); 159 return 1; 160 } 161 memset(pcr, 0, SHA_DIGEST_LENGTH); /* initial PCR content 0..0 */ 162 memset(zero, 0, SHA_DIGEST_LENGTH); 163 memset(fox, 0xff, SHA_DIGEST_LENGTH); 164 165 print_info("### PCR HASH " 166 "TEMPLATE-NAME\n"); 167 while (fread(&template.header, sizeof template.header, 1, fp)) { 168 SHA_CTX c; 169 170 /* Extend simulated PCR with new template digest */ 171 SHA1_Init(&c); 172 SHA1_Update(&c, pcr, SHA_DIGEST_LENGTH); 173 if (validate) { 174 if (memcmp(template.header.digest, zero, 20) == 0) 175 memset(template.header.digest, 0xFF, 20); 176 } 177 SHA1_Update(&c, template.header.digest, 20); 178 SHA1_Final(pcr, &c); 179 180 print_info("%3d %03u ", count++, template.header.pcr); 181 display_sha1_digest(template.header.digest); 182 if (template.header.name_len > TCG_EVENT_NAME_LEN_MAX) { 183 printf("%d ERROR: event name too long!\n", 184 template.header.name_len); 185 exit(1); 186 } 187 memset(template.name, 0, sizeof template.name); 188 fread(template.name, template.header.name_len, 1, fp); 189 print_info(" %s ", template.name); 190 191 memset(&template.ima_data, 0, sizeof template.ima_data); 192 fread(&template.ima_data.digest, 193 sizeof template.ima_data.digest, 1, fp); 194 display_sha1_digest(template.ima_data.digest); 195 196 fread(&template.filename_len, 197 sizeof template.filename_len, 1, fp); 198 fread(template.ima_data.filename, template.filename_len, 1, fp); 199 print_info(" %s\n", template.ima_data.filename); 200 201 if (verify) 202 if (verify_template_hash(&template) != 0) { 203 tst_resm(TFAIL, "Hash failed"); 204 } 205 } 206 fclose(fp); 207 208 verbose = 1; 209 print_info("PCRAggr (re-calculated):"); 210 display_sha1_digest(pcr); 211 tst_exit(); 212 } 213 214 #else 215 int main(void) 216 { 217 tst_brkm(TCONF, NULL, "test requires libcrypto and openssl development packages"); 218 } 219 #endif 220