OSDN Git Service

Re-organize console out and logging out
[openpts/openpts.git] / src / ir.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) 2010 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/ir.c
26  * \brief Generate Integrity Report from IML
27  * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
28  * @date 2010-04-01
29  * cleanup 2011-07-06 SM
30  *
31  *  TSS Event Struct -> IR
32  *  IML and PCR may not match, since the read them is not an atmic operation
33  *
34  *  Get PCR
35  *  Get Event(IML)
36  *  Event-> XML, calc PCR(c)
37  *  get TPM PCR(t)
38  *
39  *  PCR(c) == PCR(t)
40  *   then, next PCR
41  *   else, error or
42  *         try again or
43  *         if PCR(t) is old, ignore new events
44  *
45  *  TOCTOU?
46  *
47  *
48  */
49
50 #include <sys/stat.h>
51 #include <stdio.h>
52 #include <string.h>
53 #include <unistd.h>
54 #include <fcntl.h>
55 #include <errno.h>
56
57 #include <libxml/encoding.h>
58 #include <libxml/xmlwriter.h>
59 #include <libxml/parser.h>
60
61 #include <openpts.h>
62 // #include <log.h>
63
64 enum {
65     TEXT_WRITER_START_ELEMENT,
66     TEXT_WRITER_WRITE_ATTR,
67     TEXT_WRITER_WRITE_FORMAT_ELEMENT,
68     TEXT_WRITER_END_ELEMENT,
69     TEXT_WRITER_WRITE_BASE64,
70     TEXT_WRITER_START_DOC,
71     TEXT_WRITER_FLUSH,
72     TEXT_WRITER_END_DOC,
73     XML_FUNC_END
74 };
75
76 void displayXmlError(int errorIndex, int rc) {
77     char *xmlFuncStrings[XML_FUNC_END] = {
78         "xmlTextWriterStartElement",
79         "xmlTextWriterWriteAttribute",
80         "xmlTextWriterWriteFormatElement",
81         "xmlTextWriterEndElement",
82         "xmlTextWriterWriteBase64",
83         "xmlTextWriterStartDocument",
84         "xmlTextWriterFlush",
85         "xmlTextWriterEndDocument",
86     };
87
88     /* check */
89     if (errorIndex >= XML_FUNC_END) {
90         LOG(LOG_ERR, "errorIndex(%d) > XML_FUNC_END(%d)",errorIndex, XML_FUNC_END);
91         return;
92     }
93
94     /* log */
95     LOG(LOG_ERR, "XML function '%s' returned '%d'\n", xmlFuncStrings[errorIndex], rc);
96 }
97
98 /**
99  * free  All FSM in ctx
100  *
101  * @return
102  *   PTS_SUCCESS
103  */
104 int freeAllFsm(OPENPTS_CONTEXT *ctx) {
105     OPENPTS_SNAPSHOT *ss;
106     int i, j;
107
108     DEBUG_CAL("resetFsm\n");
109
110     /* check */
111     if (ctx == NULL) {
112         LOG(LOG_ERR, "null input");
113         return PTS_FATAL;
114     }
115
116     if (ctx->ss_table == NULL) {
117         // DEBUG("resetFsm() - no SS table\n");
118         return PTS_SUCCESS;
119     }
120
121     /* free FSMs */
122     for (i = 0; i <  MAX_PCRNUM; i++) {
123         for (j = 0; j <  MAX_SSLEVEL; j++) {
124             /* get SS */
125             ss = getSnapshotFromTable(ctx->ss_table, i, j);
126
127             if (ss != NULL) {
128                 /* free event wrapper chain */
129                 if (ss->start != NULL) {
130                     freeEventWrapperChain(ss->start);
131                     ss->start = NULL;
132                 }
133
134                 if (ss->fsm_behavior != NULL) {
135                     // DEBUG("free pcr %d, level 0, BHV-FSM\n",i);
136                     freeFsmContext(ss->fsm_behavior);
137                     ss->fsm_behavior = NULL;
138                 }
139                 if (ss->fsm_binary != NULL) {
140                     // DEBUG("free pcr %d, level 0, BIN-FSM\n",i);
141                     freeFsmContext(ss->fsm_binary);
142                     ss->fsm_binary = NULL;
143                 }
144
145                 /* reset PCR */
146                 memset(ss->curr_pcr, 0, SHA1_DIGEST_SIZE);
147                 memset(ss->tpm_pcr, 0, SHA1_DIGEST_SIZE);
148
149                 ss->level = j;
150                 ss->event_num = 0;
151             }
152         }  // Level
153         setActiveSnapshotLevel(ctx->ss_table, i, 0);
154     }  // PCR
155
156     return PTS_SUCCESS;
157 }
158
159 /**
160  * New IR context
161  *
162  * @return
163  *   pointer to OPENPTS_IR_CONTEXT OR NULL
164  *
165  */
166 OPENPTS_IR_CONTEXT *newIrContext() {
167     OPENPTS_IR_CONTEXT *ctx;
168
169     ctx = (OPENPTS_IR_CONTEXT *) xmalloc(sizeof(OPENPTS_IR_CONTEXT));
170     if (ctx == NULL) {
171         LOG(LOG_ERR, "no memory");
172         return NULL;
173     }
174     memset(ctx, 0, sizeof(OPENPTS_IR_CONTEXT));
175
176     ctx->buf = xmalloc(EVENTDATA_BUF_SIZE);
177     if (ctx->buf == NULL) {
178         LOG(LOG_ERR, "no memory");
179         xfree(ctx);
180         return NULL;
181     }
182     memset(ctx->buf, 0, EVENTDATA_BUF_SIZE);
183
184     return ctx;
185 }
186
187 /**
188  * Free IT Context
189  *
190  * @return void
191  *
192  */
193 void freeIrContext(OPENPTS_IR_CONTEXT *ctx) {
194     /* check */
195     if (ctx == NULL) {
196         LOG(LOG_ERR, "null input");
197         return;
198     }
199
200     /* free */
201     if (ctx->buf != NULL) {
202         xfree(ctx->buf);
203     }
204
205     xfree(ctx);
206 }
207
208
209 /**
210  * write ComponentID by PCR.
211  *
212  * This code does not support stacked components by IR
213  * To supports stacked component, we need FSM model to parse the IML.
214  * But, if we use the FSM model, verifier can validate the IML without stacked component
215  *
216  * @retval PTS_SUCCESS
217  * @retval PTS_INTERNAL_ERROR
218  *
219  *
220  */
221 int writeComponentID(
222         xmlTextWriterPtr writer,
223         PTS_ComponentId * cid,
224         int pcrIndex) {
225     int rc = PTS_INTERNAL_ERROR;
226     char id[256];
227
228     /* check */
229     if (cid == NULL) {
230         LOG(LOG_ERR, "null input");
231         return PTS_FATAL;
232     }
233
234     /* get strings */
235     BYTE *simpleName = snmalloc2(cid->dataBlock.dataBlock,
236                                  cid->simpleName.offset,
237                                  cid->simpleName.length);
238
239     BYTE *vendor = snmalloc2(cid->dataBlock.dataBlock,
240                              cid->vendor.offset,
241                              cid->vendor.length);
242
243     BYTE *versionString = snmalloc2(cid->dataBlock.dataBlock,
244                                     cid->versionString.offset,
245                                     cid->versionString.length);
246
247     /* element "core:ComponentID" */
248     rc = xmlTextWriterStartElement(writer, BAD_CAST "core:ComponentID");
249     if (rc < 0) {
250         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
251         goto error;
252     }
253
254     /* Add an attribute with name "Id" */
255     snprintf(id, sizeof(id), "CID_%d", pcrIndex);
256     rc = xmlTextWriterWriteAttribute(
257             writer,
258             BAD_CAST "Id",
259             BAD_CAST id);
260     if (rc < 0) {
261         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
262         goto error;
263     }
264
265     /* Add an attribute with name "ModelSystemClass" */
266     rc = xmlTextWriterWriteAttribute(
267             writer,
268             BAD_CAST "ModelSystemClass",
269             BAD_CAST "TBD");  // TODO(munetoh)
270     if (rc < 0) {
271         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
272         goto error;
273     }
274
275     /* Add an attribute with name "SimpleName" */
276     rc = xmlTextWriterWriteAttribute(
277             writer,
278             BAD_CAST "SimpleName",
279             BAD_CAST simpleName);
280     if (rc < 0) {
281         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
282         goto error;
283     }
284
285     /* Add an attribute with name "VersionBuild" */
286     rc = xmlTextWriterWriteAttribute(
287             writer,
288             BAD_CAST "VersionBuild",
289             BAD_CAST "1250694000000"); // TODO(munetoh)
290     if (rc < 0) {
291         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
292         goto error;
293     }
294
295     /* Add an attribute with name "VersionString" */
296
297     rc = xmlTextWriterWriteAttribute(
298             writer,
299             BAD_CAST "VersionString",
300             BAD_CAST versionString);
301     if (rc < 0) {
302         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
303         goto error;
304     }
305
306     /* Start an element named "core:VendorID" as child of "core:ComponentID". */
307     rc = xmlTextWriterStartElement(
308             writer,
309             BAD_CAST "core:VendorID");
310     if (rc < 0) {
311         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
312         goto error;
313     }
314
315     /* Add an attribute with name "Name" */
316     rc = xmlTextWriterWriteAttribute(
317             writer,
318             BAD_CAST "Name",
319             BAD_CAST vendor);
320     if (rc < 0) {
321         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
322         goto error;
323     }
324
325
326     /* element "core:SmiVendorId" */
327     rc = xmlTextWriterWriteFormatElement(
328             writer,
329             BAD_CAST "core:SmiVendorId", "%d", 0);
330     if (rc < 0) {
331         displayXmlError(TEXT_WRITER_WRITE_FORMAT_ELEMENT, rc);
332         goto error;
333     }
334
335
336     /* element "core:TcgVendorId" */
337     rc = xmlTextWriterWriteFormatElement(
338             writer,
339             BAD_CAST "core:TcgVendorId", "%s", "DEMO");  // TODO(munetoh)
340     if (rc < 0) {
341         displayXmlError(TEXT_WRITER_WRITE_FORMAT_ELEMENT, rc);
342         goto error;
343     }
344
345     /* Close the element "core:VendorID". */
346     rc = xmlTextWriterEndElement(writer);
347     if (rc < 0) {
348         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
349         goto error;
350     }
351
352     /* Close the element"core:ComponentID". */
353     rc = xmlTextWriterEndElement(writer);
354     if (rc < 0) {
355         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
356         goto error;
357     }
358
359     rc = PTS_SUCCESS;
360     goto free;
361
362  error:
363     rc = PTS_INTERNAL_ERROR;
364
365  free:
366     if (simpleName != NULL)
367         xfree(simpleName);
368     if (vendor != NULL)
369         xfree(vendor);
370     if (versionString != NULL)
371         xfree(versionString);
372
373     return rc;
374 }
375
376 /**
377  * write core:DigestMethod
378  *
379  * @retval PTS_SUCCESS
380  * @retval PTS_INTERNAL_ERROR
381  *
382  */
383 int writeDigestMethod(xmlTextWriterPtr writer) {
384     int rc;
385
386     /* Start element "core:DigestMethod" */
387     rc = xmlTextWriterStartElement(
388             writer,
389             BAD_CAST "core:DigestMethod");
390     if (rc < 0) {
391         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
392         return PTS_INTERNAL_ERROR;
393     }
394
395     /* Add an attribute with name "Algorithm" */
396     rc = xmlTextWriterWriteAttribute(
397             writer,
398             BAD_CAST "Algorithm",
399             BAD_CAST "unknown");
400     if (rc < 0) {
401         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
402         return PTS_INTERNAL_ERROR;
403     }
404
405     /* Add an attribute with name "Id" */
406     rc = xmlTextWriterWriteAttribute(
407             writer,
408             BAD_CAST "Id",
409             BAD_CAST "sha1");
410     if (rc < 0) {
411         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
412         return PTS_INTERNAL_ERROR;
413     }
414
415     /* Close the element named "core:DigestMethod". */
416     rc = xmlTextWriterEndElement(writer);
417     if (rc < 0) {
418         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
419         return PTS_INTERNAL_ERROR;
420     }
421
422     return PTS_SUCCESS;
423 }
424
425
426 /**
427  * write stuff:Objects
428  * this is a single event.
429  *
430  * @param writer
431  * @param event
432  * @param algtype
433  * @param ss_level
434  * @param eventindex
435  *
436  * @retval PTS_SUCCESS
437  * @retval PTS_INTERNAL_ERROR
438  *
439  *
440  */
441 int writeStuffObjects(
442         xmlTextWriterPtr writer,
443         TSS_PCR_EVENT * event,
444         int algtype,
445         int ss_level,
446         int eventindex) {
447     char id[256];  // TODO(munetoh)
448     int rc;
449
450     /* check */
451     if (event == NULL) {
452         LOG(LOG_ERR, "null input");
453         return PTS_FATAL;
454     }
455
456     /* ID */
457     snprintf(id, sizeof(id), "PCR_%d_LV%d_%d_%d_EVENT",
458         event->ulPcrIndex, ss_level, event->eventType, eventindex);
459
460     DEBUG_XML("addStuffObjects - pcr %d,id %s\n", event->ulPcrIndex, id);
461
462     /* start "stuff:Objects" */
463     rc = xmlTextWriterStartElement(
464             writer,
465             BAD_CAST "stuff:Objects");
466     if (rc < 0) {
467         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
468         goto error;
469     }
470
471     /* start "stuff:Hash" */
472     rc = xmlTextWriterStartElement(
473             writer,
474             BAD_CAST "stuff:Hash");
475     if (rc < 0) {
476         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
477         goto error;
478     }
479
480     /* Add an attribute with name "AlgRef" */
481     rc = xmlTextWriterWriteAttribute(
482             writer,
483             BAD_CAST "AlgRef",
484             // BAD_CAST ALG_NAME[algtype]) < 0)
485             BAD_CAST getAlgString(algtype));
486     if (rc < 0) {
487         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
488         goto error;
489     }
490
491     /* Add an attribute with name "Id" */
492     rc = xmlTextWriterWriteAttribute(
493             writer,
494             BAD_CAST "Id",
495             BAD_CAST id);
496     if (rc < 0) {
497         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
498         goto error;
499     }
500
501     /* Write a text  */
502     rc = xmlTextWriterWriteBase64(
503             writer,
504             (const char *) event->rgbPcrValue,
505             0,
506             event->ulPcrValueLength);
507     if (rc < 0) {
508         displayXmlError(TEXT_WRITER_WRITE_BASE64, rc);
509         goto error;
510     }
511
512     /* Close the element named "stuff:Hash". */
513     rc = xmlTextWriterEndElement(writer);
514     if (rc < 0) {
515         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
516         goto error;
517     }
518
519     /* Write an element named "pcrindex" */
520     rc = xmlTextWriterWriteFormatElement(
521             writer,
522             BAD_CAST "pcrindex",
523             "%d", event->ulPcrIndex);
524     if (rc < 0) {
525         displayXmlError(TEXT_WRITER_WRITE_FORMAT_ELEMENT, rc);
526         goto error;
527     }
528
529     /* Write an element named "eventtype" */
530     rc = xmlTextWriterWriteFormatElement(
531             writer,
532             BAD_CAST "eventtype",
533             "%d", event->eventType);
534     if (rc < 0) {
535         displayXmlError(TEXT_WRITER_WRITE_FORMAT_ELEMENT, rc);
536         goto error;
537     }
538
539     if (event->ulEventLength > 0) {
540         /* Start an element named "eventdata" as child of "eventdata". */
541         rc = xmlTextWriterStartElement(
542                 writer,
543                 BAD_CAST "eventdata");
544         if (rc < 0) {
545             displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
546             goto error;
547         }
548
549         /* Write a text */
550         rc = xmlTextWriterWriteBase64(
551                 writer,
552                 (const char *) event->rgbEvent,
553                 0,
554                 event->ulEventLength);
555         if (rc < 0) {
556             displayXmlError(TEXT_WRITER_WRITE_BASE64, rc);
557             goto error;
558         }
559
560         /* Close the element named "eventdata". */
561         rc = xmlTextWriterEndElement(writer);
562         if (rc < 0) {
563             displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
564             goto error;
565         }
566     } else {
567         // no eventdata
568     }
569
570     /* Close the element named "stuff:Objects". */
571     rc = xmlTextWriterEndElement(writer);
572     if (rc < 0) {
573         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
574         goto error;
575     }
576
577     return PTS_SUCCESS;
578
579   error:
580     LOG(LOG_ERR, "writeStuffObjects() XML ERROR\n");
581     return PTS_INTERNAL_ERROR;
582 }
583
584 /**
585  * write PcrHash
586  *
587 <PcrHash AlgRef="sha1"
588          Id="_06bd159d-365c-4d80-b968-9c2fe12c4d66_pcrhash"
589          IsResetable="false"
590          Number="0"
591          StartHash="AAAAAAAAAAAAAAAAAAAAAAAAAAA=">
592   j7/z7OqcVMjRxCz+qT1r8BvzQFs=
593 </PcrHash>
594  *
595  * @retval PTS_SUCCESS
596  * @retval PTS_INTERNAL_ERROR
597  *
598  */
599
600 int writePcrHash(
601         xmlTextWriterPtr writer,
602         int pcrIndex,
603         int ss_level,
604         BYTE * startHash,
605         BYTE * hash,
606         int algtype) {
607     // int rc = PTS_SUCCESS;
608     char id[256];  // TODO(munetoh) 11+1+1 = 12?
609     int rc;
610
611     DEBUG_CAL("writePcrHash - PCR[%d] level %d \n", pcrIndex, ss_level);
612
613     /* check */
614     if (startHash == NULL) {
615         LOG(LOG_ERR, "null input");
616         return PTS_FATAL;
617     }
618     if (hash == NULL) {
619         LOG(LOG_ERR, "null input");
620         return PTS_FATAL;
621     }
622
623     /* ID */
624     snprintf(id, sizeof(id), "PCR_%d_LV%d_HASH", pcrIndex, ss_level);
625
626     /* Start an element named "eventdata" as child of "PcrHash". */
627     rc = xmlTextWriterStartElement(writer, BAD_CAST "PcrHash");
628     if (rc < 0) {
629         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
630         goto error;
631     }
632
633     /* Add an attribute with name "AlgRef" */
634     rc = xmlTextWriterWriteAttribute(
635             writer,
636             BAD_CAST "AlgRef",
637             // BAD_CAST ALG_NAME[algtype]) < 0)
638             BAD_CAST getAlgString(algtype));
639     if (rc < 0) {
640         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
641         goto error;
642     }
643
644     /* Add an attribute with name "Id" */
645     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "Id", BAD_CAST id);
646     if (rc < 0) {
647         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
648         goto error;
649     }
650
651     /* Add an attribute with name "IsResetable" */
652     rc = xmlTextWriterWriteAttribute(
653             writer,
654             BAD_CAST "IsResetable",
655             BAD_CAST "false");
656     if (rc < 0) {
657         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
658         goto error;
659     }
660
661     /* Add an attribute with name "Number" */
662     snprintf(id, sizeof(id), "%d", pcrIndex);
663     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "Number", BAD_CAST id);
664     if (rc < 0) {
665         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
666         goto error;
667     }
668
669     /* Add an attribute with name "StartHash" */
670     // TODO(munetoh) convert startHash to base64 string
671     rc = xmlTextWriterWriteAttribute(
672             writer,
673             BAD_CAST "StartHash",
674             BAD_CAST "AAAAAAAAAAAAAAAAAAAAAAAAAAA=");
675     if (rc < 0) {
676         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
677         goto error;
678     }
679
680     /* Write a text */
681     rc = xmlTextWriterWriteBase64(writer, (const char *) hash, 0, 20);
682     if (rc < 0) {
683         displayXmlError(TEXT_WRITER_WRITE_BASE64, rc);
684         goto error;
685     }
686
687     /* Close the element named "PcrHash". */
688     rc = xmlTextWriterEndElement(writer);
689     if (rc < 0) {
690         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
691         goto error;
692     }
693
694     return PTS_SUCCESS;
695
696   error:
697     return PTS_INTERNAL_ERROR;
698 }
699
700 /**
701  * write Snapshot
702  *
703  * @retval PTS_SUCCESS
704  * @retval PTS_INTERNAL_ERROR
705  */
706 int writeSnapshot(
707         xmlTextWriterPtr writer,
708         OPENPTS_TPM_CONTEXT *tpm,
709         PTS_ComponentId *cid,
710         int index,
711         OPENPTS_SNAPSHOT *ss) {
712     int rc = PTS_SUCCESS;
713     int j;
714     PTS_UUID *ir_uuid;
715     char *str_ir_uuid;
716     char id[256];  // TODO 3 + UUID = 3 + 36 = 39
717     int level;
718     OPENPTS_PCR_EVENT_WRAPPER *eventWrapper;
719
720     /* check */
721     if (tpm == NULL) {
722         LOG(LOG_ERR, "null input");
723         return PTS_FATAL;
724     }
725     if (cid == NULL) {
726         LOG(LOG_ERR, "null input");
727         return PTS_FATAL;
728     }
729     if (ss == NULL) {
730         LOG(LOG_ERR, "null input");
731         return PTS_FATAL;
732     }
733     level = ss->level;
734
735
736     /* reset PCR */
737     // FSM resetPCR(n) exist
738     if (ss->reset_pcr == 1) {
739         LOG(LOG_TODO, "reset PCR[%d]\n", index);
740         resetTpmPcr(tpm, index);
741     }
742
743
744     /* set initial PCR value */
745     rc = getTpmPcrValue(tpm, index, ss->start_pcr);
746
747     DEBUG_CAL("addSnapshot - start pcr%d snapshot level %d num %d\n",
748         index, level, ss->event_num);
749
750     /* Start an element named "SnapshotCollection" as child of Report. */
751     rc = xmlTextWriterStartElement(writer, BAD_CAST "SnapshotCollection");
752     if (rc < 0) {
753         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
754         rc = PTS_INTERNAL_ERROR;
755         goto error;
756     }
757
758     /* new UUID */
759     ir_uuid = newUuid();
760     if (ir_uuid == NULL) {
761         LOG(LOG_ERR, "UUID \n");
762         rc = PTS_INTERNAL_ERROR;
763         goto error;
764     }
765     str_ir_uuid = getStringOfUuid(ir_uuid);
766     if (str_ir_uuid == NULL) {
767         LOG(LOG_ERR, "UUID \n");
768         rc = PTS_INTERNAL_ERROR;
769         xfree(ir_uuid);
770         goto error;
771     }
772
773     snprintf(id, sizeof(id), "IR_%s", str_ir_uuid);
774
775     /* Add an attribute with name "Id" */
776     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "Id", BAD_CAST id);
777     if (rc < 0) {
778         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
779         rc = PTS_INTERNAL_ERROR;
780         goto free;
781     }
782
783     /* Add an attribute with name "UUID" */
784     rc = xmlTextWriterWriteAttribute(
785             writer, BAD_CAST "UUID", BAD_CAST str_ir_uuid);
786     if (rc < 0) {
787         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
788         rc = PTS_INTERNAL_ERROR;
789         goto free;
790     }
791     /* Add an attribute with name "RevLevel" */
792     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "RevLevel", BAD_CAST "0");
793     if (rc < 0) {
794         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
795         rc = PTS_INTERNAL_ERROR;
796         goto free;
797     }
798
799     rc = writeComponentID(writer, cid, index);
800
801     rc = writeDigestMethod(writer);
802
803     /* Start an element named "core:Values" as child of "SnapshotCollection". */
804     rc = xmlTextWriterStartElement(writer, BAD_CAST "core:Values");
805     if (rc < 0) {
806         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
807         rc = PTS_INTERNAL_ERROR;
808         goto free;
809     }
810
811     /* Start "stuff:SimpleSnapshotObject" */
812     rc = xmlTextWriterStartElement(
813             writer, BAD_CAST "stuff:SimpleSnapshotObject");
814     if (rc < 0) {
815         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
816         rc = PTS_INTERNAL_ERROR;
817         goto free;
818     }
819
820     /* Events at PCR[i] */
821
822     eventWrapper = ss->start;
823
824     if (eventWrapper == NULL) {
825         LOG(LOG_ERR, "writeSnapshot- eventWrapper is NULL\n");
826         rc = PTS_FATAL;
827         goto free;
828     }
829
830     for (j = 0; j < ss->event_num; j++) {
831         DEBUG_XML("genIr - start snapshot - event %d \n", j);
832         rc = writeStuffObjects(writer, eventWrapper->event, ALGTYPE_SHA1, level, j);
833
834         rc = extendTpm(tpm, eventWrapper->event);
835
836         /* move to next */
837         eventWrapper = eventWrapper->next_pcr;
838     }
839
840     /* Close the element named "stuff:SimpleSnapshotObject". */
841     rc = xmlTextWriterEndElement(writer);
842     if (rc < 0) {
843         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
844         rc = PTS_INTERNAL_ERROR;
845         goto free;
846     }
847
848     /* Close the element named "core:Values". */
849     rc = xmlTextWriterEndElement(writer);
850     if (rc < 0) {
851         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
852         rc = PTS_INTERNAL_ERROR;
853         goto free;
854     }
855
856     /* set curr PCR value */
857     rc = getTpmPcrValue(tpm, index, ss->curr_pcr);
858     if (rc != PTS_SUCCESS) {
859         LOG(LOG_ERR, "getTpmPcrValue() fail");
860         rc = PTS_INTERNAL_ERROR;
861         goto free;
862     }
863
864     /* check with TPM value if this is the last snapshot */
865     // TODO(munetoh) copy level0 tpm_pcr to level1
866
867     /* add PcrHash element */
868     rc = writePcrHash(writer, index, level, ss->start_pcr, ss->curr_pcr, ALGTYPE_SHA1);
869     if (rc != PTS_SUCCESS) {
870         LOG(LOG_ERR, "writePcrHash() fail");
871         rc = PTS_INTERNAL_ERROR;
872         goto free;
873     }
874
875     /* Close the element named "SnapshotCollection". */
876     rc = xmlTextWriterEndElement(writer);
877     if (rc < 0) {
878         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
879         rc = PTS_INTERNAL_ERROR;
880         goto free;
881     }
882
883     rc = PTS_SUCCESS;
884
885   free:
886     xfree(ir_uuid);
887     xfree(str_ir_uuid);
888
889   error:
890     DEBUG_CAL("addSnapshot - done, rc=%d\n", rc);
891
892     return rc;
893 }
894
895 /**
896  * write Quote
897  *
898  *
899  * @retval PTS_SUCCESS
900  * @retval PTS_INTERNAL_ERROR
901  *
902  */
903 /*
904   <QuoteData ID="XXXX">
905     <Quote>
906       <PcrComposite>
907         <PcrSelection SizeOfSelect="3" PcrSelect="AAM1BQA="/>
908         <ValueSize>120</ValueSize>
909         <PcrValue PcrNumber="0">lavylWbp6wz29tPTGu8uXQgBXZY=</PcrValue>
910         <PcrValue PcrNumber="2">4skssUfiCqP4sq8brID5lh/UHqA=</PcrValue>
911         <PcrValue PcrNumber="4">ooe0hpRSNq7AF5p8flBBNCigU14=</PcrValue>
912         <PcrValue PcrNumber="5">aNAgqKiy8qF8rUilK2GP/ny0TsE=</PcrValue>
913         <PcrValue PcrNumber="8">Mx3F5PbzeH/a/iBof4NKEyPlLPw=</PcrValue>
914         <PcrValue PcrNumber="10">OpUxai7OgR6KNabQ1ftXoArHFqU=</PcrValue>
915       </PcrComposite>
916       <QuoteInfo VersionMajor="1" VersionMinor="1" VersionRevMajor="0" VersionRevMinor="0" Fixed="QUOT" DigestValue="tZ87wnYe8mAVW8ByvTjHjWzqCgY=" ExternalData="+saVas74wMg9V9N8rpe4gcP1uCo="/>
917     </Quote>
918     <TpmSignature>
919       <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
920       <SignatureValue>x3rjafy577XLUw+7Guam3XTPojTWeVe9CD2E/9B0ZxdiWuLF2Kv34qDCDiAmHpE7a9fiawEhLntQ1Lmqsev/NKoKlL57/vJiJuON4/nRow0FBGHcsrZnOSl9WWL+Eob/rAZPglcL4O8SMM2sqvaIK6XBLJhF2P7+fxWRWnH27w/w+lnWV6J3ItxYLhk9Bs1NWAeI+z4barv6RxmYH1/91hlbByWUA1XAX6t1NC3lBgwLRrUqu2aQAPikle+2SxjpW3squT/LICVE8Qzcd9s6G+D1jfmmPBkxoRQE4NTjsVxJJitnL2ADnuVheEHTd3+heJEb6n+n/aKq93M6VnKjhg==</SignatureValue>
921       <KeyInfo>
922         <KeyValue>AMxWrZm0Aiq3F/1U9xbA5vqWejd18zT195sB6uTAUR96hNkJg/+Q2ffUXRdzIYdVgMddZDJtEz2Dzyg3lllwL7ssHi+vusEgrhgDmpQrwQNySFWC0ce64ckosC+HG4xjNeoAEFOWGqDvIFAsmT6T2kFgZnYs1GiKbg+qpmw0xY4qQPXiMP58w4JlTBM6cClnen60+A01aSSjiCioeYOy+4AItVYINrretBcrDmbPhGqWT32HpqpmNu3lQBg0aUtHMG5X+FhG0Mu9zemXT0nHxLljEDCRgkdzY9oXGjG08Wxn5OzOX9JVoDuMnLgeuAIlqSXIOEFhFJfvBLeGnriLktM=</KeyValue>
923       </KeyInfo>
924     </TpmSignature>
925   </QuoteData>
926 */
927 int writeQuote(
928         xmlTextWriterPtr writer,
929         OPENPTS_CONTEXT *ctx) {
930     int rc;
931     int i;
932     char *b64buf = NULL;
933     int b64buf_len;
934     int size_of_select = 0;
935     int select_int = 0;
936     BYTE select_byte[3];  // TODO TPM1.2, 24PCRs => 3 bytes
937     char tagbuf[128];
938
939     /* check */
940     if (ctx == NULL) {
941         LOG(LOG_ERR, "null input");
942         return PTS_FATAL;
943     }
944     if (ctx->pcrs == NULL) {
945         LOG(LOG_TODO, "writeQuote - OPENPTS_PCRS is NULL, SKIP QuoteData\n");
946         return PTS_FATAL;
947     }
948     if (ctx->validation_data == NULL) {
949         LOG(LOG_TODO, "writeQuote - TSS_VALIDATION is NULL, SKIP QuoteData\n");
950         return PTS_FATAL;
951     }
952
953     /* Start an element named "QuoteData" as child of Report. */
954     rc = xmlTextWriterStartElement(writer, BAD_CAST "QuoteData");
955     if (rc < 0) {
956         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
957         return PTS_INTERNAL_ERROR;
958     }
959
960     /* Add an attribute with name "ID" */
961     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "ID", BAD_CAST "TBD");
962     if (rc < 0) {
963         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
964         return PTS_INTERNAL_ERROR;
965     }
966
967     /* Start an element named "Quote" as child of QuoteData. */
968     rc = xmlTextWriterStartElement(writer, BAD_CAST "Quote");
969     if (rc < 0) {
970         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
971         return PTS_INTERNAL_ERROR;
972     }
973
974     /* Start an element named "PcrComposit" as child of Quote. */
975     rc = xmlTextWriterStartElement(writer, BAD_CAST "PcrComposit");
976     if (rc < 0) {
977         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
978         return PTS_INTERNAL_ERROR;
979     }
980
981     /* PcrSelection */
982     // is 2 if call TPM_Quote
983     // TODO gen pcrselect bit map
984
985     if (ctx->pcrs->pcr_num == 24) {
986         size_of_select = 3;
987         select_int = 0;
988         ctx->pcrs->value_size = 0;
989         for (i = 0; i< ctx->pcrs->pcr_num; i++) {
990             if (ctx->pcrs->pcr_select[i] == 1) {
991                 select_int = select_int | 1;
992                 ctx->pcrs->value_size += 20;  // TODO digest size
993             }
994             select_int = select_int << 1;
995         }
996         select_int = select_int >> 1;  // TODO
997         // DEBUG("PCR SELECT %x\n", select_int);
998         select_byte[0] = (select_int & 0xFF0000) >> 16;
999         select_byte[1] = (select_int & 0xFF00) >> 8;
1000         select_byte[2] = select_int & 0xFF;
1001     } else {
1002         // TODO
1003         LOG(LOG_ERR, " PCR NUM != 24\n");
1004     }
1005
1006     /* Start an element named "PcrSelection" as child of PcrComposit. */
1007     rc = xmlTextWriterStartElement(writer, BAD_CAST "PcrSelection");
1008     if (rc < 0) {
1009         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1010         return PTS_INTERNAL_ERROR;
1011     }
1012
1013     /* Add an attribute with name "SizeOfSelect", int */
1014     snprintf(tagbuf, sizeof(tagbuf), "%d", size_of_select);
1015     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "SizeOfSelect", BAD_CAST tagbuf);
1016     if (rc < 0) {
1017         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1018         return PTS_INTERNAL_ERROR;
1019     }
1020
1021     /* Add an attribute with name "PcrSelect", base64 */
1022     b64buf = (char *)encodeBase64(
1023         (unsigned char *)select_byte,
1024         size_of_select,
1025         &b64buf_len);
1026     if (b64buf == NULL) {
1027         LOG(LOG_ERR, "encodeBase64 fail");  // TODO ERROR => displayXmlError
1028         return PTS_INTERNAL_ERROR;
1029     }
1030     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "PcrSelect", BAD_CAST b64buf);
1031     if (rc < 0) {
1032         // LOG(LOG_ERR, "Error at xmlTextWriterWriteAttribute\n");
1033         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1034         return PTS_INTERNAL_ERROR;
1035     }
1036     free(b64buf);
1037     b64buf = NULL;
1038
1039     /* Close the element named "PcrSelection". */
1040     rc = xmlTextWriterEndElement(writer);
1041     if (rc < 0) {
1042         // LOG(LOG_ERR, "Error at xmlTextWriterEndElement\n");
1043         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1044         return PTS_INTERNAL_ERROR;
1045     }
1046
1047     /* ValueSize */
1048
1049     /* Write an element named "ValueSize" as child of PcrComposit */
1050     rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ValueSize", "%d", ctx->pcrs->value_size);
1051     if (rc < 0) {
1052         displayXmlError(TEXT_WRITER_WRITE_FORMAT_ELEMENT, rc);
1053         return PTS_INTERNAL_ERROR;
1054     }
1055
1056     /* PcrValue, loop */
1057
1058     for (i = 0; i < ctx->pcrs->pcr_num; i ++) {
1059         if (ctx->pcrs->pcr_select[i] == 1) {
1060             /* Start an element named "PcrValue" as child of PcrComposit. */
1061             rc = xmlTextWriterStartElement(writer, BAD_CAST "PcrValue");
1062             if (rc < 0) {
1063                 displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1064                 return PTS_INTERNAL_ERROR;
1065             }
1066             /* Add an attribute with name "PcrNumber", int */
1067             snprintf(tagbuf, sizeof(tagbuf), "%d", i);
1068             rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "PcrNumber", BAD_CAST tagbuf);
1069             // rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "PcrNumber", BAD_CAST "0");
1070             if (rc < 0) {
1071                 displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1072                 return PTS_INTERNAL_ERROR;
1073             }
1074
1075             /* Write a text, PCR, base64  */
1076             rc = xmlTextWriterWriteBase64(
1077                     writer,
1078                     (const char *) ctx->pcrs->pcr[i],
1079                     0,
1080                     20);  // TODO add length to OPENPTS_PCRS
1081             if (rc < 0) {
1082                 displayXmlError(TEXT_WRITER_WRITE_BASE64, rc);
1083                 return PTS_INTERNAL_ERROR;
1084             }
1085
1086             /* Close the element named "PcrValue" */
1087             rc = xmlTextWriterEndElement(writer);
1088             if (rc < 0) {
1089                 displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1090                 return PTS_INTERNAL_ERROR;
1091             }
1092         }  // selected
1093     }  // loop
1094
1095     /* Close the element named "PcrComposit". */
1096     rc = xmlTextWriterEndElement(writer);
1097     if (rc < 0) {
1098         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1099         return PTS_INTERNAL_ERROR;
1100     }
1101
1102     /* Quote Info */
1103     /* Start an element named "QuoteInfo" as child of Quote. */
1104     rc = xmlTextWriterStartElement(writer, BAD_CAST "QuoteInfo");
1105     if (rc < 0) {
1106         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1107         return PTS_INTERNAL_ERROR;
1108     }
1109
1110     /* Add an attribute with name "VersionMajor", int */
1111     snprintf(tagbuf, sizeof(tagbuf), "%d", ctx->validation_data->versionInfo.bMajor);
1112     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "VersionMajor", BAD_CAST tagbuf);
1113     if (rc < 0) {
1114         // LOG(LOG_ERR, "Error at xmlTextWriterWriteAttribute\n");
1115         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1116         return PTS_INTERNAL_ERROR;
1117     }
1118     /* Add an attribute with name "VersionMinor", int */
1119     snprintf(tagbuf, sizeof(tagbuf), "%d", ctx->validation_data->versionInfo.bMinor);
1120     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "VersionMinor", BAD_CAST tagbuf);
1121     if (rc < 0) {
1122         // LOG(LOG_ERR, "Error at xmlTextWriterWriteAttribute\n");
1123         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1124         return PTS_INTERNAL_ERROR;
1125     }
1126     /* Add an attribute with name "VersionRevMajor", int */
1127     snprintf(tagbuf, sizeof(tagbuf), "%d", ctx->validation_data->versionInfo.bRevMajor);
1128     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "VersionRevMajor", BAD_CAST tagbuf);
1129     if (rc < 0) {
1130         // LOG(LOG_ERR, "Error at xmlTextWriterWriteAttribute\n");
1131         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1132         return PTS_INTERNAL_ERROR;
1133     }
1134
1135     /* Add an attribute with name "VersionRevMinor", int */
1136     snprintf(tagbuf, sizeof(tagbuf), "%d", ctx->validation_data->versionInfo.bRevMinor);
1137     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "VersionRevMinor", BAD_CAST tagbuf);
1138     if (rc < 0) {
1139         // LOG(LOG_ERR, "Error at xmlTextWriterWriteAttribute\n");
1140         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1141         return PTS_INTERNAL_ERROR;
1142     }
1143
1144     /* Add an attribute with name "Fixed", int */
1145     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "Fixed", BAD_CAST "QUOT");
1146     if (rc < 0) {
1147         // LOG(LOG_ERR, "Error at xmlTextWriterWriteAttribute\n");
1148         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1149         return -1;
1150     }
1151
1152     /* Add an attribute with name "DigestValue", base64 */
1153     b64buf = encodeBase64(
1154         (unsigned char *)&ctx->validation_data->rgbData[8],  // skip 01010000 51554f54
1155         20,
1156         &b64buf_len);  // ctx->validation_data->ulDataLength);
1157     if (b64buf == NULL) {
1158         LOG(LOG_ERR, "encodeBase64() fail");
1159         return PTS_INTERNAL_ERROR;
1160     }
1161     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "DigestValue", BAD_CAST b64buf);
1162     if (rc < 0) {
1163         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1164         return PTS_INTERNAL_ERROR;
1165     }
1166     free(b64buf);
1167     b64buf = NULL;
1168
1169     // TODO we used DH-nonce exchange but here, we put plain nonce:-P
1170     // TODO is this option attribute? can we suppress?
1171     /* Add an attribute with name "ExternalData", base64 */
1172     b64buf = encodeBase64(
1173         (unsigned char *)ctx->validation_data->rgbExternalData,
1174         ctx->validation_data->ulExternalDataLength,
1175         &b64buf_len);
1176     if (b64buf == NULL) {
1177         LOG(LOG_ERR, "encodeBase64() fail");
1178         return PTS_INTERNAL_ERROR;
1179     }
1180     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "ExternalData", BAD_CAST b64buf);
1181     if (rc < 0) {
1182         // LOG(LOG_ERR, "Error at xmlTextWriterWriteAttribute\n");
1183         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1184         return PTS_INTERNAL_ERROR;
1185     }
1186     free(b64buf);
1187     b64buf = NULL;
1188
1189     /* Close the element named "QuoteInfo". */
1190     rc = xmlTextWriterEndElement(writer);
1191     if (rc < 0) {
1192         // LOG(LOG_ERR, "Error at xmlTextWriterEndElement\n");
1193         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1194         return PTS_INTERNAL_ERROR;
1195     }
1196
1197     /* Close the element named "Quote". */
1198     rc = xmlTextWriterEndElement(writer);
1199     if (rc < 0) {
1200         // LOG(LOG_ERR, "Error at xmlTextWriterEndElement\n");
1201         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1202         return PTS_INTERNAL_ERROR;
1203     }
1204
1205     /* TpmSignature ------------------------------------ */
1206
1207     /* Start an element named "TpmSignature" as child of QuoteData. */
1208     rc = xmlTextWriterStartElement(writer, BAD_CAST "TpmSignature");
1209     if (rc < 0) {
1210         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1211         return PTS_INTERNAL_ERROR;
1212     }
1213
1214     /* SignatureMethod */
1215
1216     /* Start an element named "SignatureMethod" as child of TpmSignature. */
1217     rc = xmlTextWriterStartElement(writer, BAD_CAST "SignatureMethod");
1218     if (rc < 0) {
1219         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1220         return PTS_INTERNAL_ERROR;
1221     }
1222     /* Add an attribute with name "Algorithm", string */
1223     rc = xmlTextWriterWriteAttribute(writer,
1224             BAD_CAST "Algorithm",
1225             BAD_CAST "http://www.w3.org/2000/09/xmldsig#rsa-sha1");  // TODO
1226     if (rc < 0) {
1227         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1228         return PTS_INTERNAL_ERROR;
1229     }
1230     /* Close the element named "SignatureMethod". */
1231     rc = xmlTextWriterEndElement(writer);
1232     if (rc < 0) {
1233         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1234         return PTS_INTERNAL_ERROR;
1235     }
1236
1237     /* SignatureValue */
1238
1239     /* Start an element named "SignatureValue" as child of TpmSignature. */
1240     rc = xmlTextWriterStartElement(writer, BAD_CAST "SignatureValue");
1241     if (rc < 0) {
1242         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1243         return PTS_INTERNAL_ERROR;
1244     }
1245     /* Write a text, signature, base64  */
1246     rc = xmlTextWriterWriteBase64(
1247             writer,
1248             (const char *) ctx->validation_data->rgbValidationData,
1249             0,
1250             ctx->validation_data->ulValidationDataLength);
1251     if (rc < 0) {
1252         displayXmlError(TEXT_WRITER_WRITE_BASE64, rc);
1253         return PTS_INTERNAL_ERROR;
1254     }
1255     /* Close the element named "SignatureValue". */
1256     rc = xmlTextWriterEndElement(writer);
1257     if (rc < 0) {
1258         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1259         return PTS_INTERNAL_ERROR;
1260     }
1261
1262     /* Close the element named "TpmSignature". */
1263     rc = xmlTextWriterEndElement(writer);
1264     if (rc < 0) {
1265         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1266         return PTS_INTERNAL_ERROR;
1267     }
1268
1269     /* Close the element named "QuoteData". */
1270     rc = xmlTextWriterEndElement(writer);
1271     if (rc < 0) {
1272         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1273         return PTS_INTERNAL_ERROR;
1274     }
1275
1276     return PTS_SUCCESS;
1277 }
1278
1279
1280 /**
1281  * Quote2
1282  *
1283  * QuoteData
1284  *   Quote2Type
1285  *     QuoteInfo2Type
1286  *       Tag  - unsignedShort
1287  *       Fixed - String
1288  *       ExtendedData - base64
1289  *       PcrInfoShort
1290  *     CapVersioninfoType
1291  *
1292  * @retval PTS_SUCCESS
1293  * @retval PTS_INTERNAL_ERROR
1294  */
1295 int writeQuote2(
1296         xmlTextWriterPtr writer,
1297         OPENPTS_CONTEXT *ctx) {
1298     int rc;
1299     int i;
1300     char *b64buf = NULL;
1301     int b64buf_len;
1302     int size_of_select = 0;
1303     BYTE select_byte[3];
1304     int tag;
1305     char fixed[5];
1306     int locality;
1307     BYTE *composite_hash;
1308     char tagbuf[128];  // Quote tag
1309
1310     /* check */
1311     if (ctx == NULL) {
1312         LOG(LOG_ERR, "null input");
1313         return PTS_FATAL;
1314     }
1315     if (ctx->pcrs == NULL) {
1316         LOG(LOG_TODO, "writeQuote2 - OPENPTS_PCRS is NULL, SKIP QuoteData\n");
1317         return PTS_FATAL;
1318     }
1319     if (ctx->validation_data == NULL) {
1320         LOG(LOG_TODO, "writeQuote2 - TSS_VALIDATION is NULL, SKIP QuoteData\n");
1321         return PTS_FATAL;
1322     }
1323
1324     /* Quote2 - tag [0:1] */
1325     tag = ctx->validation_data->rgbData[0];
1326     tag = tag << 8;
1327     tag += ctx->validation_data->rgbData[1];
1328
1329     /* Quote2 - Fixed [2:5] */
1330     memcpy(fixed, &ctx->validation_data->rgbData[2], 4);
1331     fixed[4] = 0;
1332
1333
1334     /* Quote2 - Nonce [6:25] */
1335     // external_data = &ctx->validation_data->rgbData[6];
1336
1337     /* Quote2 - PcrSelection [26:27] */
1338     size_of_select = ctx->validation_data->rgbData[27];
1339
1340     /* Quote2 - Selection [28:30] */
1341     // TODO 3 only
1342     select_byte[0] = ctx->validation_data->rgbData[28];
1343     select_byte[1] = ctx->validation_data->rgbData[29];
1344     select_byte[2] = ctx->validation_data->rgbData[30];
1345
1346     /* Quote2 - locallity [31] */
1347     locality = ctx->validation_data->rgbData[31];
1348
1349     /* Quote2 - CompositHash [32:51] */
1350     composite_hash = &ctx->validation_data->rgbData[32];
1351
1352     /* QuoteData - start */
1353     rc = xmlTextWriterStartElement(writer, BAD_CAST "QuoteData");
1354     if (rc < 0) {
1355         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1356         return PTS_INTERNAL_ERROR;
1357     }
1358     /* Add an attribute with name "ID" */
1359     // TODO Set UUID based on now
1360     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "ID", BAD_CAST "TBD");
1361     if (rc < 0) {
1362         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1363         return PTS_INTERNAL_ERROR;
1364     }
1365
1366     /* Quote2 - start */
1367     rc = xmlTextWriterStartElement(writer, BAD_CAST "Quote2");
1368     if (rc < 0) {
1369         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1370         return PTS_INTERNAL_ERROR;
1371     }
1372
1373     /* QuoteInfo2 - start */
1374     rc = xmlTextWriterStartElement(writer, BAD_CAST "QuoteInfo2");
1375     if (rc < 0) {
1376         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1377         return PTS_INTERNAL_ERROR;
1378     }
1379
1380     /* QuoteInfo2 - attribute - Tag */
1381     snprintf(tagbuf, sizeof(tagbuf), "%d", tag);
1382     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "Tag", BAD_CAST tagbuf);
1383     if (rc < 0) {
1384         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1385         return PTS_INTERNAL_ERROR;
1386     }
1387     /* QuoteInfo2 - attribute - Fixed - char */
1388     DEBUG("fixed : %s", fixed);
1389     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "Fixed", BAD_CAST fixed);
1390     if (rc < 0) {
1391         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1392         return PTS_INTERNAL_ERROR;
1393     }
1394     /* QuoteInfo2 - attribute - ExternalData - base64 */
1395     b64buf = encodeBase64(
1396         (unsigned char *)ctx->validation_data->rgbExternalData,
1397         ctx->validation_data->ulExternalDataLength,
1398         &b64buf_len);
1399     if (b64buf == NULL) {
1400         LOG(LOG_ERR, "encodeBase64 fail");
1401         return PTS_INTERNAL_ERROR;
1402     }
1403     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "ExternalData", BAD_CAST b64buf);
1404     free(b64buf);
1405     if (rc < 0) {
1406         // LOG(LOG_ERR, "Error at xmlTextWriterWriteAttribute\n");
1407         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1408         return PTS_INTERNAL_ERROR;
1409     }
1410
1411     /* PcrInfoShort - start */
1412     rc = xmlTextWriterStartElement(writer, BAD_CAST "PcrInfoShort");
1413     if (rc < 0) {
1414         // LOG(LOG_ERR, "Error at xmlTextWriterStartElement\n");
1415         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1416         return PTS_INTERNAL_ERROR;
1417     }
1418
1419     /* PcrSelection - start */
1420     rc = xmlTextWriterStartElement(writer, BAD_CAST "PcrSelection");
1421     if (rc < 0) {
1422         // LOG(LOG_ERR, "Error at xmlTextWriterStartElement\n");
1423         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1424         return PTS_INTERNAL_ERROR;
1425     }
1426     /* Add an attribute with name "SizeOfSelect", int */
1427     snprintf(tagbuf, sizeof(tagbuf), "%d", size_of_select);
1428     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "SizeOfSelect", BAD_CAST tagbuf);
1429     if (rc < 0) {
1430         // LOG(LOG_ERR, "Error at xmlTextWriterWriteAttribute\n");
1431         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1432         return PTS_INTERNAL_ERROR;
1433     }
1434     /* Add an attribute with name "PcrSelect", base64 */
1435     b64buf = encodeBase64(
1436         (unsigned char *)select_byte,
1437         size_of_select,
1438         &b64buf_len);
1439     if (b64buf == NULL) {
1440         LOG(LOG_ERR, "encodeBase64 fail");
1441         return PTS_INTERNAL_ERROR;
1442     }
1443     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "PcrSelect", BAD_CAST b64buf);
1444     free(b64buf);
1445     if (rc < 0) {
1446         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1447         return PTS_INTERNAL_ERROR;
1448     }
1449     /* PcrSelection - end */
1450     rc = xmlTextWriterEndElement(writer);
1451     if (rc < 0) {
1452         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1453         return PTS_INTERNAL_ERROR;
1454     }
1455
1456
1457     /* LocalityAtRelease - element */
1458     rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "LocalityAtRelease", "%d", locality);
1459     if (rc < 0) {
1460         displayXmlError(TEXT_WRITER_WRITE_FORMAT_ELEMENT, rc);
1461         return PTS_INTERNAL_ERROR;
1462     }
1463
1464     /* CompositeHash - element */
1465     b64buf = encodeBase64(
1466         (unsigned char *)composite_hash,
1467         20,
1468         &b64buf_len);
1469     if (b64buf == NULL) {
1470         LOG(LOG_ERR, "encodeBase64 fail");
1471         return PTS_INTERNAL_ERROR;
1472     }
1473     rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "CompositeHash", "%s", b64buf);
1474     free(b64buf);
1475     if (rc < 0) {
1476         displayXmlError(TEXT_WRITER_WRITE_FORMAT_ELEMENT, rc);
1477         return PTS_INTERNAL_ERROR;
1478     }
1479
1480
1481     /* PcrComposite - start */
1482     rc = xmlTextWriterStartElement(writer, BAD_CAST "PcrComposit");
1483     if (rc < 0) {
1484         // LOG(LOG_ERR, "Error at xmlTextWriterStartElement\n");
1485         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1486         return PTS_INTERNAL_ERROR;
1487     }
1488
1489     /* PcrSelection - start */
1490     rc = xmlTextWriterStartElement(writer, BAD_CAST "PcrSelection");
1491     if (rc < 0) {
1492         // LOG(LOG_ERR, "Error at xmlTextWriterStartElement\n");
1493         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1494         return PTS_INTERNAL_ERROR;
1495     }
1496     /* Add an attribute with name "SizeOfSelect", int */
1497     snprintf(tagbuf, sizeof(tagbuf), "%d", size_of_select);
1498     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "SizeOfSelect", BAD_CAST tagbuf);
1499     if (rc < 0) {
1500         // LOG(LOG_ERR, "Error at xmlTextWriterWriteAttribute\n");
1501         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1502         return PTS_INTERNAL_ERROR;
1503     }
1504     /* Add an attribute with name "PcrSelect", base64 */
1505     b64buf = encodeBase64(
1506         (unsigned char *)select_byte,
1507         size_of_select,
1508         &b64buf_len);
1509     if (b64buf == NULL) {
1510         LOG(LOG_ERR, "encodeBase64 fail");
1511         return PTS_INTERNAL_ERROR;
1512     }
1513     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "PcrSelect", BAD_CAST b64buf);
1514     free(b64buf);
1515     if (rc < 0) {
1516         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1517         return PTS_INTERNAL_ERROR;
1518     }
1519     /* PcrSelection - end */
1520     rc = xmlTextWriterEndElement(writer);
1521     if (rc < 0) {
1522         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1523         return PTS_INTERNAL_ERROR;
1524     }
1525     /* ValueSize - element */
1526     rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ValueSize", "%d", ctx->pcrs->value_size);
1527     if (rc < 0) {
1528          displayXmlError(TEXT_WRITER_WRITE_FORMAT_ELEMENT, rc);
1529         return PTS_INTERNAL_ERROR;
1530     }
1531     /* PcrValue, loop */
1532     for (i = 0; i < ctx->pcrs->pcr_num; i ++) {
1533         if (ctx->pcrs->pcr_select[i] == 1) {
1534             /* PcrValue - start */
1535             rc = xmlTextWriterStartElement(writer, BAD_CAST "PcrValue");
1536             if (rc < 0) {
1537                 // LOG(LOG_ERR, "Error at xmlTextWriterStartElement\n");
1538                 displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1539                 return PTS_INTERNAL_ERROR;
1540             }
1541             /* Add an attribute - PcrNumber - int */
1542             snprintf(tagbuf, sizeof(tagbuf), "%d", i);
1543             rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "PcrNumber", BAD_CAST tagbuf);
1544             if (rc < 0) {
1545                 // LOG(LOG_ERR, "Error at xmlTextWriterWriteAttribute\n");
1546                 displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1547                 return PTS_INTERNAL_ERROR;
1548             }
1549
1550
1551             /* Write a text, PCR, base64  */
1552             rc = xmlTextWriterWriteBase64(
1553                     writer,
1554                     (const char *) ctx->pcrs->pcr[i],
1555                     0,
1556                     20);  // TODO add length to OPENPTS_PCRS
1557             if (rc < 0) {
1558                 displayXmlError(TEXT_WRITER_WRITE_BASE64, rc);
1559                 return PTS_INTERNAL_ERROR;
1560             }
1561
1562             /* PcrValue - end */
1563             rc = xmlTextWriterEndElement(writer);
1564             if (rc < 0) {
1565                 displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1566                 return PTS_INTERNAL_ERROR;
1567             }
1568         }  // selected
1569     }  // loop
1570     /* PcrComposite - end */
1571     rc = xmlTextWriterEndElement(writer);
1572     if (rc < 0) {
1573         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1574         return PTS_INTERNAL_ERROR;
1575     }
1576
1577     /* PcrInfoShort - end */
1578     rc = xmlTextWriterEndElement(writer);
1579     if (rc < 0) {
1580         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1581         return PTS_INTERNAL_ERROR;
1582     }
1583
1584     /* QuoteInfo2 - end  */
1585     rc = xmlTextWriterEndElement(writer);
1586     if (rc < 0) {
1587         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1588         return PTS_INTERNAL_ERROR;
1589     }
1590
1591     /* Quote2 - end */
1592     rc = xmlTextWriterEndElement(writer);
1593     if (rc < 0) {
1594         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1595         return PTS_INTERNAL_ERROR;
1596     }
1597
1598     /* TpmSignature ------------------------------------ */
1599
1600     /* Start an element named "TpmSignature" as child of QuoteData. */
1601     rc = xmlTextWriterStartElement(writer, BAD_CAST "TpmSignature");
1602     if (rc < 0) {
1603         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1604         return PTS_INTERNAL_ERROR;
1605     }
1606
1607     /* SignatureMethod */
1608
1609     /* Start an element named "SignatureMethod" as child of TpmSignature. */
1610     rc = xmlTextWriterStartElement(writer, BAD_CAST "SignatureMethod");
1611     if (rc < 0) {
1612         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1613         return PTS_INTERNAL_ERROR;
1614     }
1615     /* Add an attribute with name "Algorithm", string */
1616     rc = xmlTextWriterWriteAttribute(writer,
1617             BAD_CAST "Algorithm",
1618             BAD_CAST "http://www.w3.org/2000/09/xmldsig#rsa-sha1");  // TODO
1619     if (rc < 0) {
1620         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1621         return PTS_INTERNAL_ERROR;
1622     }
1623     /* Close the element named "SignatureMethod". */
1624     rc = xmlTextWriterEndElement(writer);
1625     if (rc < 0) {
1626         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1627         return PTS_INTERNAL_ERROR;
1628     }
1629
1630     /* SignatureValue */
1631
1632     /* Start an element named "SignatureValue" as child of TpmSignature. */
1633     rc = xmlTextWriterStartElement(writer, BAD_CAST "SignatureValue");
1634     if (rc < 0) {
1635         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1636         return PTS_INTERNAL_ERROR;
1637     }
1638     /* Write a text, signature, base64  */
1639     rc = xmlTextWriterWriteBase64(
1640             writer,
1641             (const char *) ctx->validation_data->rgbValidationData,
1642             0,
1643             ctx->validation_data->ulValidationDataLength);
1644     if (rc < 0) {
1645         displayXmlError(TEXT_WRITER_WRITE_BASE64, rc);
1646         return PTS_INTERNAL_ERROR;
1647     }
1648     /* Close the element named "SignatureValue". */
1649     rc = xmlTextWriterEndElement(writer);
1650     if (rc < 0) {
1651         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1652         return PTS_INTERNAL_ERROR;
1653     }
1654
1655     /* Close the element named "TpmSignature". */
1656     rc = xmlTextWriterEndElement(writer);
1657     if (rc < 0) {
1658         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1659         return PTS_INTERNAL_ERROR;
1660     }
1661
1662     /* Close the element named "QuoteData". */
1663     rc = xmlTextWriterEndElement(writer);
1664     if (rc < 0) {
1665         displayXmlError(TEXT_WRITER_END_ELEMENT, rc);
1666         return PTS_INTERNAL_ERROR;
1667     }
1668
1669     return PTS_SUCCESS;
1670 }
1671
1672
1673 /**
1674  * generate IR in XML (common)
1675  *
1676  * @param file  - filename of generated IR
1677  * @param XX PCR select
1678  * @param XX AIK auth
1679  * @param XX nonce
1680  *
1681  * return 0:success, -1:error
1682  *  TODO PTS_SUCCESS PTS_XXX
1683  *
1684  * @retval PTS_SUCCESS
1685  * @retval PTS_INTERNAL_ERROR
1686  *
1687  */
1688 // TODO remove file
1689 int writeIr(
1690     OPENPTS_CONTEXT *ctx,
1691     const char *filenameDP,  // in  (set ctx->conf->ir_filename in normal operation)
1692     int *savedFd)            // out
1693 {
1694     int rc = PTS_SUCCESS;
1695     int i;
1696     int irFd;
1697     int lengthOfIrFile;
1698     xmlTextWriterPtr writer;
1699     xmlBufferPtr xmlbuf;
1700     PTS_ComponentId cid;
1701     OPENPTS_TPM_CONTEXT tpm;  // to calc snapshot PCR
1702     PTS_UUID *ir_uuid;
1703     char *str_ir_uuid;
1704     char *filename = NULL;
1705
1706     PTS_Byte smbios[12] = { 0x4A, 0x4A, 0x4A, 0x4A, 0x4A,
1707                             0x4A, 0x4A, 0x4A, 0x4A, 0x4A,
1708                             0x4A, 0x4A
1709                           };
1710     char id[256];
1711     OPENPTS_SNAPSHOT *ss;
1712
1713     DEBUG_CAL("writeIr - start\n");
1714
1715     /* check */
1716     if (ctx == NULL) {
1717         LOG(LOG_ERR, "null input");
1718         return PTS_FATAL;
1719     }
1720
1721
1722     // TODO(munetoh) dummy data
1723     cid.vendor.offset = 0;
1724     cid.vendor.length = 2;
1725     cid.simpleName.offset = 0;
1726     cid.simpleName.length = 2;
1727     cid.modelName.offset = 0;
1728     cid.modelName.length = 2;
1729     cid.modelNumber.offset = 0;
1730     cid.modelNumber.length = 2;
1731     cid.modelSerialNumber.offset = 0;
1732     cid.modelSerialNumber.length = 2;
1733     cid.modelSystemClass.offset = 0;
1734     cid.modelSystemClass.length = 2;
1735
1736     cid.majorVersion = 0;
1737     cid.minorVersion = 1;
1738     cid.buildNumber = 0;
1739
1740     cid.versionString.offset = 0;
1741     cid.versionString.length = 2;
1742     cid.patchLevel.offset = 0;
1743     cid.patchLevel.length = 2;
1744     cid.discretePatches.offset = 0;
1745     cid.discretePatches.length = 2;
1746
1747     cid.buildDate.sec = 0;
1748     cid.buildDate.min = 0;
1749     cid.buildDate.hour = 0;
1750     cid.buildDate.mday = 0;
1751     cid.buildDate.mon = 0;
1752     cid.buildDate.wday = 0;
1753     cid.buildDate.yday = 0;
1754     cid.buildDate.isDst = 0;
1755
1756     cid.dataBlock.blockSize = 0;
1757     cid.dataBlock.dataBlock = smbios;
1758
1759     /* reset TPM */
1760     resetTpm(&tpm, ctx->drtm);
1761
1762     /* Create a new XML buffer */
1763     xmlbuf = xmlBufferCreate();
1764     if (xmlbuf == NULL) {
1765         LOG(LOG_ERR, "creating the xml buffer fail\n");
1766         rc = PTS_INTERNAL_ERROR;
1767         goto error;
1768     }
1769
1770     /* Create a new XmlWriter for memory */
1771     writer = xmlNewTextWriterMemory(xmlbuf, 0);
1772     if (writer == NULL) {
1773         LOG(LOG_ERR, "creating the xml writer fail\n");
1774         rc = PTS_INTERNAL_ERROR;
1775         goto freexml;
1776     }
1777
1778     /* Start the document */
1779     rc = xmlTextWriterStartDocument(writer, "1.0", XML_ENCODING, "no");
1780     if (rc < 0) {
1781         displayXmlError(TEXT_WRITER_START_DOC, rc);
1782         rc = PTS_INTERNAL_ERROR;
1783         goto freexml;
1784     }
1785
1786     /* Start an element named "Report", the root element of the document. */
1787     rc = xmlTextWriterStartElement(writer, BAD_CAST "Report");
1788     if (rc < 0) {
1789         displayXmlError(TEXT_WRITER_START_ELEMENT, rc);
1790         rc = PTS_INTERNAL_ERROR;
1791         goto freexml;
1792     }
1793
1794     DEBUG_CAL("genIr - uuid done\n");
1795
1796     /* Add an attribute of Schemas */
1797     rc = xmlTextWriterWriteAttribute(
1798             writer,
1799             BAD_CAST "xmlns:core",
1800             BAD_CAST XMLNS_CORE);
1801     if (rc < 0) {
1802         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1803         rc = PTS_INTERNAL_ERROR;
1804         goto freexml;
1805     }
1806
1807     rc = xmlTextWriterWriteAttribute(
1808             writer,
1809             BAD_CAST "xmlns:stuff",
1810             BAD_CAST XMLNS_STUFF);
1811     if (rc < 0) {
1812         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1813         rc = PTS_INTERNAL_ERROR;
1814         goto freexml;
1815     }
1816
1817
1818     rc = xmlTextWriterWriteAttribute(
1819             writer,
1820             BAD_CAST "xmlns:xsi",
1821             BAD_CAST "http://www.w3.org/2001/XMLSchema-instance");
1822     if (rc < 0) {
1823         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1824         rc = PTS_INTERNAL_ERROR;
1825         goto freexml;
1826     }
1827
1828     rc = xmlTextWriterWriteAttribute(
1829             writer,
1830             BAD_CAST "xmlns",
1831             BAD_CAST XMLNS_IR);
1832     if (rc < 0) {
1833         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1834         rc = PTS_INTERNAL_ERROR;
1835         goto freexml;
1836     }
1837
1838     /* generate UUID */
1839     ir_uuid = newUuid();
1840     if (ir_uuid == NULL) {
1841         LOG(LOG_ERR, "fail UUID generation\n");
1842         rc = PTS_INTERNAL_ERROR;
1843         goto freexml;
1844     }
1845
1846     str_ir_uuid = getStringOfUuid(ir_uuid);
1847     if (str_ir_uuid == NULL) {
1848         LOG(LOG_ERR, "fail UUID generation\n");
1849         rc = PTS_INTERNAL_ERROR;
1850         xfree(ir_uuid);
1851         goto freexml;
1852     }
1853
1854     /* Add an attribute with name Document ID */
1855     snprintf(id, sizeof(id), "IR_%s", str_ir_uuid);
1856
1857     rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "ID", BAD_CAST id);
1858     if (rc < 0) {
1859         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1860         rc = PTS_INTERNAL_ERROR;
1861         goto free;
1862     }
1863
1864     /* Add an attribute with name UUID */
1865     rc = xmlTextWriterWriteAttribute(
1866             writer, BAD_CAST "UUID", BAD_CAST str_ir_uuid);
1867     if (rc < 0) {
1868         displayXmlError(TEXT_WRITER_WRITE_ATTR, rc);
1869         rc = PTS_INTERNAL_ERROR;
1870         goto free;
1871     }
1872     // TODO(munetoh) SnapshotCollection Loop by selected PCR
1873
1874     /* Quote*/
1875     if (ctx->conf->iml_mode == 0) {
1876         if (ctx->conf->ir_without_quote == 1) {
1877             LOG(LOG_TODO, "skip TPM_Quote\n");
1878         } else {
1879             if (ctx->conf->tpm_quote_type == 1) {
1880                 /* Quote */
1881                 rc = writeQuote(writer, ctx);
1882                 if (rc < 0) {
1883                     LOG(LOG_ERR, "writeIr - writeQuote() rc = %d\n", rc);
1884                     rc = PTS_INTERNAL_ERROR;
1885                     goto free;
1886                 }
1887             } else {
1888                 /* Quote2 */
1889                 rc = writeQuote2(writer, ctx);
1890                 if (rc < 0) {
1891                     LOG(LOG_ERR, "writeIr - writeQuote2() rc = %d\n", rc);
1892                     rc = PTS_INTERNAL_ERROR;
1893                     goto free;
1894                 }
1895             }
1896         }
1897     } else {
1898         // DEBUG("iml.mode!=tss, skip writeQuote()\n");
1899     }
1900
1901     /* add Snapshots */
1902     DEBUG_CAL("genIr - start snapshot\n");
1903
1904     for (i = 0; i < MAX_PCRNUM; i++) {
1905         /* level 0, platform */
1906         ss = getSnapshotFromTable(ctx->ss_table, i, 0);
1907         if (ss != NULL) {
1908             if (ss->event_num > 0) {
1909                 // level 0
1910                 // LOG(LOG_ERR, "writeIr PCR[%d] LV0 num=%d\n", i,ss->event_num);
1911                 writeSnapshot(writer, &tpm, &cid, i, ss);
1912             }
1913         }
1914
1915         /* level 1, runtime */
1916         ss = getSnapshotFromTable(ctx->ss_table, i, 1);
1917         if (ss != NULL) {
1918             if (ss->event_num > 0) {
1919                 // LOG(LOG_ERR, "writeIr PCR[%d] LV1 num=%d\n", i,ss->event_num);
1920                 // writeSnapshot(writer, &tpm, &cid, i, ss);
1921                 if (i == OPENPTS_PCR_INDEX) {
1922                     DEBUG("genIr - Not writing snapshot for OPENPTS_PCR_INDEX (%d)\n",
1923                         OPENPTS_PCR_INDEX);
1924                 } else {
1925                     writeSnapshot(writer, &tpm, &cid, i, ss);
1926                 }
1927             }
1928         }
1929     }  // PCR LOOP
1930
1931     /* Close all elements */
1932     rc = xmlTextWriterEndDocument(writer);
1933     if (rc < 0) {
1934         displayXmlError(TEXT_WRITER_END_DOC, rc);
1935         rc = PTS_INTERNAL_ERROR;
1936         goto free;
1937     }
1938
1939     rc = xmlTextWriterFlush(writer);
1940     if (rc < 0) {
1941         // LOG(LOG_ERR, "writeRm: Error at xmlTextWriterFlush\n");
1942         displayXmlError(TEXT_WRITER_FLUSH, rc);
1943         rc = PTS_INTERNAL_ERROR;
1944         goto free;
1945     }
1946
1947     /* Close all elements */
1948     rc = xmlTextWriterEndDocument(writer);
1949     if (rc < 0) {
1950         LOG(LOG_ERR, "testXmlwriterMemory: Error at xmlTextWriterEndDocument\n");
1951         rc = PTS_INTERNAL_ERROR;
1952         goto free;
1953     }
1954
1955
1956
1957     /* check filename */
1958     if (filenameDP != NULL) {
1959         /* use given filename  for the Unit Test*/
1960     } else {
1961         /* create new IR filename, save to ctx->ir_filename */
1962         char buf[1024];
1963         /* use default filename */
1964         if (ctx->conf->ir_dir == NULL) {
1965             LOG(LOG_ERR, "Set ir.dir in %s.\n", ctx->conf->config_file);
1966             ctx->conf->ir_dir = smalloc("/tmp/.ptsc");
1967         }
1968         snprintf(buf, sizeof(buf), "%s_%s.xml",
1969             ctx->str_uuid,
1970             str_ir_uuid);
1971
1972         ctx->ir_filename = getFullpathName(ctx->conf->ir_dir, buf);
1973         filenameDP = ctx->ir_filename;
1974     }
1975
1976     //filename = ctx->ir_filename;
1977     DEBUG("Write Integrity Report (IR)  : %s\n", filenameDP);  //filename);
1978
1979     /* write to file */
1980     xmlFreeTextWriter(writer);
1981
1982     irFd = open(filenameDP, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
1983     if (-1 == irFd) {
1984         LOG(LOG_ERR, "Failed to open ir file '%s' for writing, errno = %d\n", filename, errno);
1985         rc = PTS_INTERNAL_ERROR;
1986         goto free;
1987     }
1988
1989     /* If savedFd is not NULL, the user wanted a little bit extra security
1990        by not leaving the file lying around on the filesystem to be read/hacked/etc.
1991        This is most useful during verification when running "ptsc -m". Anyway,
1992        serious hackers probably wouldn't be deterred by this ... */
1993     if (NULL != savedFd &&
1994         -1 == unlink(filenameDP)) {
1995         LOG(LOG_ERR, "Failed to unlink file '%s', errno = %d\n", filename, errno);
1996     }
1997
1998     lengthOfIrFile = xmlbuf->use;
1999     {
2000         int writeRc = write(irFd, xmlbuf->content, lengthOfIrFile);
2001         if ( lengthOfIrFile != writeRc ) {
2002             LOG(LOG_ERR, "Failed to write contents to IR file - rc %d, errno %d\n", writeRc, errno);
2003             rc = PTS_INTERNAL_ERROR;
2004             close(irFd);
2005         } else {
2006             rc = PTS_SUCCESS;  // 0
2007             if (NULL != savedFd) {
2008                 *savedFd = irFd;
2009                 /* keep the file open - the caller will close it later */
2010             } else {
2011                 close(irFd);
2012             }
2013         }
2014     }
2015
2016  free:
2017     xfree(ir_uuid);
2018     xfree(str_ir_uuid);
2019
2020  freexml:
2021     xmlBufferFree(xmlbuf);
2022
2023  error:
2024     DEBUG_CAL("writeIr - done\n");
2025
2026     return rc;
2027 }
2028
2029
2030 /*
2031 <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">
2032   <SnapshotCollection Id="IR_1bd0ac8f-d091-4a14-af05-651386f312a1" UUID="1bd0ac8f-d091-4a14-af05-651386f312a1" RevLevel="0">
2033     <core:ComponentID Id="CID_0" ModelSystemClass="745749J" SimpleName="JJ" VersionBuild="1250694000000" VersionString="JJ">
2034       <core:VendorID Name="JJ">
2035         <core:SmiVendorId>0</core:SmiVendorId>
2036         <core:TcgVendorId>DEMO</core:TcgVendorId>
2037       </core:VendorID>
2038     </core:ComponentID>
2039     <core:DigestMethod Algorithm="unknown" Id="sha1"/>
2040     <core:Values>
2041       <stuff:SimpleSnapshotObject>
2042         <stuff:Objects>
2043           <stuff:Hash AlgRef="sha1" Id="PCR_0_LV0_8_0_EVENT">VnKCP/hHGXIdJtuXyR1gR7HnqXs=</stuff:Hash>
2044           <pcrindex>0</pcrindex>
2045           <eventtype>8</eventtype>
2046           <eventdata>CAD+//////8FAAAA</eventdata>
2047         </stuff:Objects>
2048
2049     </core:Values>
2050     <PcrHash AlgRef="sha1" Id="PCR_0_LV0_HASH" IsResetable="false" Number="0" StartHash="AAAAAAAAAAAAAAAAAAAAAAAAAAA=">j7/z7OqcVMjRxCz+qT1r8BvzQFs=</Pc
2051 rHash>
2052   </SnapshotCollection>
2053
2054 */
2055
2056 // TODO dynamic?
2057 #define IR_SAX_BUFFER_SIZE 2048
2058
2059 /**
2060  * SAX parser
2061  */
2062 void  irStartDocument(void * ctx) {
2063     OPENPTS_CONTEXT * pctx = (OPENPTS_CONTEXT *)ctx;
2064     OPENPTS_IR_CONTEXT * ir_ctx = pctx->ir_ctx;
2065
2066     /* check */
2067     if (ctx == NULL) {
2068         LOG(LOG_ERR, "null input");
2069         return;
2070     }
2071
2072     ir_ctx->sax_error = 0;
2073     ir_ctx->event_index = 0;
2074
2075     /* reset TPM */
2076     // por();
2077 }
2078
2079 /**
2080  * SAX parser
2081  */
2082 void  irEndDocument(void * ctx) {
2083     /* check */
2084     if (ctx == NULL) {
2085         LOG(LOG_ERR, "null input");
2086         return;
2087     }
2088 }
2089
2090 /* This prevents real world buffer over-run attacks using malformed IRs
2091    where pcr is basically an index onto the heap or stack. It has been 
2092    already been demonstrated that this type of attack could fool the verifier
2093    wrongly into presenting a valid attestation of a compromised system. */
2094 static int getPcrIndexFromIR(char *value) {
2095     unsigned int index = atoi(value);
2096
2097     /* check */
2098     if (value == NULL) {
2099         LOG(LOG_ERR, "null input");
2100         return -1;
2101     }
2102
2103     index = atoi(value);
2104     if ( index > MAX_PCRNUM ) {
2105         return -1;
2106     } else {
2107         return index;
2108     }
2109 }
2110
2111 /**
2112  * SAX parser - Start of Element
2113  */
2114 void  irStartElement(void* ctx, const xmlChar* name, const xmlChar** atts) {
2115     OPENPTS_CONTEXT * pctx;
2116     OPENPTS_IR_CONTEXT * ir_ctx;
2117     TSS_VALIDATION *validation_data;
2118     OPENPTS_PCRS *pcrs;
2119     BYTE *b64buf = NULL;
2120     int b64buf_len;
2121     int i;
2122     char *type;
2123     char *value;
2124
2125     /* check */
2126     if (ctx == NULL) {
2127         LOG(LOG_ERR, "null input");
2128         return;
2129     }
2130     pctx = (OPENPTS_CONTEXT *)ctx;
2131     ir_ctx = pctx->ir_ctx;
2132     if (ir_ctx == NULL) {
2133         LOG(LOG_ERR, "null input");
2134         return;
2135     }
2136     pcrs = pctx->pcrs;
2137     if (pcrs == NULL) {
2138         LOG(LOG_ERR, "null input");
2139         return;
2140     }
2141     if (name == NULL) {
2142         LOG(LOG_ERR, "null input");
2143         return;
2144     }
2145     validation_data = pctx->validation_data;  // ckeck later
2146
2147     /* IR */
2148     ir_ctx->char_size = 0;
2149
2150     if (!strcmp((char *)name, "Report")) {
2151         //
2152     } else if (!strcmp((char *)name, "SnapshotCollection")) {
2153         //
2154     } else if (!strcmp((char *)name, "core:ComponentID")) {
2155         //
2156     } else if (!strcmp((char *)name, "core:VendorID")) {
2157         //
2158     } else if (!strcmp((char *)name, "core:TcgVendorId")) {
2159         //
2160     } else if (!strcmp((char *)name, "core:SmiVendorId")) {
2161         //
2162     } else if (!strcmp((char *)name, "core:DigestMethod")) {
2163         //
2164     } else if (!strcmp((char *)name, "core:Values")) {
2165         //
2166     } else if (!strcmp((char *)name, "stuff:SimpleSnapshotObject")) {
2167         //
2168     } else if (!strcmp((char *)name, "pcrindex")) {
2169         /* stuff:Hash -> PCR value (base64) */
2170         // DEBUG("START ELEMENT [%s]  <<<< HASH HASH \n",name);
2171         // ir_ctx->sax_state = IR_SAX_STATE_PCR_INDEX;
2172
2173     } else if (!strcmp((char *)name, "eventtype")) {
2174         // DEBUG("START ELEMENT [%s]  <<<< HASH HASH \n",name);
2175         // ir_ctx->sax_state = IR_SAX_STATE_EVENT_TYPE;
2176
2177     } else if (!strcmp((char *)name, "stuff:Hash")) {
2178         // DEBUG("START ELEMENT [%s]  <<<< DIGEST \n",name);
2179         // ir_ctx->sax_state = IR_SAX_STATE_DIGEST;
2180
2181     } else if (!strcmp((char *)name, "eventdata")) {
2182         // DEBUG("START ELEMENT [%s]  <<<<  EVENT_DATA\n",name);
2183         // ir_ctx->sax_state = IR_SAX_STATE_EVENT_DATA;
2184
2185     } else if (!strcmp((char *)name, "PcrHash")) {
2186         // DEBUG("START ELEMENT [%s]  <<<<  EVENT_DATA\n",name);
2187         // ir_ctx->sax_state = IR_SAX_STATE_PCR;
2188
2189         /* get Number =pcrindex) attribute ( */
2190         if (atts != NULL) {
2191             for (i = 0;(atts[i] != NULL);i++) {
2192                 type = (char *)atts[i++];
2193                 if (atts[i] != NULL) {
2194                     value= (char *)atts[i];
2195                     if (!strcmp(type, "Number")) {
2196                         ir_ctx->pcr_index = getPcrIndexFromIR(value);
2197                     }
2198                 }
2199             }
2200         }
2201     } else if (!strcmp((char *)name, "stuff:Objects")) {
2202         /* New event */
2203         /* malloc */
2204         ir_ctx->event = (TSS_PCR_EVENT *) xmalloc(sizeof(TSS_PCR_EVENT));
2205         if (ir_ctx->event == NULL) {
2206             return;
2207         }
2208         memset(ir_ctx->event, 0, sizeof(TSS_PCR_EVENT));
2209         // see irEndElement
2210     } else if (!strcmp((char *)name, "QuoteData")) {
2211         /* Quote */
2212         // <QuoteData ID="TBD">...
2213         // TODO check ID?
2214         if (pcrs == NULL) {
2215             pcrs = xmalloc_assert(sizeof(OPENPTS_PCRS));
2216             // TODO check
2217             memset(pcrs, 0, sizeof(OPENPTS_PCRS));
2218             pctx->pcrs = pcrs;
2219             // DEBUG("malloc OPENPTS_PCRS %p\n", pcrs);
2220         }
2221         if (validation_data == NULL) {
2222             validation_data = xmalloc_assert(sizeof(TSS_VALIDATION));
2223             // TODO check
2224             memset(validation_data, 0, sizeof(TSS_VALIDATION));
2225             pctx->validation_data = validation_data;
2226             // DEBUG("malloc TSS_VALIDATION %p\n", validation_data);
2227         }
2228     } else if (!strcmp((char *)name, "Quote")) {
2229         // <Quote>...
2230     } else if (!strcmp((char *)name, "Quote2")) {
2231         // <Quote2>...
2232     } else if (!strcmp((char *)name, "PcrComposit")) {
2233         // <PcrComposit>...
2234     } else if (!strcmp((char *)name, "PcrSelection")) {
2235         int attr_cnt = 0;
2236         // <PcrSelection SizeOfSelect="3" PcrSelect="/6AA"/>
2237         //   SizeOfSelect => ctx->pcrs->pcr_select_size
2238         //   PcrSelect    => ctx->pcrs->pcr_select
2239         //  note) PcrSelection is not used to verify the quote. - 20101125 SM
2240         if (atts != NULL) {
2241             for (i = 0;(atts[i] != NULL);i++) {
2242                 type = (char *)atts[i++];
2243                 if (atts[i] != NULL) {
2244                     value= (char *)atts[i];
2245                     if (!strcmp(type, "SizeOfSelect")) {
2246                         /* TPM1.2 - 24 PCRS -> 3 */
2247                         pcrs->pcr_select_size = atoi(value);
2248                         attr_cnt++;
2249                         // DEBUG("SizeOfSelect = %d\n", ir_ctx->pcr_select_size);
2250                     }
2251                     if (!strcmp(type, "PcrSelect")) {
2252                         /* used later */
2253                         if (b64buf != NULL) {
2254                             LOG(LOG_ERR, "bad memory management");
2255                             free(b64buf);
2256                         }
2257                         b64buf = (BYTE *) decodeBase64(
2258                             (char *)value,
2259                             strlen(value),
2260                             &b64buf_len);
2261                         // attr_cnt++;
2262                         // DEBUG("PcrSelect = 0x%02x %02x %02x \n", buf[0],buf[1],buf[2]);
2263                         if (b64buf == NULL) {
2264                             LOG(LOG_ERR, "Failed to decode base64 string\n");
2265                             ir_ctx->sax_error++;
2266                             pcrs->pcr_select_size = 0;
2267                         } else {
2268                             attr_cnt++;
2269                         }
2270                     }
2271                 }
2272             }
2273         }
2274         /* set pcr_select */
2275         // if (pcrs->pcr_select_size > 0) {
2276         if (attr_cnt == 2) {
2277             // ir_ctx->pcrs->pcr_select_byte
2278             if (pcrs->pcr_select_byte != NULL) {
2279                 xfree(pcrs->pcr_select_byte);
2280             }
2281             pcrs->pcr_select_byte = xmalloc(pcrs->pcr_select_size);
2282             if (pcrs->pcr_select_byte != NULL) {
2283                 if (b64buf != NULL) {
2284                     memcpy(pcrs->pcr_select_byte, b64buf, pcrs->pcr_select_size);
2285                 } else {
2286                     LOG(LOG_ERR, "pcr_select_byte is missing");
2287                 }
2288             } else {
2289                 LOG(LOG_ERR, "no memory\n");
2290             }
2291         } else {
2292             /* BAD IR */
2293             LOG(LOG_ERR, "BAD IR SizeOfSelect or PcrSelect are missing\n");
2294         }
2295         /* free Base64 buffer */
2296         if (b64buf != NULL) {
2297             free(b64buf);
2298             b64buf = NULL;
2299         }
2300     } else if (!strcmp((char *)name, "ValueSize")) {
2301         // <ValueSize>200</ValueSize>
2302         //     Text => ctx->pcrs->value_size  - irEndElement()
2303     } else if (!strcmp((char *)name, "PcrValue")) {
2304         // <PcrValue PcrNumber="0">j7/z7OqcVMjRxCz+qT1r8BvzQFs=</PcrValue>
2305         //   PcrNumber => ir_ctx->pcr_index
2306         //   Text      => ir_ctx->pcr
2307         if (atts != NULL) {
2308             for (i = 0;(atts[i] != NULL);i++) {
2309                 type = (char *)atts[i++];
2310                 if (atts[i] != NULL) {
2311                     value= (char *)atts[i];
2312                     if (!strcmp(type, "PcrNumber")) {
2313                         ir_ctx->pcr_index = getPcrIndexFromIR(value);
2314                     }
2315                 }
2316             }
2317         }
2318     } else if (!strcmp((char *)name, "QuoteInfo")) {
2319         // <QuoteInfo VersionMajor="1" VersionMinor="2" VersionRevMajor="0" VersionRevMinor="0" Fixed="QUOT"
2320         // DigestValue="AQEAAFFVT1RjiS4FS/WTFp0ynrVBQKD559YRGnM9C4gDMct9ZZo5kd8yf2tW46Qs"
2321         // ExternalData="cz0LiAMxy31lmjmR3zJ/a1bjpCw="/>
2322
2323         // DEBUG("QuoteInfo attribute\n");
2324         // DigestValue=base64,
2325         // ExternalData=base64
2326         if (atts != NULL) {
2327             for (i = 0;(atts[i] != NULL);i++) {
2328                 type = (char *)atts[i++];
2329
2330                 if (validation_data == NULL) {
2331                     LOG(LOG_ERR, "validation_data == NULL");
2332                     return;
2333                 }
2334                 if (validation_data->rgbData == NULL) {
2335                     // TODO 1.2 only
2336                     validation_data->ulDataLength = 48;
2337                     validation_data->rgbData = xmalloc_assert(48);
2338                 }
2339
2340                 if (atts[i] != NULL) {
2341                     value= (char *)atts[i];
2342                     if (!strcmp(type, "VersionMajor")) {
2343                         validation_data->versionInfo.bMajor = atoi(value);
2344                         validation_data->rgbData[0] = atoi(value);
2345                     }
2346                     if (!strcmp(type, "VersionMinor")) {
2347                         validation_data->versionInfo.bMinor = atoi(value);
2348                         validation_data->rgbData[1] = atoi(value);
2349                     }
2350                     if (!strcmp(type, "VersionRevMajor")) {
2351                         validation_data->versionInfo.bRevMajor = atoi(value);
2352                         validation_data->rgbData[2] = atoi(value);
2353                     }
2354                     if (!strcmp(type, "VersionRevMinor")) {
2355                         validation_data->versionInfo.bRevMinor = atoi(value);
2356                         validation_data->rgbData[3] = atoi(value);
2357                     }
2358                     if (!strcmp(type, "Fixed")) {
2359                         // TODO check size
2360                         validation_data->rgbData[4] = value[0];
2361                         validation_data->rgbData[5] = value[1];
2362                         validation_data->rgbData[6] = value[2];
2363                         validation_data->rgbData[7] = value[3];
2364                     }
2365                     if (!strcmp(type, "DigestValue")) {
2366                         // TODO check buf len
2367                         b64buf = decodeBase64(
2368                             (char *)value,
2369                             strlen(value),
2370                             &b64buf_len);
2371                         if (b64buf == NULL) {
2372                             LOG(LOG_ERR, "decodeBase64 fail");
2373                             ir_ctx->sax_error++;
2374                             return;  // TODO  return?
2375                         }
2376                         if (b64buf_len == 20) {
2377                             memcpy(&validation_data->rgbData[8], b64buf, 20);
2378                         } else {
2379                             LOG(LOG_ERR, "size of decodeBase64 out is not 20 but %d", b64buf_len);
2380                             ir_ctx->sax_error++;
2381                             return;  // TODO
2382                         }
2383
2384                         free(b64buf);
2385                     }
2386                     if (!strcmp(type, "ExternalData")) {
2387                         b64buf = decodeBase64(
2388                             (char *)value,
2389                             strlen(value),
2390                             &b64buf_len);
2391                         if (b64buf == NULL) {
2392                             LOG(LOG_ERR, "decodeBase64 fail");
2393                             ir_ctx->sax_error++;
2394                             return;  // TODO
2395                         }
2396                         if (b64buf_len == 20) {
2397                             validation_data->ulExternalDataLength = b64buf_len;
2398                             if (validation_data->rgbExternalData != NULL) {
2399                                 free(validation_data->rgbExternalData);
2400                             }
2401                             validation_data->rgbExternalData = b64buf;
2402                             // TODO remove?
2403                             // memcpy(validation_data->rgbExternalData, buf, rc);
2404                             memcpy(&validation_data->rgbData[28], b64buf, 20);
2405                         } else {
2406                             LOG(LOG_ERR, "Failed to decode base64 string, len = %d not 20\n", b64buf_len);
2407                             ir_ctx->sax_error++;
2408                             return;  // TODO
2409                         }
2410                     }
2411                 }
2412             }
2413         }
2414     } else if (!strcmp((char *)name, "QuoteInfo2")) {
2415         // <QuoteInfo2 Tag="54" Fixed="QUT2" ExternalData="WlpaWlpaWlpaWlpaWlpaWlpaWlo=">
2416         if (atts != NULL) {
2417             for (i = 0;(atts[i] != NULL);i++) {
2418                 type = (char *)atts[i++];
2419
2420                 if (validation_data == NULL) {
2421                     LOG(LOG_ERR, "validation_data == NULL");
2422                     return;
2423                 }
2424                 if (validation_data->rgbData == NULL) {
2425                     // TODO 1.2 only
2426                     validation_data->ulDataLength = 52;
2427                     validation_data->rgbData = xmalloc_assert(52);
2428                 }
2429
2430                 if (atts[i] != NULL) {
2431                     value= (char *)atts[i];
2432                     if (!strcmp(type, "Tag")) {
2433                         int tag = atoi(value);
2434                         validation_data->rgbData[0] = (tag >> 8) & 0xFF;
2435                         validation_data->rgbData[1] = tag & 0xFF;
2436                     }
2437                     if (!strcmp(type, "Fixed")) {
2438                         // TODO check size
2439                         validation_data->rgbData[2] = value[0];
2440                         validation_data->rgbData[3] = value[1];
2441                         validation_data->rgbData[4] = value[2];
2442                         validation_data->rgbData[5] = value[3];
2443                     }
2444                     if (!strcmp(type, "ExternalData")) {
2445                         b64buf = decodeBase64(
2446                             (char *)value,
2447                             strlen(value),
2448                             &b64buf_len);
2449                         if (b64buf == NULL) {
2450                             LOG(LOG_ERR, "decodeBase64 fail");
2451                             ir_ctx->sax_error++;
2452                             return;
2453                         }
2454                         if (b64buf_len == 20) {
2455                             validation_data->ulExternalDataLength = b64buf_len;
2456                             validation_data->rgbExternalData = b64buf;
2457                             // memcpy(validation_data->rgbExternalData, b64buf, rc);
2458                             memcpy(&validation_data->rgbData[6], b64buf, 20);
2459                         } else {
2460                             LOG(LOG_ERR, "Failed to decode base64 string, len = %d not 20\n", b64buf_len);
2461                             ir_ctx->sax_error++;
2462                             return;  // TODO
2463                         }
2464                     }
2465                 }
2466             }
2467         }
2468     } else if (!strcmp((char *)name, "PcrInfoShort")) {
2469         //
2470     } else if (!strcmp((char *)name, "LocalityAtRelease")) {
2471         // end
2472     } else if (!strcmp((char *)name, "CompositeHash")) {
2473         // end
2474     } else if (!strcmp((char *)name, "TpmSignature")) {
2475         // TODO
2476     } else if (!strcmp((char *)name, "SignatureMethod")) {
2477         // TODO check alg
2478     } else if (!strcmp((char *)name, "SignatureValue")) {
2479         // DONE LOG(LOG_TODO, "get value(base64)\n");
2480     } else if (!strcmp((char *)name, "KeyInfo")) {
2481         // TODO
2482     } else if (!strcmp((char *)name, "KeyValue")) {
2483         // DONE LOG(LOG_TODO, "get value(base64)\n");
2484     } else { /* Else? */
2485         LOG(LOG_ERR, "START ELEMENT [%s] \n", name);
2486         ir_ctx->sax_state = IR_SAX_STATE_IDOL;
2487     }
2488 }
2489
2490 /**
2491  * SAX parser - End of Element
2492  */
2493 void irEndElement(void * ctx, const xmlChar * name) {
2494     OPENPTS_CONTEXT * pctx;
2495     OPENPTS_IR_CONTEXT * ir_ctx;
2496     TSS_VALIDATION *validation_data;
2497     OPENPTS_PCRS *pcrs;
2498     int rc;
2499     BYTE *b64buf = NULL;
2500     int b64buf_len;
2501
2502     /* check */
2503     if (ctx == NULL) {
2504         LOG(LOG_ERR, "null input");
2505         return;
2506     }
2507     pctx = (OPENPTS_CONTEXT *)ctx;
2508     ir_ctx = pctx->ir_ctx;
2509     if (ir_ctx == NULL) {
2510         LOG(LOG_ERR, "null input");
2511         return;
2512     }
2513     pcrs = pctx->pcrs;
2514     if (pcrs == NULL) {
2515         LOG(LOG_ERR, "null input");
2516         return;
2517     }
2518     if (name == NULL) {
2519         LOG(LOG_ERR, "null input");
2520         return;
2521     }
2522     validation_data = pctx->validation_data;  // ckeck later
2523
2524     /* END ELEMENT */
2525     if (!strcmp((char *)name, "stuff:Objects")) {
2526         int extend = 0;
2527         int pcr_index = -1;
2528         BYTE* digest = NULL;
2529
2530         /* Event finish, let's get into our structure */
2531         ir_ctx->event_index++;
2532
2533         /* Add new event wrapper and update the chain */
2534         ir_ctx->ew_last = ir_ctx->ew_new;
2535         /* malloc */
2536         ir_ctx->ew_new = (OPENPTS_PCR_EVENT_WRAPPER *)
2537             xmalloc(sizeof(OPENPTS_PCR_EVENT_WRAPPER));
2538         if (ir_ctx->ew_new == NULL) {
2539             ir_ctx->sax_error++;
2540             return;
2541         }
2542         memset(ir_ctx->ew_new, 0, sizeof(OPENPTS_PCR_EVENT_WRAPPER));
2543
2544         /* set the event structure */
2545         if (ir_ctx->event == NULL) {
2546             LOG(LOG_ERR, "internal error\n");
2547             ir_ctx->ew_new->event = NULL;
2548             ir_ctx->sax_error++;
2549         } else {
2550             /* TPM extend - after FSM push  */
2551             extend = 1;
2552             pcr_index = ir_ctx->event->ulPcrIndex;
2553             digest = ir_ctx->event->rgbPcrValue;
2554
2555             /* move to the EW chain */
2556             ir_ctx->ew_new->event = ir_ctx->event;
2557             ir_ctx->event = NULL;
2558         }
2559
2560         /* map to the snapshot, push FSM  */
2561         rc = addEventToSnapshotBin(pctx, ir_ctx->ew_new);  // iml.c
2562         if (rc != PTS_SUCCESS) {
2563             // LOG(LOG_ERR, "validateIr:irStartElement - addEventToSnapshotBin rc = %d\n", rc);
2564             ir_ctx->integrity = OPENPTS_RESULT_INVALID;
2565             return;
2566         }
2567         /* extend after FSM push. after execution of Action() in FSM */
2568         if (extend == 1) {
2569             extendTpm2(
2570                 &pctx->tpm,
2571                 pcr_index,
2572                 digest);
2573         }
2574
2575
2576     } else if (!strcmp((char *)name, "SnapshotCollection")) {
2577         /*  snapshot finish  */
2578         /* Push FSM until Final state to run actions */
2579
2580         rc = flashSnapshot(pctx, ir_ctx->pcr_index);  // iml.c
2581         if (rc == PTS_INVALID_SNAPSHOT) {
2582             DEBUG_FSM("irEndElement() -- SS has validation error\n");
2583             ir_ctx->fsm_error_count++;
2584         } else if (rc != PTS_SUCCESS) {
2585             LOG(LOG_ERR, "SnapshotCollection -> FSM flash was fail\n");
2586             ir_ctx->sax_error++;
2587             return;
2588         }
2589     } else if (!strcmp((char *)name, "pcrindex")) {
2590         ir_ctx->buf[ir_ctx->char_size] = 0;
2591         // ir_ctx->event->ulPcrIndex = atoi(ir_ctx->buf);
2592         ir_ctx->event->ulPcrIndex = getPcrIndexFromIR(ir_ctx->buf);
2593     } else if (!strcmp((char *)name, "stuff:Hash")) {
2594         ir_ctx->buf[ir_ctx->char_size] = 0;
2595         /* base64 -> plain */
2596         ir_ctx->event->rgbPcrValue = decodeBase64(
2597             (char *)ir_ctx->buf,
2598             ir_ctx->char_size,
2599             &b64buf_len);
2600         if (ir_ctx->event->rgbPcrValue == NULL) {
2601             LOG(LOG_ERR, "decodeBase64 fail");
2602             ir_ctx->sax_error++;
2603             return;  // TODO
2604         } else {
2605             ir_ctx->event->ulPcrValueLength = b64buf_len;
2606         }
2607     } else if (!strcmp((char *)name, "eventtype")) {
2608         ir_ctx->buf[ir_ctx->char_size] = 0;
2609         ir_ctx->event->eventType = atoi(ir_ctx->buf);
2610     } else if (!strcmp((char *)name, "eventdata")) {
2611         ir_ctx->buf[ir_ctx->char_size] = 0;  // null terminate
2612         /* base64 -> plain */
2613         ir_ctx->event->rgbEvent = decodeBase64(
2614             (char *)ir_ctx->buf,
2615             ir_ctx->char_size,
2616             &b64buf_len);
2617         if (ir_ctx->event->rgbEvent == NULL) {
2618             LOG(LOG_ERR, "decodeBase64 fail");
2619             ir_ctx->sax_error++;
2620             return;  // TODO
2621         } else {
2622             ir_ctx->event->ulEventLength = b64buf_len;
2623         }
2624     } else if (!strcmp((char *)name, "PcrHash")) {
2625         /* PCR value */
2626         ir_ctx->buf[ir_ctx->char_size] = 0;  // null terminate
2627         /* base64 -> plain */
2628         b64buf = decodeBase64(
2629             (char *)ir_ctx->buf,
2630             ir_ctx->char_size,
2631             &b64buf_len);
2632         if (b64buf == NULL) {
2633             LOG(LOG_ERR, "decodeBase64 fail");
2634             ir_ctx->sax_error++;
2635             return;  // TODO
2636         }
2637         if (b64buf_len > MAX_DIGEST_SIZE) {
2638             LOG(LOG_ERR, "decodeBase64 out is too latge, %d > %d",
2639                 b64buf_len, MAX_DIGEST_SIZE);
2640             ir_ctx->sax_error++;
2641             return;  // TODO
2642         } else {
2643             memcpy(ir_ctx->pcr, b64buf, b64buf_len);
2644         }
2645         free(b64buf);
2646         /* Check with PCR in TPM */
2647         rc = checkTpmPcr2(&pctx->tpm, ir_ctx->pcr_index, ir_ctx->pcr);
2648         if (rc != PTS_SUCCESS) {
2649             LOG(LOG_ERR, "ERROR PCR[%d] != IML\n", ir_ctx->pcr_index);
2650             ir_ctx->sax_error = 1;
2651             // verbose = DEBUG_FLAG | DEBUG_TPM_FLAG;  // switch DEBUG MODE
2652             if (isDebugFlagSet(DEBUG_FLAG)) {
2653                 BYTE pcr[20];
2654                 DEBUG("PCR[%d]\n", ir_ctx->pcr_index);
2655                 getTpmPcrValue(&pctx->tpm, ir_ctx->pcr_index, pcr);
2656                 debugHex("", pcr, 20, " (emulated)\n");
2657                 debugHex("", ir_ctx->pcr, 20, " (IR)\n");
2658             }
2659         } else {
2660             /* IML and PCR are consistent :-) */
2661             DEBUG_FSM("PCR[%d] == IML\n", ir_ctx->pcr_index);
2662             // TODO(munetoh) add property?  tpm.pcr.N.snapshot.N.integrity=valid
2663
2664             /* update pcrs, used by validatePcrCompositeV11 */
2665             if (pctx->conf->iml_mode == 0) {
2666                 if (pcrs == NULL) {
2667                     /* malloc OPENPTS_PCRS */
2668                     // LOG(LOG_ERR, "PCR is not intialized - No QuoteData element\n");
2669                     pcrs = xmalloc(sizeof(OPENPTS_PCRS));
2670                     if (pcrs == NULL) {
2671                         LOG(LOG_ERR, "no memory\n");
2672                         return;
2673                     }
2674                     memset(pcrs, 0, sizeof(OPENPTS_PCRS));
2675                     pctx->pcrs = pcrs;
2676                 }
2677                 // TODO PcrValue and PcrHash
2678                 // pcrs->pcr_select[ir_ctx->pcr_index] = 1;
2679                 // memcpy(pcrs->pcr[ir_ctx->pcr_index], ir_ctx->pcr, 20);  // TODO pcr size
2680
2681             } else {
2682                 // DEBUG("iml.mode!=tss, skip pcr copy to PCRS\n");
2683             }
2684         }
2685     } else if (!strcmp((char *)name, "LocalityAtRelease")) {
2686         // TODO
2687         if (validation_data == NULL) {
2688             LOG(LOG_ERR, "validation_data == NULL");
2689             return;
2690         }
2691         validation_data->rgbData[31] = atoi(ir_ctx->buf);
2692     } else if (!strcmp((char *)name, "CompositeHash")) {
2693         // DEBUG("CompositeHash %s", ir_ctx->buf);
2694         if (validation_data == NULL) {
2695             LOG(LOG_ERR, "validation_data == NULL");
2696             return;
2697         }
2698         b64buf = decodeBase64(
2699             (char *)ir_ctx->buf,
2700             ir_ctx->char_size,
2701             &b64buf_len);
2702         if (b64buf == NULL) {
2703             LOG(LOG_ERR, "decodeBase64 fail");
2704             ir_ctx->sax_error++;
2705             return;
2706         }
2707         memcpy(&validation_data->rgbData[32], b64buf, 20);
2708         free(b64buf);
2709     } else if (!strcmp((char *)name, "ValueSize")) {
2710         // <ValueSize>200</ValueSize>
2711         //   Text => ctx->pcrs->value_size
2712         ir_ctx->buf[ir_ctx->char_size] = 0;  // end of string
2713         pcrs->value_size = atoi(ir_ctx->buf);
2714     } else if (!strcmp((char *)name, "PcrValue")) {
2715         // <PcrValue PcrNumber="0">j7/z7OqcVMjRxCz+qT1r8BvzQFs=</PcrValue>
2716         //  Text => ctx->pcrs->pcr[0]
2717         ir_ctx->buf[ir_ctx->char_size] = 0;
2718         b64buf = decodeBase64(
2719             (char *)ir_ctx->buf,
2720             ir_ctx->char_size,
2721             &b64buf_len);
2722         if (b64buf == NULL) {
2723             LOG(LOG_ERR, "decodeBase64 fail");
2724             ir_ctx->sax_error++;
2725             return;
2726         }
2727         if (b64buf_len < SHA1_DIGEST_SIZE) {
2728             LOG(LOG_ERR, "decodeBase64 outout is too small, %d < %d", b64buf_len, SHA1_DIGEST_SIZE);
2729             ir_ctx->sax_error++;
2730             return;
2731         }
2732         if (b64buf_len > MAX_DIGEST_SIZE) {
2733             LOG(LOG_ERR, "decodeBase64 outout is too large, %d < %d", b64buf_len, MAX_DIGEST_SIZE);
2734             ir_ctx->sax_error++;
2735             return;
2736         }
2737
2738         memcpy(pcrs->pcr[ir_ctx->pcr_index], b64buf, b64buf_len);
2739         free(b64buf);
2740
2741         pcrs->pcr_select[ir_ctx->pcr_index] = 1;
2742
2743         // DEBUG("PCR[%d] base64=%s\n", ir_ctx->pcr_index,ir_ctx->buf);
2744         // printHex("", (BYTE *)pcrs->pcr[ir_ctx->pcr_index], 20, "\n");
2745
2746         // DEBUG("set reference PCR values\n");
2747         {
2748             // tpm.quote.pcr.0=base64
2749             // note) Do not use PCR10(IMA) as policy
2750             char name[64];
2751             snprintf(name, sizeof(name), "disable.quote.pcr.%d", ir_ctx->pcr_index);
2752             if (NULL != getProperty(ctx, name)) {
2753                 DEBUG("Found disabled quote property '%s'\n", name);
2754                 snprintf(name, sizeof(name), "# tpm.quote.pcr.%d", ir_ctx->pcr_index);
2755             } else {
2756                 snprintf(name, sizeof(name), "tpm.quote.pcr.%d", ir_ctx->pcr_index);
2757             }
2758             addProperty(ctx, name, ir_ctx->buf);
2759
2760             // char buf2[20];
2761             // snprintf(buf2, sizeof(buf2), "tpm.quote.pcr.%d", ir_ctx->pcr_index);
2762             // addProperty(ctx, buf2, ir_ctx->buf);
2763         }
2764     } else if (!strcmp((char *)name, "QuoteInfo2")) {
2765         /* pcr select => validation_data */
2766         if (pcrs->pcr_select_byte == NULL) {
2767             LOG(LOG_ERR, "pcrs->pcr_select_byte is null");
2768         } else {
2769             if (validation_data == NULL) {
2770                 LOG(LOG_ERR, "validation_data == NULL");
2771                 return;
2772             }
2773             validation_data->rgbData[26] = 0;
2774             validation_data->rgbData[27] = pcrs->pcr_select_size;
2775             validation_data->rgbData[28] = pcrs->pcr_select_byte[0];
2776             validation_data->rgbData[29] = pcrs->pcr_select_byte[1];
2777             validation_data->rgbData[30] = pcrs->pcr_select_byte[2];
2778         }
2779     } else if (!strcmp((char *)name, "SignatureValue")) {
2780         ir_ctx->buf[ir_ctx->char_size] = 0;
2781         if (ir_ctx->char_size > IR_SAX_BUFFER_SIZE) {  // TODO check buf size
2782             LOG(LOG_ERR, "buf is small %d \n", ir_ctx->char_size);
2783             ir_ctx->sax_error++;
2784         } else {
2785             if (validation_data == NULL) {
2786                 LOG(LOG_ERR, "validation_data == NULL");
2787                 return;
2788             }
2789             if (validation_data->rgbValidationData != NULL) {
2790                 xfree(validation_data->rgbValidationData);
2791             }
2792             /* base64 -> plain */
2793             validation_data->rgbValidationData = decodeBase64(
2794                 (char *)ir_ctx->buf,
2795                 ir_ctx->char_size,
2796                 &b64buf_len);
2797             if (validation_data->rgbValidationData == NULL) {
2798                 LOG(LOG_ERR, "decodeBase64 fail");
2799                 ir_ctx->sax_error++;
2800                 return;  // TODO
2801             }
2802             validation_data->ulValidationDataLength = b64buf_len;
2803         }
2804     } else if (!strcmp((char *)name, "KeyValue")) {
2805         ir_ctx->buf[ir_ctx->char_size] = 0;
2806         if (ir_ctx->char_size > IR_SAX_BUFFER_SIZE) {  // TODO check buf size
2807             LOG(LOG_ERR, "buf is small %d \n", ir_ctx->char_size);
2808         } else {
2809             pcrs->pubkey = decodeBase64(
2810                 (char *)ir_ctx->buf,
2811                 ir_ctx->char_size,
2812                 &b64buf_len);
2813             if (pcrs->pubkey == NULL) {
2814                 LOG(LOG_ERR, "decodeBase64 fail");
2815                 ir_ctx->sax_error++;
2816                 return;
2817             }
2818             pcrs->pubkey_length = b64buf_len;
2819         }
2820     } else if (!strcmp((char *)name, "QuoteData")) {
2821         /* check Nonce */
2822         /* Validate QuoteData */
2823
2824         if ( ir_ctx->sax_error > 0 ) {
2825             LOG(LOG_ERR, "Unable to validate quote data due to %d SAX parse errors\n", ir_ctx->sax_error);
2826         } else {
2827             rc = validateQuoteData(pcrs, validation_data);
2828             // DEBUG("validateQuoteData = %d\n", rc);
2829             if (rc != PTS_SUCCESS) {
2830                 LOG(LOG_ERR, "---------------------------------------------------------------------------\n");
2831                 LOG(LOG_ERR, "BAD QUOTE DATA!!!  BAD QUOTE DATA!!!  BAD QUOTE DATA!!!  BAD QUOTE DATA!!!\n");
2832                 LOG(LOG_ERR, "---------------------------------------------------------------------------\n");
2833                 addProperty(pctx, "tpm.quote.signature", "invalid");
2834                 // TODO set error
2835                 ir_ctx->bad_quote = 1;
2836             } else {
2837 #if 0
2838                 LOG(LOG_TODO, "---------------------------------------------------------------------------\n");
2839                 LOG(LOG_TODO, "GOOD QUOTE DATA!!! GOOD QUOTE DATA!!! GOOD QUOTE DATA!!! GOOD QUOTE DATA!!!\n");
2840                 LOG(LOG_TODO, "---------------------------------------------------------------------------\n");
2841 #endif
2842                 addProperty(pctx, "tpm.quote.signature", "valid");
2843             }
2844         }
2845
2846         pctx->conf->ir_without_quote = 0;
2847     } else {
2848         /* Else? */
2849     }
2850
2851     ir_ctx->sax_state = IR_SAX_STATE_IDOL;
2852 }
2853
2854 /**
2855  * SAX parser  - Text of Element
2856  *
2857  * This called multiple time:-(
2858  * 
2859  */
2860 void irCharacters(void* ctx, const xmlChar * ch, int len) {
2861     OPENPTS_CONTEXT * pctx;
2862     OPENPTS_IR_CONTEXT * ir_ctx;
2863
2864     /* check */
2865     if (ctx == NULL) {
2866         LOG(LOG_ERR, "null input");
2867         return;
2868     }
2869     pctx = (OPENPTS_CONTEXT *)ctx;
2870     ir_ctx = pctx->ir_ctx;
2871     if (ir_ctx == NULL) {
2872         LOG(LOG_ERR, "null input");
2873         return;
2874     }
2875     //if (ch == NULL) {
2876     //    LOG(LOG_ERR, "null input");
2877     //    return;
2878     //}
2879
2880
2881     /* copy to buf at ir_ctx, but check length first, ensuring additional space
2882        for NULL terminator */
2883     if ((ir_ctx->char_size + len + 1) > EVENTDATA_BUF_SIZE) {
2884         LOG(LOG_ERR, "Buffer for EVENTDATA is too small, %d + %d > %d\n", ir_ctx->char_size, len, EVENTDATA_BUF_SIZE);
2885         return;
2886     }
2887     memcpy(&ir_ctx->buf[ir_ctx->char_size], ch, len);
2888     ir_ctx->char_size += len;
2889 }
2890
2891 /**
2892  * Validate Integrity Report (IR) by using SAX parser
2893  * @param ctx PTS_CONTEXT
2894  * @param filename IR file
2895  *
2896  * @retval OPENPTS_RESULT_VALID
2897  * @retval OPENPTS_RESULT_INVALID
2898  * @retval OPENPTS_RESULT_UNKNOWN
2899  *
2900  * @retval PTS_FATAL
2901  *
2902  * Capability is Limited at this moment.
2903  * - check the consistency between IML and PCR
2904  *
2905  * Will supports
2906  * - validate quote signature
2907  * - validate with Reference Manifest
2908  * - validate with Integrity Database
2909  *
2910  */
2911
2912 /*
2913  * 20100522 move global variable to ir_ctx
2914  * *** glibc detected *** ./check_fsm: double free or corruption (!prev): 0x090d5420 ***
2915  * Just avoid error
2916  *    export MALLOC_CHECK_=0
2917  * Fix error
2918  *    valgrind --leak-check=full --show-reachable=yes -v tests/check_fsm
2919  *
2920  */
2921 // int validateIr(OPENPTS_CONTEXT *ctx, const char *filenameNG) {
2922 int validateIr(OPENPTS_CONTEXT *ctx) {
2923     xmlSAXHandler  sax_handler;
2924     int rc = PTS_VERIFY_FAILED;  // guilty until proven innocent
2925     OPENPTS_CONFIG *conf;
2926     OPENPTS_PCRS *pcrs;
2927
2928
2929     DEBUG("validateIr - start\n");
2930
2931     /* check */
2932     if (ctx == NULL) {
2933         LOG(LOG_ERR, "null input");
2934         return PTS_FATAL;
2935     }
2936     if (ctx->target_conf == NULL) {
2937         LOG(LOG_ERR, "null input");
2938         return PTS_FATAL;
2939     }
2940     if (ctx->ir_filename == NULL) {
2941         LOG(LOG_ERR, "null input");
2942         return PTS_FATAL;
2943     }
2944     conf = ctx->target_conf;
2945     if (conf == NULL) {
2946         LOG(LOG_ERR, "null input");
2947         return PTS_FATAL;
2948     }
2949
2950     /* new */
2951     if (ctx->pcrs == NULL) {
2952         /* malloc OPENPTS_PCRS */
2953         ctx->pcrs = xmalloc(sizeof(OPENPTS_PCRS));
2954         if (ctx->pcrs == NULL) {
2955             rc = PTS_FATAL;
2956             goto free;
2957         }
2958         memset(ctx->pcrs, 0, sizeof(OPENPTS_PCRS));
2959     }
2960     pcrs = ctx->pcrs;
2961     pcrs->pubkey_length = conf->pubkey_length;
2962     pcrs->pubkey        = conf->pubkey;
2963
2964     /* new */
2965     if (ctx->ir_ctx == NULL) {
2966         ctx->ir_ctx = newIrContext();
2967         if (ctx->ir_ctx == NULL) {
2968             rc = PTS_FATAL;
2969             goto free;
2970         }
2971     }
2972
2973     memset(&sax_handler, 0, sizeof(xmlSAXHandler));
2974
2975     /* setup handlers */
2976     sax_handler.startDocument = irStartDocument;
2977     sax_handler.endDocument = irEndDocument;
2978     sax_handler.startElement = irStartElement;
2979     sax_handler.endElement = irEndElement;
2980     sax_handler.characters = irCharacters;
2981
2982 #ifdef CONFIG_AIDE
2983     /* AIDE */
2984     if (conf->ima_validation_mode == OPENPTS_VALIDATION_MODE_AIDE) {
2985         if (ctx->aide_ctx == NULL) {
2986             /* setup AIDE as IIDB*/
2987             ctx->aide_ctx = newAideContext();
2988
2989 #ifdef CONFIG_SQLITE
2990             // DEBUG("loadSQLiteDatabaseFile %s\n", ctx->conf->aide_sqlite_filename);
2991             rc = loadSQLiteDatabaseFile(ctx->aide_ctx, conf->aide_sqlite_filename);
2992             if (rc != PTS_SUCCESS) {
2993                 LOG(LOG_ERR, "loadSQLiteDatabaseFile fail\n");
2994                 rc = PTS_FATAL;
2995                 goto free;
2996             }
2997 #else
2998             rc = loadAideDatabaseFile(ctx->aide_ctx, conf->aide_database_filename);
2999             // TODO check rc
3000 #endif
3001         } else {
3002             // pre loaded (see iml2aide.c)
3003             LOG(LOG_TODO, "AIDE DB pre loaded\n");
3004         }
3005
3006         if (ctx->conf->aide_ignorelist_filename != NULL) {
3007             rc = readAideIgnoreNameFile(ctx->aide_ctx, conf->aide_ignorelist_filename);
3008             // TODO check rc
3009         }
3010     }
3011 #endif
3012
3013     /* Apply Validation Policy */
3014     // set policy as a property (e.g. name=unknown)
3015     // addProperty(ctx,"hoge", "unknown");
3016
3017     /* default conf is missing QuoteData */
3018     // conf->ir_without_quote = 1;
3019
3020     /* read IR, IR -> IML SAX */
3021
3022     DEBUG("validateIr - Validate IR     : %s\n", ctx->ir_filename);
3023
3024     // http://xmlsoft.org/html/libxml-parser.html#xmlSAXUserParseFile
3025     if ((rc = xmlSAXUserParseFile(&sax_handler, (void *)ctx, ctx->ir_filename)) != 0) {
3026         // SAX parse error
3027         DEBUG("validateIr() - SAX parse error rc=%d\n", rc);
3028         rc = PTS_INTERNAL_ERROR;
3029         goto free;
3030     } else {
3031         rc = ctx->ir_ctx->sax_error;
3032         DEBUG("validateIr() - SAX parse     : PASS (rc=%d)\n", rc);
3033     }
3034
3035     // DEBUG("validatePcrComposite, ctx->conf->ir_without_quote %d\n", ctx->conf->ir_without_quote);
3036     // LOG(LOG_ERR, "conf->pubkey_length %d\n",conf->pubkey_length);
3037
3038     /* validate PCR values by QuoteData */
3039     if ((conf->iml_mode == 0) && (conf->ir_without_quote == 0)) {
3040         // DEBUG("validate PCR values by QuoteData\n");
3041         /* */
3042         if (ctx->validation_data == NULL) {
3043             // TODO set properties
3044             // DEBUG("Without QUote?\n");
3045             addProperty(ctx, "tpm.quote.pcrs", "unknown");  // check by policy
3046         } else if (conf->pubkey_length > 0) {
3047             // TODO no more?
3048             ctx->pcrs->pubkey_length = conf->pubkey_length;
3049             ctx->pcrs->pubkey = conf->pubkey;
3050
3051             if (ctx->conf->tpm_quote_type == 1) {
3052                 /* Quote */
3053                 rc = validatePcrCompositeV11(ctx->pcrs, ctx->validation_data);  // tss.c
3054             } else {
3055                 /* Quote2 */
3056                 rc = validatePcrCompositeV12(ctx->pcrs, ctx->validation_data);
3057             }
3058
3059             DEBUG("validateIr() - validatePcrComposite, set rc=%d\n", rc);
3060             // DBEUG("validatePcrCompositeV11 = %d\n",rc);
3061             if (rc == PTS_SUCCESS) {
3062                 addProperty(ctx, "tpm.quote.pcrs", "valid");
3063             } else if (rc == PTS_VERIFY_FAILED) {
3064                 // ptsc - if FSM config in ptsc.conf is wrong this happen
3065                 addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_IR_PCR_COMPOSITE_VERIFY_FAILED,
3066                     "[QUOTE] verification of PCR Composite has failed, "
3067                     "(tscd - bad FSM configuration in /etc/ptsc.conf)"));
3068                 addProperty(ctx, "tpm.quote.pcrs", "invalid");
3069             } else {
3070                 addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_IR_PCR_COMPOSITE_VERIFY_FAILED,
3071                                "[QUOTE] verification of PCR Composite has failed"));
3072                 addProperty(ctx, "tpm.quote.pcrs", "invalid");
3073             }
3074         } else {
3075             LOG(LOG_ERR, "PUBKEY is missing\n");
3076             addProperty(ctx, "tpm.quote.pcrs", "unknown");
3077         }
3078     } else {
3079         DEBUG("validateIr() - skip validatePcrCompositeV11 conf->iml_mode=%d conf->ir_without_quote=%d\n",
3080             conf->iml_mode, conf->ir_without_quote);
3081     }
3082
3083     // TODO use policy or not
3084
3085     /* Check Properties by Policy (if exist) */
3086     if (ctx->policy_start != NULL) {
3087         rc = checkPolicy(ctx);
3088         DEBUG("validateIr() - checkPolicy   : rc=%d\n", rc);
3089     } else {
3090         /* Use the result by IR validation by RM(FSM) */
3091         if (ctx->ir_ctx->sax_error > 0) {
3092             DEBUG("validateIr() - ctx->ir_ctx->sax_error > %d => rc = OPENPTS_RESULT_INVALID\n",
3093                 ctx->ir_ctx->sax_error);
3094             rc = OPENPTS_RESULT_INVALID;
3095         }
3096         if (ctx->ir_ctx->fsm_error_count > 0) {
3097             DEBUG("validateIr() - ctx->ir_ctx->fsm_error_count > %d => rc = OPENPTS_RESULT_INVALID\n",
3098                 ctx->ir_ctx->fsm_error_count);
3099             rc = OPENPTS_RESULT_INVALID;
3100         }
3101     }
3102
3103     if (ctx->ima_unknown > 0) {
3104         if (conf->ima_validation_unknown == 1) {
3105             DEBUG("ctx->ima_unknown = %d, result is INVALID\n", ctx->ima_unknown);
3106             addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_IR_SEVERAL_UNKNOWN_IMA,
3107                 "[LINUX-IMA] There are several unknown IMA measurements. "
3108                 "Please check and update your AIDE ignore list."));
3109             rc = OPENPTS_RESULT_UNKNOWN;
3110         }
3111     }
3112
3113     if (ctx->ir_ctx->bad_quote == 1) {
3114         addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_IR_QUOTE_VERIFY_FAILED,
3115             "[QUOTE] verification of quote signature has failed."));
3116         rc = OPENPTS_RESULT_INVALID;
3117     }
3118
3119   free:
3120     /* free */
3121
3122 #ifdef CONFIG_AIDE
3123     /* AIDE */
3124     if (ctx->aide_ctx != NULL) {
3125          freeAideContext(ctx->aide_ctx);
3126     }
3127 #endif
3128     // TODO Keep PCRs?
3129     if (ctx->pcrs != NULL) {
3130         xfree(ctx->pcrs);
3131         ctx->pcrs = NULL;
3132     }
3133
3134
3135     if (ctx->ir_ctx != NULL) {
3136         if (ctx->ir_ctx->buf != NULL) {
3137             xfree(ctx->ir_ctx->buf);
3138         }
3139         xfree(ctx->ir_ctx);
3140         ctx->ir_ctx = NULL;
3141     }
3142
3143     DEBUG("validateIr - done\n");
3144
3145     return rc;
3146 }
3147
3148
3149 /**
3150  *  gen IR from Securityfs
3151  *
3152  * @retval PTS_SUCCESS
3153  * @retval PTS_INTERNAL_ERROR
3154  */
3155 int genIrFromSecurityfs(
3156     OPENPTS_CONTEXT *ctx,
3157     int *savedFd /* out*/ ) {
3158     int rc;
3159     /* get IML via securityfs */
3160
3161     /* TPM Quote */
3162 #ifdef CONFIG_NO_TSS
3163     DEBUG("Build with --without-tss. skip TPM_quote\n");
3164 #else
3165     DEBUG("TPM Quote not work with config option iml.mode=securityfs\n");
3166 #endif
3167
3168     /* check */
3169     if (ctx == NULL) {
3170         LOG(LOG_ERR, "null input");
3171         return PTS_FATAL;
3172     }
3173
3174     /* reset TPM emu */
3175     resetTpm(&ctx->tpm, ctx->drtm);
3176
3177     /* reset FSM */
3178     rc = freeAllFsm(ctx);
3179
3180     /* setup FSM */
3181     rc = readFsmFromPropFile(ctx, ctx->conf->config_file);
3182     if (rc != PTS_SUCCESS) {
3183         LOG(LOG_ERR, "readFsmFromPropFile %s failed\n", ctx->conf->config_file);
3184         return PTS_INTERNAL_ERROR;
3185     }
3186
3187     /* read BIOS IML */
3188     rc = readBiosImlFile(ctx, ctx->conf->bios_iml_filename, ctx->conf->iml_endian);
3189     if (rc != PTS_SUCCESS) {
3190         LOG(LOG_ERR, "fail to load BIOS IML, rc = %d\n", rc);
3191         return PTS_INTERNAL_ERROR;
3192     }
3193
3194     if (ctx->conf->runtime_iml_filename != NULL) {
3195         int count;
3196         /* read Runtime IML */
3197         rc = readImaImlFile(ctx, ctx->conf->runtime_iml_filename,
3198                 ctx->conf->runtime_iml_type, 0, &count);  // TODO endian?
3199         if (rc != PTS_SUCCESS) {
3200             LOG(LOG_ERR, "fail to load IMA IML, rc = %d\n", rc);
3201             return PTS_INTERNAL_ERROR;
3202         }
3203     }
3204
3205     /* read PCRS */
3206     rc = getPcrBySysfsFile(ctx, ctx->conf->pcrs_filename);
3207     if (rc < 0) {
3208         LOG(LOG_ERR, "fail to load PCR, rc = %d -- (pcr file is missing)\n", rc);
3209         LOG(LOG_TODO, "Get or Create PCR file for this testcase\n");
3210         // return -1;
3211     }
3212
3213     // do not use tempnum,
3214     // if (ctx->conf->ir_filename != NULL) {
3215     //    LOG(LOG_ERR, "Redefining the IR file location %s", ctx->conf->ir_filename);
3216     // }
3217     // ctx->conf->ir_filename = tempnam(NULL, "ir_");
3218
3219     /* save IR (new file in tmp dir) */
3220     rc = writeIr(ctx, NULL, savedFd);
3221     // rc = writeIr(ctx, ctx->ir_filename, savedFd);
3222     if (rc != 0) {
3223         LOG(LOG_ERR, "fail to write IR, rc = %d\n", rc);
3224         return PTS_INTERNAL_ERROR;
3225     }
3226
3227     return PTS_SUCCESS;
3228 }
3229
3230
3231 /**
3232  * gen IR from Securityfs
3233  *
3234  * @retval PTS_SUCCESS
3235  * @retval PTS_INTERNAL_ERROR 
3236  */
3237 int genIrFromTss(
3238     OPENPTS_CONTEXT *ctx,
3239     int *savedFd /* out */ ) {
3240     int rc;
3241
3242     /* check */
3243     if (ctx == NULL) {
3244         LOG(LOG_ERR, "null input");
3245         return PTS_FATAL;
3246     }
3247
3248     /* get IML via securityfs */
3249
3250     /* reset TPM emu */
3251     resetTpm(&ctx->tpm, ctx->drtm);
3252
3253     /* reset FSM */
3254     rc = freeAllFsm(ctx);
3255
3256     /* reset OPENPTS_PCRS */
3257     if (ctx->pcrs == NULL) {
3258         ctx->pcrs = xmalloc_assert(sizeof(OPENPTS_PCRS));  // TODO NULL check, or gen at newCtx
3259         // TODO check
3260     }
3261     memset(ctx->pcrs, 0, sizeof(OPENPTS_PCRS));
3262
3263     /* setup FSM */
3264     // pcrSelect is set at PCR with FSM
3265     rc = readFsmFromPropFile(ctx, ctx->conf->config_file);  // fsm.c
3266     if (rc != PTS_SUCCESS) {
3267         LOG(LOG_ERR, "read FSM failed\n");
3268         return PTS_INTERNAL_ERROR;
3269     }
3270
3271     /* TSS_VALIDATION */
3272     if (ctx->validation_data == NULL) {
3273         ctx->validation_data = xmalloc_assert(sizeof(TSS_VALIDATION));
3274     }
3275
3276     /* Nonce */
3277     if (ctx->nonce->nonce_length > 0) {
3278         ctx->validation_data->ulExternalDataLength = ctx->nonce->nonce_length;
3279         // NG ctx->validation_data->rgbExternalData= ctx->nonce->nonce;
3280         /* copy */
3281         ctx->validation_data->rgbExternalData = malloc(ctx->nonce->nonce_length);
3282         if (ctx->validation_data->rgbExternalData == NULL) {
3283             LOG(LOG_ERR, "no memory");
3284             return PTS_FATAL;
3285         }
3286         memcpy(
3287             ctx->validation_data->rgbExternalData,
3288             ctx->nonce->nonce,
3289             ctx->nonce->nonce_length);
3290     } else {
3291         LOG(LOG_ERR, "genIrFromTss - nonce is missing, DH-nonce? \n");
3292         ctx->validation_data->ulExternalDataLength = 0;
3293         ctx->validation_data->rgbExternalData = NULL;
3294     }
3295     /* quote info */
3296     ctx->validation_data->ulDataLength = 0;
3297     ctx->validation_data->rgbData= NULL;  // ptr
3298     /* signature */
3299     ctx->validation_data->ulValidationDataLength = 0;
3300     ctx->validation_data->rgbValidationData = NULL;  // ptr
3301
3302
3303     if (ctx->conf->ir_without_quote == 1) {
3304         LOG(LOG_TODO, "skip TPM_Quote\n");
3305     } else {
3306         /* TPM Quote or TPM Quote2 */
3307         if (ctx->conf->tpm_quote_type == 1) {
3308             rc = quoteTss(
3309                     ctx->conf->uuid->uuid,
3310                     ctx->conf->aik_storage_type,
3311                     ctx->conf->srk_password_mode,
3312                     ctx->conf->aik_storage_filename,
3313                     ctx->conf->aik_auth_type,
3314                     NULL,
3315                     ctx->pcrs,
3316                     ctx->validation_data);  // tss.c
3317         } else {
3318             rc = quote2Tss(
3319                     ctx->conf->uuid->uuid,
3320                     ctx->conf->aik_storage_type,
3321                     ctx->conf->srk_password_mode,
3322                     ctx->conf->aik_storage_filename,
3323                     ctx->conf->aik_auth_type,
3324                     NULL,
3325                     ctx->pcrs,
3326                     ctx->validation_data);  // tss.c
3327         }
3328         if (rc != 0) {
3329             LOG(LOG_ERR, "quoteTss fail, rc = 0x%04d\n", rc);
3330             return PTS_INTERNAL_ERROR;
3331         }
3332     }
3333
3334     /* set PCR to snapshot */
3335     rc = setPcrsToSnapshot(ctx, ctx->pcrs);  // TODO
3336     if (rc < 0) {
3337         LOG(LOG_ERR, "fail to load PCR, rc = %d\n", rc);
3338         return PTS_INTERNAL_ERROR;
3339     }
3340
3341     /* get BIOS/IMA IML */
3342     rc = getIml(ctx, 0);
3343     if (rc < 0) {
3344         LOG(LOG_ERR, "fail to load BIOS IML, rc = %d\n", rc);
3345         return PTS_INTERNAL_ERROR;
3346     }
3347
3348     if (ctx->conf->ir_filename != NULL) {
3349         LOG(LOG_ERR, "Redefining the IR file location %s", ctx->conf->ir_filename);
3350     }
3351     //ctx->conf->ir_filename = tempnam(NULL, "ir_");
3352     //DEBUG("ctx->conf->ir_filename : %s\n", ctx->conf->ir_filename);
3353
3354     /* save IR (new file in tmp dir) */
3355     rc = writeIr(ctx, NULL, savedFd);
3356     // rc = writeIr(ctx, ctx->ir_filename, savedFd);  // ir.c
3357     if (rc != 0) {
3358         LOG(LOG_ERR, "fail to write IR, rc = %d\n", rc);
3359         return PTS_INTERNAL_ERROR;
3360     }
3361
3362     return PTS_SUCCESS;
3363 }
3364
3365
3366 /**
3367  *  gen IR file
3368  *
3369  * @retval PTS_SUCCESS
3370  * @retval PTS_INTERNAL_ERROR
3371  */
3372 int genIr(
3373     OPENPTS_CONTEXT *ctx,
3374     int *savedFd /* out */) {
3375     int rc = PTS_INTERNAL_ERROR;
3376
3377     /* check */
3378     if (ctx == NULL) {
3379         LOG(LOG_ERR, "null input");
3380         return PTS_FATAL;
3381     }
3382
3383
3384     /* gen */
3385     if (ctx->conf->iml_mode == 1) {
3386         rc = genIrFromSecurityfs(ctx, savedFd);
3387         if (rc != PTS_SUCCESS) {
3388             LOG(LOG_ERR, "writePtsTlvToSock - gen IR failed\n");
3389             return rc;
3390         }
3391     } else {
3392 #ifdef CONFIG_NO_TSS
3393         LOG(LOG_TODO, "OpenPTS was build with --without-tss and config option iml.mode=tssand, skip IR gen.\n");
3394 #else
3395         // DEBUG("get IML/PCR via TSS is not ready\n");
3396         rc = genIrFromTss(ctx, savedFd);
3397         if (rc != PTS_SUCCESS) {
3398             LOG(LOG_ERR, "gen IR failed\n");
3399             return rc;
3400         }
3401 #endif
3402     }
3403
3404     return rc;
3405 }
3406
3407