OSDN Git Service

f5ea0cb5f3e412c037be20faa86eb629586e0402
[openpts/openpts.git] / src / tboot2iml.c
1 /*
2  * This file is part of the OpenPTS project.
3  *
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.
8  *
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)
12  * any later version.
13  *
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.
18  *
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.
22  */
23
24 /**
25  * \file src/tboot2iml.c
26  * \brief create pseudo IML of tboot, standalone tool
27  * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
28  * @date 2011-03-28
29  * cleanup 2011-07-06 SM
30  * refactoring
31  *
32  *
33  *  Test
34  * 
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
38  *
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
40  *
41  * ./src/iml2text -D -v -V -i tests/data/ThinkpadX200_Fedora15_tboot/eventlog2
42  * 
43  */
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <unistd.h>  // getopt
49 #include <stdint.h>
50 #include <sys/types.h>
51 #include <sys/stat.h>
52 #include <sys/mman.h>
53 #include <fcntl.h>
54 #include <arpa/inet.h>
55
56 #include <zlib.h>
57
58 #include <openssl/sha.h>
59
60 #include <openpts.h>
61 #include <openpts_tboot.h>
62
63 // Local TCSD
64 #define SERVER    NULL
65
66 #define MAX_PCRNUM 24  // TPM v1.2
67
68 #define CHAR_TAB   0x09
69 #define CHAR_SPACE 0x20
70
71
72 int verbose = 0;
73
74 // PCR
75 unsigned char pcr[MAX_PCRNUM][SHA1_DIGEST_SIZE];
76
77
78 void debugPrintHex(char *head, BYTE *data, int num, char *tail) {
79     int i;
80     if (verbose > 0) {
81         printf("%s", head);
82         for (i = 0; i < num; i++) {
83             printf("%02X", data[i]);
84         }
85         printf("%s", tail);
86     }
87 }
88
89
90
91 void resetPcr() {
92     int i, j;
93
94     for (i = 0;i < MAX_PCRNUM; i ++) {
95         for (j = 0;j < SHA1_DIGEST_SIZE; j ++) {
96             pcr[i][j] = 0;
97         }
98     }
99 }
100
101 void resetPcrWithSecret(int i, BYTE *digest) {
102     int j;
103
104     for (j = 0;j < SHA1_DIGEST_SIZE; j ++) {
105         pcr[i][j] = digest[j];
106     }
107 }
108
109 void extend(int index, unsigned char* digest) {
110     SHA_CTX ctx;
111
112     SHA1_Init(&ctx);
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);
116 }
117
118
119 enum {
120     TXTSTAT_START,
121
122     TXTSTAT_SINIT_MLE_DATA,
123     TXTSTAT_BIOS_ACM_ID,
124     TXTSTAT_SINIT_HASH,
125     TXTSTAT_MLE_HASH,
126     TXTSTAT_STM_HASH,
127     TXTSTAT_LCP_POLICY_HASH,
128
129     TXTSTAT_VL_MEASUREMENT,
130     TXTSTAT_PCRS_BEFORE_EXTENTING,
131     TXTSTAT_PCRS_AFTER_EXTENTING,
132     TXTSTAT_END,
133     TXTSTAT_NA
134 };
135
136 BYTE hex2byte(char *buf, int offset) {
137     UINT32 tmp;
138     char *e;
139     char buf2[3];
140
141     memcpy(buf2, &buf[offset], 2);
142     buf[2] = 0;
143
144     tmp = strtol(buf2, &e, 16);
145
146     return (BYTE) (0xFF & tmp);
147 }
148
149
150 /**
151  * parse TXT-stat file 
152  */
153 int parseTxtStatFile(OPENPTS_TBOOT_CONTEXT *ctx, char *filename) {
154     FILE *fp;
155     char line[1024];  // TODO(munetoh)
156     int j;
157     int state = TXTSTAT_START;
158     int next_state = TXTSTAT_START;
159
160     /* open */
161     if (filename != NULL) {
162         /* open */
163         if ((fp = fopen(filename, "r")) == NULL) {
164             ERROR("parseTxtStatFile - %s file is missing\n", filename);
165             return PTS_FATAL;  // TODO
166         }
167     } else {
168         fp = stdin;
169     }
170
171     /* line by line */
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");
177         }
178
179
180         // TBOOT: sinit_mle_data (@0x799301b8, 0x260):
181         if (!strncmp(line, "TBOOT: sinit_mle_data", 21)) {
182             next_state = TXTSTAT_SINIT_MLE_DATA;
183         }
184         // TBOOT:        version: 6
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);
189         }
190         // TBOOT:        bios_acm_id:
191         if (!strncmp(line, "TBOOT:       bios_acm_id:", 21)) {
192             next_state = TXTSTAT_BIOS_ACM_ID;
193         }
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);
199             }
200             next_state = TXTSTAT_NA;
201             DEBUG("bios_acm_id\n");
202             // printHex("bios_acm_id ", ctx->bios_acm_id, 20, "\n");
203         }
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);
209             }
210             next_state = TXTSTAT_NA;
211             DEBUG("edx_senter_flags\n");
212             // printHex("edx_senter_flags ", ctx->edx_senter_flags, 4, "\n");
213         }
214
215
216         // TBOOT:        mseg_valid: 0x0
217         // TBOOT:        sinit_hash:
218         if (!strncmp(line, "TBOOT:       sinit_hash:", 20)) {
219             next_state = TXTSTAT_SINIT_HASH;
220         }
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);
226             }
227             next_state = TXTSTAT_NA;
228             DEBUG("sinit_hash\n");
229             debugPrintHex("  sinit_hash : ", ctx->sinit_hash, 20, "\n");
230         }
231         // TBOOT:        mle_hash:
232         if (!strncmp(line, "TBOOT:       mle_hash:", 18)) {
233             next_state = TXTSTAT_MLE_HASH;
234         }
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);
240             }
241             next_state = TXTSTAT_NA;
242             DEBUG("mle_hash\n");
243             debugPrintHex("  mle_hash ", ctx->mle_hash, 20, "\n");
244         }
245         // TBOOT:        stm_hash:
246         if (!strncmp(line, "TBOOT:       stm_hash:", 18)) {
247             next_state = TXTSTAT_STM_HASH;
248         }
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);
254             }
255             next_state = TXTSTAT_NA;
256             DEBUG("stm_hash\n");
257             // printHex("stm_hash ", ctx->stm_hash, 20, "\n");
258         }
259         // TBOOT:        lcp_policy_hash:
260         if (!strncmp(line, "TBOOT:       lcp_policy_hash:", 25)) {
261             next_state = TXTSTAT_LCP_POLICY_HASH;
262         }
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);
268             }
269             next_state = TXTSTAT_NA;
270             DEBUG("lcp_policy_hash\n");
271             // printHex("lcp_policy_hash ", ctx->lcp_policy_hash, 20, "\n");
272         }
273         // TBOOT:        lcp_policy_control: 0x00000000
274
275
276         // TBOOT:        policy_control: 00000001 (EXTEND_PCR17)
277         // UINT32
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);
281             }
282             DEBUG("pol_control");
283             // printHex("pol_control ", ctx->pol_control, 4, "\n");
284         }
285
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);
291             }
292             DEBUG("pol_hash PCR17");
293             // printHex("pol_hash ", ctx->pol_hash, 20, "\n");
294         }
295
296         // TBOOT:        VL measurements:
297         if (!strncmp(line, "TBOOT:       VL measurements", 24)) {
298             next_state = TXTSTAT_VL_MEASUREMENT;
299         }
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);
308             }
309             DEBUG("vl PCR17");
310             debugPrintHex("  PCR17 ", ctx->vl_pcr17, 20, "\n");
311         }
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);
317             }
318             DEBUG("vl PCR18");
319             debugPrintHex("  PCR18 ", ctx->vl_pcr18, 20, "\n");
320         }
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);
326             }
327             DEBUG("vl PCR19");
328             debugPrintHex("  PCR19 ", ctx->vl_pcr19, 20, "\n");
329         }
330
331
332         // TBOOT: PCRs after extending:
333         if (!strncmp(line, "TBOOT: PCRs after extending:", 28)) {
334             next_state = TXTSTAT_PCRS_AFTER_EXTENTING;
335         }
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);
343             }
344             DEBUG("final PCR17");
345             debugPrintHex("  PCR17 ", ctx->final_pcr17, 20, "\n");
346         }
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);
352             }
353             DEBUG("final PCR18");
354             debugPrintHex("  PCR18 ", ctx->final_pcr18, 20, "\n");
355         }
356
357         state = next_state;
358     }  // line
359
360     /* close */
361     if (filename != NULL) {
362         fclose(fp);
363     }
364     return PTS_SUCCESS;
365 }
366
367 /**
368  * skip space/tab at start
369  */
370 char * skipspace(char *str) {
371     while ((*str == CHAR_SPACE) || (*str == CHAR_TAB)) {
372         str++;
373     }
374     return str;
375 }
376
377 /**
378  * skip to space or end
379  */
380 char * skip2space(char *str) {
381     int len;
382     int i;
383
384     if (*str == 0) {
385         return NULL;
386     }
387     if (*str == 0x0a) {  // \n
388         return NULL;
389     }
390
391     len = strlen(str);
392
393     for (i = 0; i < len; i++) {
394         if (str[i] == 0x20) {
395             return &str[i];
396         }
397         if (*str == 0x0a) {
398             return NULL;
399         }
400     }
401
402     return NULL;
403 }
404
405 /**
406  * remove \n at the end
407  */
408 void removecr(char *str) {
409     int len;
410
411     len = strlen(str);
412     if (str[len - 1] == 0x0a) {
413         str[len - 1] = 0;
414     }
415 }
416
417
418 // ACM UUID
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|
421 // 0x4c0 = 1216
422 int checkSinitAcm(BYTE *buf) {
423     BYTE UUID[16] =
424         {0xaa, 0x3a, 0xc0, 0x7f, 0xa7, 0x46, 0xdb, 0x18,
425          0x2e, 0xac, 0x69, 0x8f, 0x8d, 0x41, 0x7f, 0x5a};
426
427     if (memcmp(&buf[0x4c0], UUID, 16) == 0) {
428         // HIT
429         DEBUG("SINIT ACM\n");
430         return 1;
431     }
432     return 0;
433 }
434
435 typedef struct {
436     UINT32 MopduleType;
437     UINT32 HeaderLen;
438     UINT32 HeaderVersion;
439     UINT16 ChipsetID;
440     UINT16 Flags;
441     UINT32 ModuleVender;
442     UINT32 Date;
443     UINT32 Size;
444     UINT32 Reserved1;
445     UINT32 CodeControl;
446     UINT32 ErrorEntryPoint;
447     UINT32 GDTLimit;
448     UINT32 GDTBasePtr;
449     UINT32 SegSel;
450     UINT32 EntryPoint;
451     BYTE   Reserved2[64];
452     UINT32 KeySize;
453     UINT32 ScratchSize;
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
459 } SINIT_ACM;
460
461 int sinit_acm_hash(char *filename, int size, BYTE *sha1_digest, BYTE *sha256_digest) {
462     FILE *fp;
463     char buf[2048];
464     char *acmbuf = NULL;
465     char *ptr;
466     SINIT_ACM *acm;
467     SHA_CTX sha_ctx;
468     SHA256_CTX sha256_ctx;
469     int len;
470     int user_area;
471     int rc = PTS_SUCCESS;
472
473     DEBUG("sinit_acm_hash() file = %s, size = %d\n", filename, size);
474
475     acmbuf = malloc(size);
476     if (acmbuf == NULL) {
477         ERROR("no memory");
478         rc = PTS_FATAL;
479         goto error;
480     }
481     memset(acmbuf, 0, size);
482
483     /* open */
484     fp = fopen(filename, "rb");
485     if (fp == NULL) {
486         ERROR("File %s does not exist\n", filename);
487         rc = PTS_FATAL;
488         goto error;
489     }
490
491     /* load */
492     ptr = acmbuf;
493     do {
494         len = fread(buf, 1, sizeof(buf), fp);
495
496         if ( len == 0 )
497             break;
498         memcpy(ptr, buf, len);
499         ptr += len;
500     } while ( 1 );
501
502     /* close */
503     fclose(fp);
504
505     /* check */
506     acm = (SINIT_ACM *)acmbuf;
507     DEBUG("  MopduleType : 0x%08X\n", acm->MopduleType);
508     DEBUG("  Size        : %d\n", acm->Size);
509     DEBUG("  EntryPoint  : %d, 0x%08X\n", acm->EntryPoint, acm->EntryPoint);
510     DEBUG("  KeySize     : %d, 0x%08X\n", acm->KeySize, acm->KeySize);
511     DEBUG("  ScratchSize : %d, 0x%08X\n", acm->ScratchSize, acm->ScratchSize);
512     user_area = 644 + (acm->ScratchSize * 4);
513     DEBUG("  User Area   : %d, 0x%08X\n", user_area, user_area);
514
515     SHA1_Init(&sha_ctx);
516     SHA1_Update(&sha_ctx, &acmbuf[0], 128);
517     SHA1_Update(&sha_ctx, &acmbuf[user_area], size - user_area);
518     SHA1_Final(sha1_digest, &sha_ctx);
519
520     debugPrintHex(" SHA1 Digest   : ", sha1_digest, 20, "\n");
521
522     SHA256_Init(&sha256_ctx);
523     SHA256_Update(&sha256_ctx, &acmbuf[0], 128);
524     SHA256_Update(&sha256_ctx, &acmbuf[user_area], size - user_area);
525     SHA256_Final(sha256_digest, &sha256_ctx);
526
527     debugPrintHex(" SHA256 Digest : ", sha256_digest, 32, "\n");
528
529   error:
530     free(acmbuf);
531     return rc;
532 }
533
534
535 int sha1sum_unzip(char *filename, int *filesize, BYTE *digest) {
536     FILE *fp;
537     char buf[2048];
538     SHA_CTX sha_ctx;
539     int len;
540     int rdCnt = 0;
541     int is_sinit_acm = 0;
542     int size = 0;
543
544     /* open */
545     fp = gzopen(filename, "rb");
546     if (fp == NULL) {
547         ERROR("File %s does not exist\n", filename);
548         return 0;
549     }
550
551     /* calc */
552     SHA1_Init(&sha_ctx);
553     do {
554         len = gzread(fp, buf, sizeof(buf));
555         if ((rdCnt == 0) && (len > 1216 + 16)) {
556             is_sinit_acm = checkSinitAcm((BYTE *)buf);
557         }
558
559         if ( len == 0 )
560             break;
561         SHA1_Update(&sha_ctx, buf, len);
562         rdCnt++;
563         size += len;
564     } while ( 1 );
565
566     SHA1_Final(digest, &sha_ctx);
567
568     /* close */
569     gzclose(fp);
570     *filesize = size;
571     return is_sinit_acm;
572 }
573
574 /**
575  * parse grub.conf file
576  *
577  * just check the default setting
578  */
579 int parseGrubConfFile(OPENPTS_TBOOT_CONTEXT *ctx, char *filename, char *path) {
580     int rc = PTS_SUCCESS;
581     FILE *fp;
582     char line[1024];
583     int default_num = 0;
584     int count = -1;
585     int module_count = 0;
586     char *ptr;
587     char *module_filename;
588     char *module_option;
589     SHA_CTX sha_ctx;
590     TBOOT_MODULE *prev_module = NULL;
591     int is_sinit_acm;
592     int size;
593
594     /* open */
595     if ((fp = fopen(filename, "r")) == NULL) {
596         ERROR("parseTxtStatFile - %s file is missing\n", filename);
597         return PTS_FATAL;  // TODO
598     }
599
600     /**/
601     /* line by line */
602     while (fgets(line, sizeof(line), fp) != NULL) {  // read line
603         // default=0
604         if (!strncmp(line, "default=", 8)) {
605             default_num = atoi(&line[8]);
606             DEBUG("default_num = %d\n", default_num);
607         }
608
609         // title Fedora (2.6.38.1-6.fc15.x86_64) tboot
610         if (!strncmp(line, "title", 5)) {
611             count = count + 1;
612             module_count = 0;
613             DEBUG("title[%d] : %s", count, line);
614         } else if (default_num == count) {
615             ptr = skipspace(line);
616             DEBUG("%s", ptr);
617             // root (hd0,0)
618             // kernel /tboot.gz logging=serial,vga,memory vga_delay=5
619             // TODO
620             // module /vmlinuz-2.6.38.1-6.fc15.x86_64 ro...
621             // module /initramfs-2.6.38.1-6.fc15.x86_64.img
622             // module /GM45_GS45_PM45_SINIT_21.BIN
623             if (!strncmp(ptr, "module", 6)) {
624                 TBOOT_MODULE *module;
625                 OPENPTS_EVENT_TBOOT_MODULE *eventdata;
626                 /* module structure */
627                 module = malloc(sizeof(TBOOT_MODULE));
628                 eventdata = malloc(sizeof(OPENPTS_EVENT_TBOOT_MODULE));
629                 module->eventdata = eventdata;
630                 module->next = NULL;
631                 if (prev_module == NULL) {
632                     /* 1st */
633                     ctx->module = module;
634                 } else {
635                     prev_module->next = module;
636                 }
637
638                 /* filename */
639                 if (ptr[7] == '/') {
640                     // skip root
641                     module_filename = &ptr[8];
642                 } else {
643                     module_filename = &ptr[7];
644                 }
645
646                 /* option */
647                 ptr = skip2space(&ptr[7]);
648                 if (ptr != NULL) {
649                     *ptr = 0;
650                     eventdata->filename = getFullpathName(path, module_filename);
651                     eventdata->filename_size = strlen(eventdata->filename);
652                     ptr++;
653                     module_option = ptr;
654                     removecr(module_option);
655                     eventdata->command = smalloc(module_option);
656                     eventdata->command_size = strlen(eventdata->command);
657                     DEBUG("module[%d] file   : '%s'", module_count, eventdata->filename);
658                     DEBUG("module[%d] option : '%s'", module_count, eventdata->command);
659                 } else {
660                     module_option = NULL;
661                     removecr(module_filename);
662                     eventdata->filename = getFullpathName(path, module_filename);
663                     eventdata->filename_size = strlen(eventdata->filename);
664                     eventdata->command = NULL;
665                     eventdata->command_size = 0;
666                     DEBUG("module[%d] file   : '%s'", module_count, eventdata->filename);
667                 }
668
669
670
671                 is_sinit_acm = sha1sum_unzip(eventdata->filename, &size, eventdata->file_hash);
672                 if (is_sinit_acm == 1) {
673                     // calc hash of SINIT ACM
674                     sinit_acm_hash(
675                         eventdata->filename,
676                         size,
677                         ctx->sinit_hash_from_file,
678                         ctx->sinit_hash256_from_file);
679                 } else {
680                     // Kernel or Initrd
681                     debugPrintHex(" SHA1(file)    : ", eventdata->file_hash, 20, "\n");
682
683                     SHA1_Init(&sha_ctx);
684                     SHA1_Update(&sha_ctx, eventdata->command, eventdata->command_size);
685                     SHA1_Final(eventdata->command_hash, &sha_ctx);
686
687                     debugPrintHex(" SHA1(command) : ", eventdata->command_hash, 20, "\n");
688
689                     SHA1_Init(&sha_ctx);
690                     SHA1_Update(&sha_ctx, eventdata->command_hash, 20);
691                     SHA1_Update(&sha_ctx, eventdata->file_hash, 20);
692                     SHA1_Final(module->digest, &sha_ctx);
693
694                     debugPrintHex(" extend        : ", module->digest, 20, "\n");
695                 }
696
697                 prev_module = module;
698                 module_count++;
699                 ctx->module_num++;
700             }
701         }
702     }  // line
703
704     /* close */
705     fclose(fp);
706     return rc;
707 }
708
709 /**
710  * Verify Tboot Measurement
711  *
712  * setup OPENPTS_TBOOT_CONTEXT before call this
713  */
714 int emulateTboot(OPENPTS_TBOOT_CONTEXT *ctx) {
715     int rc = PTS_SUCCESS;
716     SHA_CTX sha_ctx;
717     unsigned char digest[20];
718
719     DEBUG("emulateTboot()\n");
720
721     resetPcr();
722
723     // PCR 17
724     // Ref: Dev Guide 1.9.1 PCR 17 - p.14
725     if (ctx->mle_version == 6) {
726         // Extend(SHA-1(SinitMleData.SinitHash |
727         //              SinitMleData.EdxSenterFlags))
728         SHA1_Init(&sha_ctx);
729         SHA1_Update(&sha_ctx, ctx->sinit_hash, 20);
730         SHA1_Update(&sha_ctx, ctx->edx_senter_flags, 4);
731         SHA1_Final(digest, &sha_ctx);
732         extend(17, digest);
733         if (verbose > 0) {
734             DEBUG("PCR17(mle v6)\n");
735             debugPrintHex("  sinit_hash         : ", ctx->sinit_hash, 20, "\n");
736             debugPrintHex("  edx_senter_flags   : ", ctx->edx_senter_flags, 4, "\n");
737             debugPrintHex("  extend             : ", digest, 20, "\n");
738             debugPrintHex("  PCR[17]            : ", &pcr[17][0], 20, "\n");
739         }
740
741         // Extend(SHA-1(SinitMleData.BiosAcm.ID |
742         //              SinitMleData.MsegValid |
743         //              SinitMleData.StmHash |
744         //              SinitMleData.PolicyControl |
745         //              SinitMleData.LcpPolicyHash |
746         //              (OsSinitData.Capabilities, 0)))
747         SHA1_Init(&sha_ctx);
748         SHA1_Update(&sha_ctx, ctx->bios_acm_id, 20);
749         SHA1_Update(&sha_ctx, ctx->mseg_valid, 8);
750         SHA1_Update(&sha_ctx, ctx->stm_hash, 20);
751         SHA1_Update(&sha_ctx, ctx->lcp_policy_control, 4);
752         SHA1_Update(&sha_ctx, ctx->lcp_policy_hash, 20);
753         SHA1_Update(&sha_ctx, ctx->capabilities, 4);
754         SHA1_Final(digest, &sha_ctx);
755         extend(17, digest);
756         if (verbose > 0) {
757             DEBUG("PCR17(mle v6)\n");
758             debugPrintHex("  bios_acm_id        : ", ctx->bios_acm_id, 20, "\n");
759             debugPrintHex("  mseg_valid         : ", ctx->mseg_valid, 8, "\n");
760             debugPrintHex("  stm_hash           : ", ctx->stm_hash, 20, "\n");
761             debugPrintHex("  lcp_policy_control : ", ctx->lcp_policy_control, 4, "\n");
762             debugPrintHex("  lcp_policy_hash    : ", ctx->lcp_policy_hash, 20, "\n");
763             debugPrintHex("  capabilities       : ", ctx->capabilities, 4, "\n");
764             debugPrintHex("  extend             : ", digest, 20, "\n");
765             debugPrintHex("  PCR[17]            : ", &pcr[17][0], 20, "\n");
766         }
767     } else if (ctx->mle_version == 7) {
768         DEBUG("mle v7\n");
769         // Extend(Hidden Value)
770         // SinitMleData.SinitHash = PCR17
771         // Extend(SHA-1(SinitMleData.BiosAcm.ID |
772         //              SinitMleData.MsegValid |
773         //              SinitMleData.StmHash |
774         //              SinitMleData.PolicyControl |
775         //              SinitMleData.LcpPolicyHash |
776         //              (OsSinitData.Capabilities, 0)))
777         //
778         // SHA-1(SinitMleData.SinitHash |
779         //       SHA-1( SinitMleData.BiosAcm.ID |
780         //              SinitMleData.MsegValid |
781         //              SinitMleData.StmHash |
782         //              SinitMleData.PolicyControl |
783         //              SinitMleData.LcpPolicyHash |
784         //              (OsSinitData.Capabilities, 0)))
785
786         // SHA256(sinit)
787         SHA1_Init(&sha_ctx);
788         SHA1_Update(&sha_ctx, ctx->sinit_hash256_from_file, 32);
789         SHA1_Update(&sha_ctx, ctx->edx_senter_flags, 4);
790         SHA1_Final(digest, &sha_ctx);
791         extend(17, digest);
792         if (verbose > 0) {
793             DEBUG("PCR17(mle v6)\n");
794             debugPrintHex("  sinit_hash         : ", ctx->sinit_hash256_from_file, 32, "\n");
795             debugPrintHex("  edx_senter_flags   : ", ctx->edx_senter_flags, 4, "\n");
796             debugPrintHex("  extend             : ", digest, 20, "\n");
797             debugPrintHex("  PCR[17]            : ", &pcr[17][0], 20, "\n");
798         }
799
800         // extend(17, ctx->sinit_hash256_from_file);
801         // extend(17, ctx->sinit_hash_from_file);
802         // debugPrintHex("  mle v7 PCR17 ", &pcr[17][0], 20, "  (SINIT ACM)\n");
803
804         // Force
805         resetPcrWithSecret(17, ctx->sinit_hash);
806         debugPrintHex("  SINIT hash   ", ctx->sinit_hash, 20, "\n");
807         debugPrintHex("  mle v7 PCR17 ", &pcr[17][0], 20, "\n");
808         //
809         SHA1_Init(&sha_ctx);
810         SHA1_Update(&sha_ctx, ctx->bios_acm_id, 20);
811         SHA1_Update(&sha_ctx, ctx->mseg_valid, 8);
812         SHA1_Update(&sha_ctx, ctx->stm_hash, 20);
813         SHA1_Update(&sha_ctx, ctx->lcp_policy_control, 4);
814         SHA1_Update(&sha_ctx, ctx->lcp_policy_hash, 20);
815         SHA1_Update(&sha_ctx, ctx->capabilities, 4);
816         SHA1_Final(digest, &sha_ctx);
817         extend(17, digest);
818         debugPrintHex("  mle v7 PCR17 ", &pcr[17][0], 20, "\n");
819     } else if (ctx->mle_version == 8) {
820         DEBUG("mle v8\n");
821         // PCR17 = ???
822         // SHA-1(SinitMleData.SinitHash |
823         //       SHA-1(SinitMleData.BiosAcm.ID |
824         //             SinitMleData.MsegValid |
825         //             SinitMleData.StmHash |
826         //             SinitMleData.PolicyControl |
827         //             SinitMleData.LcpPolicyHash |
828         //             (OsSinitData.Capabilities, 0) |
829         //             SinitMleData.ProcessorSCRTMStatus))  << added
830
831         // SHA256(sinit)
832         extend(17, ctx->sinit_hash256_from_file);
833         debugPrintHex("  mle v8 PCR17 ", &pcr[17][0], 20, "\n");
834
835         // Force
836         // resetPcrWithSecret(17, ctx->sinit_hash);
837         //
838         SHA1_Init(&sha_ctx);
839         SHA1_Update(&sha_ctx, ctx->bios_acm_id, 20);
840         SHA1_Update(&sha_ctx, ctx->mseg_valid, 8);
841         SHA1_Update(&sha_ctx, ctx->stm_hash, 20);
842         SHA1_Update(&sha_ctx, ctx->lcp_policy_control, 4);
843         SHA1_Update(&sha_ctx, ctx->lcp_policy_hash, 20);
844         SHA1_Update(&sha_ctx, ctx->capabilities, 4);
845         SHA1_Update(&sha_ctx, ctx->ProcessorSCRTMStatus, 4);
846         SHA1_Final(digest, &sha_ctx);
847         extend(17, digest);
848         debugPrintHex("  mle v8 PCR17 ", &pcr[17][0], 20, "\n");
849     } else {
850         ERROR("mle_version = %d \n", ctx->mle_version);
851     }
852
853     extend(18, ctx->mle_hash);
854
855 #if 0
856     printHex("PCR-17", &pcr[17][0], 20, "\n");
857     printHex("PCR-18", &pcr[18][0], 20, "\n");
858     printHex("PCR-19", &pcr[19][0], 20, "\n");
859 #endif
860
861     extend(17, ctx->vl_pcr17);
862     debugPrintHex("  extend  : ", ctx->vl_pcr17, 20, "\n");
863     debugPrintHex("  PCR[17] : ", &pcr[17][0], 20, "\n");
864
865     extend(18, ctx->vl_pcr18);
866     debugPrintHex("  extend  : ", ctx->vl_pcr18, 20, "\n");
867     debugPrintHex("  PCR[18] : ", &pcr[18][0], 20, "\n");
868
869     extend(19, ctx->vl_pcr19);
870     debugPrintHex("  extend  : ", ctx->vl_pcr19, 20, "\n");
871     debugPrintHex("  PCR[19] : ", &pcr[19][0], 20, "\n");
872
873 #if 0
874     printHex("PCR-17", &pcr[17][0], 20, "\n");
875     printHex("PCR-18", &pcr[18][0], 20, "\n");
876     printHex("PCR-19", &pcr[19][0], 20, "\n");
877 #endif
878
879     /* check PCR values after DRTM */
880
881     /* check (within TXT-STAT) */
882     if (memcmp(&pcr[17][0], ctx->final_pcr17, 20) != 0) {
883         ERROR("bad PCR17\n");
884         printHex("PCR-17", &pcr[17][0], 20, "\n");
885         rc = PTS_FATAL;
886     }
887     if (memcmp(&pcr[18][0], ctx->final_pcr18, 20) != 0) {
888         ERROR("bad PCR18\n");
889         printHex("PCR-18", &pcr[18][0], 20, "\n");
890         rc = PTS_FATAL;
891     }
892     // TODO check PCR19 - with PCRs
893
894     return rc;
895 }
896
897
898 /**
899  * writeEvent
900  */
901 int writeEvent(FILE *fp, TSS_PCR_EVENT *event) {
902     int rc = 0;
903     rc = fwrite((BYTE *)&event->ulPcrIndex, 1, 4, fp);     // PCR index
904     rc = fwrite((BYTE *)&event->eventType, 1, 4, fp);      // Event type
905     rc = fwrite(event->rgbPcrValue, 1, 20, fp);   // PCR
906     rc = fwrite((BYTE *)&event->ulEventLength, 1, 4, fp);  // EventData length
907     if ((event->rgbEvent != NULL) && (event->ulEventLength > 0)) {
908         rc = fwrite(event->rgbEvent, 1, event->ulEventLength, fp);  // EventData
909     }
910     return rc;
911 }
912
913 /**
914  *
915  * filename IML(binary) file
916  */
917 int generateEventlog(OPENPTS_TBOOT_CONTEXT *ctx, char *filename) {
918     int rc = PTS_SUCCESS;
919     FILE *fp;
920     TSS_PCR_EVENT *event;
921     SHA_CTX sha_ctx;
922
923     DEBUG("generateEventlog() - filename = %s\n", filename);
924
925     /* open */
926     if (filename != NULL) {
927         /* open */
928         if ((fp = fopen(filename, "wb")) == NULL) {
929             ERROR("generateEventlog - %s file can't open\n", filename);
930             return PTS_FATAL;  // TODO
931         }
932     } else {
933         fp = stdout;
934     }
935
936     /* event  */
937     event = malloc(sizeof(TSS_PCR_EVENT));
938     if (event == NULL) {
939         ERROR("no memory");
940         goto free;
941     }
942     memset(event, 0, sizeof(TSS_PCR_EVENT));
943
944     /* PCR/digest */
945     event->rgbPcrValue = malloc(20);
946     if (event->rgbPcrValue == NULL) {
947         ERROR("no memory");
948         goto free;
949     }
950
951     /* */
952     if (ctx->mle_version == 6) {
953         OPENPTS_EVENT_TBOOT_SINIT_V6 data0;
954         OPENPTS_EVENT_TBOOT_STM_V6 data1;
955
956         event->ulPcrIndex = 17;
957         event->eventType = EV_TBOOT_SINIT_V6;
958         memcpy(data0.sinit_hash, ctx->sinit_hash, 20);
959         memcpy(data0.edx_senter_flags, ctx->edx_senter_flags, 4);
960         event->ulEventLength = 24;
961         event->rgbEvent = (BYTE *)&data0;
962         SHA1_Init(&sha_ctx);
963         SHA1_Update(&sha_ctx, event->rgbEvent, event->ulEventLength);
964         SHA1_Final(event->rgbPcrValue, &sha_ctx);
965         writeEvent(fp, event);
966
967
968         event->ulPcrIndex = 17;
969         event->eventType = EV_TBOOT_STM_V6;
970         memcpy(data1.bios_acm_id, ctx->bios_acm_id, 20);
971         memcpy(data1.mseg_valid, ctx->mseg_valid, 8);
972         memcpy(data1.stm_hash, ctx->stm_hash, 20);
973         memcpy(data1.lcp_policy_control, ctx->lcp_policy_control, 4);
974         memcpy(data1.lcp_policy_hash, ctx->lcp_policy_hash, 20);
975         memcpy(data1.capabilities, ctx->capabilities, 4);
976         event->ulEventLength = 76;
977         event->rgbEvent = (BYTE *)&data1;
978         SHA1_Init(&sha_ctx);
979         SHA1_Update(&sha_ctx, event->rgbEvent, event->ulEventLength);
980         SHA1_Final(event->rgbPcrValue, &sha_ctx);
981         writeEvent(fp, event);
982     } else if (ctx->mle_version == 7) {
983         DEBUG("TBD mle_version = %d \n", ctx->mle_version);
984         OPENPTS_EVENT_TBOOT_SINIT_V7 data0;
985         OPENPTS_EVENT_TBOOT_STM_V6 data1;
986
987         event->ulPcrIndex = 17;
988         event->eventType = EV_TBOOT_SINIT_V7;
989         memcpy(data0.sinit_hash, ctx->sinit_hash256_from_file, 32);
990         memcpy(data0.edx_senter_flags, ctx->edx_senter_flags, 4);
991         event->ulEventLength = 36;
992         event->rgbEvent = (BYTE *)&data0;
993         SHA1_Init(&sha_ctx);
994         SHA1_Update(&sha_ctx, event->rgbEvent, event->ulEventLength);
995         SHA1_Final(event->rgbPcrValue, &sha_ctx);
996         writeEvent(fp, event);
997
998
999         event->ulPcrIndex = 17;
1000         event->eventType = EV_TBOOT_STM_V6;
1001         memcpy(data1.bios_acm_id, ctx->bios_acm_id, 20);
1002         memcpy(data1.mseg_valid, ctx->mseg_valid, 8);
1003         memcpy(data1.stm_hash, ctx->stm_hash, 20);
1004         memcpy(data1.lcp_policy_control, ctx->lcp_policy_control, 4);
1005         memcpy(data1.lcp_policy_hash, ctx->lcp_policy_hash, 20);
1006         memcpy(data1.capabilities, ctx->capabilities, 4);
1007         event->ulEventLength = 76;
1008         event->rgbEvent = (BYTE *)&data1;
1009         SHA1_Init(&sha_ctx);
1010         SHA1_Update(&sha_ctx, event->rgbEvent, event->ulEventLength);
1011         SHA1_Final(event->rgbPcrValue, &sha_ctx);
1012         writeEvent(fp, event);
1013
1014
1015     } else if (ctx->mle_version == 8) {
1016          TODO("TBD mle_version = %d \n", ctx->mle_version);
1017     } else {
1018          TODO("TBD mle_version = %d \n", ctx->mle_version);
1019     }
1020
1021
1022     event->ulPcrIndex = 18;
1023     event->eventType = EV_TBOOT_MLE_HASH;
1024     event->ulEventLength = 0;
1025     memcpy(event->rgbPcrValue, ctx->mle_hash, 20);
1026     writeEvent(fp, event);
1027
1028
1029     /* TBOOT Policy => PCR17 */
1030     {
1031         OPENPTS_EVENT_TBOOT_POLCTL polctl;
1032
1033         // ctx->pol_control[0] = 1;  // TODO extend PCR17
1034         // ctx->pol_control[1] = 0;
1035         // ctx->pol_control[2] = 0;
1036         // ctx->pol_control[3] = 0;
1037
1038         // SHA1_Init(&sha_ctx);
1039         // SHA1_Update(&sha_ctx, ctx->pol_control, 4);
1040         // SHA1_Update(&sha_ctx, ctx->pol_hash, 20);
1041         // SHA1_Final(digest, &sha_ctx);
1042         // extend(17, digest);
1043
1044         // DEBUG("PCR17 \n");
1045         // printHex("PCR-17", digest, 20, "\n");
1046         // printHex("PCR-17", ctx->vl_pcr17, 20, "\n");
1047
1048         event->ulPcrIndex = 17;
1049         event->eventType = EV_TBOOT_POLCTL;
1050         event->ulEventLength = 24;
1051         event->rgbEvent = (BYTE *)&polctl;
1052         memcpy(&polctl.pol_control, ctx->pol_control, 4);
1053         memcpy(&polctl.pol_hash, ctx->pol_hash, 20);
1054         memcpy(event->rgbPcrValue, ctx->vl_pcr17, 20);
1055         writeEvent(fp, event);
1056     }
1057
1058
1059     /* Module[0] */
1060     DEBUG("  module[0]\n");
1061     event->ulPcrIndex = 18;
1062     event->eventType = EV_TBOOT_MODULE;
1063     if (ctx->module != NULL) {
1064         TBOOT_MODULE *module;
1065         OPENPTS_EVENT_TBOOT_MODULE *eventdata;
1066         BYTE *ptr;
1067
1068         module = ctx->module;
1069         if (memcmp(module->digest, ctx->vl_pcr18, 20) != 0) {
1070             ERROR("Module[0] digest did not match\n");
1071             debugPrintHex("  TXT-STAT : ", ctx->vl_pcr18, 20, "\n");
1072             debugPrintHex("  Calc     : ", module->digest, 20, "\n");
1073         }
1074         eventdata = module->eventdata;
1075         event->ulEventLength = 20 + 20 + 4 + 4 + eventdata->command_size + eventdata->filename_size;
1076         event->rgbEvent = malloc(event->ulEventLength);
1077         if (event->rgbEvent == NULL) {
1078             ERROR("no memory");
1079             goto free;
1080         }
1081         ptr = event->rgbEvent;
1082         memcpy(ptr, eventdata->command_hash, 20);
1083         ptr += 20;
1084         memcpy(ptr, eventdata->file_hash, 20);
1085         ptr += 20;
1086         memcpy(ptr, &eventdata->command_size, 4);
1087         ptr += 4;
1088         memcpy(ptr, eventdata->command, eventdata->command_size);
1089         ptr += eventdata->command_size;
1090         memcpy(ptr, &eventdata->filename_size, 4);
1091         ptr += 4;
1092         memcpy(ptr, eventdata->filename, eventdata->filename_size);
1093         // DEBUG("%s\n", eventdata->command);
1094         // DEBUG("%s\n", eventdata->filename);
1095     } else {
1096         event->ulEventLength = 0;
1097         event->rgbEvent = NULL;
1098         DEBUG("  module[0] eventdata = null, check the default value in the grub.conf\n");
1099     }
1100     memcpy(event->rgbPcrValue, ctx->vl_pcr18, 20);
1101     writeEvent(fp, event);
1102
1103     /* Module[1] */
1104     DEBUG("  module[1]\n");
1105     event->ulPcrIndex = 19;
1106     event->eventType = EV_TBOOT_MODULE;
1107     if ((ctx->module != NULL) && (ctx->module->next != NULL)) {
1108         TBOOT_MODULE *module;
1109         OPENPTS_EVENT_TBOOT_MODULE *eventdata;
1110         BYTE *ptr;
1111
1112         module = ctx->module->next;
1113         if (memcmp(module->digest, ctx->vl_pcr19, 20) != 0) {
1114             ERROR("Module[1] digest did not match\n");
1115             debugPrintHex("  TXT-STAT : ", ctx->vl_pcr19, 20, "\n");
1116             debugPrintHex("  Calc     : ", module->digest, 20, "\n");
1117         }
1118         eventdata = module->eventdata;
1119         event->ulEventLength = 20 + 20 + 4 + 4 + eventdata->command_size + eventdata->filename_size;
1120         if (event->rgbEvent != NULL) free(event->rgbEvent);
1121         event->rgbEvent = malloc(event->ulEventLength);
1122         if (event->rgbEvent == NULL) {
1123             ERROR("no memory");
1124             goto free;
1125         }
1126         ptr = event->rgbEvent;
1127         memcpy(ptr, eventdata->command_hash, 20);
1128         ptr += 20;
1129         memcpy(ptr, eventdata->file_hash, 20);
1130         ptr += 20;
1131         memcpy(ptr, &eventdata->command_size, 4);
1132         ptr += 4;
1133         memcpy(ptr, eventdata->command, eventdata->command_size);
1134         ptr += eventdata->command_size;
1135         memcpy(ptr, &eventdata->filename_size, 4);
1136         ptr += 4;
1137         memcpy(ptr, eventdata->filename, eventdata->filename_size);
1138         // DEBUG("%s\n", eventdata->command);
1139         // DEBUG("%s\n", eventdata->filename);
1140     } else {
1141         event->ulEventLength = 0;
1142         event->rgbEvent = NULL;
1143         DEBUG("  module[0] eventdata = null, check the default value in the grub.conf\n");
1144     }
1145     memcpy(event->rgbPcrValue, ctx->vl_pcr19, 20);
1146     writeEvent(fp, event);
1147
1148
1149   free:
1150     if (event != NULL) {
1151         if (event->rgbPcrValue != NULL) free(event->rgbPcrValue);
1152         if (event->rgbEvent != NULL) free(event->rgbEvent);
1153         free(event);
1154     }
1155
1156     /* close */
1157     if (filename != NULL) {
1158         fclose(fp);
1159     }
1160     return rc;
1161 }
1162
1163
1164
1165 void usage(void) {
1166     fprintf(stderr, "OpenPTS command\n\n");
1167     fprintf(stderr, "Usage: tboot2iml [options]\n\n");
1168     fprintf(stderr, "Options:\n");
1169     fprintf(stderr, "  -i filename           txt-stat file to read (default is STDIN)\n");
1170     fprintf(stderr, "  -g filename           grub.conf file to read (OPTION)\n");
1171     fprintf(stderr, "  -p path               grub path (OPTION)\n");
1172     fprintf(stderr, "  -o filename           Output to file (default is STDOUT)\n");
1173     fprintf(stderr, "  -v                    Verbose message\n");
1174     fprintf(stderr, "  -h                    Help\n");
1175     fprintf(stderr, "\n");
1176 }
1177
1178 int main(int argc, char *argv[]) {
1179     int c;
1180     char *txt_stat_filename = NULL;
1181     char *grub_conf_filename = NULL;
1182     char *iml_filename = NULL;
1183     OPENPTS_TBOOT_CONTEXT *ctx = NULL;
1184     int rc;
1185     char *grub_path = NULL;  // TODO
1186
1187
1188     while ((c = getopt(argc, argv, "i:g:p:o:vh")) != EOF) {
1189         switch (c) {
1190         case 'i':       /* input file name */
1191             txt_stat_filename = optarg;
1192             break;
1193         case 'g':       /* input file name */
1194             grub_conf_filename = optarg;
1195             break;
1196         case 'p':       /* input file name */
1197             grub_path = optarg;
1198             break;
1199         case 'o':       /* output file name */
1200             iml_filename = optarg;
1201             break;
1202         case 'v':       /*  */
1203             verbose = DEBUG_FLAG;
1204             break;
1205         case 'h':       /* help */
1206             usage();
1207             goto close;
1208         default:
1209             usage();
1210             goto close;
1211         }
1212     }
1213
1214     // printf("tboot to IML (%s)\n", txt_stat_filename);
1215
1216     /* check */
1217     if ((grub_conf_filename != NULL) && (grub_path == NULL)) {
1218         fprintf(stderr, "set the root path used by crub.conf\n");
1219         usage();
1220         goto close;
1221     }
1222
1223     /* ctx */
1224     ctx = malloc(sizeof(OPENPTS_TBOOT_CONTEXT));
1225     memset(ctx, 0, sizeof(OPENPTS_TBOOT_CONTEXT));
1226     ctx->lcp_policy_version = 1;
1227
1228     /* parse TXT stat */
1229     rc = parseTxtStatFile(ctx, txt_stat_filename);
1230     if (rc != PTS_SUCCESS) {
1231         ERROR("parse of %s file was failed\n", txt_stat_filename);
1232     }
1233
1234     /* parse grub.conf */
1235     if (grub_conf_filename != NULL) {
1236         rc = parseGrubConfFile(ctx, grub_conf_filename, grub_path);
1237     }
1238
1239     /* parse grub.conf */
1240     // TODO
1241
1242     /* validate IML and PCRs */
1243     rc = emulateTboot(ctx);
1244
1245     // ctx = malloc(sizeof(OPENPTS_TBOOT_CONTEXT));
1246
1247
1248     /* generate IML */
1249     rc = generateEventlog(ctx, iml_filename);
1250
1251
1252   close:
1253     free(ctx);
1254     return 0;
1255 }