OSDN Git Service

0bb597968fc800a1348683169f38e470c2c202a8
[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         OUTPUT("%s", head);
82         for (i = 0; i < num; i++) {
83             OUTPUT("%02X", data[i]);
84         }
85         OUTPUT("%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             LOG(LOG_ERR, "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 = xmalloc(size);
476     if (acmbuf == NULL) {
477         rc = PTS_FATAL;
478         goto error;
479     }
480     memset(acmbuf, 0, size);
481
482     /* open */
483     fp = fopen(filename, "rb");
484     if (fp == NULL) {
485         LOG(LOG_ERR, "File %s does not exist\n", filename);
486         rc = PTS_FATAL;
487         goto error;
488     }
489
490     /* load */
491     ptr = acmbuf;
492     do {
493         len = fread(buf, 1, sizeof(buf), fp);
494
495         if ( len == 0 )
496             break;
497         memcpy(ptr, buf, len);
498         ptr += len;
499     } while ( 1 );
500
501     /* close */
502     fclose(fp);
503
504     /* check */
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);
513
514     SHA1_Init(&sha_ctx);
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);
518
519     debugPrintHex(" SHA1 Digest   : ", sha1_digest, 20, "\n");
520
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);
525
526     debugPrintHex(" SHA256 Digest : ", sha256_digest, 32, "\n");
527
528   error:
529     xfree(acmbuf);
530     return rc;
531 }
532
533
534 int sha1sum_unzip(char *filename, int *filesize, BYTE *digest) {
535     FILE *fp;
536     char buf[2048];
537     SHA_CTX sha_ctx;
538     int len;
539     int rdCnt = 0;
540     int is_sinit_acm = 0;
541     int size = 0;
542
543     /* open */
544     fp = gzopen(filename, "rb");
545     if (fp == NULL) {
546         LOG(LOG_ERR, "File %s does not exist\n", filename);
547         return 0;
548     }
549
550     /* calc */
551     SHA1_Init(&sha_ctx);
552     do {
553         len = gzread(fp, buf, sizeof(buf));
554         if ((rdCnt == 0) && (len > 1216 + 16)) {
555             is_sinit_acm = checkSinitAcm((BYTE *)buf);
556         }
557
558         if ( len == 0 )
559             break;
560         SHA1_Update(&sha_ctx, buf, len);
561         rdCnt++;
562         size += len;
563     } while ( 1 );
564
565     SHA1_Final(digest, &sha_ctx);
566
567     /* close */
568     gzclose(fp);
569     *filesize = size;
570     return is_sinit_acm;
571 }
572
573 /**
574  * parse grub.conf file
575  *
576  * just check the default setting
577  */
578 int parseGrubConfFile(OPENPTS_TBOOT_CONTEXT *ctx, char *filename, char *path) {
579     int rc = PTS_SUCCESS;
580     FILE *fp;
581     char line[1024];
582     int default_num = 0;
583     int count = -1;
584     int module_count = 0;
585     char *ptr;
586     char *module_filename;
587     char *module_option;
588     SHA_CTX sha_ctx;
589     TBOOT_MODULE *prev_module = NULL;
590     int is_sinit_acm;
591     int size;
592
593     /* open */
594     if ((fp = fopen(filename, "r")) == NULL) {
595         LOG(LOG_ERR, "parseTxtStatFile - %s file is missing\n", filename);
596         return PTS_FATAL;  // TODO
597     }
598
599     /**/
600     /* line by line */
601     while (fgets(line, sizeof(line), fp) != NULL) {  // read line
602         // default=0
603         if (!strncmp(line, "default=", 8)) {
604             default_num = atoi(&line[8]);
605             DEBUG("default_num = %d\n", default_num);
606         }
607
608         // title Fedora (2.6.38.1-6.fc15.x86_64) tboot
609         if (!strncmp(line, "title", 5)) {
610             count = count + 1;
611             module_count = 0;
612             DEBUG("title[%d] : %s", count, line);
613         } else if (default_num == count) {
614             ptr = skipspace(line);
615             DEBUG("%s", ptr);
616             // root (hd0,0)
617             // kernel /tboot.gz logging=serial,vga,memory vga_delay=5
618             // TODO
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;
629                 module->next = NULL;
630                 if (prev_module == NULL) {
631                     /* 1st */
632                     ctx->module = module;
633                 } else {
634                     prev_module->next = module;
635                 }
636
637                 /* filename */
638                 if (ptr[7] == '/') {
639                     // skip root
640                     module_filename = &ptr[8];
641                 } else {
642                     module_filename = &ptr[7];
643                 }
644
645                 /* option */
646                 ptr = skip2space(&ptr[7]);
647                 if (ptr != NULL) {
648                     *ptr = 0;
649                     eventdata->filename = getFullpathName(path, module_filename);
650                     eventdata->filename_size = strlen(eventdata->filename);
651                     ptr++;
652                     module_option = ptr;
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);
658                 } else {
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);
666                 }
667
668
669
670                 is_sinit_acm = sha1sum_unzip(eventdata->filename, &size, eventdata->file_hash);
671                 if (is_sinit_acm == 1) {
672                     // calc hash of SINIT ACM
673                     sinit_acm_hash(
674                         eventdata->filename,
675                         size,
676                         ctx->sinit_hash_from_file,
677                         ctx->sinit_hash256_from_file);
678                 } else {
679                     // Kernel or Initrd
680                     debugPrintHex(" SHA1(file)    : ", eventdata->file_hash, 20, "\n");
681
682                     SHA1_Init(&sha_ctx);
683                     SHA1_Update(&sha_ctx, eventdata->command, eventdata->command_size);
684                     SHA1_Final(eventdata->command_hash, &sha_ctx);
685
686                     debugPrintHex(" SHA1(command) : ", eventdata->command_hash, 20, "\n");
687
688                     SHA1_Init(&sha_ctx);
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);
692
693                     debugPrintHex(" extend        : ", module->digest, 20, "\n");
694                 }
695
696                 prev_module = module;
697                 module_count++;
698                 ctx->module_num++;
699             }
700         }
701     }  // line
702
703     /* close */
704     fclose(fp);
705     return rc;
706 }
707
708 /**
709  * Verify Tboot Measurement
710  *
711  * setup OPENPTS_TBOOT_CONTEXT before call this
712  */
713 int emulateTboot(OPENPTS_TBOOT_CONTEXT *ctx) {
714     int rc = PTS_SUCCESS;
715     SHA_CTX sha_ctx;
716     unsigned char digest[20];
717
718     DEBUG("emulateTboot()\n");
719
720     resetPcr();
721
722     // PCR 17
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))
727         SHA1_Init(&sha_ctx);
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);
731         extend(17, digest);
732         if (verbose > 0) {
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");
738         }
739
740         // Extend(SHA-1(SinitMleData.BiosAcm.ID |
741         //              SinitMleData.MsegValid |
742         //              SinitMleData.StmHash |
743         //              SinitMleData.PolicyControl |
744         //              SinitMleData.LcpPolicyHash |
745         //              (OsSinitData.Capabilities, 0)))
746         SHA1_Init(&sha_ctx);
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);
754         extend(17, digest);
755         if (verbose > 0) {
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");
765         }
766     } else if (ctx->mle_version == 7) {
767         DEBUG("mle v7\n");
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)))
776         //
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)))
784
785         // SHA256(sinit)
786         SHA1_Init(&sha_ctx);
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);
790         extend(17, digest);
791         if (verbose > 0) {
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");
797         }
798
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");
802
803         // Force
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");
807         //
808         SHA1_Init(&sha_ctx);
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);
816         extend(17, digest);
817         debugPrintHex("  mle v7 PCR17 ", &pcr[17][0], 20, "\n");
818     } else if (ctx->mle_version == 8) {
819         DEBUG("mle v8\n");
820         // PCR17 = ???
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
829
830         // SHA256(sinit)
831         extend(17, ctx->sinit_hash256_from_file);
832         debugPrintHex("  mle v8 PCR17 ", &pcr[17][0], 20, "\n");
833
834         // Force
835         // resetPcrWithSecret(17, ctx->sinit_hash);
836         //
837         SHA1_Init(&sha_ctx);
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);
846         extend(17, digest);
847         debugPrintHex("  mle v8 PCR17 ", &pcr[17][0], 20, "\n");
848     } else {
849         LOG(LOG_ERR, "mle_version = %d \n", ctx->mle_version);
850     }
851
852     extend(18, ctx->mle_hash);
853
854 #if 0
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");
858 #endif
859
860     extend(17, ctx->vl_pcr17);
861     debugPrintHex("  extend  : ", ctx->vl_pcr17, 20, "\n");
862     debugPrintHex("  PCR[17] : ", &pcr[17][0], 20, "\n");
863
864     extend(18, ctx->vl_pcr18);
865     debugPrintHex("  extend  : ", ctx->vl_pcr18, 20, "\n");
866     debugPrintHex("  PCR[18] : ", &pcr[18][0], 20, "\n");
867
868     extend(19, ctx->vl_pcr19);
869     debugPrintHex("  extend  : ", ctx->vl_pcr19, 20, "\n");
870     debugPrintHex("  PCR[19] : ", &pcr[19][0], 20, "\n");
871
872 #if 0
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");
876 #endif
877
878     /* check PCR values after DRTM */
879
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");
884         rc = PTS_FATAL;
885     }
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");
889         rc = PTS_FATAL;
890     }
891     // TODO check PCR19 - with PCRs
892
893     return rc;
894 }
895
896
897 /**
898  * writeEvent
899  */
900 int writeEvent(FILE *fp, TSS_PCR_EVENT *event) {
901     int rc = 0;
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
908     }
909     return rc;
910 }
911
912 /**
913  *
914  * filename IML(binary) file
915  */
916 int generateEventlog(OPENPTS_TBOOT_CONTEXT *ctx, char *filename) {
917     int rc = PTS_SUCCESS;
918     FILE *fp;
919     TSS_PCR_EVENT *event;
920     SHA_CTX sha_ctx;
921
922     DEBUG("generateEventlog() - filename = %s\n", filename);
923
924     /* open */
925     if (filename != NULL) {
926         /* open */
927         if ((fp = fopen(filename, "wb")) == NULL) {
928             LOG(LOG_ERR, "generateEventlog - %s file can't open\n", filename);
929             return PTS_FATAL;  // TODO
930         }
931     } else {
932         fp = stdout;
933     }
934
935     /* event  */
936     event = xmalloc(sizeof(TSS_PCR_EVENT));
937     if (event == NULL) {
938         goto free;
939     }
940     memset(event, 0, sizeof(TSS_PCR_EVENT));
941
942     /* PCR/digest */
943     event->rgbPcrValue = xmalloc(20);
944     if (event->rgbPcrValue == NULL) {
945         goto free;
946     }
947
948     /* */
949     if (ctx->mle_version == 6) {
950         OPENPTS_EVENT_TBOOT_SINIT_V6 data0;
951         OPENPTS_EVENT_TBOOT_STM_V6 data1;
952
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;
959         SHA1_Init(&sha_ctx);
960         SHA1_Update(&sha_ctx, event->rgbEvent, event->ulEventLength);
961         SHA1_Final(event->rgbPcrValue, &sha_ctx);
962         writeEvent(fp, event);
963
964
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;
975         SHA1_Init(&sha_ctx);
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;
983
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;
990         SHA1_Init(&sha_ctx);
991         SHA1_Update(&sha_ctx, event->rgbEvent, event->ulEventLength);
992         SHA1_Final(event->rgbPcrValue, &sha_ctx);
993         writeEvent(fp, event);
994
995
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);
1010
1011
1012     } else if (ctx->mle_version == 8) {
1013          LOG(LOG_TODO, "TBD mle_version = %d \n", ctx->mle_version);
1014     } else {
1015          LOG(LOG_TODO, "TBD mle_version = %d \n", ctx->mle_version);
1016     }
1017
1018
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);
1024
1025
1026     /* TBOOT Policy => PCR17 */
1027     {
1028         OPENPTS_EVENT_TBOOT_POLCTL polctl;
1029
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;
1034
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);
1040
1041         // DEBUG("PCR17 \n");
1042         // printHex("PCR-17", digest, 20, "\n");
1043         // printHex("PCR-17", ctx->vl_pcr17, 20, "\n");
1044
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);
1053     }
1054
1055
1056     /* Module[0] */
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;
1063         BYTE *ptr;
1064
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");
1070         }
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) {
1075             goto free;
1076         }
1077         ptr = event->rgbEvent;
1078         memcpy(ptr, eventdata->command_hash, 20);
1079         ptr += 20;
1080         memcpy(ptr, eventdata->file_hash, 20);
1081         ptr += 20;
1082         memcpy(ptr, &eventdata->command_size, 4);
1083         ptr += 4;
1084         memcpy(ptr, eventdata->command, eventdata->command_size);
1085         ptr += eventdata->command_size;
1086         memcpy(ptr, &eventdata->filename_size, 4);
1087         ptr += 4;
1088         memcpy(ptr, eventdata->filename, eventdata->filename_size);
1089         // DEBUG("%s\n", eventdata->command);
1090         // DEBUG("%s\n", eventdata->filename);
1091     } else {
1092         event->ulEventLength = 0;
1093         event->rgbEvent = NULL;
1094         DEBUG("  module[0] eventdata = null, check the default value in the grub.conf\n");
1095     }
1096     memcpy(event->rgbPcrValue, ctx->vl_pcr18, 20);
1097     writeEvent(fp, event);
1098
1099     /* Module[1] */
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;
1106         BYTE *ptr;
1107
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");
1113         }
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) {
1119             goto free;
1120         }
1121         ptr = event->rgbEvent;
1122         memcpy(ptr, eventdata->command_hash, 20);
1123         ptr += 20;
1124         memcpy(ptr, eventdata->file_hash, 20);
1125         ptr += 20;
1126         memcpy(ptr, &eventdata->command_size, 4);
1127         ptr += 4;
1128         memcpy(ptr, eventdata->command, eventdata->command_size);
1129         ptr += eventdata->command_size;
1130         memcpy(ptr, &eventdata->filename_size, 4);
1131         ptr += 4;
1132         memcpy(ptr, eventdata->filename, eventdata->filename_size);
1133         // DEBUG("%s\n", eventdata->command);
1134         // DEBUG("%s\n", eventdata->filename);
1135     } else {
1136         event->ulEventLength = 0;
1137         event->rgbEvent = NULL;
1138         DEBUG("  module[0] eventdata = null, check the default value in the grub.conf\n");
1139     }
1140     memcpy(event->rgbPcrValue, ctx->vl_pcr19, 20);
1141     writeEvent(fp, event);
1142
1143
1144   free:
1145     if (event != NULL) {
1146         if (event->rgbPcrValue != NULL) xfree(event->rgbPcrValue);
1147         if (event->rgbEvent != NULL) xfree(event->rgbEvent);
1148         xfree(event);
1149     }
1150
1151     /* close */
1152     if (filename != NULL) {
1153         fclose(fp);
1154     }
1155     return rc;
1156 }
1157
1158
1159
1160 void usage(void) {
1161     OUTPUT( // TODO NLS
1162         "OpenPTS command\n\n"
1163         "Usage: tboot2iml [options]\n\n"
1164         "Options:\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"
1170         "  -h                    Help\n"
1171         "\n");
1172 }
1173
1174 int main(int argc, char *argv[]) {
1175     int c;
1176     char *txt_stat_filename = NULL;
1177     char *grub_conf_filename = NULL;
1178     char *iml_filename = NULL;
1179     OPENPTS_TBOOT_CONTEXT *ctx = NULL;
1180     int rc;
1181     char *grub_path = NULL;  // TODO
1182
1183
1184     while ((c = getopt(argc, argv, "i:g:p:o:vh")) != EOF) {
1185         switch (c) {
1186         case 'i':       /* input file name */
1187             txt_stat_filename = optarg;
1188             break;
1189         case 'g':       /* input file name */
1190             grub_conf_filename = optarg;
1191             break;
1192         case 'p':       /* input file name */
1193             grub_path = optarg;
1194             break;
1195         case 'o':       /* output file name */
1196             iml_filename = optarg;
1197             break;
1198         case 'v':       /*  */
1199             verbose = DEBUG_FLAG;
1200             break;
1201         case 'h':       /* help */
1202             usage();
1203             goto close;
1204         default:
1205             usage();
1206             goto close;
1207         }
1208     }
1209
1210     /* check */
1211     if ((grub_conf_filename != NULL) && (grub_path == NULL)) {
1212         ERROR(  // TODO NLS
1213             "set the root path used by crub.conf\n");
1214         usage();
1215         goto close;
1216     }
1217
1218     /* ctx */
1219     ctx = xmalloc_assert(sizeof(OPENPTS_TBOOT_CONTEXT));
1220     memset(ctx, 0, sizeof(OPENPTS_TBOOT_CONTEXT));
1221     ctx->lcp_policy_version = 1;
1222
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);
1227     }
1228
1229     /* parse grub.conf */
1230     if (grub_conf_filename != NULL) {
1231         rc = parseGrubConfFile(ctx, grub_conf_filename, grub_path);
1232     }
1233
1234     /* parse grub.conf */
1235     // TODO
1236
1237     /* validate IML and PCRs */
1238     rc = emulateTboot(ctx);
1239
1240     // ctx = malloc(sizeof(OPENPTS_TBOOT_CONTEXT));
1241
1242
1243     /* generate IML */
1244     rc = generateEventlog(ctx, iml_filename);
1245
1246
1247   close:
1248     xfree(ctx);
1249     return 0;
1250 }