OSDN Git Service

Re-organize console out and logging out
[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     // END DOC
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         // DEBUG("START ELEMENT [%s]  <<<< HASH HASH \n",name);
317         // ctx->sax_state = IR_SAX_STATE_PCR_INDEX;
318     } else if (!strcmp((char *)name, "eventtype")) {
319         // DEBUG("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         // DEBUG("START ELEMENT [%s]  <<<< DIGEST \n",name);
323         // ctx->sax_state = IR_SAX_STATE_DIGEST;
324     } else if (!strcmp((char *)name, "eventdata")) {
325         // DEBUG("START ELEMENT [%s]  <<<<  EVENT_DATA\n",name);
326         // ctx->sax_state = IR_SAX_STATE_EVENT_DATA;
327     } else if (!strcmp((char *)name, "PcrHash")) {
328         // DEBUG("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                 if (atts[i] != NULL) {
336                     value= (char *)atts[i];
337                     if (!strcmp(type, "Number")) {
338                         ctx->pcr_index = atoi(value);
339                     }
340                 }
341             }
342         }
343     } else if (!strcmp((char *)name, "stuff:Objects")) {
344         /* New event */
345         /* malloc */
346         ctx->event = (TSS_PCR_EVENT *) xmalloc(sizeof(TSS_PCR_EVENT));
347         if (ctx->event == NULL) {
348             return;
349         }
350         memset(ctx->event, 0, sizeof(TSS_PCR_EVENT));
351         // see irEndElement
352     } else if (!strcmp((char *)name, "QuoteData")) {
353         // <>
354     } else if (!strcmp((char *)name, "Quote")) {
355         // <Quote>...
356     } else if (!strcmp((char *)name, "PcrComposit")) {
357         // <PcrComposit>...
358     } else if (!strcmp((char *)name, "PcrSelection")) {
359     } else if (!strcmp((char *)name, "ValueSize")) {
360     } else if (!strcmp((char *)name, "PcrValue")) {
361     } else if (!strcmp((char *)name, "QuoteInfo")) {
362     } else if (!strcmp((char *)name, "TpmSignature")) {
363     } else if (!strcmp((char *)name, "SignatureMethod")) {
364         // TODO check alg
365     } else if (!strcmp((char *)name, "SignatureValue")) {
366         // DONE LOG(LOG_TODO, "get value(base64)\n");
367     } else if (!strcmp((char *)name, "KeyInfo")) {
368     } else if (!strcmp((char *)name, "KeyValue")) {
369         // DONE LOG(LOG_TODO, "get value(base64)\n");
370     } else {
371         /* Else? */
372         LOG(LOG_ERR, "START ELEMENT [%s] \n", name);
373         ctx->sax_state = IR_SAX_STATE_IDOL;
374     }
375 }
376
377 /**
378  * SAX parser - End of Element
379  */
380 void irEndElement(void * context, const xmlChar * name) {
381     IR_CONTEXT *ctx = (IR_CONTEXT *)context;
382     int rc = 0;
383     UINT32 padding = 0;
384     int pad_len;
385
386     if (!strcmp((char *)name, "stuff:Objects")) {
387         /* Event finish, let's print out */
388         ctx->event_index++;
389
390         /* set the event structure */
391         if (ctx->event == NULL) {
392             LOG(LOG_ERR, "internal error\n");
393             ctx->sax_error++;
394         } else {
395             if (ctx->binary == 0) {
396                 /* text */
397                 fprintf(ctx->fp, "%5d %2d 0x%08x ",
398                     ctx->event_index,
399                     ctx->event->ulPcrIndex,
400                     ctx->event->eventType);
401                 fprintHex(ctx->fp, ctx->event->rgbPcrValue, 20);
402                 fprintf(ctx->fp, " [");
403                 fprintEventData(ctx->fp, ctx->event->eventType, ctx->event->ulEventLength, ctx->event->rgbEvent);
404                 fprintf(ctx->fp, "]\n");
405             } else {
406                 /* binary */
407                 if (ctx->endian == 0) {
408                     // TODO check rc
409                     rc = fwrite((BYTE *)&ctx->event->ulPcrIndex, 1, 4, ctx->fp);     // PCR index
410                     rc = fwrite((BYTE *)&ctx->event->eventType, 1, 4, ctx->fp);      // Event type
411                     rc = fwrite(ctx->event->rgbPcrValue, 1, 20, ctx->fp);   // PCR
412                     rc = fwrite((BYTE *)&ctx->event->ulEventLength, 1, 4, ctx->fp);  // EventData length
413                     rc = fwrite(ctx->event->rgbEvent, 1, ctx->event->ulEventLength, ctx->fp);  // EventData
414                 } else {
415                     /* convert endian */
416                     // TODO used htonl()
417                     UINT32 u;
418                     u = econv(ctx->event->ulPcrIndex);
419                     rc = fwrite((BYTE *)&u, 1, 4, ctx->fp);  // PCR index
420                     u = econv(ctx->event->eventType);
421                     rc = fwrite((BYTE *)&u, 1, 4, ctx->fp);  // Event type
422                     rc = fwrite(ctx->event->rgbPcrValue, 1, 20, ctx->fp);  // PCR
423                     u = econv(ctx->event->ulEventLength);
424                     rc = fwrite((BYTE *)&u, 1, 4, ctx->fp);  // EventData length
425                     rc = fwrite(ctx->event->rgbEvent, 1, ctx->event->ulEventLength, ctx->fp);  // EventData
426                 }
427                 /* padding */
428                 if (ctx->aligned > 0) {
429                     // TODO base64 IR already contains padding?
430                     // DEBUG("padding\n");
431                     pad_len = ctx->event->ulEventLength % ctx->aligned;
432                     if (pad_len > 0) {
433                         /* add padding */
434                         rc = fwrite((BYTE *)&padding, 1, pad_len, ctx->fp);  // Padding
435                         LOG(LOG_TODO, "%d mod  %d => %d\n", ctx->event->ulEventLength, ctx->aligned, pad_len);
436                     }
437                 }
438             }
439
440             /* extend to eTPM */
441             extend(
442                 ctx->event->ulPcrIndex,
443                 ctx->event->rgbPcrValue);
444
445             ctx->event = NULL;
446         }
447     } else if (!strcmp((char *)name, "SnapshotCollection")) {
448         /*  snapshot finish  */
449     } else if (!strcmp((char *)name, "pcrindex")) {
450         ctx->buf[ctx->char_size] = 0;
451         ctx->event->ulPcrIndex = atoi(ctx->buf);
452     } else if (!strcmp((char *)name, "stuff:Hash")) {
453         ctx->buf[ctx->char_size] = 0;
454         ctx->event->rgbPcrValue = decodeBase64(
455             (char *)ctx->buf,
456             ctx->char_size,
457             (int *)&ctx->event->ulPcrValueLength);
458         if (ctx->event->rgbEvent == NULL) {
459             // LOG(LOG_ERR, )
460             ctx->event->ulPcrValueLength = 0;
461         }
462     } else if (!strcmp((char *)name, "eventtype")) {
463         ctx->buf[ctx->char_size] = 0;
464         ctx->event->eventType = atoi(ctx->buf);
465     } else if (!strcmp((char *)name, "eventdata")) {
466         ctx->buf[ctx->char_size] = 0;  // null terminate
467         ctx->event->rgbEvent = decodeBase64(
468             (char *)ctx->buf,
469             ctx->char_size,
470             (int *)&ctx->event->ulEventLength);
471         if (ctx->event->rgbEvent == NULL) {
472             // LOG(LOG_ERR, )
473             ctx->event->ulEventLength = 0;
474         }
475     } else if (!strcmp((char *)name, "PcrHash")) {
476         /* PCR value */
477         ctx->buf[ctx->char_size] = 0;  // null terminate
478         // decodeBase64(ctx->pcr, (unsigned char *)ctx->buf, ctx->char_size);
479
480         /* Check with PCR in TPM */
481         // rc = checkTpmPcr2(&pctx->tpm, ctx->pcr_index, ctx->pcr);
482
483         if (rc != 0) {
484             LOG(LOG_ERR, "ERROR PCR[%d] != IML\n", ctx->pcr_index);
485             ctx->sax_error = 1;
486         } else {
487             /* IML and PCR are consistent :-) */
488             // DEBUG_FSM("PCR[%d] == IML\n", ctx->pcr_index);
489             // TODO(munetoh) add property?  tpm.pcr.N.snapshot.N.integrity=valid
490
491 #if 0
492             /* update pcrs, used by validatePcrCompositeV11 */
493             if (pctx->conf->iml_mode == 0) {
494                 if (pcrs == NULL) {
495                     /* malloc OPENPTS_PCRS */
496                     // LOG(LOG_ERR, "PCR is not intialized - No QuoteData element\n");
497                     pcrs = xmalloc(sizeof(OPENPTS_PCRS));
498                     if (pcrs == NULL) {
499                         return;
500                     }
501                     memset(pcrs, 0, sizeof(OPENPTS_PCRS));
502                     pctx->pcrs = pcrs;
503                 }
504                 pcrs->pcr_select[ctx->pcr_index] = 1;
505                 memcpy(pcrs->pcr[ctx->pcr_index], ctx->pcr, 20);  // TODO pcr size
506             } else {
507                 // DEBUG("iml.mode!=tss, skip pcr copy to PCRS\n");
508             }
509 #endif
510         }
511     } else if (!strcmp((char *)name, "ValueSize")) {
512         DEBUG("ignore ValueSize\n");
513     } else if (!strcmp((char *)name, "PcrValue")) {
514         DEBUG("ignore PcrValue\n");
515     } else if (!strcmp((char *)name, "SignatureValue")) {
516         DEBUG("ignore SignatureValue\n");
517     } else if (!strcmp((char *)name, "KeyValue")) {
518         DEBUG("ignore KeyValue\n");
519     } else if (!strcmp((char *)name, "QuoteData")) {
520         DEBUG("ignore QuoteData\n");
521     } else {
522         /* Else? */
523         DEBUG("END ELEMENT [%s] ",name);
524     }
525
526     ctx->sax_state = IR_SAX_STATE_IDOL;
527 }
528
529 /**
530  * SAX parser  - Text of Element
531  *
532  * This called multiple time:-(
533  * 
534  */
535 void irCharacters(void* context, const xmlChar * ch, int len) {
536     IR_CONTEXT *ctx = (IR_CONTEXT *)context;
537
538     /* copy to buf at ctx */
539     if (ctx->char_size + len > EVENTDATA_BUF_SIZE) {
540         LOG(LOG_ERR, "Buffer for EVENTDATA is too small, %d + %d > %d\n", ctx->char_size, len, EVENTDATA_BUF_SIZE);
541         return;
542     }
543     memcpy(&ctx->buf[ctx->char_size], ch, len);
544     ctx->char_size += len;
545 }
546
547 /**
548  * read Integrity Report (IR) by using SAX parser
549  *
550  */
551 int readIr(IR_CONTEXT *context, const char *filename) {
552     xmlSAXHandler  sax_handler;
553     int rc = 0;
554
555     memset(&sax_handler, 0, sizeof(xmlSAXHandler));
556
557     /* setup handlers */
558     sax_handler.startDocument = irStartDocument;
559     sax_handler.endDocument = irEndDocument;
560     sax_handler.startElement = irStartElement;
561     sax_handler.endElement = irEndElement;
562     sax_handler.characters = irCharacters;
563
564     /* read IR, IR -> IML SAX */
565     if ((rc = xmlSAXUserParseFile(&sax_handler, (void *)context, filename)) != 0) {
566         /* error  */
567         // return rc;
568     } else {
569         /* ok */
570         // return rc;
571     }
572     /* free */
573     return rc;
574 }
575
576
577 /**
578  * Usage
579  */
580 void usage(void) {
581     OUTPUT(NLS(MS_OPENPTS, OPENPTS_IR2TEXT_USAGE,
582         "OpenPTS command\n\n"
583         "Usage: ir2text [options]\n\n"
584         "Options:\n"
585         "  -i filename           Set IR file\n"
586         "  -o filename           Set output file, else stdout\n"
587         "  -P filename           Set PCR output file (option)\n"
588         "  -b                    Binary, (Convert IR to IML)\n"
589         "  -E                    Enable endian conversion (BE->LE or LE->BE)\n"
590         "  -h                    Show this help message\n"
591         "\n"));
592 }
593
594 int main(int argc, char *argv[]) {
595     int rc = 0;
596     char *ir_filename = NULL;
597     char *out_filename = NULL;
598     char *pcrout_filename = NULL;
599     int c;
600     IR_CONTEXT *ctx;
601
602     initCatalog();
603
604     resetPcr();
605
606     ctx = xmalloc(sizeof(IR_CONTEXT));
607     ctx = (IR_CONTEXT *) xmalloc(sizeof(IR_CONTEXT));
608     if (ctx == NULL) {
609         return -1;
610     }
611     memset(ctx, 0, sizeof(IR_CONTEXT));
612
613     ctx->buf = xmalloc(EVENTDATA_BUF_SIZE);
614     if (ctx->buf == NULL) {
615         xfree(ctx);
616         return -1;
617     }
618
619
620     ctx->fp = stdout;
621
622     /* Args */
623     while ((c = getopt(argc, argv, "i:o:P:bEAdh")) != EOF) {
624         switch (c) {
625         case 'i':
626             ir_filename = optarg;
627             break;
628         case 'o':
629             out_filename = optarg;
630             break;
631         case 'P':
632             pcrout_filename = optarg;
633             break;
634         case 'b':  /* Binary mode  */
635             ctx->binary = 1;
636             break;
637         case 'E':  /* Enable Endian Conversion */
638             // DEBUG("enable endian conversion\n");
639             ctx->endian = 1;
640             break;
641         case 'A':  /*  four byte aligned event data */
642             ctx->aligned = 4;
643             break;
644         case 'd':  /* DEBUG */
645             setDebugFlags(DEBUG_FLAG);
646             break;
647         case 'h':
648             usage();
649             return 0;
650         default:
651             ERROR(NLS(MS_OPENPTS, OPENPTS_IR2TEXT_BAD_OPTION_C,
652                 "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                 LOG(LOG_ERR, "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             ERROR(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             LOG(LOG_ERR, "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         LOG(LOG_TODO, "pcrout_filename = %s\n", pcrout_filename);
706
707         /* open output file */
708         fp = fopen(pcrout_filename, "w");
709         if (fp == NULL) {
710             LOG(LOG_ERR, "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