OSDN Git Service

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