OSDN Git Service

a354f3e36c6f6abf8fda9648cec1d59c14541e96
[openpts/openpts.git] / src / ir2text.c
1 /*
2  * The Initial Developer of the Original Code is International
3  * Business Machines Corporation. Portions created by IBM
4  * Corporation are Copyright (C) 2010 International Business
5  * Machines Corporation. All Rights Reserved.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the Common Public License as published by
9  * IBM Corporation; either version 1 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * Common Public License for more details.
16  *
17  * You should have received a copy of the Common Public License
18  * along with this program; if not, a copy can be viewed at
19  * http://www.opensource.org/licenses/cpl1.0.php.
20  */
21
22 /**
23  * \file src/ir2text.c
24  * \brief Convert IR file to plaintext (or binary)
25  * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
26  * @date 2010-12-01
27  * cleanup 2011-01-22 SM
28  *
29  *  IR(XML) -> SAX -> ctx->snapshot -> print
30  *
31  *  this SAX code is based on ir.c. but remove the dependancy to other code.
32  *
33  */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39
40 #include <libxml/encoding.h>
41 #include <libxml/xmlwriter.h>
42 #include <libxml/parser.h>
43
44 #include <openssl/sha.h>
45
46 #include <tss/tss_structs.h>
47
48 #include <openpts.h>
49
50 /* Convert endian - 32bit */
51 #define econv(x) ((UINT32)( \
52     (((UINT32)(x) & (UINT32)0x000000ffUL) << 24) | \
53     (((UINT32)(x) & (UINT32)0x0000ff00UL) <<  8) | \
54     (((UINT32)(x) & (UINT32)0x00ff0000UL) >>  8) | \
55     (((UINT32)(x) & (UINT32)0xff000000UL) >> 24)))
56
57 #define MAX_DIGEST_SIZE 64
58 #define EVENTDATA_BUF_SIZE 100000
59
60 #define MAX_PCRNUM 24
61 #define SHA1_DIGEST_SIZE 20
62 BYTE pcr[MAX_PCRNUM][SHA1_DIGEST_SIZE];
63
64
65 /* Element tag */
66 #define IR_SAX_STATE_IDOL       0
67 #define IR_SAX_STATE_PCR_INDEX  1
68 #define IR_SAX_STATE_EVENT_TYPE 2
69 #define IR_SAX_STATE_DIGEST     3
70 #define IR_SAX_STATE_EVENT_DATA 4
71 #define IR_SAX_STATE_PCR        5
72
73 typedef struct {
74     /* for SAX parser */
75     int  sax_state;
76     int  sax_error;
77     int  char_size;
78     // char buf[EVENTDATA_BUF_SIZE];  // TODO(munetoh) fixed buffer
79     char *buf;  /**< buffer for the text element */
80     /* IML -> FSM */
81     int  event_index;
82     int  pcr_index;
83     BYTE pcr[MAX_DIGEST_SIZE];
84     TSS_PCR_EVENT *event;
85     /**/
86     FILE *fp; /* output */
87     /* mode */
88     int endian;  // 0:normal 1:convert
89     int aligned;
90     int binary;  // 0: plain text, 1: binary (BIOS format)
91 } IR_CONTEXT;
92
93
94 /* Event table */
95
96 typedef struct {
97     UINT32 type;
98     char *name;
99     int print_mode;
100 } PCR_EVENTTYPE_TABLE;
101
102
103 #define PCR_EVENTDATA_PRINT_NONE   0
104 #define PCR_EVENTDATA_PRINT_HEX    1
105 #define PCR_EVENTDATA_PRINT_STRING 2
106
107 /* event type (TCG) */
108 #define EV_PREBOOT_CERT       0x00
109 #define EV_POST_CODE          0x01
110 #define EV_SEPARATOR          0x04
111 #define EV_EVENT_TAG          0x06
112 #define EV_IPL                0x0d
113 #define EV_IPL_PARTITION_DATA 0x0e
114
115 /* event type (OpenPTS) */
116 #define EV_COLLECTOR_START 0x80
117 #define EV_UPDATE_START       0x81
118 #define EV_NEW_EVENT          0x82
119 #define EV_UPDATE_END         0x83
120 #define EV_FILE_SCAN          0x84
121
122 #define PCR_EVENTTYPE_TABLE_SIZE 11
123
124 PCR_EVENTTYPE_TABLE _event_table[] = {
125     {EV_PREBOOT_CERT,       "EV_PREBOOT_CERT",       PCR_EVENTDATA_PRINT_NONE},
126     {EV_POST_CODE,          "EV_POST_CODE",          PCR_EVENTDATA_PRINT_NONE},
127     {EV_SEPARATOR,          "EV_SEPARATOR",          PCR_EVENTDATA_PRINT_HEX},
128     {EV_EVENT_TAG,          "EV_EVENT_TAG",          PCR_EVENTDATA_PRINT_NONE},
129     {EV_IPL,                "EV_IPL",                PCR_EVENTDATA_PRINT_NONE},
130     {EV_IPL_PARTITION_DATA, "EV_IPL_PARTITION_DATA", PCR_EVENTDATA_PRINT_NONE},
131     /* OpenPTS */
132     {EV_COLLECTOR_START, "EV_COLLECTOR_START", PCR_EVENTDATA_PRINT_HEX},
133     {EV_UPDATE_START,    "EV_UPDATE_START",    PCR_EVENTDATA_PRINT_HEX},
134     {EV_NEW_EVENT,       "EV_NEW_EVENT",       PCR_EVENTDATA_PRINT_NONE},
135     {EV_UPDATE_END,      "EV_UPDATE_END",      PCR_EVENTDATA_PRINT_HEX},
136     {EV_FILE_SCAN,       "EV_FILE_SCAN",       PCR_EVENTDATA_PRINT_NONE}
137 };
138
139
140
141 /**
142  * TPM
143  */
144
145 /**
146  * reset TPM/PCR
147  */
148 int resetPcr() {
149     int i, j;
150     for (i = 0; i < MAX_PCRNUM; i++) {
151         for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
152             pcr[i][j] = 0;
153         }
154     }
155     // no DRTM
156     for (i = 17; i < 23; i++) {
157         for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
158             pcr[i][j] = 0xff;
159         }
160     }
161     return 0;
162 }
163
164
165 /**
166  * extend
167  */
168 int extend(int index, BYTE * digest) {
169     SHA_CTX ctx;
170
171     if (index >= MAX_PCRNUM)
172         return -1;
173
174     // if (index == 10) {  // Linux-IML, 0000... -> FFFF...
175     //     if (isZero(digest) == 1) {
176     //         setFF(digest);
177     //     }
178     // }
179
180     SHA1_Init(&ctx);
181     SHA1_Update(&ctx, &(pcr[index][0]), SHA1_DIGEST_SIZE);
182     SHA1_Update(&ctx, digest, SHA1_DIGEST_SIZE);
183     SHA1_Final(&(pcr[index][0]), &ctx);
184
185     return 0;  // TODO(munetoh)
186 }
187
188
189
190
191 char *getEventName(UINT32 type) {
192     int i;
193
194     for (i = 0; i < PCR_EVENTTYPE_TABLE_SIZE; i++) {
195         if (type == _event_table[i].type) {
196             return _event_table[i].name;
197         }
198     }
199     return NULL;
200 }
201
202 void fprintEventData(FILE *fp, UINT32 type, UINT32 len, BYTE *eventdata) {
203     int i;
204     int j;
205
206     for (i = 0; i < PCR_EVENTTYPE_TABLE_SIZE; i++) {
207         if (type == _event_table[i].type) {
208             /* i know this :-)*/
209             fprintf(fp, "%s", _event_table[i].name);
210
211             /* common */
212             switch (_event_table[i].print_mode) {
213             case PCR_EVENTDATA_PRINT_NONE:
214                 fprintf(fp, "[%d]", len);
215                 break;
216             case PCR_EVENTDATA_PRINT_HEX:
217                 fprintf(fp, "[%d]=0x", len);
218                 for (j = 0; j < (int) len; j++) fprintf(fp, "%02X", eventdata[j]);
219                 break;
220             case PCR_EVENTDATA_PRINT_STRING:
221                 fprintf(fp, " = ");
222                 break;
223             default:
224                 fprintf(fp, "[%d]", len);
225                 break;
226             }
227
228             /* OK done */
229             return;
230         }
231     }
232
233     /* unknown */
234     fprintf(fp, "TBD");
235     return;
236 }
237
238
239 /*
240 <Report xmlns:core="http://www.trustedcomputinggroup.org/XML/SCHEMA/1_0_1/core_integrity#" xmlns:stuff="http://www.trustedcomputinggroup.org/XML/SCHEMA/1_0/simple_object#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.trustedcomputinggroup.org/XML/SCHEMA/1_0/integrity_report#" ID="IR_24868831-1b3c-4eb5-8e15-83b74f54d033" UUID="24868831-1b3c-4eb5-8e15-83b74f54d033">
241   <SnapshotCollection Id="IR_1bd0ac8f-d091-4a14-af05-651386f312a1" UUID="1bd0ac8f-d091-4a14-af05-651386f312a1" RevLevel="0">
242     <core:ComponentID Id="CID_0" ModelSystemClass="745749J" SimpleName="JJ" VersionBuild="1250694000000" VersionString="JJ">
243       <core:VendorID Name="JJ">
244         <core:SmiVendorId>0</core:SmiVendorId>
245         <core:TcgVendorId>DEMO</core:TcgVendorId>
246       </core:VendorID>
247     </core:ComponentID>
248     <core:DigestMethod Algorithm="unknown" Id="sha1"/>
249     <core:Values>
250       <stuff:SimpleSnapshotObject>
251         <stuff:Objects>
252           <stuff:Hash AlgRef="sha1" Id="PCR_0_LV0_8_0_EVENT">VnKCP/hHGXIdJtuXyR1gR7HnqXs=</stuff:Hash>
253           <pcrindex>0</pcrindex>
254           <eventtype>8</eventtype>
255           <eventdata>CAD+//////8FAAAA</eventdata>
256         </stuff:Objects>
257
258     </core:Values>
259     <PcrHash AlgRef="sha1" Id="PCR_0_LV0_HASH" IsResetable="false" Number="0" StartHash="AAAAAAAAAAAAAAAAAAAAAAAAAAA=">j7/z7OqcVMjRxCz+qT1r8BvzQFs=</Pc
260 rHash>
261   </SnapshotCollection>
262
263 */
264
265 // TODO dynamic?
266 #define IR_SAX_BUFFER_SIZE 2048
267
268 /**
269  * SAX parser
270  */
271 void  irStartDocument(void * ctx) {
272     // OPENPTS_CONTEXT * pctx = (OPENPTS_CONTEXT *)ctx;
273     // OPENPTS_IR_CONTEXT * ctx = pctx->ctx;
274     // ctx->sax_error = 0;
275     // ctx->event_index = 0;
276 }
277
278 /**
279  * SAX parser
280  */
281 void  irEndDocument(void * ctx) {
282     // printf("END DOC \n");
283 }
284
285 /**
286  * SAX parser - Start of Element
287  */
288 void  irStartElement(void* context, const xmlChar* name, const xmlChar** atts) {
289     IR_CONTEXT *ctx = (IR_CONTEXT *)context;
290     int i;
291     char *type;
292     char *value;
293
294     ctx->char_size = 0;
295
296     if (!strcmp((char *)name, "Report")) {
297         //
298     } else if (!strcmp((char *)name, "SnapshotCollection")) {
299         //
300     } else if (!strcmp((char *)name, "core:ComponentID")) {
301         //
302     } else if (!strcmp((char *)name, "core:VendorID")) {
303         //
304     } else if (!strcmp((char *)name, "core:TcgVendorId")) {
305         //
306     } else if (!strcmp((char *)name, "core:SmiVendorId")) {
307         //
308     } else if (!strcmp((char *)name, "core:DigestMethod")) {
309         //
310     } else if (!strcmp((char *)name, "core:Values")) {
311         //
312     } else if (!strcmp((char *)name, "stuff:SimpleSnapshotObject")) {
313         //
314     } else if (!strcmp((char *)name, "pcrindex")) {
315         /* stuff:Hash -> PCR value (base64) */
316         // printf("START ELEMENT [%s]  <<<< HASH HASH \n",name);
317         // ctx->sax_state = IR_SAX_STATE_PCR_INDEX;
318     } else if (!strcmp((char *)name, "eventtype")) {
319         // printf("START ELEMENT [%s]  <<<< HASH HASH \n",name);
320         // ctx->sax_state = IR_SAX_STATE_EVENT_TYPE;
321     } else if (!strcmp((char *)name, "stuff:Hash")) {
322         // printf("START ELEMENT [%s]  <<<< DIGEST \n",name);
323         // ctx->sax_state = IR_SAX_STATE_DIGEST;
324     } else if (!strcmp((char *)name, "eventdata")) {
325         // printf("START ELEMENT [%s]  <<<<  EVENT_DATA\n",name);
326         // ctx->sax_state = IR_SAX_STATE_EVENT_DATA;
327     } else if (!strcmp((char *)name, "PcrHash")) {
328         // printf("START ELEMENT [%s]  <<<<  EVENT_DATA\n",name);
329         // ctx->sax_state = IR_SAX_STATE_PCR;
330
331         /* get Number =pcrindex) attribute ( */
332         if (atts != NULL) {
333             for (i = 0;(atts[i] != NULL);i++) {
334                 type = (char *)atts[i++];
335                 // printf(", %s='", type);
336                 if (atts[i] != NULL) {
337                     value= (char *)atts[i];
338                     // printf("%s'", value);
339                     if (!strcmp(type, "Number")) {
340                         ctx->pcr_index = atoi(value);
341                     }
342                 }
343             }
344         }
345     } else if (!strcmp((char *)name, "stuff:Objects")) {
346         /* New event */
347         /* malloc */
348         ctx->event = (TSS_PCR_EVENT *) xmalloc(sizeof(TSS_PCR_EVENT));
349         if (ctx->event == NULL) {
350             return;
351         }
352         memset(ctx->event, 0, sizeof(TSS_PCR_EVENT));
353         // see irEndElement
354     } else if (!strcmp((char *)name, "QuoteData")) {
355         // <>
356     } else if (!strcmp((char *)name, "Quote")) {
357         // <Quote>...
358     } else if (!strcmp((char *)name, "PcrComposit")) {
359         // <PcrComposit>...
360     } else if (!strcmp((char *)name, "PcrSelection")) {
361     } else if (!strcmp((char *)name, "ValueSize")) {
362     } else if (!strcmp((char *)name, "PcrValue")) {
363     } else if (!strcmp((char *)name, "QuoteInfo")) {
364     } else if (!strcmp((char *)name, "TpmSignature")) {
365     } else if (!strcmp((char *)name, "SignatureMethod")) {
366         // TODO check alg
367     } else if (!strcmp((char *)name, "SignatureValue")) {
368         // DONE TODO("get value(base64)\n");
369     } else if (!strcmp((char *)name, "KeyInfo")) {
370     } else if (!strcmp((char *)name, "KeyValue")) {
371         // DONE TODO("get value(base64)\n");
372     } else {
373         /* Else? */
374         ERROR("START ELEMENT [%s] \n", name);
375         ctx->sax_state = IR_SAX_STATE_IDOL;
376     }
377 }
378
379 /**
380  * SAX parser - End of Element
381  */
382 void irEndElement(void * context, const xmlChar * name) {
383     IR_CONTEXT *ctx = (IR_CONTEXT *)context;
384     int rc = 0;
385     UINT32 padding = 0;
386     int pad_len;
387
388     if (!strcmp((char *)name, "stuff:Objects")) {
389         /* Event finish, let's print out */
390         ctx->event_index++;
391
392         /* set the event structure */
393         if (ctx->event == NULL) {
394             ERROR("internal error\n");
395             ctx->sax_error++;
396         } else {
397             if (ctx->binary == 0) {
398                 /* text */
399                 fprintf(ctx->fp, "%5d %2d 0x%08x ",
400                     ctx->event_index,
401                     ctx->event->ulPcrIndex,
402                     ctx->event->eventType);
403                 fprintHex(ctx->fp, ctx->event->rgbPcrValue, 20);
404                 fprintf(ctx->fp, " [");
405                 fprintEventData(ctx->fp, ctx->event->eventType, ctx->event->ulEventLength, ctx->event->rgbEvent);
406                 fprintf(ctx->fp, "]\n");
407             } else {
408                 /* binary */
409                 if (ctx->endian == 0) {
410                     // TODO check rc
411                     rc = fwrite((BYTE *)&ctx->event->ulPcrIndex, 1, 4, ctx->fp);     // PCR index
412                     rc = fwrite((BYTE *)&ctx->event->eventType, 1, 4, ctx->fp);      // Event type
413                     rc = fwrite(ctx->event->rgbPcrValue, 1, 20, ctx->fp);   // PCR
414                     rc = fwrite((BYTE *)&ctx->event->ulEventLength, 1, 4, ctx->fp);  // EventData length
415                     rc = fwrite(ctx->event->rgbEvent, 1, ctx->event->ulEventLength, ctx->fp);  // EventData
416                 } else {
417                     /* convert endian */
418                     // TODO used htonl()
419                     UINT32 u;
420                     u = econv(ctx->event->ulPcrIndex);
421                     rc = fwrite((BYTE *)&u, 1, 4, ctx->fp);  // PCR index
422                     u = econv(ctx->event->eventType);
423                     rc = fwrite((BYTE *)&u, 1, 4, ctx->fp);  // Event type
424                     rc = fwrite(ctx->event->rgbPcrValue, 1, 20, ctx->fp);  // PCR
425                     u = econv(ctx->event->ulEventLength);
426                     rc = fwrite((BYTE *)&u, 1, 4, ctx->fp);  // EventData length
427                     rc = fwrite(ctx->event->rgbEvent, 1, ctx->event->ulEventLength, ctx->fp);  // EventData
428                 }
429                 /* padding */
430                 if (ctx->aligned > 0) {
431                     // TODO base64 IR already contains padding?
432                     // DEBUG("padding\n");
433                     pad_len = ctx->event->ulEventLength % ctx->aligned;
434                     if (pad_len > 0) {
435                         /* add padding */
436                         rc = fwrite((BYTE *)&padding, 1, pad_len, ctx->fp);  // Padding
437                         TODO("%d mod  %d => %d\n", ctx->event->ulEventLength, ctx->aligned, pad_len);
438                     }
439                 }
440             }
441
442             /* extend to eTPM */
443             extend(
444                 ctx->event->ulPcrIndex,
445                 ctx->event->rgbPcrValue);
446
447             ctx->event = NULL;
448         }
449     } else if (!strcmp((char *)name, "SnapshotCollection")) {
450         /*  snapshot finish  */
451     } else if (!strcmp((char *)name, "pcrindex")) {
452         ctx->buf[ctx->char_size] = 0;
453         ctx->event->ulPcrIndex = atoi(ctx->buf);
454     } else if (!strcmp((char *)name, "stuff:Hash")) {
455         ctx->buf[ctx->char_size] = 0;
456         ctx->event->rgbPcrValue = decodeBase64(
457             (char *)ctx->buf,
458             ctx->char_size,
459             (int *)&ctx->event->ulPcrValueLength);
460         if (ctx->event->rgbEvent == NULL) {
461             // ERROR()
462             ctx->event->ulPcrValueLength = 0;
463         }
464     } else if (!strcmp((char *)name, "eventtype")) {
465         ctx->buf[ctx->char_size] = 0;
466         ctx->event->eventType = atoi(ctx->buf);
467     } else if (!strcmp((char *)name, "eventdata")) {
468         ctx->buf[ctx->char_size] = 0;  // null terminate
469         ctx->event->rgbEvent = decodeBase64(
470             (char *)ctx->buf,
471             ctx->char_size,
472             (int *)&ctx->event->ulEventLength);
473         if (ctx->event->rgbEvent == NULL) {
474             // ERROR()
475             ctx->event->ulEventLength = 0;
476         }
477     } else if (!strcmp((char *)name, "PcrHash")) {
478         /* PCR value */
479         ctx->buf[ctx->char_size] = 0;  // null terminate
480         // decodeBase64(ctx->pcr, (unsigned char *)ctx->buf, ctx->char_size);
481
482         /* Check with PCR in TPM */
483         // rc = checkTpmPcr2(&pctx->tpm, ctx->pcr_index, ctx->pcr);
484
485         if (rc != 0) {
486             ERROR("ERROR PCR[%d] != IML\n", ctx->pcr_index);
487             ctx->sax_error = 1;
488         } else {
489             /* IML and PCR are consistent :-) */
490             // DEBUG_FSM("PCR[%d] == IML\n", ctx->pcr_index);
491             // TODO(munetoh) add property?  tpm.pcr.N.snapshot.N.integrity=valid
492
493 #if 0
494             /* update pcrs, used by validatePcrCompositeV11 */
495             if (pctx->conf->iml_mode == 0) {
496                 if (pcrs == NULL) {
497                     /* malloc OPENPTS_PCRS */
498                     // ERROR("PCR is not intialized - No QuoteData element\n");
499                     pcrs = xmalloc(sizeof(OPENPTS_PCRS));
500                     if (pcrs == NULL) {
501                         return;
502                     }
503                     memset(pcrs, 0, sizeof(OPENPTS_PCRS));
504                     pctx->pcrs = pcrs;
505                 }
506                 pcrs->pcr_select[ctx->pcr_index] = 1;
507                 memcpy(pcrs->pcr[ctx->pcr_index], ctx->pcr, 20);  // TODO pcr size
508             } else {
509                 // DEBUG("iml.mode!=tss, skip pcr copy to PCRS\n");
510             }
511 #endif
512         }
513     } else if (!strcmp((char *)name, "ValueSize")) {
514         DEBUG("ignore ValueSize\n");
515     } else if (!strcmp((char *)name, "PcrValue")) {
516         DEBUG("ignore PcrValue\n");
517     } else if (!strcmp((char *)name, "SignatureValue")) {
518         DEBUG("ignore SignatureValue\n");
519     } else if (!strcmp((char *)name, "KeyValue")) {
520         DEBUG("ignore KeyValue\n");
521     } else if (!strcmp((char *)name, "QuoteData")) {
522         DEBUG("ignore QuoteData\n");
523     } else {
524         /* Else? */
525         // printf("END ELEMENT [%s] ",name);
526     }
527
528     ctx->sax_state = IR_SAX_STATE_IDOL;
529 }
530
531 /**
532  * SAX parser  - Text of Element
533  *
534  * This called multiple time:-(
535  * 
536  */
537 void irCharacters(void* context, const xmlChar * ch, int len) {
538     IR_CONTEXT *ctx = (IR_CONTEXT *)context;
539
540     /* copy to buf at ctx */
541     if (ctx->char_size + len > EVENTDATA_BUF_SIZE) {
542         ERROR("Buffer for EVENTDATA is too small, %d + %d > %d\n", ctx->char_size, len, EVENTDATA_BUF_SIZE);
543         return;
544     }
545     memcpy(&ctx->buf[ctx->char_size], ch, len);
546     ctx->char_size += len;
547 }
548
549 /**
550  * read Integrity Report (IR) by using SAX parser
551  *
552  */
553 int readIr(IR_CONTEXT *context, const char *filename) {
554     xmlSAXHandler  sax_handler;
555     int rc = 0;
556
557     memset(&sax_handler, 0, sizeof(xmlSAXHandler));
558
559     /* setup handlers */
560     sax_handler.startDocument = irStartDocument;
561     sax_handler.endDocument = irEndDocument;
562     sax_handler.startElement = irStartElement;
563     sax_handler.endElement = irEndElement;
564     sax_handler.characters = irCharacters;
565
566     /* read IR, IR -> IML SAX */
567     if ((rc = xmlSAXUserParseFile(&sax_handler, (void *)context, filename)) != 0) {
568         /* error  */
569         // return rc;
570     } else {
571         /* ok */
572         // return rc;
573     }
574     /* free */
575     return rc;
576 }
577
578
579 /**
580  * Usage
581  */
582 void usage(void) {
583     fprintf(stderr, NLS(MS_OPENPTS, OPENPTS_IR2TEXT_USAGE, "OpenPTS command\n\n"
584                     "Usage: ir2text [options]\n\n"
585                     "Options:\n"
586                     "  -i filename           Set IR file\n"
587                     "  -o filename           Set output file, else stdout\n"
588                     "  -P filename           Set PCR output file (option)\n"
589                     "  -b                    Binary, (Convert IR to IML)\n"
590                     "  -E                    Enable endian conversion (BE->LE or LE->BE)\n"
591                     "  -h                    Show this help message\n"
592                     "\n"));
593 }
594
595 int main(int argc, char *argv[]) {
596     int rc = 0;
597     char *ir_filename = NULL;
598     char *out_filename = NULL;
599     char *pcrout_filename = NULL;
600     int c;
601     IR_CONTEXT *ctx;
602
603     initCatalog();
604
605     resetPcr();
606
607     ctx = xmalloc(sizeof(IR_CONTEXT));
608     ctx = (IR_CONTEXT *) xmalloc(sizeof(IR_CONTEXT));
609     if (ctx == NULL) {
610         return -1;
611     }
612     memset(ctx, 0, sizeof(IR_CONTEXT));
613
614     ctx->buf = xmalloc(EVENTDATA_BUF_SIZE);
615     if (ctx->buf == NULL) {
616         xfree(ctx);
617         return -1;
618     }
619
620
621     ctx->fp = stdout;
622
623     /* Args */
624     while ((c = getopt(argc, argv, "i:o:P:bEAdh")) != EOF) {
625         switch (c) {
626         case 'i':
627             ir_filename = optarg;
628             break;
629         case 'o':
630             out_filename = optarg;
631             break;
632         case 'P':
633             pcrout_filename = optarg;
634             break;
635         case 'b':  /* Binary mode  */
636             ctx->binary = 1;
637             break;
638         case 'E':  /* Enable Endian Conversion */
639             // DEBUG("enable endian conversion\n");
640             ctx->endian = 1;
641             break;
642         case 'A':  /*  four byte aligned event data */
643             ctx->aligned = 4;
644             break;
645         case 'd':  /* DEBUG */
646             setDebugFlags(DEBUG_FLAG);
647             break;
648         case 'h':
649             usage();
650             return 0;
651         default:
652             fprintf(stderr, NLS(MS_OPENPTS, OPENPTS_IR2TEXT_BAD_OPTION_C, "bad option %c\n"), c);
653             usage();
654             return -1;
655         }
656     }
657     argc -= optind;
658     argv += optind;
659
660     /* check  */
661     if (ctx->binary == 0) {
662         /* print IR in plain text */
663         DEBUG("ir2text - plain text mode\n");
664
665         if (out_filename != NULL) {
666             /* open output file */
667             ctx->fp = fopen(out_filename, "w");
668             if (ctx->fp == NULL) {
669                 ERROR("output file %s - open failed\n", out_filename);
670                 return rc;
671             }
672         }
673     } else {
674         /* print IR in binary text, with -o option */
675         if (out_filename == NULL) {
676             fprintf(stderr, NLS(MS_OPENPTS, OPENPTS_IR2TEXT_OUTPUT_BINARY_MODE,
677                 "set the output file for the binary mode\n"));
678             usage();
679             return -1;
680         }
681         DEBUG("ir2text - binary mode (IR -> IML)\n");
682
683         /* open output file */
684         ctx->fp = fopen(out_filename, "wb");
685         if (ctx->fp == NULL) {
686             ERROR("output file %s - open failed\n", out_filename);
687             return rc;
688         }
689     }
690
691     /* read IR and gen output */
692     rc = readIr(ctx, ir_filename);
693
694     /* close output file */
695     if (out_filename != NULL) {
696         /* close output file */
697         fclose(ctx->fp);
698     }
699
700     /* PCR output*/
701     // PCR-00: 8F BF F3 EC EA 9C 54 C8 D1 C4 2C FE A9 3D 6B F0 1B F3 40 5B
702     if (pcrout_filename != NULL) {
703         FILE *fp;
704         int i, j;
705         TODO("pcrout_filename = %s\n", pcrout_filename);
706
707         /* open output file */
708         fp = fopen(pcrout_filename, "w");
709         if (fp == NULL) {
710             ERROR("PCR output file %s - open failed\n", pcrout_filename);
711             return -1;
712         }
713
714         for (i = 0; i < MAX_PCRNUM; i++) {
715             fprintf(fp, "PCR-%02d:", i);
716             for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
717                 fprintf(fp, " %02X", pcr[i][j]);
718             }
719             fprintf(fp, "\n");
720         }
721         fclose(fp);
722     }
723     return rc;
724 }
725
726
727
728