2 * This file is part of the OpenPTS project.
4 * The Initial Developer of the Original Code is International
5 * Business Machines Corporation. Portions created by IBM
6 * Corporation are Copyright (C) 2011 International Business
7 * Machines Corporation. All Rights Reserved.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the Common Public License as published by
11 * IBM Corporation; either version 1 of the License, or (at your option)
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * Common Public License for more details.
19 * You should have received a copy of the Common Public License
20 * along with this program; if not, a copy can be viewed at
21 * http://www.opensource.org/licenses/cpl1.0.php.
25 * \file src/tboot2iml.c
26 * \brief create pseudo IML of tboot, standalone tool
27 * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
29 * cleanup 2011-07-06 SM
35 * cat tests/data/ThinkpadX200_Fedora15_tboot/txt-stat.20110328 | ./src/tboot2iml > tests/data/ThinkpadX200_Fedora15_tboot/eventlog2
36 * ./src/tboot2iml -i tests/data/ThinkpadX200_Fedora15_tboot/txt-stat.20110328 -o tests/data/ThinkpadX200_Fedora15_tboot/eventlog2
37 * ./src/iml2text -i tests/data/ThinkpadX200_Fedora15_tboot/eventlog2
39 * ./src/tboot2iml -v -i tests/data/ThinkpadX200_Fedora15_tboot/txt-stat.20110328 -g tests/data/ThinkpadX200_Fedora15_tboot/grub.conf -p ./tests/data/ThinkpadX200_Fedora15_tboot -o tests/data/ThinkpadX200_Fedora15_tboot/eventlog2
41 * ./src/iml2text -D -v -V -i tests/data/ThinkpadX200_Fedora15_tboot/eventlog2
48 #include <unistd.h> // getopt
50 #include <sys/types.h>
54 #include <arpa/inet.h>
58 #include <openssl/sha.h>
61 #include <openpts_tboot.h>
66 #define MAX_PCRNUM 24 // TPM v1.2
69 #define CHAR_SPACE 0x20
75 unsigned char pcr[MAX_PCRNUM][SHA1_DIGEST_SIZE];
78 void debugPrintHex(char *head, BYTE *data, int num, char *tail) {
82 for (i = 0; i < num; i++) {
83 OUTPUT("%02X", data[i]);
94 for (i = 0;i < MAX_PCRNUM; i ++) {
95 for (j = 0;j < SHA1_DIGEST_SIZE; j ++) {
101 void resetPcrWithSecret(int i, BYTE *digest) {
104 for (j = 0;j < SHA1_DIGEST_SIZE; j ++) {
105 pcr[i][j] = digest[j];
109 void extend(int index, unsigned char* digest) {
113 SHA1_Update(&ctx, &pcr[index][0], SHA1_DIGEST_SIZE);
114 SHA1_Update(&ctx, digest, SHA1_DIGEST_SIZE);
115 SHA1_Final(&pcr[index][0], &ctx);
122 TXTSTAT_SINIT_MLE_DATA,
127 TXTSTAT_LCP_POLICY_HASH,
129 TXTSTAT_VL_MEASUREMENT,
130 TXTSTAT_PCRS_BEFORE_EXTENTING,
131 TXTSTAT_PCRS_AFTER_EXTENTING,
136 BYTE hex2byte(char *buf, int offset) {
141 memcpy(buf2, &buf[offset], 2);
144 tmp = strtol(buf2, &e, 16);
146 return (BYTE) (0xFF & tmp);
151 * parse TXT-stat file
153 int parseTxtStatFile(OPENPTS_TBOOT_CONTEXT *ctx, char *filename) {
155 char line[1024]; // TODO(munetoh)
157 int state = TXTSTAT_START;
158 int next_state = TXTSTAT_START;
161 if (filename != NULL) {
163 if ((fp = fopen(filename, "r")) == NULL) {
164 LOG(LOG_ERR, "parseTxtStatFile - %s file is missing\n", filename);
165 return PTS_FATAL; // TODO
172 while (fgets(line, sizeof(line), fp) != NULL) { // read line
173 // TBOOT: v2 LCP policy data found
174 if (!strncmp(line, "TBOOT: v2 LCP policy data found", 31)) {
175 ctx->lcp_policy_version = 2;
176 DEBUG("lcp_policy_version : 2\n");
180 // TBOOT: sinit_mle_data (@0x799301b8, 0x260):
181 if (!strncmp(line, "TBOOT: sinit_mle_data", 21)) {
182 next_state = TXTSTAT_SINIT_MLE_DATA;
185 if ((state == TXTSTAT_SINIT_MLE_DATA) &&
186 (!strncmp(line, "TBOOT: version:", 17))) {
187 ctx->mle_version = atoi(&line[18]);
188 DEBUG("ctx->mle_version = %d\n", ctx->mle_version);
190 // TBOOT: bios_acm_id:
191 if (!strncmp(line, "TBOOT: bios_acm_id:", 21)) {
192 next_state = TXTSTAT_BIOS_ACM_ID;
194 // 80 00 00 00 20 08 05 15 00 00 2a 40 00 00 00 00 ff ff ff ff
195 if (state == TXTSTAT_BIOS_ACM_ID) {
196 for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
197 ctx->bios_acm_id[j] = 0;
198 ctx->bios_acm_id[j] = hex2byte(line, 1 + j * 3);
200 next_state = TXTSTAT_NA;
201 DEBUG("bios_acm_id\n");
202 // printHex("bios_acm_id ", ctx->bios_acm_id, 20, "\n");
204 // TBOOT: edx_senter_flags: 0x00000000
205 if (!strncmp(line, "TBOOT: edx_senter_flags:", 26)) {
206 for (j = 0; j < 4; j++) {
207 ctx->edx_senter_flags[j] = 0;
208 ctx->edx_senter_flags[j] = hex2byte(line, 29 + j * 2);
210 next_state = TXTSTAT_NA;
211 DEBUG("edx_senter_flags\n");
212 // printHex("edx_senter_flags ", ctx->edx_senter_flags, 4, "\n");
216 // TBOOT: mseg_valid: 0x0
217 // TBOOT: sinit_hash:
218 if (!strncmp(line, "TBOOT: sinit_hash:", 20)) {
219 next_state = TXTSTAT_SINIT_HASH;
221 // d0 29 d1 14 d6 d4 d2 f0 70 98 db 05 85 24 f9 5e a2 7c 72 a5
222 if (state == TXTSTAT_SINIT_HASH) {
223 for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
224 ctx->sinit_hash[j] = 0;
225 ctx->sinit_hash[j] = hex2byte(line, 1 + j * 3);
227 next_state = TXTSTAT_NA;
228 DEBUG("sinit_hash\n");
229 debugPrintHex(" sinit_hash : ", ctx->sinit_hash, 20, "\n");
232 if (!strncmp(line, "TBOOT: mle_hash:", 18)) {
233 next_state = TXTSTAT_MLE_HASH;
235 // 88 43 1c c6 0c 5f 11 5b 29 08 2f 04 43 8d de 94 93 47 62 46
236 if (state == TXTSTAT_MLE_HASH) {
237 for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
238 ctx->mle_hash[j] = 0;
239 ctx->mle_hash[j] = hex2byte(line, 1 + j * 3);
241 next_state = TXTSTAT_NA;
243 debugPrintHex(" mle_hash ", ctx->mle_hash, 20, "\n");
246 if (!strncmp(line, "TBOOT: stm_hash:", 18)) {
247 next_state = TXTSTAT_STM_HASH;
249 // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
250 if (state == TXTSTAT_STM_HASH) {
251 for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
252 ctx->stm_hash[j] = 0;
253 ctx->stm_hash[j] = hex2byte(line, 1 + j * 3);
255 next_state = TXTSTAT_NA;
257 // printHex("stm_hash ", ctx->stm_hash, 20, "\n");
259 // TBOOT: lcp_policy_hash:
260 if (!strncmp(line, "TBOOT: lcp_policy_hash:", 25)) {
261 next_state = TXTSTAT_LCP_POLICY_HASH;
263 // 88 43 1c c6 0c 5f 11 5b 29 08 2f 04 43 8d de 94 93 47 62 46
264 if (state == TXTSTAT_LCP_POLICY_HASH) {
265 for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
266 ctx->lcp_policy_hash[j] = 0;
267 ctx->lcp_policy_hash[j] = hex2byte(line, 1 + j * 3);
269 next_state = TXTSTAT_NA;
270 DEBUG("lcp_policy_hash\n");
271 // printHex("lcp_policy_hash ", ctx->lcp_policy_hash, 20, "\n");
273 // TBOOT: lcp_policy_control: 0x00000000
276 // TBOOT: policy_control: 00000001 (EXTEND_PCR17)
278 if (!strncmp(line, "TBOOT: policy_control:", 24)) {
279 for (j = 0; j < 4; j++) {
280 ctx->pol_control[j] = hex2byte(line, 25 + (3 - j) * 2);
282 DEBUG("pol_control");
283 // printHex("pol_control ", ctx->pol_control, 4, "\n");
286 // TBOOT: pol_hash: 5a 14 3f 34 f5 03 41 ff a2 01 34 0f b8 8e f9 98 73 b7 e0 3d
287 if (!strncmp(line, "TBOOT: pol_hash:", 18)) {
288 for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
289 ctx->pol_hash[j] = 0;
290 ctx->pol_hash[j] = hex2byte(line, 19 + j * 3);
292 DEBUG("pol_hash PCR17");
293 // printHex("pol_hash ", ctx->pol_hash, 20, "\n");
296 // TBOOT: VL measurements:
297 if (!strncmp(line, "TBOOT: VL measurements", 24)) {
298 next_state = TXTSTAT_VL_MEASUREMENT;
300 // TBOOT: PCR 17: a8 21 ff be 39 69 21 f3 bd 8d 79 e7 70 ec 8f 75 41 ba 5c 5e
301 // TBOOT: PCR 18: d2 5c 5b 18 2a 9a 62 ce 15 e4 6d 08 91 9d 4e fc 1b 7c fc ad
302 // TBOOT: PCR 19: 0f 93 a8 2c 3b 3b 20 30 98 61 39 a2 03 2e 38 23 73 3f c6 42
303 if ((state == TXTSTAT_VL_MEASUREMENT) &&
304 (!strncmp(line, "TBOOT: PCR 17:", 18))) {
305 for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
306 ctx->vl_pcr17[j] = 0;
307 ctx->vl_pcr17[j] = hex2byte(line, 19 + j * 3);
310 debugPrintHex(" PCR17 ", ctx->vl_pcr17, 20, "\n");
312 if ((state == TXTSTAT_VL_MEASUREMENT) &&
313 (!strncmp(line, "TBOOT: PCR 18:", 18))) {
314 for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
315 ctx->vl_pcr18[j] = 0;
316 ctx->vl_pcr18[j] = hex2byte(line, 19 + j * 3);
319 debugPrintHex(" PCR18 ", ctx->vl_pcr18, 20, "\n");
321 if ((state == TXTSTAT_VL_MEASUREMENT) &&
322 (!strncmp(line, "TBOOT: PCR 19:", 18))) {
323 for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
324 ctx->vl_pcr19[j] = 0;
325 ctx->vl_pcr19[j] = hex2byte(line, 19 + j * 3);
328 debugPrintHex(" PCR19 ", ctx->vl_pcr19, 20, "\n");
332 // TBOOT: PCRs after extending:
333 if (!strncmp(line, "TBOOT: PCRs after extending:", 28)) {
334 next_state = TXTSTAT_PCRS_AFTER_EXTENTING;
336 // TBOOT: PCR 17: bb 0f 68 4f df 3a 42 b9 24 93 80 6d 5d a5 4e 36 62 c5 c5 52
337 // TBOOT: PCR 18: 5e 24 63 ef f8 ee 13 c3 28 1e 13 03 d2 0e d4 79 69 5f 15 d7
338 if ((state == TXTSTAT_PCRS_AFTER_EXTENTING) &&
339 (!strncmp(line, "TBOOT: PCR 17:", 16))) {
340 for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
341 ctx->final_pcr17[j] = 0;
342 ctx->final_pcr17[j] = hex2byte(line, 17 + j * 3);
344 DEBUG("final PCR17");
345 debugPrintHex(" PCR17 ", ctx->final_pcr17, 20, "\n");
347 if ((state == TXTSTAT_PCRS_AFTER_EXTENTING) &&
348 (!strncmp(line, "TBOOT: PCR 18:", 16))) {
349 for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
350 ctx->final_pcr18[j] = 0;
351 ctx->final_pcr18[j] = hex2byte(line, 17 + j * 3);
353 DEBUG("final PCR18");
354 debugPrintHex(" PCR18 ", ctx->final_pcr18, 20, "\n");
361 if (filename != NULL) {
368 * skip space/tab at start
370 char * skipspace(char *str) {
371 while ((*str == CHAR_SPACE) || (*str == CHAR_TAB)) {
378 * skip to space or end
380 char * skip2space(char *str) {
387 if (*str == 0x0a) { // \n
393 for (i = 0; i < len; i++) {
394 if (str[i] == 0x20) {
406 * remove \n at the end
408 void removecr(char *str) {
412 if (str[len - 1] == 0x0a) {
419 // 000004c0 aa 3a c0 7f a7 46 db 18 2e ac 69 8f 8d 41 7f 5a
420 // 000004c0 aa 3a c0 7f a7 46 db 18 2e ac 69 8f 8d 41 7f 5a |.:...F....i..A.Z|
422 int checkSinitAcm(BYTE *buf) {
424 {0xaa, 0x3a, 0xc0, 0x7f, 0xa7, 0x46, 0xdb, 0x18,
425 0x2e, 0xac, 0x69, 0x8f, 0x8d, 0x41, 0x7f, 0x5a};
427 if (memcmp(&buf[0x4c0], UUID, 16) == 0) {
429 DEBUG("SINIT ACM\n");
438 UINT32 HeaderVersion;
446 UINT32 ErrorEntryPoint;
454 BYTE RSAPubKey[256]; // 128 not included
455 BYTE RSAPubExp[4]; // not included
456 BYTE RSASig[256]; // not included
457 BYTE Scratch[1]; // not included
458 // UserArea[] // 644+ScratchSize*4
461 int sinit_acm_hash(char *filename, int size, BYTE *sha1_digest, BYTE *sha256_digest) {
468 SHA256_CTX sha256_ctx;
471 int rc = PTS_SUCCESS;
473 DEBUG("sinit_acm_hash() file = %s, size = %d\n", filename, size);
475 acmbuf = xmalloc(size);
476 if (acmbuf == NULL) {
480 memset(acmbuf, 0, size);
483 fp = fopen(filename, "rb");
485 LOG(LOG_ERR, "File %s does not exist\n", filename);
493 len = fread(buf, 1, sizeof(buf), fp);
497 memcpy(ptr, buf, len);
505 acm = (SINIT_ACM *)acmbuf;
506 DEBUG(" MopduleType : 0x%08X\n", acm->MopduleType);
507 DEBUG(" Size : %d\n", acm->Size);
508 DEBUG(" EntryPoint : %d, 0x%08X\n", acm->EntryPoint, acm->EntryPoint);
509 DEBUG(" KeySize : %d, 0x%08X\n", acm->KeySize, acm->KeySize);
510 DEBUG(" ScratchSize : %d, 0x%08X\n", acm->ScratchSize, acm->ScratchSize);
511 user_area = 644 + (acm->ScratchSize * 4);
512 DEBUG(" User Area : %d, 0x%08X\n", user_area, user_area);
515 SHA1_Update(&sha_ctx, &acmbuf[0], 128);
516 SHA1_Update(&sha_ctx, &acmbuf[user_area], size - user_area);
517 SHA1_Final(sha1_digest, &sha_ctx);
519 debugPrintHex(" SHA1 Digest : ", sha1_digest, 20, "\n");
521 SHA256_Init(&sha256_ctx);
522 SHA256_Update(&sha256_ctx, &acmbuf[0], 128);
523 SHA256_Update(&sha256_ctx, &acmbuf[user_area], size - user_area);
524 SHA256_Final(sha256_digest, &sha256_ctx);
526 debugPrintHex(" SHA256 Digest : ", sha256_digest, 32, "\n");
534 int sha1sum_unzip(char *filename, int *filesize, BYTE *digest) {
540 int is_sinit_acm = 0;
544 fp = gzopen(filename, "rb");
546 LOG(LOG_ERR, "File %s does not exist\n", filename);
553 len = gzread(fp, buf, sizeof(buf));
554 if ((rdCnt == 0) && (len > 1216 + 16)) {
555 is_sinit_acm = checkSinitAcm((BYTE *)buf);
560 SHA1_Update(&sha_ctx, buf, len);
565 SHA1_Final(digest, &sha_ctx);
574 * parse grub.conf file
576 * just check the default setting
578 int parseGrubConfFile(OPENPTS_TBOOT_CONTEXT *ctx, char *filename, char *path) {
579 int rc = PTS_SUCCESS;
584 int module_count = 0;
586 char *module_filename;
589 TBOOT_MODULE *prev_module = NULL;
594 if ((fp = fopen(filename, "r")) == NULL) {
595 LOG(LOG_ERR, "parseTxtStatFile - %s file is missing\n", filename);
596 return PTS_FATAL; // TODO
601 while (fgets(line, sizeof(line), fp) != NULL) { // read line
603 if (!strncmp(line, "default=", 8)) {
604 default_num = atoi(&line[8]);
605 DEBUG("default_num = %d\n", default_num);
608 // title Fedora (2.6.38.1-6.fc15.x86_64) tboot
609 if (!strncmp(line, "title", 5)) {
612 DEBUG("title[%d] : %s", count, line);
613 } else if (default_num == count) {
614 ptr = skipspace(line);
617 // kernel /tboot.gz logging=serial,vga,memory vga_delay=5
619 // module /vmlinuz-2.6.38.1-6.fc15.x86_64 ro...
620 // module /initramfs-2.6.38.1-6.fc15.x86_64.img
621 // module /GM45_GS45_PM45_SINIT_21.BIN
622 if (!strncmp(ptr, "module", 6)) {
623 TBOOT_MODULE *module;
624 OPENPTS_EVENT_TBOOT_MODULE *eventdata;
625 /* module structure */
626 module = xmalloc_assert(sizeof(TBOOT_MODULE));
627 eventdata = xmalloc_assert(sizeof(OPENPTS_EVENT_TBOOT_MODULE));
628 module->eventdata = eventdata;
630 if (prev_module == NULL) {
632 ctx->module = module;
634 prev_module->next = module;
640 module_filename = &ptr[8];
642 module_filename = &ptr[7];
646 ptr = skip2space(&ptr[7]);
649 eventdata->filename = getFullpathName(path, module_filename);
650 eventdata->filename_size = strlen(eventdata->filename);
653 removecr(module_option);
654 eventdata->command = smalloc(module_option);
655 eventdata->command_size = strlen(eventdata->command);
656 DEBUG("module[%d] file : '%s'", module_count, eventdata->filename);
657 DEBUG("module[%d] option : '%s'", module_count, eventdata->command);
659 module_option = NULL;
660 removecr(module_filename);
661 eventdata->filename = getFullpathName(path, module_filename);
662 eventdata->filename_size = strlen(eventdata->filename);
663 eventdata->command = NULL;
664 eventdata->command_size = 0;
665 DEBUG("module[%d] file : '%s'", module_count, eventdata->filename);
670 is_sinit_acm = sha1sum_unzip(eventdata->filename, &size, eventdata->file_hash);
671 if (is_sinit_acm == 1) {
672 // calc hash of SINIT ACM
676 ctx->sinit_hash_from_file,
677 ctx->sinit_hash256_from_file);
680 debugPrintHex(" SHA1(file) : ", eventdata->file_hash, 20, "\n");
683 SHA1_Update(&sha_ctx, eventdata->command, eventdata->command_size);
684 SHA1_Final(eventdata->command_hash, &sha_ctx);
686 debugPrintHex(" SHA1(command) : ", eventdata->command_hash, 20, "\n");
689 SHA1_Update(&sha_ctx, eventdata->command_hash, 20);
690 SHA1_Update(&sha_ctx, eventdata->file_hash, 20);
691 SHA1_Final(module->digest, &sha_ctx);
693 debugPrintHex(" extend : ", module->digest, 20, "\n");
696 prev_module = module;
709 * Verify Tboot Measurement
711 * setup OPENPTS_TBOOT_CONTEXT before call this
713 int emulateTboot(OPENPTS_TBOOT_CONTEXT *ctx) {
714 int rc = PTS_SUCCESS;
716 unsigned char digest[20];
718 DEBUG("emulateTboot()\n");
723 // Ref: Dev Guide 1.9.1 PCR 17 - p.14
724 if (ctx->mle_version == 6) {
725 // Extend(SHA-1(SinitMleData.SinitHash |
726 // SinitMleData.EdxSenterFlags))
728 SHA1_Update(&sha_ctx, ctx->sinit_hash, 20);
729 SHA1_Update(&sha_ctx, ctx->edx_senter_flags, 4);
730 SHA1_Final(digest, &sha_ctx);
733 DEBUG("PCR17(mle v6)\n");
734 debugPrintHex(" sinit_hash : ", ctx->sinit_hash, 20, "\n");
735 debugPrintHex(" edx_senter_flags : ", ctx->edx_senter_flags, 4, "\n");
736 debugPrintHex(" extend : ", digest, 20, "\n");
737 debugPrintHex(" PCR[17] : ", &pcr[17][0], 20, "\n");
740 // Extend(SHA-1(SinitMleData.BiosAcm.ID |
741 // SinitMleData.MsegValid |
742 // SinitMleData.StmHash |
743 // SinitMleData.PolicyControl |
744 // SinitMleData.LcpPolicyHash |
745 // (OsSinitData.Capabilities, 0)))
747 SHA1_Update(&sha_ctx, ctx->bios_acm_id, 20);
748 SHA1_Update(&sha_ctx, ctx->mseg_valid, 8);
749 SHA1_Update(&sha_ctx, ctx->stm_hash, 20);
750 SHA1_Update(&sha_ctx, ctx->lcp_policy_control, 4);
751 SHA1_Update(&sha_ctx, ctx->lcp_policy_hash, 20);
752 SHA1_Update(&sha_ctx, ctx->capabilities, 4);
753 SHA1_Final(digest, &sha_ctx);
756 DEBUG("PCR17(mle v6)\n");
757 debugPrintHex(" bios_acm_id : ", ctx->bios_acm_id, 20, "\n");
758 debugPrintHex(" mseg_valid : ", ctx->mseg_valid, 8, "\n");
759 debugPrintHex(" stm_hash : ", ctx->stm_hash, 20, "\n");
760 debugPrintHex(" lcp_policy_control : ", ctx->lcp_policy_control, 4, "\n");
761 debugPrintHex(" lcp_policy_hash : ", ctx->lcp_policy_hash, 20, "\n");
762 debugPrintHex(" capabilities : ", ctx->capabilities, 4, "\n");
763 debugPrintHex(" extend : ", digest, 20, "\n");
764 debugPrintHex(" PCR[17] : ", &pcr[17][0], 20, "\n");
766 } else if (ctx->mle_version == 7) {
768 // Extend(Hidden Value)
769 // SinitMleData.SinitHash = PCR17
770 // Extend(SHA-1(SinitMleData.BiosAcm.ID |
771 // SinitMleData.MsegValid |
772 // SinitMleData.StmHash |
773 // SinitMleData.PolicyControl |
774 // SinitMleData.LcpPolicyHash |
775 // (OsSinitData.Capabilities, 0)))
777 // SHA-1(SinitMleData.SinitHash |
778 // SHA-1( SinitMleData.BiosAcm.ID |
779 // SinitMleData.MsegValid |
780 // SinitMleData.StmHash |
781 // SinitMleData.PolicyControl |
782 // SinitMleData.LcpPolicyHash |
783 // (OsSinitData.Capabilities, 0)))
787 SHA1_Update(&sha_ctx, ctx->sinit_hash256_from_file, 32);
788 SHA1_Update(&sha_ctx, ctx->edx_senter_flags, 4);
789 SHA1_Final(digest, &sha_ctx);
792 DEBUG("PCR17(mle v6)\n");
793 debugPrintHex(" sinit_hash : ", ctx->sinit_hash256_from_file, 32, "\n");
794 debugPrintHex(" edx_senter_flags : ", ctx->edx_senter_flags, 4, "\n");
795 debugPrintHex(" extend : ", digest, 20, "\n");
796 debugPrintHex(" PCR[17] : ", &pcr[17][0], 20, "\n");
799 // extend(17, ctx->sinit_hash256_from_file);
800 // extend(17, ctx->sinit_hash_from_file);
801 // debugPrintHex(" mle v7 PCR17 ", &pcr[17][0], 20, " (SINIT ACM)\n");
804 resetPcrWithSecret(17, ctx->sinit_hash);
805 debugPrintHex(" SINIT hash ", ctx->sinit_hash, 20, "\n");
806 debugPrintHex(" mle v7 PCR17 ", &pcr[17][0], 20, "\n");
809 SHA1_Update(&sha_ctx, ctx->bios_acm_id, 20);
810 SHA1_Update(&sha_ctx, ctx->mseg_valid, 8);
811 SHA1_Update(&sha_ctx, ctx->stm_hash, 20);
812 SHA1_Update(&sha_ctx, ctx->lcp_policy_control, 4);
813 SHA1_Update(&sha_ctx, ctx->lcp_policy_hash, 20);
814 SHA1_Update(&sha_ctx, ctx->capabilities, 4);
815 SHA1_Final(digest, &sha_ctx);
817 debugPrintHex(" mle v7 PCR17 ", &pcr[17][0], 20, "\n");
818 } else if (ctx->mle_version == 8) {
821 // SHA-1(SinitMleData.SinitHash |
822 // SHA-1(SinitMleData.BiosAcm.ID |
823 // SinitMleData.MsegValid |
824 // SinitMleData.StmHash |
825 // SinitMleData.PolicyControl |
826 // SinitMleData.LcpPolicyHash |
827 // (OsSinitData.Capabilities, 0) |
828 // SinitMleData.ProcessorSCRTMStatus)) << added
831 extend(17, ctx->sinit_hash256_from_file);
832 debugPrintHex(" mle v8 PCR17 ", &pcr[17][0], 20, "\n");
835 // resetPcrWithSecret(17, ctx->sinit_hash);
838 SHA1_Update(&sha_ctx, ctx->bios_acm_id, 20);
839 SHA1_Update(&sha_ctx, ctx->mseg_valid, 8);
840 SHA1_Update(&sha_ctx, ctx->stm_hash, 20);
841 SHA1_Update(&sha_ctx, ctx->lcp_policy_control, 4);
842 SHA1_Update(&sha_ctx, ctx->lcp_policy_hash, 20);
843 SHA1_Update(&sha_ctx, ctx->capabilities, 4);
844 SHA1_Update(&sha_ctx, ctx->ProcessorSCRTMStatus, 4);
845 SHA1_Final(digest, &sha_ctx);
847 debugPrintHex(" mle v8 PCR17 ", &pcr[17][0], 20, "\n");
849 LOG(LOG_ERR, "mle_version = %d \n", ctx->mle_version);
852 extend(18, ctx->mle_hash);
855 printHex("PCR-17", &pcr[17][0], 20, "\n");
856 printHex("PCR-18", &pcr[18][0], 20, "\n");
857 printHex("PCR-19", &pcr[19][0], 20, "\n");
860 extend(17, ctx->vl_pcr17);
861 debugPrintHex(" extend : ", ctx->vl_pcr17, 20, "\n");
862 debugPrintHex(" PCR[17] : ", &pcr[17][0], 20, "\n");
864 extend(18, ctx->vl_pcr18);
865 debugPrintHex(" extend : ", ctx->vl_pcr18, 20, "\n");
866 debugPrintHex(" PCR[18] : ", &pcr[18][0], 20, "\n");
868 extend(19, ctx->vl_pcr19);
869 debugPrintHex(" extend : ", ctx->vl_pcr19, 20, "\n");
870 debugPrintHex(" PCR[19] : ", &pcr[19][0], 20, "\n");
873 printHex("PCR-17", &pcr[17][0], 20, "\n");
874 printHex("PCR-18", &pcr[18][0], 20, "\n");
875 printHex("PCR-19", &pcr[19][0], 20, "\n");
878 /* check PCR values after DRTM */
880 /* check (within TXT-STAT) */
881 if (memcmp(&pcr[17][0], ctx->final_pcr17, 20) != 0) {
882 LOG(LOG_ERR, "bad PCR17\n");
883 printHex("PCR-17", &pcr[17][0], 20, "\n");
886 if (memcmp(&pcr[18][0], ctx->final_pcr18, 20) != 0) {
887 LOG(LOG_ERR, "bad PCR18\n");
888 printHex("PCR-18", &pcr[18][0], 20, "\n");
891 // TODO check PCR19 - with PCRs
900 int writeEvent(FILE *fp, TSS_PCR_EVENT *event) {
902 rc = fwrite((BYTE *)&event->ulPcrIndex, 1, 4, fp); // PCR index
903 rc = fwrite((BYTE *)&event->eventType, 1, 4, fp); // Event type
904 rc = fwrite(event->rgbPcrValue, 1, 20, fp); // PCR
905 rc = fwrite((BYTE *)&event->ulEventLength, 1, 4, fp); // EventData length
906 if ((event->rgbEvent != NULL) && (event->ulEventLength > 0)) {
907 rc = fwrite(event->rgbEvent, 1, event->ulEventLength, fp); // EventData
914 * filename IML(binary) file
916 int generateEventlog(OPENPTS_TBOOT_CONTEXT *ctx, char *filename) {
917 int rc = PTS_SUCCESS;
919 TSS_PCR_EVENT *event;
922 DEBUG("generateEventlog() - filename = %s\n", filename);
925 if (filename != NULL) {
927 if ((fp = fopen(filename, "wb")) == NULL) {
928 LOG(LOG_ERR, "generateEventlog - %s file can't open\n", filename);
929 return PTS_FATAL; // TODO
936 event = xmalloc(sizeof(TSS_PCR_EVENT));
940 memset(event, 0, sizeof(TSS_PCR_EVENT));
943 event->rgbPcrValue = xmalloc(20);
944 if (event->rgbPcrValue == NULL) {
949 if (ctx->mle_version == 6) {
950 OPENPTS_EVENT_TBOOT_SINIT_V6 data0;
951 OPENPTS_EVENT_TBOOT_STM_V6 data1;
953 event->ulPcrIndex = 17;
954 event->eventType = EV_TBOOT_SINIT_V6;
955 memcpy(data0.sinit_hash, ctx->sinit_hash, 20);
956 memcpy(data0.edx_senter_flags, ctx->edx_senter_flags, 4);
957 event->ulEventLength = 24;
958 event->rgbEvent = (BYTE *)&data0;
960 SHA1_Update(&sha_ctx, event->rgbEvent, event->ulEventLength);
961 SHA1_Final(event->rgbPcrValue, &sha_ctx);
962 writeEvent(fp, event);
965 event->ulPcrIndex = 17;
966 event->eventType = EV_TBOOT_STM_V6;
967 memcpy(data1.bios_acm_id, ctx->bios_acm_id, 20);
968 memcpy(data1.mseg_valid, ctx->mseg_valid, 8);
969 memcpy(data1.stm_hash, ctx->stm_hash, 20);
970 memcpy(data1.lcp_policy_control, ctx->lcp_policy_control, 4);
971 memcpy(data1.lcp_policy_hash, ctx->lcp_policy_hash, 20);
972 memcpy(data1.capabilities, ctx->capabilities, 4);
973 event->ulEventLength = 76;
974 event->rgbEvent = (BYTE *)&data1;
976 SHA1_Update(&sha_ctx, event->rgbEvent, event->ulEventLength);
977 SHA1_Final(event->rgbPcrValue, &sha_ctx);
978 writeEvent(fp, event);
979 } else if (ctx->mle_version == 7) {
980 DEBUG("TBD mle_version = %d \n", ctx->mle_version);
981 OPENPTS_EVENT_TBOOT_SINIT_V7 data0;
982 OPENPTS_EVENT_TBOOT_STM_V6 data1;
984 event->ulPcrIndex = 17;
985 event->eventType = EV_TBOOT_SINIT_V7;
986 memcpy(data0.sinit_hash, ctx->sinit_hash256_from_file, 32);
987 memcpy(data0.edx_senter_flags, ctx->edx_senter_flags, 4);
988 event->ulEventLength = 36;
989 event->rgbEvent = (BYTE *)&data0;
991 SHA1_Update(&sha_ctx, event->rgbEvent, event->ulEventLength);
992 SHA1_Final(event->rgbPcrValue, &sha_ctx);
993 writeEvent(fp, event);
996 event->ulPcrIndex = 17;
997 event->eventType = EV_TBOOT_STM_V6;
998 memcpy(data1.bios_acm_id, ctx->bios_acm_id, 20);
999 memcpy(data1.mseg_valid, ctx->mseg_valid, 8);
1000 memcpy(data1.stm_hash, ctx->stm_hash, 20);
1001 memcpy(data1.lcp_policy_control, ctx->lcp_policy_control, 4);
1002 memcpy(data1.lcp_policy_hash, ctx->lcp_policy_hash, 20);
1003 memcpy(data1.capabilities, ctx->capabilities, 4);
1004 event->ulEventLength = 76;
1005 event->rgbEvent = (BYTE *)&data1;
1006 SHA1_Init(&sha_ctx);
1007 SHA1_Update(&sha_ctx, event->rgbEvent, event->ulEventLength);
1008 SHA1_Final(event->rgbPcrValue, &sha_ctx);
1009 writeEvent(fp, event);
1012 } else if (ctx->mle_version == 8) {
1013 LOG(LOG_TODO, "TBD mle_version = %d \n", ctx->mle_version);
1015 LOG(LOG_TODO, "TBD mle_version = %d \n", ctx->mle_version);
1019 event->ulPcrIndex = 18;
1020 event->eventType = EV_TBOOT_MLE_HASH;
1021 event->ulEventLength = 0;
1022 memcpy(event->rgbPcrValue, ctx->mle_hash, 20);
1023 writeEvent(fp, event);
1026 /* TBOOT Policy => PCR17 */
1028 OPENPTS_EVENT_TBOOT_POLCTL polctl;
1030 // ctx->pol_control[0] = 1; // TODO extend PCR17
1031 // ctx->pol_control[1] = 0;
1032 // ctx->pol_control[2] = 0;
1033 // ctx->pol_control[3] = 0;
1035 // SHA1_Init(&sha_ctx);
1036 // SHA1_Update(&sha_ctx, ctx->pol_control, 4);
1037 // SHA1_Update(&sha_ctx, ctx->pol_hash, 20);
1038 // SHA1_Final(digest, &sha_ctx);
1039 // extend(17, digest);
1041 // DEBUG("PCR17 \n");
1042 // printHex("PCR-17", digest, 20, "\n");
1043 // printHex("PCR-17", ctx->vl_pcr17, 20, "\n");
1045 event->ulPcrIndex = 17;
1046 event->eventType = EV_TBOOT_POLCTL;
1047 event->ulEventLength = 24;
1048 event->rgbEvent = (BYTE *)&polctl;
1049 memcpy(&polctl.pol_control, ctx->pol_control, 4);
1050 memcpy(&polctl.pol_hash, ctx->pol_hash, 20);
1051 memcpy(event->rgbPcrValue, ctx->vl_pcr17, 20);
1052 writeEvent(fp, event);
1057 DEBUG(" module[0]\n");
1058 event->ulPcrIndex = 18;
1059 event->eventType = EV_TBOOT_MODULE;
1060 if (ctx->module != NULL) {
1061 TBOOT_MODULE *module;
1062 OPENPTS_EVENT_TBOOT_MODULE *eventdata;
1065 module = ctx->module;
1066 if (memcmp(module->digest, ctx->vl_pcr18, 20) != 0) {
1067 LOG(LOG_ERR, "Module[0] digest did not match\n");
1068 debugPrintHex(" TXT-STAT : ", ctx->vl_pcr18, 20, "\n");
1069 debugPrintHex(" Calc : ", module->digest, 20, "\n");
1071 eventdata = module->eventdata;
1072 event->ulEventLength = 20 + 20 + 4 + 4 + eventdata->command_size + eventdata->filename_size;
1073 event->rgbEvent = xmalloc(event->ulEventLength);
1074 if (event->rgbEvent == NULL) {
1077 ptr = event->rgbEvent;
1078 memcpy(ptr, eventdata->command_hash, 20);
1080 memcpy(ptr, eventdata->file_hash, 20);
1082 memcpy(ptr, &eventdata->command_size, 4);
1084 memcpy(ptr, eventdata->command, eventdata->command_size);
1085 ptr += eventdata->command_size;
1086 memcpy(ptr, &eventdata->filename_size, 4);
1088 memcpy(ptr, eventdata->filename, eventdata->filename_size);
1089 // DEBUG("%s\n", eventdata->command);
1090 // DEBUG("%s\n", eventdata->filename);
1092 event->ulEventLength = 0;
1093 event->rgbEvent = NULL;
1094 DEBUG(" module[0] eventdata = null, check the default value in the grub.conf\n");
1096 memcpy(event->rgbPcrValue, ctx->vl_pcr18, 20);
1097 writeEvent(fp, event);
1100 DEBUG(" module[1]\n");
1101 event->ulPcrIndex = 19;
1102 event->eventType = EV_TBOOT_MODULE;
1103 if ((ctx->module != NULL) && (ctx->module->next != NULL)) {
1104 TBOOT_MODULE *module;
1105 OPENPTS_EVENT_TBOOT_MODULE *eventdata;
1108 module = ctx->module->next;
1109 if (memcmp(module->digest, ctx->vl_pcr19, 20) != 0) {
1110 LOG(LOG_ERR, "Module[1] digest did not match\n");
1111 debugPrintHex(" TXT-STAT : ", ctx->vl_pcr19, 20, "\n");
1112 debugPrintHex(" Calc : ", module->digest, 20, "\n");
1114 eventdata = module->eventdata;
1115 event->ulEventLength = 20 + 20 + 4 + 4 + eventdata->command_size + eventdata->filename_size;
1116 if (event->rgbEvent != NULL) xfree(event->rgbEvent);
1117 event->rgbEvent = xmalloc(event->ulEventLength);
1118 if (event->rgbEvent == NULL) {
1121 ptr = event->rgbEvent;
1122 memcpy(ptr, eventdata->command_hash, 20);
1124 memcpy(ptr, eventdata->file_hash, 20);
1126 memcpy(ptr, &eventdata->command_size, 4);
1128 memcpy(ptr, eventdata->command, eventdata->command_size);
1129 ptr += eventdata->command_size;
1130 memcpy(ptr, &eventdata->filename_size, 4);
1132 memcpy(ptr, eventdata->filename, eventdata->filename_size);
1133 // DEBUG("%s\n", eventdata->command);
1134 // DEBUG("%s\n", eventdata->filename);
1136 event->ulEventLength = 0;
1137 event->rgbEvent = NULL;
1138 DEBUG(" module[0] eventdata = null, check the default value in the grub.conf\n");
1140 memcpy(event->rgbPcrValue, ctx->vl_pcr19, 20);
1141 writeEvent(fp, event);
1145 if (event != NULL) {
1146 if (event->rgbPcrValue != NULL) xfree(event->rgbPcrValue);
1147 if (event->rgbEvent != NULL) xfree(event->rgbEvent);
1152 if (filename != NULL) {
1162 "OpenPTS command\n\n"
1163 "Usage: tboot2iml [options]\n\n"
1165 " -i filename txt-stat file to read (default is STDIN)\n"
1166 " -g filename grub.conf file to read (OPTION)\n"
1167 " -p path grub path (OPTION)\n"
1168 " -o filename Output to file (default is STDOUT)\n"
1169 " -v Verbose message\n"
1174 int main(int argc, char *argv[]) {
1176 char *txt_stat_filename = NULL;
1177 char *grub_conf_filename = NULL;
1178 char *iml_filename = NULL;
1179 OPENPTS_TBOOT_CONTEXT *ctx = NULL;
1181 char *grub_path = NULL; // TODO
1184 while ((c = getopt(argc, argv, "i:g:p:o:vh")) != EOF) {
1186 case 'i': /* input file name */
1187 txt_stat_filename = optarg;
1189 case 'g': /* input file name */
1190 grub_conf_filename = optarg;
1192 case 'p': /* input file name */
1195 case 'o': /* output file name */
1196 iml_filename = optarg;
1199 verbose = DEBUG_FLAG;
1201 case 'h': /* help */
1211 if ((grub_conf_filename != NULL) && (grub_path == NULL)) {
1213 "set the root path used by crub.conf\n");
1219 ctx = xmalloc_assert(sizeof(OPENPTS_TBOOT_CONTEXT));
1220 memset(ctx, 0, sizeof(OPENPTS_TBOOT_CONTEXT));
1221 ctx->lcp_policy_version = 1;
1223 /* parse TXT stat */
1224 rc = parseTxtStatFile(ctx, txt_stat_filename);
1225 if (rc != PTS_SUCCESS) {
1226 LOG(LOG_ERR, "parse of %s file was failed\n", txt_stat_filename);
1229 /* parse grub.conf */
1230 if (grub_conf_filename != NULL) {
1231 rc = parseGrubConfFile(ctx, grub_conf_filename, grub_path);
1234 /* parse grub.conf */
1237 /* validate IML and PCRs */
1238 rc = emulateTboot(ctx);
1240 // ctx = malloc(sizeof(OPENPTS_TBOOT_CONTEXT));
1244 rc = generateEventlog(ctx, iml_filename);