2 * This file is part of the OpenPTS project.
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.
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)
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.
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.
25 * \file src/collector.c
26 * \brief TCG IF-M collector functions
27 * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
29 * cleanup 2011-07-20 SM
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <netinet/in.h>
45 #include <arpa/inet.h> // inet_ntoa
53 #include <openssl/sha.h>
61 void printFsmInfo(OPENPTS_CONTEXT *ctx, char * indent) {
65 printf("%sPCR lv FSM files\n", indent);
66 printf("%s-----------------------------------------------------\n", indent);
68 for (i = 0; i < MAX_PCRNUM; i++) {
69 ss = getSnapshotFromTable(ctx->ss_table, i, 0);
72 if (ss->fsm_behavior != NULL) {
73 printf("%s%2d 0 ", indent, i);
74 printf("%s\n", ss->fsm_behavior->uml_file);
79 ss = getSnapshotFromTable(ctx->ss_table, i, 1);
81 if (ss->fsm_behavior != NULL) {
82 printf("%s%2d 1 ", indent, i);
83 printf("%s\n", ss->fsm_behavior->uml_file);
87 printf("%s-----------------------------------------------------\n", indent);
95 * 154 11 0x00000080 f7412718d74b9292d33dedc9d946aad7afa5c11b [Unknown Event:size=56]
97 int extendEvCollectorStart(OPENPTS_CONFIG *conf) {
98 TSS_PCR_EVENT* event; // /usr/include/tss/tss_structs.h
99 OPENPTS_EVENT_COLLECTOR_START *collector_start;
100 BYTE pcr[SHA1_DIGEST_SIZE];
104 /* malloc eventlog */
105 collector_start = malloc(sizeof(OPENPTS_EVENT_COLLECTOR_START));
106 event = malloc(sizeof(TSS_PCR_EVENT));
108 /*fill collector_start */
109 memcpy(&collector_start->pts_version, &conf->pts_version, 4);
110 memcpy(&collector_start->collector_uuid, conf->uuid->uuid, 16);
111 memcpy(&collector_start->manifest_uuid, conf->rm_uuid->uuid, 16);
115 // memcpy(&collector_start->pcr_value;make
116 readPcr(conf->openpts_pcr_index, pcr);
117 memcpy(&collector_start->pcr_value, pcr, SHA1_DIGEST_SIZE);
125 sizeof(OPENPTS_EVENT_COLLECTOR_START));
126 SHA1_Final(pcr, &sha_ctx);
129 // event->versionInfo // set by TSP?
130 event->ulPcrIndex = conf->openpts_pcr_index; // set by TSP?
131 event->eventType = EV_COLLECTOR_START; // openpts_tpm.h
132 event->ulPcrValueLength = SHA1_DIGEST_SIZE;
133 event->rgbPcrValue = pcr;
134 event->ulEventLength = sizeof(OPENPTS_EVENT_COLLECTOR_START);
135 event->rgbEvent = (BYTE *) collector_start;
141 free(collector_start);
153 * 2. generate Sign Key (NA)
154 * 3. get platform information, call dmidecode or BIOS IML? (NA)
158 * ./src/ptsc -i -c tests/data/Fedora12/ptscd.conf
166 OPENPTS_CONFIG *conf,
168 OPENPTS_PROPERTY *prop_start,
169 OPENPTS_PROPERTY *prop_end) {
170 int rc = PTS_SUCCESS;
171 OPENPTS_CONTEXT *ctx;
176 ctx = newPtsContext(conf);
178 ERROR("no memory\n");
179 return PTS_INTERNAL_ERROR;
183 if (prop_count > 0) {
184 ctx->prop_start = prop_start;
185 ctx->prop_end = prop_end;
186 ctx->prop_count = prop_count;
191 if (conf->config_dir == NULL) {
192 ERROR("missing config dir, check your config file %s\n", conf->config_file);
193 return PTS_INTERNAL_ERROR;
196 rc = checkDir(conf->config_dir);
197 if (rc == PTS_SUCCESS) {
201 INFO("create new config dir, %s", conf->config_dir);
202 makeDir(conf->config_dir);
205 // DEBUG("config dir : %s\n", conf->config_dir);
207 /* Generate UUID of this platform */
209 if (conf->uuid == NULL) {
210 // TODO UUID filename is missing
211 ERROR(" bad conf file\n");
212 return PTS_INTERNAL_ERROR;
213 } else if (conf->uuid->status == OPENPTS_UUID_FILENAME_ONLY) {
215 rc = genOpenptsUuid(conf->uuid);
218 DEBUG("init() - use given UUID %s (for TEST)\n", conf->uuid->str);
222 /* Create TPM Sign Key */
223 // TODO we use single sign key for all verifiers
224 // it depends on the onwer of key, now ptscd is the owner of sign key.
225 // if verifier take the ownership of sign key, we needs the key for each verifier.
226 // auth can be transferd by IF-M (DH excnage)
228 rc = createTssSignKey(
230 conf->aik_storage_type,
231 conf->aik_storage_filename,
234 conf->srk_password_mode);
235 if (rc == 0x0001) { // 0x0001
236 fprintf(stderr, "createSignKey failed. "
237 "if you uses well known SRK secret, "
238 "all zeros (20 bytes of zeros) try -z option\n");
239 rc = PTS_INTERNAL_ERROR;
241 } else if (rc != PTS_SUCCESS) {
242 fprintf(stderr, "createSignKey failed, rc = 0x%x\n", rc);
243 rc = PTS_INTERNAL_ERROR;
246 printf("Sign key location : SYSTEM\n");
248 DEBUG("init() - skip key gen for the given UUID\n");
252 /* Write UUID file */
253 rc = writeOpenptsUuidFile(conf->uuid, 0);
254 if (rc == PTS_DENIED) {
257 /* if UUID file exist => exit, admin must delete the UUID file, then init again */
258 /* check existing UUID */
259 rc = readOpenptsUuidFile(conf->uuid);
260 str_uuid = getStringOfUuid(conf->uuid->uuid);
261 time = getDateTimeOfUuid(conf->uuid->uuid);
263 fprintf(stderr, "uuid file, '%s' exist, please remove this file if you want to re-intialize the platform\n",
264 conf->uuid->filename);
265 fprintf(stderr, " existing uuid = %s\n", str_uuid);
266 fprintf(stderr, " creation date = %d-%d-%d\n",
274 } else if (rc != PTS_SUCCESS) {
276 fprintf(stderr, "uuid file, '%s' generation was failed\n", conf->uuid->filename);
277 rc = PTS_INTERNAL_ERROR;
282 printf("Generate uuid : %s \n", conf->uuid->str);
287 rc = readFsmFromPropFile(ctx, conf->config_file);
288 if (rc != PTS_SUCCESS) {
289 ERROR("read FSM failed\n");
290 rc = PTS_INTERNAL_ERROR;
295 if (conf->rm_uuid == NULL) {
296 // init/set by readPtsConf
297 ERROR("conf->rm_uuid == NULL\n");
298 } else if (conf->rm_uuid->status == OPENPTS_UUID_FILENAME_ONLY) {
299 rc = genOpenptsUuid(conf->rm_uuid);
302 DEBUG("init() - use given RM UUID %s\n", conf->rm_uuid->str);
305 /* save to rm_uuid file */
306 rc = writeOpenptsUuidFile(conf->rm_uuid, 0); // do not overwrite
307 if (rc != PTS_SUCCESS) {
308 ERROR("writeOpenptsUuidFile fail\n");
313 rc = makeRmSetDir(conf);
314 if (rc != PTS_SUCCESS) {
315 ERROR("mkdir of RM set dir was failed\n");
320 printf("Generate UUID (for RM) : %s \n", conf->rm_uuid->str);
322 /* read IML to fill the BIOS binary measurement, and translate BHV->BIN FSM */
324 /* load current IML using FSMs */
325 if (conf->iml_mode == 0) { // TODO use def
327 ERROR("Build with --without-tss. iml.mode=tss is not supported\n");
332 } else if (conf->iml_mode == 1) {
333 // TODO change to generic name? conf->iml_filename[0] conf->iml_filename[1]
334 /* from securityfs */
336 rc = readBiosImlFile(
338 conf->bios_iml_filename, conf->iml_endian);
339 if (rc != PTS_SUCCESS) {
340 DEBUG("getBiosImlFile() was failed\n");
341 fprintf(stderr, "Oops! Something is wrong. Please see the reason below\n");
346 /* RUNTIME IML (Linux-IMA) */
347 if (ctx->conf->runtime_iml_filename != NULL) {
351 conf->runtime_iml_filename,
352 conf->runtime_iml_type, 0, &count); // TODO endian?
353 if (rc != PTS_SUCCESS) {
354 fprintf(stderr, "read IMA IML, %s was failed\n", conf->runtime_iml_filename);
355 rc = PTS_INTERNAL_ERROR;
360 ERROR("unknown IML mode, %d\n", conf->iml_mode);
363 /* get SMBIOS data */
366 /* create Reference Manifest */
367 for (i = 0; i < conf->rm_num; i++) {
368 if (conf->rm_filename[i] != NULL) {
369 rc = writeRm(ctx, conf->rm_filename[i], i);
370 if (rc != PTS_SUCCESS) {
371 fprintf(stderr, "ERROR, initialization was failed\n");
373 "[INIT] Failed to create the manifest file, %s",
374 conf->rm_filename[i]);
379 printf("level %d Reference Manifest : %s\n", i, conf->rm_filename[i]);
381 ERROR("missing RM file for level %d\n", i);
384 printf("\nptsc is successfully initialized!\n");
398 * - Find right RM for this boot
400 * Check RM set by rm_uuid file
401 * OK-> OPENPTS_SELFTEST_SUCCESS
403 * Check RM set by newrm_uuid file
404 * OK -> OPENPTS_SELFTEST_RENEWED
406 * Check RM set by oldrm_uuid file
407 * OK -> OPENPTS_SELFTEST_FALLBACK
408 * NG -> OPENPTS_SELFTEST_FAILED
412 * OPENPTS_SELFTEST_SUCCESS stable:-)
413 * OPENPTS_SELFTEST_RENEWED update/reboot -> success
414 * OPENPTS_SELFTEST_FALLBACK
415 * OPENPTS_SELFTEST_FAILED
416 * PTS_INTERNAL_ERROR something wrong:-(
418 int selftest(OPENPTS_CONFIG *conf, int prop_count, OPENPTS_PROPERTY *prop_start, OPENPTS_PROPERTY *prop_end) {
419 int rc = PTS_INTERNAL_ERROR;
421 OPENPTS_CONTEXT *ctx;
423 OPENPTS_PROPERTY *prop;
425 DEBUG("selftest() start\n");
427 /* Step 1 - IR gen */
430 ctx = newPtsContext(conf);
432 ERROR("no memory\n");
433 return PTS_INTERNAL_ERROR;
436 /* copy properties */
438 for (i = 0; i < prop_count; i++) {
440 ERROR("prop == NULL\n");
441 return PTS_INTERNAL_ERROR; // TODO free
443 addProperty(ctx, prop->name, prop->value);
448 /* set dummy nonce for IR gen */
449 ctx->nonce->nonce_length = 20;
450 ctx->nonce->nonce = malloc(20);
451 memset(ctx->nonce->nonce, 0x5A, 20);
453 ctx->str_uuid = smalloc("SELFTEST");
456 rc = genIr(ctx); // ir.c
457 if (rc != PTS_SUCCESS) {
458 ERROR("selftest() - genIR failed\n");
459 rc = PTS_INTERNAL_ERROR;
467 // DEBUG("selftest() - generate IR file => %s\n", conf->ir_filename);
468 DEBUG("selftest() - generate IR - done\n");
470 /* Step 2 - Validate IR */
472 /* Keep conf but reset some flags in conf */
473 // conf->aru_count = 0;
475 #ifdef CONFIG_AUTO_RM_UPDATE
476 conf->update_exist = 0;
479 ctx = newPtsContext(conf);
481 ERROR("no memory\n");
482 return PTS_INTERNAL_ERROR;
486 rc = getRmSetDir(conf);
487 if (rc != PTS_SUCCESS) {
488 ERROR("selftest() - getRmSetDir() failed\n");
489 TODO("conf->rm_uuid->filename %s\n", conf->rm_uuid->filename);
490 TODO("conf->rm_uuid->str %s\n", conf->rm_uuid->str);
491 rc = PTS_INTERNAL_ERROR;
496 for (i = 0; i < conf->rm_num; i++) {
497 rc = readRmFile(ctx, conf->rm_filename[i], i);
499 ERROR("readRmFile fail\n");
500 rc = PTS_INTERNAL_ERROR;
507 DEBUG("selftest() - validate IR - start\n");
509 // TODO 2011-01-21 SM just use same conf
510 ctx->target_conf = ctx->conf;
513 // 2011-01-28 SM, If FSM did not covers all PCRs Quote validation will fail?
514 // iml_mode = ctx->conf->iml_mode;
515 // ir_without_quote = ctx->conf->ir_without_quote;
516 // ctx->conf->iml_mode = 1;
517 // ctx->conf->ir_without_quote = 1;
521 result = validateIr(ctx, conf->ir_filename); /* ir.c */
525 /* check RM integrity status */
526 DEBUG("selftest() - validate IR - done (rc = %d)\n", result);
527 if ((rc != OPENPTS_RESULT_VALID) && (verbose & DEBUG_FLAG)) {
531 if (result != OPENPTS_RESULT_VALID) {
532 addReason(ctx, "[SELFTEST] selftest was failed");
533 if ((conf->newrm_uuid != NULL) && (conf->newrm_uuid->uuid != NULL)) {
534 /* New RM exist (for reboot after the update), Try the new RM */
536 /* chenge the UUID */ // TODO add exchange func
537 conf->rm_uuid->uuid = conf->newrm_uuid->uuid;
538 conf->rm_uuid->str = conf->newrm_uuid->str;
539 conf->rm_uuid->time = conf->newrm_uuid->time;
542 conf->newrm_uuid->uuid = NULL;
543 conf->newrm_uuid->str = NULL;
544 conf->newrm_uuid->time = NULL;
548 /* try selftest again */
549 DEBUG("selftest again UUID=%s\n", conf->rm_uuid->str);
550 rc = selftest(conf, prop_count, prop_start, prop_end);
551 if (rc == OPENPTS_SELFTEST_SUCCESS) {
552 /* Update the RM UUID by NEWRM_UUID */
553 DEBUG("use UUID=%s\n", conf->rm_uuid->str);
555 rc = writeOpenptsUuidFile(conf->rm_uuid, 1);
556 if (rc != PTS_SUCCESS) {
557 ERROR("writeOpenptsUuidFile fail\n");
561 /* delete newrm_uuid */
562 rc = remove(conf->newrm_uuid->filename);
564 rc = OPENPTS_SELFTEST_RENEWED;
568 addReason(ctx, "[SELFTEST] selftest using both current and new UUID was failed");
570 rc = OPENPTS_SELFTEST_FAILED;
573 addReason(ctx, "[SELFTEST] selftest was failed");
575 rc = OPENPTS_SELFTEST_FAILED;
579 rc = OPENPTS_SELFTEST_SUCCESS;
597 * ./src/ptsc -i -c tests/data/Fedora12/ptscd.conf
604 int newrm(OPENPTS_CONFIG *conf, int prop_count, OPENPTS_PROPERTY *prop_start, OPENPTS_PROPERTY *prop_end) {
605 int rc = PTS_SUCCESS;
606 OPENPTS_CONTEXT *ctx;
608 OPENPTS_PROPERTY *prop;
611 ctx = newPtsContext(conf);
613 ERROR("no memory\n");
614 return PTS_INTERNAL_ERROR;
618 /* copy properties */
620 for (i = 0; i < prop_count; i++) {
622 ERROR("prop == NULL\n");
623 return PTS_INTERNAL_ERROR; // TODO free
625 addProperty(ctx, prop->name, prop->value);
630 if (prop_count > 0) {
631 ctx->prop_start = prop_start;
632 ctx->prop_end = prop_end;
633 ctx->prop_count = prop_count;
638 rc = readFsmFromPropFile(ctx, conf->config_file);
639 if (rc != PTS_SUCCESS) {
640 ERROR("read FSM failed\n");
641 rc = PTS_INTERNAL_ERROR;
646 if (conf->rm_uuid == NULL) {
647 ERROR("conf->rm_uuid == NULL");
648 } else if (conf->rm_uuid->status == OPENPTS_UUID_FILENAME_ONLY) {
649 rc = genOpenptsUuid(conf->rm_uuid);
652 DEBUG("init() - use given RM UUID %s\n", conf->rm_uuid->str);
655 /* save/update rm_uuid file */
656 rc = writeOpenptsUuidFile(conf->rm_uuid, 1); // TODO overwite?
657 if (rc != PTS_SUCCESS) {
658 ERROR("writeOpenptsUuidFile fail\n");
662 rc = makeRmSetDir(conf);
663 if (rc != PTS_SUCCESS) {
664 ERROR("mkdir of RM set dir was failed\n");
669 printf("Generate UUID (for RM) : %s \n", conf->rm_uuid->str);
671 /* read IML to fill the BIOS binary measurement, and translate BHV->BIN FSM */
673 /* load current IML using FSMs */
674 if (conf->iml_mode == 0) { // TODO use def
676 ERROR("Build with --without-tss. iml.mode=tss is not supported\n");
681 } else if (conf->iml_mode == 1) {
682 // TODO change to generic name? conf->iml_filename[0] conf->iml_filename[1]
683 /* from securityfs */
685 rc = readBiosImlFile(
687 conf->bios_iml_filename, conf->iml_endian);
688 if (rc != PTS_SUCCESS) {
689 DEBUG("getBiosImlFile() was failed\n");
690 fprintf(stderr, "Oops! Something is wrong. Please see the reason below\n");
695 /* RUNTIME IML (Linux-IMA) */
696 if (ctx->conf->runtime_iml_filename != NULL) {
700 conf->runtime_iml_filename,
701 conf->runtime_iml_type, 0, &count); // TODO endian?
702 if (rc != PTS_SUCCESS) {
703 fprintf(stderr, "read IMA IML, %s was failed\n", conf->runtime_iml_filename);
704 rc = PTS_INTERNAL_ERROR;
709 ERROR("unknown IML mode, %d\n", conf->iml_mode);
712 /* get SMBIOS data */
715 /* create Reference Manifest */
716 for (i = 0; i < conf->rm_num; i++) {
717 if (conf->rm_filename[i] != NULL) {
718 rc = writeRm(ctx, conf->rm_filename[i], i);
719 if (rc != PTS_SUCCESS) {
720 fprintf(stderr, "write RM, %s was failed\n", conf->rm_filename[i]);
721 rc = PTS_INTERNAL_ERROR;
724 printf("level %d Reference Manifest : %s\n", i, conf->rm_filename[i]);
726 ERROR("missing RM file for level %d\n", i);
729 // printf("\nptsc is successfully initialized!\n");
740 * Print the configuration of PTS collector
745 int printCollectorStatus(OPENPTS_CONFIG *conf) {
746 int rc = PTS_SUCCESS;
747 OPENPTS_CONTEXT *ctx;
749 ctx = newPtsContext(conf);
751 printf("%s version %s \n\n", PACKAGE, VERSION);
753 printf("config file : %s\n", conf->config_file);
755 printf("UUID : %s (%s)\n", ctx->conf->uuid->str, conf->uuid->filename);
758 if (conf->iml_mode == 0) {
759 printf("IML access mode : TSS\n");
760 } else if (conf->iml_mode == 1) {
761 printf("IML access : SecurityFS\n");
762 printf(" BIOS IML file : %s\n", conf->bios_iml_filename);
763 printf(" Runtime IML file : %s\n", conf->runtime_iml_filename);
764 printf(" PCR file : %s\n", conf->pcrs_filename);
766 ERROR("unknown IML mode, %d\n", conf->iml_mode);
770 switch (conf->runtime_iml_type) {
771 case BINARY_IML_TYPE_IMA_ORIGINAL:
772 printf(" Runtime IML type : Linux-IMA patch (kernel 2.6.18-2.6.29)\n");
774 case BINARY_IML_TYPE_IMA_31:
775 printf(" Runtime IML type : IMA (kernel 2.6.30-31)\n");
777 case BINARY_IML_TYPE_IMA:
778 printf(" Runtime IML type : IMA (kernel 2.6.32)\n");
780 case BINARY_IML_TYPE_IMA_NG:
781 printf(" Runtime IML type : IMA NG (kernel 2.6.XX)\n");
783 case BINARY_IML_TYPE_IMA_NGLONG:
784 printf(" Runtime IML type : IMA NG LONG (kernel 2.6.XX)\n");
787 printf(" Runtime IML type : unknown type 0x%x\n", conf->runtime_iml_type);
791 /* Reference Manifest */
793 /* UUID of this platform */
794 printf("RM UUID (current) : %s\n", conf->rm_uuid->str);
795 printf("RM UUID (for next boot) : %s\n", conf->newrm_uuid->str);
798 getRmList(conf, conf->config_dir);
799 printf("List of RM set : %d RM set in config dir\n", conf->rmsets->rmset_num);
800 printRmList(conf, " ");
801 printf("Integrity Report : %s\n", conf->ir_filename);
804 // TODO remove ctx from readFsmFromPropFile
806 rc = readFsmFromPropFile(ctx, conf->config_file);
807 if (rc != PTS_SUCCESS) {
808 ERROR("read FSM failed\n");
812 printf("Model dir : %s\n", conf->model_dir);
813 printf(" Behavior Models\n");
814 printFsmInfo(ctx, " ");