OSDN Git Service

e498c2c1dc5c8640a13b9673791521161a8c171b
[openpts/openpts.git] / src / action.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/action.c
26  * \brief FSM action
27  * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
28  * @date 2010-06-19
29  * cleanup 2011-07-20 SM
30  *
31  * FSM Action (UML2 doActivity)
32  *
33  * functions executed at the state.
34  * setAssertion(ipl.integrity, valid)
35  *
36  * TODO need generic way to support platform specific actions
37  *
38  *  common action
39  *  vendor action => table
40  *
41  */
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46
47 #include <tss/platform.h>
48 #include <tss/tss_defines.h>
49 #include <tss/tss_typedef.h>
50 #include <tss/tss_structs.h>
51 #include <tss/tss_error.h>
52 #include <tss/tspi.h>
53
54 #include <openssl/sha.h>
55
56 #include <openpts.h>
57
58 typedef struct {
59     char *name;
60     int  name_len;
61     int  type;
62     int (*func_1)(OPENPTS_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper);
63     int (*func_2)(OPENPTS_CONTEXT *ctx, char *name, char* b64digest, char *integrity);  // TODO NA?
64     int (*func_3)(OPENPTS_CONTEXT *ctx);
65     int (*func_4)(OPENPTS_CONTEXT *ctx, char *name);
66     // validateProperty
67     int (*func_5)(OPENPTS_CONTEXT *ctx, char *name, char *value, char *action);
68     // setProperty
69     int (*func_6)(OPENPTS_CONTEXT *ctx, char *name, char *value, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper);
70     int (*func_7)(OPENPTS_CONTEXT *ctx, char *value, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper);
71     int rc;
72 } OPENPTS_ACTION_TABLE;
73
74 /* FSM */
75
76
77 /**
78  *  resetPCR(pcr_index)
79  *
80  *  action   - reset PCR[pcr_index]
81  *  location - startup of the FSM
82  *
83  *  value    - string of pcr index value, 0-23
84  */
85 int resetPCR(OPENPTS_CONTEXT *ctx, char *value) {
86     int rc;
87     int pcr_index = -1;
88
89     pcr_index = atoi(value);
90
91     DEBUG_FSM("resetPCR(%d)\n", pcr_index);
92     rc = resetTpmPcr(&ctx->tpm, pcr_index);
93     if (rc != PTS_SUCCESS) {
94         ERROR("reset PCR[%d] was failed, check the model");
95         return PTS_INTERNAL_ERROR;
96     }
97
98     /* Also, reset the action counter */
99     ctx->bios_action_count = 0;
100
101     return PTS_SUCCESS;
102 }
103
104 /* BIOS */
105
106 /**
107  * addBIOSAction()
108  *
109  *  EventData(string) => Properties
110  *
111  *  bios.pcr.N.action.C=eventdata[]
112  *    N: pcr_index
113  *    C: action counter
114  */
115 int addBIOSAction(OPENPTS_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
116     TSS_PCR_EVENT *event;
117     char name[BUF_SIZE];
118     char *value;
119
120     /* check */
121     if (eventWrapper == NULL) {
122         // TODO  do not care for dummy EW
123         DEBUG("addBIOSAction() - eventWrapper is NULL\n");  // TODO is this OK?
124         // TODO define RC <-> fsm.c >> INFO:(TODO) fsm.c:986 updateFsm() - rc = 58, call updateFsm() again
125         return PTS_INTERNAL_ERROR;
126     }
127
128     event = eventWrapper->event;
129     if (event == NULL) {
130         ERROR("event is NULL\n");
131         return PTS_INTERNAL_ERROR;
132     }
133
134     /* value = eventdata */
135     value = snmalloc((char *)event->rgbEvent, event->ulEventLength);
136     if (value == NULL) {
137         ERROR("no memory\n");
138         return PTS_INTERNAL_ERROR;
139     }
140
141     /* name */
142     // ctx->bios_action_count is reset by resetPCR()
143     snprintf(name, BUF_SIZE, "bios.pcr.%d.action.%d", event->ulPcrIndex, ctx->bios_action_count);
144     ctx->bios_action_count++;
145
146
147     DEBUG_FSM("[FSM] addBIOSAction() - '%s' = '%s'\n", name, value);
148
149     updateProperty(ctx, name, value);
150
151     free(value);
152
153     return PTS_SUCCESS;
154 }
155
156
157 /**
158  * addBIOSSpecificProperty
159  * type = 0x0006
160  * 
161  * PC event
162  *
163  * EventID Descriptions                   PTS structure              Properties
164  * -----------------------------------------------------------------------------------------
165  * 0x0001  SMBIOS structure          # => conf->smbios               bios.smbios=base64
166  * 0x0003  POST BIOS ROM Strings     # => conf->post_bios_rom_string bios.post.rom.string=string
167  * 0x0004  ESCD, hash of ESCD data   # => conf-> 
168  * 0x0005  CMOS, raw CMOS data       # => conf->
169  * 0x0006  NVRAM, raw NVRAM data     # => 
170  * 0x0007  Option ROM execute        # => 
171  *
172  */
173 int addBIOSSpecificProperty(OPENPTS_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
174     TSS_PCR_EVENT *event;
175     UINT32 event_id;
176     UINT32 event_length;
177
178     /* event */
179     if (eventWrapper == NULL) {
180         ERROR("addBIOSSpecificProperty- eventWrapper is NULL\n");
181         return PTS_INTERNAL_ERROR;  // -1
182     }
183     event = eventWrapper->event;
184
185     if (event->eventType != 0x06) {
186         ERROR("addBIOSSpecificProperty - bad event type 0x%x !- 0x06\n", event->eventType);
187         return PTS_INTERNAL_ERROR;  // -1
188     }
189
190     // DEBUG("event data size = %d\n", event->ulEventLength);
191     // printHex("", event->rgbEvent, event->ulEventLength, "\n");
192
193     event_id = byte2uint32(&event->rgbEvent[0]);
194     event_length = byte2uint32(&event->rgbEvent[4]);
195
196     // DEBUG("event data size = %d, id = 0x%x, len %d,\n", event->ulEventLength, event_id, event_length);
197
198     switch (event_id) {
199         case 0x0001:
200             {
201                 char *buf;
202                 int buf_len;
203
204                 /* SMBIOS */
205                 // bios.smbios=base64()
206                 ctx->conf->smbios_length = event_length;
207                 ctx->conf->smbios = &event->rgbEvent[8];
208
209                 /* base64 */
210                 buf = encodeBase64(
211                         //(unsigned char *)b64,
212                         (unsigned char *)ctx->conf->smbios,
213                         ctx->conf->smbios_length,
214                         &buf_len);
215                 if (buf == NULL) {
216                     ERROR("encodeBase64 fail");
217                     return PTS_FATAL;
218                 }
219                 if (buf_len > BUF_SIZE) {
220                     ERROR("SMBIOS size = %d\n", buf_len);  // Thinkpad X200 => 3324
221                     updateProperty(ctx, "bios.smbios", "too big");
222                 } else {
223                     updateProperty(ctx, "bios.smbios", buf);
224                 }
225                 // rc = 0;
226                 free(buf);
227             }
228             break;
229         default:
230             // DEBUG("EventID 0x%x TBD\n", event_id);
231             // DEBUG("event data size = %d, id = 0x%x, len %d,\n", event->ulEventLength, event_id, event_length);
232             break;
233     }
234
235     return PTS_SUCCESS;  // -1;
236 }
237
238
239
240 /* Grub */
241
242 /**
243  * validateMBR()
244  *
245  */
246 int validateMBR(OPENPTS_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
247     TSS_PCR_EVENT *event;
248
249     if (eventWrapper == NULL) {
250         ERROR("eventWrapper is NULL\n");
251         return PTS_INTERNAL_ERROR;  // -1;
252     }
253
254     event = eventWrapper->event;
255
256     if (event == NULL) {
257         ERROR("event is NULL\n");
258         return PTS_INTERNAL_ERROR;  // -1;
259     }
260
261     TODO("validateMBR - NA\n");
262
263     return PTS_SUCCESS;
264 }
265
266
267 /**
268  * validate Eltorito Boot Image
269  *
270  * IPL measurement is deffent by BIOS
271  *
272  * 1) 512 bytes of BootImage(stage2_eltorito) - Panasonic?
273  * 2) 2048 bytes of BootImage(stage2_eltorito) - HP?
274  * 3) Unknown method by IBM/Lenovo (bug)
275  *
276  * IntegrationTest - check_ir check_rm
277  *            Data - ThinkpadX31_Knoppix511 - IBM/Lenovo
278  */
279 int validateEltoritoBootImage(OPENPTS_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
280     TSS_PCR_EVENT *event;
281
282     // DEBUG("validateEltoritoBootImage - NA\n");
283
284     if (eventWrapper == NULL) {
285         ERROR("eventWrapper is NULL\n");
286         return PTS_INTERNAL_ERROR;  // -1;
287     }
288
289     event = eventWrapper->event;
290     if (event == NULL) {
291         ERROR("event is NULL\n");
292         return PTS_INTERNAL_ERROR;  // -1;
293     }
294
295     updateProperty(ctx, "ipl.eltorito.integrity", "unknown");
296
297     return PTS_SUCCESS;  // -1;
298 }
299
300 /**
301  * set Module Property
302  * 
303  * grub.conf -> PCR8 
304  * Normal
305  *   Kernel
306  *   Initrd
307  *
308  *  linux.initrd.digest
309  */
310 int setModuleProperty(OPENPTS_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
311     TSS_PCR_EVENT *event;
312     char *buf;
313     int buf_len;
314
315     // DEBUG("setModuleProperty - NA\n");
316
317     /* check */
318     if (eventWrapper == NULL) {
319         ERROR("eventWrapper is NULL\n");
320         return PTS_INTERNAL_ERROR;  // -1;
321     }
322
323     event = eventWrapper->event;
324
325     if (event == NULL) {
326         ERROR("event is NULL\n");
327         return PTS_INTERNAL_ERROR;  // -1;
328     }
329
330     /* kernel.initrd.digest = PCR => B64 digest */
331     buf = encodeBase64(
332         (unsigned char *)event->rgbPcrValue,
333         SHA1_DIGEST_SIZE,
334         &buf_len);
335     if (buf == NULL) {
336         ERROR("encodeBase64 fail");
337         return PTS_INTERNAL_ERROR;
338     }
339     updateProperty(ctx, "kernel.initrd.digest", buf);
340     free(buf);
341
342     // updateProperty(ctx, "kernel.initrd.filename", (char*)event->rgbEvent);
343     /* add \n */
344     buf = malloc(event->ulEventLength + 1);
345     if (buf == NULL) {
346         ERROR("no memory\n");
347     } else {
348         memcpy(buf, event->rgbEvent, event->ulEventLength);
349         buf[event->ulEventLength] = 0;
350         updateProperty(ctx, "kernel.initrd.filename", buf);
351         free(buf);
352     }
353
354     return PTS_SUCCESS;  // -1;
355 }
356
357
358 /**
359  *  kernel comnand line -> properties
360  * 
361  * eg
362  *  kernel /vmlinuz-2.6.32.12-115.fc12.x86_64 
363  *  ro root=UUID=5c6fdd8c-eec9-45d6-8a51-0223fac9e153 noiswmd LANG=en_US.UTF-8 
364  * SYSFONT=latarcyrheb-sun16 KEYBOARDTYPE=pc KEYTABLE=jp106  intel_iommu=off 
365  * rhgb quiet tpm_tis.itpm=1 tpm_tis.force=1 tpm_tis.interrupts=0 ima_tcb=1
366  * 
367  *
368  *  linux.kernel.cmdline.ro="" 
369  *  linux.kernel.cmdline.ima_tcb="1" 
370  * 
371  *
372  * UnitTest - tests/check_action.c
373  * 
374  */
375 int setLinuxKernelCmdlineAssertion(OPENPTS_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
376     TSS_PCR_EVENT *event;
377     char * cmdline;
378     char * tp;
379     char * ep;
380     char name[BUF_SIZE];
381     char value[BUF_SIZE];
382     int cnt = 0;
383     char *saveptr = NULL;
384
385
386     DEBUG_CAL("setLinuxKernelCmdlineAssertion - start\n");
387
388     /* input check */
389     if (eventWrapper == NULL) {
390         ERROR("eventWrapper is NULL\n");
391         return PTS_INTERNAL_ERROR;  // -1;
392     }
393
394     event = eventWrapper->event;
395
396     if (event == NULL) {
397         ERROR("event is NULL\n");
398         return PTS_INTERNAL_ERROR;  // -1;
399     }
400
401     /* copy(malloc) strings */
402     cmdline = snmalloc((char *)event->rgbEvent, event->ulEventLength);
403
404     /* first string = kernel filename */
405     tp = strtok_r(cmdline, " ", &saveptr);
406
407     while (tp != NULL) {
408         tp = strtok_r(NULL, " ", &saveptr);  // TODO strtok_r
409         if ( tp != NULL ) {
410             /* A=B? */
411             ep = strchr(tp, '=');
412             if (ep != NULL) {
413                 *ep = 0;
414                 ep++;
415                 snprintf(name, BUF_SIZE, "linux.kernel.cmdline.%s", tp);
416                 snprintf(value, BUF_SIZE, "%s", ep);
417                 addProperty(ctx, name, value);
418                 cnt++;
419             } else {
420                 snprintf(name, BUF_SIZE, "linux.kernel.cmdline.%s", tp);
421                 addProperty(ctx, name, "");
422                 cnt++;
423             }
424         }
425     }
426
427     DEBUG_CAL("setLinuxKernelCmdlineAssertion - done, %d options\n", cnt);
428     // DEBUG("setLinuxKernelCmdlineAssertion  event data[%d] = %s\n", event->ulEventLength, event->rgbEvent);
429
430     /* free */
431     sfree(cmdline);
432     return PTS_SUCCESS;
433 }
434
435 /* Grub */
436
437 /* Linux */
438
439 /**
440  * deprecated
441  */
442 int validateKernelCmdline(OPENPTS_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
443     TODO("validateKernelCmdline - NA\n");
444     updateProperty(ctx, "kernel.commandline", "TBD");
445     return PTS_SUCCESS;
446 }
447
448 /* Linux - IMA */
449
450
451 /**
452  * validate IMA boot aggregate v2 (kernel 2.6.30-)
453  *
454  * aggregate = SHA1(PCR[0]+PCR[1]+..PCR[7])
455  *
456  * IntegrationTest - check_ir.c check_rm.c 
457  *            Data - ThinkpadX200_Fedora12 - w/ policy
458  * UnitTest
459  */
460 int validateImaAggregate(OPENPTS_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
461     TSS_PCR_EVENT *event;
462     int i;
463     SHA_CTX sha_ctx;
464     BYTE digest[SHA1_DIGEST_SIZE];
465
466     // DEBUG("validateImaAggregate - NA\n");
467
468     /* check */
469     if (eventWrapper == NULL) {
470         ERROR("eventWrapper is NULL\n");
471         return PTS_INTERNAL_ERROR;  // -1;
472     }
473
474     event = eventWrapper->event;
475
476     if (event == NULL) {
477         ERROR("event is NULL\n");
478         return PTS_INTERNAL_ERROR;  // -1;
479     }
480
481     /* init SHA1 */
482     SHA1_Init(&sha_ctx);
483
484     /* update with PCR 0 - 7 */
485     for (i = 0; i < 8; i++) {
486         getTpmPcrValue(&ctx->tpm, i, digest);
487         SHA1_Update(&sha_ctx, digest, SHA1_DIGEST_SIZE);
488     }
489
490     /* get aggregate */
491     SHA1_Final(digest, &sha_ctx);
492
493     /* check aggregate */
494     if (memcmp(event->rgbEvent, digest, SHA1_DIGEST_SIZE) == 0) {
495         /* HIT */
496         // DEBUG("Good IMA aggregete\n");
497         updateProperty(ctx, "ima.aggregate", "valid");
498     } else {
499         /* MISS */
500         updateProperty(ctx, "ima.aggregate", "invalid");
501
502         if (verbose && DEBUG_FLAG) {
503             int j;
504             BYTE pcr[SHA1_DIGEST_SIZE];
505             TODO("validateImaAggregate - "
506                  "Wrong IMA aggregete - check FSM, "
507                  "maybe it should use validateOldImaAggregate()\n");
508             printf("PCR   =  ");
509             for (j = 0; j < (int) event->ulPcrValueLength; j ++) {
510                 printf("%02x", event->rgbPcrValue[j]);
511             }
512             printf("\n");
513
514             for (i = 0; i < 8; i++) {
515                 printf("PCR[%d] = ", i);
516                 getTpmPcrValue(&ctx->tpm, i, pcr);
517                 for (j = 0; j < SHA1_DIGEST_SIZE; j ++) {
518                     printf("%02x", pcr[j]);
519                 }
520                 printf("\n");
521             }
522
523             printf("EDATA  = ");
524             for (j = 0; j < SHA1_DIGEST_SIZE; j ++) {
525                 printf("%02x", event->rgbEvent[j]);
526             }
527             printf(" (extended value)\n");
528
529             printf("AGGREG = ");
530             for (j = 0; j < SHA1_DIGEST_SIZE; j ++) {
531                 printf("%02x", digest[j]);
532             }
533             printf(" (cal value)\n");
534         }
535     }
536
537     // TODO(munetoh) also check the template and pcr?
538     return PTS_SUCCESS;
539 }
540
541 /**
542  * validate IMA boot aggregate v1 (kernel -2.6.29)
543  *
544  * aggregate = SHA1(PCR[0]+PCR[1]+..PCR[7])
545  *
546  * IntegrationTest - check_ir.c check_rm.c 
547  *            Data - ThinkpadX31_Knoppix511
548  */
549 int validateOldImaAggregate(OPENPTS_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
550     TSS_PCR_EVENT *event;
551     int i;
552     SHA_CTX sha_ctx;
553     BYTE digest[SHA1_DIGEST_SIZE];
554
555     // DEBUG("validateOldImaAggregate - NA\n");
556
557     /* check */
558     if (eventWrapper == NULL) {
559         ERROR("eventWrapper is NULL\n");
560         return PTS_INTERNAL_ERROR;  // -1;
561     }
562
563     event = eventWrapper->event;
564     if (event == NULL) {
565         ERROR("event is NULL\n");
566         return PTS_INTERNAL_ERROR;  // -1;
567     }
568
569     /* init SHA1 */
570     SHA1_Init(&sha_ctx);
571
572     /* update with PCR 0 - 7 */
573     for (i = 0; i < 8; i++) {
574         getTpmPcrValue(&ctx->tpm, i, digest);
575         SHA1_Update(&sha_ctx, digest, SHA1_DIGEST_SIZE);
576     }
577
578     /* get aggregate */
579     SHA1_Final(digest, &sha_ctx);
580
581     /* check aggregate */
582     if (memcmp(event->rgbPcrValue, digest, SHA1_DIGEST_SIZE) == 0) {
583         /* HIT */
584         updateProperty(ctx, "ima.aggregate", "valid");
585     } else {
586         /* MISS */
587         updateProperty(ctx, "ima.aggregate", "invalids");
588     }
589     // TODO(munetoh) also check the eventdata string?
590
591     return PTS_SUCCESS;
592 }
593
594 /**
595  *  ima.0.name=/XX/XX/XX  << AIDE or IMA
596  *  ima.0.integrity=valid/invalid/unknown
597  *  ima.0.digest=base64
598  */
599 int updateImaProperty(OPENPTS_CONTEXT *ctx, char* name, char* b64digest, char *integrity) {
600     char prop_name[256];
601
602     /* integrity */
603     snprintf(prop_name, sizeof(prop_name), "ima.%d.integrty", ctx->ima_count);
604     updateProperty(ctx, prop_name, integrity);
605
606     /* name */
607     snprintf(prop_name, sizeof(prop_name), "ima.%d.name", ctx->ima_count);
608     updateProperty(ctx, prop_name, name);
609
610     /* digest */
611     snprintf(prop_name, sizeof(prop_name), "ima.%d.digest", ctx->ima_count);
612     updateProperty(ctx, prop_name, b64digest);
613
614     ctx->ima_count++;
615     return PTS_SUCCESS;
616 }
617
618
619 /**
620  * Original IMA measurement
621  *   EventType 
622  *  --------------------------
623  *     1          Exe
624  *     2          LKM
625  *
626  * Return
627  *   -1 error
628  *    0 HIT
629  *    1 IGNORE
630  *    2 MISS
631  *
632  */
633 int validateImaMeasurement(OPENPTS_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
634 #ifdef CONFIG_AIDE
635     TSS_PCR_EVENT *event;
636 #endif
637
638     DEBUG_CAL("validateImaMeasurement - start\n");
639
640     if (eventWrapper == NULL) {
641         /* Just ignore the NULL event */
642         // TODO(munetoh) Detect LOOP
643         // DEBUG("validateImaMeasurement - eventWrapper is NULL\n");
644         // DEBUG("validateImaMeasurement - eventWrapper is null\n");
645         // return 1;  // =>  seg fault
646         return PTS_SUCCESS;  // => green
647         // TODO why?
648     }
649
650
651
652 #ifdef CONFIG_AIDE
653     event = eventWrapper->event;
654     if (ctx->conf->ima_validation_mode == OPENPTS_VALIDATION_MODE_AIDE) {
655         int rc = 0;
656         char *name;
657         char *buf;
658         int buf_len;
659
660         rc = checkEventByAide(ctx->aide_ctx, eventWrapper);
661
662         /* Get name */
663         name = (char *)event->rgbEvent;
664         name += SHA1_DIGEST_SIZE;
665         name = snmalloc(name, (event->ulEventLength - SHA1_DIGEST_SIZE));
666
667         if (rc == 0) {
668             // HIT
669             AIDE_METADATA *md = eventWrapper->aide_metadata;
670             DEBUG_FSM("validateImaMeasurement w/ AIDE - HIT, name=[%s]=[%s]\n",
671                 name,
672                 md->name);
673             ctx->ima_valid++;
674 #ifdef CONFIG_SQLITE
675             // TODO no md,
676 #else
677             buf = encodeBase64(
678                 (unsigned char *)md->sha1,
679                 SHA1_DIGEST_SIZE,
680                 &buf_len);
681             if (buf == NULL) {
682                 ERROR("encodeBase64 fail");
683                 return PTS_INTERNAL_ERROR;
684             }
685             updateImaProperty(ctx, md->name, buf, "valid");
686             free(buf);
687 #endif
688             eventWrapper->status = OPENPTS_RESULT_VALID;
689             free(name);
690             return PTS_SUCCESS;
691         } else if (rc == 1) {
692             // IGNORE
693             eventWrapper->status = OPENPTS_RESULT_IGNORE;  // TODO
694             free(name);
695             return PTS_SUCCESS;
696         } else if (rc == 2) {
697             // MISS
698             // DEBUG("validateImaMeasurement w/ AIDE - MISS name=[%s]\n", name);
699             // updateProperty(ctx, buf, "invalid");
700             ctx->ima_unknown++;
701             buf = encodeBase64(
702                 (unsigned char *)event->rgbEvent,
703                 SHA1_DIGEST_SIZE,
704                 &buf_len);
705             if (buf == NULL) {
706                 ERROR("encodeBase64 fail");
707                 return PTS_INTERNAL_ERROR;
708             }
709             updateImaProperty(ctx, name, buf, "unknown");  // action.c
710             eventWrapper->status = OPENPTS_RESULT_UNKNOWN;
711             free(buf);
712
713             /* add to */
714             {
715                 char *hex;
716                 hex = getHexString(event->rgbEvent, SHA1_DIGEST_SIZE);
717                 addReason(ctx, "[IMA-AIDE] missing, digest(hex) = %s, name = \"%s\"", hex, name);
718                 free(hex);
719             }
720             free(name);
721             return PTS_SUCCESS;
722         } else {
723             // ERROR
724             ERROR("validateImaMeasurement - checkEventByAide fail, rc - %d\n", rc);
725             eventWrapper->status = PTS_INTERNAL_ERROR;  // OPENPTS_RESULT_INT_ERROR;
726             free(name);
727             return PTS_INTERNAL_ERROR;  // -1;
728         }
729         // TODO free md
730         // freeAideMetadata(md);
731         // free(name);
732     } else if (ctx->conf->ima_validation_mode == OPENPTS_VALIDATION_MODE_IIDB) {
733         ERROR("validateImaMeasurementNG w/ IIDB - NA\n");
734     }
735 #else  // !CONFIG_AIDE
736     if (ctx->conf->ima_validation_mode == OPENPTS_VALIDATION_MODE_IIDB) {
737         ERROR("validateImaMeasurementNG w/ IIDB - NA\n");
738     }
739 #endif
740     else {
741         return PTS_SUCCESS;
742     }
743
744     ERROR("validateImaMeasurement - ERROR\n");
745     return PTS_INTERNAL_ERROR;  // -1;
746 }
747
748 /* IMA NG */
749
750 int validateImaAggregateNG(OPENPTS_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
751     ERROR("validateImaAggregateNG - NA\n");
752     updateProperty(ctx, "ima.aggregate", "TBD");
753     return PTS_INTERNAL_ERROR;  // -1;
754 }
755
756 int validateImaMeasurementNG(OPENPTS_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
757     return PTS_INTERNAL_ERROR;  // -1;
758 }
759
760
761 /* Counter */
762
763 /**
764  *
765  */
766 int resetCounter(OPENPTS_CONTEXT *ctx) {
767     ctx->count = 0;
768
769     // DEBUG("[FSM] resetCounter()");
770     return PTS_SUCCESS;
771 }
772
773 /**
774  *
775  */
776 int incrementCounter(OPENPTS_CONTEXT *ctx) {
777     ctx->count += 1;
778
779     // DEBUG("[FSM] incrementCounter() %d => %d\n", ctx->count -1, ctx->count);
780     return PTS_SUCCESS;
781 }
782
783 /* Update */
784
785
786 /**
787  * Collector Start  -  Verifier 
788  * 
789  * TODO fill 
790  */
791 int startCollector(OPENPTS_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
792     int rc = PTS_SUCCESS;
793     TSS_PCR_EVENT *event;
794     OPENPTS_EVENT_COLLECTOR_START *start = NULL;
795
796     /* check */
797     if (ctx == NULL) {
798         ERROR("startCollector() - ctx is null\n");
799         return PTS_INTERNAL_ERROR;
800     }
801
802     if (ctx->target_conf == NULL) {
803         /* collector */
804         ERROR("startCollector() - target_conf is NULL, collector side - skip\n");
805         return PTS_SUCCESS;
806     }
807
808     if (ctx->target_conf->uuid == NULL) {
809         /* collector */
810         ERROR("startCollector() - uuid is NULL\n");
811         return PTS_SUCCESS;
812     }
813
814     /* check */
815     if (eventWrapper == NULL) {
816         ERROR("startCollector() - eventWrapper is NULL\n");
817         rc = PTS_INTERNAL_ERROR;
818         goto error;
819     }
820
821     event = eventWrapper->event;
822     if (event == NULL) {
823         ERROR("startCollector() - event is NULL\n");
824         rc = PTS_INTERNAL_ERROR;
825         goto error;
826     }
827
828     if (event->ulEventLength != sizeof(OPENPTS_EVENT_COLLECTOR_START)) {
829         ERROR("startCollector() - Bad eventData size %d != %d\n",
830             event->ulEventLength,
831             sizeof(OPENPTS_EVENT_COLLECTOR_START));
832         rc = PTS_INTERNAL_ERROR;  // TODO
833         goto error;
834     }
835
836     /* Event Data */
837     start = (OPENPTS_EVENT_COLLECTOR_START *)event->rgbEvent;
838
839     /* re-set PCR */
840     // TODO if TCDS was restart, the eventlog used by PTSCD was gone.
841
842     /* validation - TSS version */
843     if (memcmp(&start->pts_version, &ctx->target_conf->pts_version, 4) != 0) {
844         DEBUG("startCollector() - Bad PTS version\n");
845         // rc = PTS_INTERNAL_ERROR;  // TODO
846         // goto error;
847     }
848
849     /* validation - Collector UUID */
850     if (memcmp(&start->collector_uuid, ctx->target_conf->uuid->uuid, 16) != 0) {
851         DEBUG("startCollector() - Bad Collector UUID (Unit Testing?)\n");
852         // TODO test will stop. must be controlable?
853         // rc = PTS_INTERNAL_ERROR;  // TODO
854         // goto error;
855     }
856
857     /* validation - Manifest UUID */
858
859     if (memcmp(&start->manifest_uuid, ctx->target_conf->rm_uuid->uuid, 16) != 0) {
860         // TODO in the test ptscd generate new RM UUID
861         DEBUG("startCollector() - Bad Manifest UUID (Unit Testing?)\n");
862         // rc = PTS_INTERNAL_ERROR;  // TODO
863         // goto error;
864     }
865
866
867     return PTS_SUCCESS;
868
869   error:
870     /* Error */
871     // printout the example IR data to create the test case
872     {
873         char *buf;
874         int buf_len;
875
876         if (start == NULL) {
877             start = malloc(sizeof(OPENPTS_EVENT_COLLECTOR_START));
878             if (start == NULL) {
879                 ERROR("no memory");
880                 return PTS_INTERNAL_ERROR;
881             }
882         }
883         printHex("OPENPTS_EVENT_COLLECTOR_START",
884             (unsigned char*)start, sizeof(OPENPTS_EVENT_COLLECTOR_START), "\n");
885         buf = encodeBase64(
886             (unsigned char *)start,
887             sizeof(OPENPTS_EVENT_COLLECTOR_START),
888             &buf_len);
889         if (buf == NULL) {
890             ERROR("encodeBase64 fail");
891             rc = PTS_INTERNAL_ERROR;
892             goto free;
893         }
894         ERROR("EventData: %s\n", buf);
895         free(buf);
896
897         memcpy(&start->pts_version, &ctx->target_conf->pts_version, 4);
898         memcpy(&start->collector_uuid, ctx->target_conf->uuid->uuid, 16);
899         memcpy(&start->manifest_uuid, ctx->target_conf->rm_uuid->uuid, 16);
900
901         printHex("OPENPTS_EVENT_COLLECTOR_START",
902             (unsigned char*)start, sizeof(OPENPTS_EVENT_COLLECTOR_START), "\n");
903         buf = encodeBase64(
904             (unsigned char *)start,
905             sizeof(OPENPTS_EVENT_COLLECTOR_START),
906             &buf_len);
907         if (buf == NULL) {
908             ERROR("encodeBase64 fail");
909             rc = PTS_INTERNAL_ERROR;
910             goto free;
911         }
912         ERROR("EventData: %s\n", buf);
913         free(buf);
914   free:
915         free(start);
916     }
917
918     return rc;  // TODO
919 }
920
921
922 #ifdef CONFIG_TBOOT
923 int addIntelTxtTbootProperty(OPENPTS_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
924     TSS_PCR_EVENT *event;
925
926     DEBUG_FSM("addIntelTxtTbootProperty - start\n");
927
928     /* event */
929     if (eventWrapper == NULL) {
930         ERROR("addBIOSSpecificProperty- eventWrapper is NULL\n");
931         return -1;
932     }
933     event = eventWrapper->event;
934
935     switch (event->eventType) {
936         case EV_TBOOT_SINIT_V6:
937             {
938                 OPENPTS_EVENT_TBOOT_SINIT_V6 *data;
939                 char *buf;
940                 data = (OPENPTS_EVENT_TBOOT_SINIT_V6 *) event->rgbEvent;
941                 buf = getHexString(data->sinit_hash, 20);
942                 updateProperty(ctx, "intel.txt.tboot.sinit.hash.hex", buf);
943                 free(buf);
944                 // TODO add rest
945             }
946             break;
947         case EV_TBOOT_SINIT_V7:
948             {
949                 OPENPTS_EVENT_TBOOT_SINIT_V7 *data;
950                 char *buf;
951                 data = (OPENPTS_EVENT_TBOOT_SINIT_V7 *) event->rgbEvent;
952                 buf = getHexString(data->sinit_hash, 32);
953                 updateProperty(ctx, "intel.txt.tboot.sinit.hash.hex", buf);
954                 free(buf);
955                 // TODO add rest
956             }
957             break;
958         case EV_TBOOT_STM_V6:
959             {
960                 OPENPTS_EVENT_TBOOT_STM_V6 *data;
961                 char *buf;
962                 data = (OPENPTS_EVENT_TBOOT_STM_V6 *) event->rgbEvent;
963                 buf = getHexString(data->bios_acm_id, 20);
964                 updateProperty(ctx, "intel.txt.tboot.bios.acm.id.hex", buf);
965                 free(buf);
966                 // TODO add rest
967             }
968             break;
969         case EV_TBOOT_POLCTL:
970             {
971                 OPENPTS_EVENT_TBOOT_POLCTL *data;
972                 char *buf;
973                 data = (OPENPTS_EVENT_TBOOT_POLCTL *) event->rgbEvent;
974                 buf = getHexString(data->pol_control, 4);
975                 updateProperty(ctx, "intel.txt.tboot.pol.control.hex", buf);
976                 free(buf);
977                 buf = getHexString(data->pol_hash, 20);
978                 updateProperty(ctx, "intel.txt.tboot.pol.hash.hex", buf);
979                 free(buf);
980                 // TODO add rest
981             }
982             break;
983         case EV_TBOOT_MLE_HASH:
984             {
985                 char *buf;
986                 buf = getHexString(event->rgbPcrValue, 20);
987                 updateProperty(ctx, "intel.txt.tboot.mle.hash.hex", buf);
988                 free(buf);
989             }
990             break;
991
992         case EV_TBOOT_MODULE:
993             {
994                 OPENPTS_EVENT_TBOOT_MODULE *data;
995                 char name[256];
996                 char *value;
997                 UINT32 size;
998                 BYTE *ptr;
999
1000                 if (event->ulEventLength < 48) {
1001                     // Bad EventData
1002                     TODO("addIntelTxtTbootProperty() bad eventdata, size = %d\n",
1003                         event->ulEventLength);
1004                 } else {
1005                     // EventData
1006                     data = (OPENPTS_EVENT_TBOOT_MODULE *) event->rgbEvent;
1007
1008                     snprintf(name, sizeof(name),
1009                         "intel.txt.tboot.pcr.%d.module.command.hash.hex",
1010                         event->ulPcrIndex);
1011                     value = getHexString(data->command_hash, 20);
1012                     updateProperty(ctx, name, value);
1013                     free(value);
1014
1015                     snprintf(name, sizeof(name),
1016                         "intel.txt.tboot.pcr.%d.module.file.hash.hex",
1017                         event->ulPcrIndex);
1018                     value = getHexString(data->file_hash, 20);
1019                     updateProperty(ctx, name, value);
1020                     free(value);
1021
1022                     snprintf(name, sizeof(name),
1023                         "intel.txt.tboot.pcr.%d.module.command",
1024                         event->ulPcrIndex);
1025                     ptr = (BYTE *)&event->rgbEvent[40];
1026                     size = *(UINT32*) ptr;
1027                     ptr += 4;
1028                     value = malloc(size + 1);
1029                     memcpy(value, (BYTE *)ptr, size);
1030                     value[size] = 0;
1031                     updateProperty(ctx, name, value);
1032                     free(value);
1033
1034                     snprintf(name, sizeof(name),
1035                         "intel.txt.tboot.pcr.%d.module.filename",
1036                         event->ulPcrIndex);
1037                     ptr += size;
1038                     size = *(UINT32*) ptr;
1039                     ptr += 4;
1040                     value = malloc(size + 1);
1041                     memcpy(value, (BYTE *)ptr, size);
1042                     value[size] = 0;
1043                     updateProperty(ctx, name, value);
1044                     free(value);
1045                 }
1046             }
1047             break;
1048
1049         default:
1050             ERROR("Unknown event tupe 0x%x\n", event->eventType);
1051             break;
1052     }
1053
1054     /* set DRTM flag => resetPcr(1) at writeIr() */
1055     // TODO
1056     ctx->drtm = 1;
1057
1058     // updateProperty(ctx, "kernel.commandline", "TBD");
1059     return PTS_SUCCESS;
1060 }
1061 #endif
1062
1063
1064
1065 /**
1066  * save counter value to property
1067  */
1068 int saveCounter(OPENPTS_CONTEXT *ctx, char * name) {
1069     char buf[128];  // TODO
1070
1071     snprintf(buf, sizeof(buf), "%d", ctx->count);
1072     addProperty(ctx, name, buf);
1073
1074     // DEBUG("[FSM] saveCounter() %s = %s\n", name, buf);
1075
1076     return PTS_SUCCESS;
1077 }
1078
1079
1080 static OPENPTS_ACTION_TABLE action_table[] = {
1081     {                                                      /* FSM control - 5 */
1082         .name = "transitFSM(",
1083         .name_len = 11,
1084         .type = 0,
1085         .rc = OPENPTS_FSM_TRANSIT
1086     }, {
1087         .name = "flashFSM(",
1088         .name_len = 9,
1089         .type = 0,
1090         .rc = OPENPTS_FSM_FLASH
1091     }, {
1092         .name = "resetPCR",
1093         .name_len = 8,
1094         .type = 4,
1095         .func_4 = resetPCR
1096     }, {
1097         .name = "validateProperty(",
1098         .name_len = 17,
1099         .type = 5,
1100         .func_5 = validateProperty
1101     }, {
1102         .name = "setAssertion(",
1103         .name_len = 13,
1104         .type = 6,
1105         .func_6 = setEventProperty  // setProperty
1106     }, {                                                       /* PC BIOS - 2 */
1107         .name = "addBIOSSpecificProperty(",
1108         .name_len = 24,
1109         .type = 1,
1110         .func_1 = addBIOSSpecificProperty
1111     }, {
1112         .name = "addBIOSAction(",
1113         .name_len = 14,
1114         .type = 1,
1115         .func_1 = addBIOSAction
1116     }, {                                                   /* Grub Legacy - 2 */
1117         .name = "validateMBR(",
1118         .name_len = 12,
1119         .type = 1,
1120         .func_1 = validateMBR
1121     }, {
1122         .name = "validateEltoritoBootImage(",
1123         .name_len = 26,
1124         .type = 1,
1125         .func_1 = validateEltoritoBootImage
1126     }, {                                                         /* Linux - 3 */
1127         .name = "setLinuxKernelCmdlineAssertion(",
1128         .name_len = 31,
1129         .type = 1,
1130         .func_1 = setLinuxKernelCmdlineAssertion
1131     }, {
1132         .name = "setModuleProperty(",
1133         .name_len = 18,
1134         .type = 1,
1135         .func_1 = setModuleProperty
1136     }, {
1137         .name = "validateKernelCmdline(",
1138         .name_len = 22,
1139         .type = 1,
1140         .func_1 = validateKernelCmdline
1141     }, {                                                       /* Linux-IMA +5*/
1142         .name = "validateOldImaAggregate(",
1143         .name_len = 24,
1144         .type = 1,
1145         .func_1 = validateOldImaAggregate
1146     }, {
1147         .name = "validateImaAggregate(",
1148         .name_len = 20,
1149         .type = 1,
1150         .func_1 = validateImaAggregate
1151     }, {
1152         .name = "validateImaMeasurement(",
1153         .name_len = 23,
1154         .type = 1,
1155         .func_1 = validateImaMeasurement
1156     }, {
1157         .name = "validateImaAggregateNG(",
1158         .name_len = 23,
1159         .type = 1,
1160         .func_1 = validateImaAggregateNG
1161     }, {
1162         .name = "validateImaMeasurementNG(",
1163         .name_len = 25,
1164         .type = 1,
1165         .func_1 = validateImaMeasurementNG
1166     }, {                                              /* counter functions +3 */
1167         .name = "resetCounter",
1168         .name_len = 12,
1169         .type = 3,
1170         .func_3 = resetCounter
1171     }, {
1172         .name = "incrementCounter",
1173         .name_len = 16,
1174         .type = 3,
1175         .func_3 = incrementCounter
1176     }, {
1177         .name = "saveCounter",
1178         .name_len = 11,
1179         .type = 4,
1180         .func_4 = saveCounter
1181     },
1182
1183 #ifdef CONFIG_AUTO_RM_UPDATE
1184     /* update function 4 */
1185     {
1186         .name = "startUpdate",
1187         .name_len = 11,
1188         .type = 1,
1189         .func_1 = startUpdate
1190     }, {
1191         .name = "deputyEvent",
1192         .name_len = 11,
1193         .type = 1,
1194         .func_1 = deputyEvent
1195     }, {
1196         .name = "endUpdate",
1197         .name_len = 9,
1198         .type = 1,
1199         .func_1 = endUpdate
1200     }, {
1201         .name = "updateCollector",
1202         .name_len = 15,
1203         .type = 1,
1204         .func_1 = updateCollector
1205     },
1206 #endif
1207 #ifdef CONFIG_TBOOT
1208     /* 1 */
1209     {
1210         .name = "addIntelTxtTbootProperty",
1211         .name_len = 24,
1212         .type = 1,
1213         .func_1 = addIntelTxtTbootProperty
1214     },
1215 #endif
1216     {
1217         .name = "startCollector",
1218         .name_len = 14,
1219         .type = 1,
1220         .func_1 = startCollector
1221     }
1222 };
1223
1224 #ifdef CONFIG_AUTO_RM_UPDATE
1225 #define OPENPTS_ACTION_TABLE_ARU_SIZE  4
1226 #else
1227 #define OPENPTS_ACTION_TABLE_ARU_SIZE  0
1228 #endif
1229
1230 #ifdef CONFIG_TBOOT
1231 #define OPENPTS_ACTION_TABLE_TBOOT_SIZE  1
1232 #else
1233 #define OPENPTS_ACTION_TABLE_TBOOT_SIZE  0
1234 #endif
1235
1236 #define OPENPTS_ACTION_TABLE_SIZE (5 + 2 + 2 + 3 + 5 + 3 + OPENPTS_ACTION_TABLE_ARU_SIZE + OPENPTS_ACTION_TABLE_TBOOT_SIZE + 1)
1237
1238 /**
1239  * doActivity
1240  *
1241  * fsmUpdate() call this function
1242  *
1243  * return
1244  *  OPENPTS_FSM_SUCCESS  0
1245  *  OPENPTS_FSM_FLASH    flash FSM
1246  *  OPENPTS_FSM_TRANSIT  transit FSM
1247  *  OPENPTS_FSM_ERROR  
1248  *  OPENPTS_FSM_MIGRATE_EVENT 
1249  */
1250 // #define BUF_SIZE 256
1251
1252 int doActivity(
1253         OPENPTS_CONTEXT *ctx,
1254         char *action,
1255         OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
1256     int rc = 0;
1257     char *name = NULL;
1258     char *value = NULL;
1259     char *buf = NULL;  // char buf[BUF_SIZE];
1260     // int len;
1261     char *saveptr;
1262     int i;
1263
1264     /* check */
1265     if (ctx == NULL) {
1266         ERROR("doActivity - ctx is NULL\n");
1267         return PTS_INTERNAL_ERROR;  // -1;
1268     }
1269
1270     if (action == NULL) {
1271         ERROR("doActivity - action is NULL\n");
1272         return PTS_INTERNAL_ERROR;  // -1;
1273     }
1274
1275     if (eventWrapper == NULL) {
1276         /* NULL event, skip evaluation */
1277         // DEBUG("doActivity - eventWrapper is NULL\n");
1278         // return 1;  //OPENPTS_FSM_SUCCESS;
1279     }
1280
1281     /* copy */
1282     buf = smalloc(action);
1283     if (buf == NULL) {
1284         ERROR("doActivity - no memory\n");
1285         return PTS_FATAL;  // -1;
1286     }
1287
1288     /* no action */
1289     if (!strcmp((char *)action, "")) {
1290         goto end;
1291     }
1292
1293     /* check the action */
1294     for (i = 0; i < OPENPTS_ACTION_TABLE_SIZE; i++) {
1295         if (!strncmp((char *)action, action_table[i].name, action_table[i].name_len)) {
1296             // DEBUG("%s HIT, name_len=%d\n", action, action_table[i].name_len);
1297             switch (action_table[i].type) {
1298             case 0:
1299                 rc = action_table[i].rc;
1300                 goto end;
1301             case 1:
1302                 /* Action(Event) */
1303                 rc = action_table[i].func_1(ctx, eventWrapper);
1304                 goto end;
1305             case 2:
1306                 break;
1307             case 3:
1308                 /* Just call  Action() */
1309                 rc = action_table[i].func_3(ctx);
1310                 goto end;
1311             case 4:
1312                 /* Action(Name) */
1313                 // INFO("doActivity type 4  %s", action);
1314                 name  = &buf[action_table[i].name_len + 1];  // 11 ; 1 =
1315                 name = strtok_r(name, ")", &saveptr);
1316                 name  = trim(name);
1317                 rc = action_table[i].func_4(ctx, name);
1318                 goto end;
1319             case 5:
1320                 /* Action(Name,Value,Action) */
1321                 name  = &buf[action_table[i].name_len];
1322                 name = strtok_r(name, ", ", &saveptr);
1323                 value   = strtok_r(NULL, ")", &saveptr);
1324                 /* value */
1325                 name  = trim(name);
1326                 value = trim(value);
1327
1328                 rc = action_table[i].func_5(ctx, name, value, action);  // validateProperty
1329                 goto end;
1330             case 6:
1331                 /* Action(Name,Value,Event) */
1332                 name  = &buf[action_table[i].name_len];
1333                 name = strtok_r(name, ", ", &saveptr);
1334                 value   = strtok_r(NULL, ")", &saveptr);
1335                 /* value */
1336                 name  = trim(name);
1337                 value = trim(value);
1338
1339                 rc = action_table[i].func_6(ctx, name, value, eventWrapper);  // setProperty
1340                 goto end;
1341             case 7:
1342                 /* Action(Value,Event) */
1343                 value  = &buf[action_table[i].name_len + 1];  // 11 ; 1 =
1344                 value = strtok_r(value, ")", &saveptr);
1345                 value  = trim(value);
1346                 rc = action_table[i].func_7(ctx, value, eventWrapper);
1347                 goto end;
1348             default:
1349                 ERROR("unknown OPENPTS_ACTION_TABLE func tyoe\n");
1350                 break;
1351             }
1352         }
1353     }
1354
1355     /* error */
1356     ERROR("unknown action '%s'\n", action);
1357     addReason(ctx, "[FSM] Unknown action='%s'", action);
1358     rc = OPENPTS_FSM_ERROR;
1359
1360   end:
1361     if (buf != NULL) free(buf);
1362     /* check the RC */
1363     if (rc == OPENPTS_FSM_ERROR) {
1364         DEBUG("doActivity rc = %d\n", rc);
1365     }
1366
1367     return rc;
1368 }