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) 2011 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.
26 * \brief PTS collector command
27 * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
28 * @author Olivier Valentin <olivier.valentin@us.ibm.com>
29 * @author Alexandre Ratchov <alexandre.ratchov@bull.net>
31 * cleanup 2011-07-06 SM
35 #include <sys/types.h>
36 #include <sys/socket.h>
38 #include <sys/socketvar.h>
45 #include <sys/stat.h> // chmod
50 int verbose = 0; /**< DEBUG */
51 static int terminate = 0;
57 OPENPTS_PROPERTY *start = NULL;
58 OPENPTS_PROPERTY *end = NULL;
63 * TODO support single connection.
64 * TODO for multiple conenction, multiple ctxs are required.
65 * TODO disable remote connection
67 int collector2(OPENPTS_CONFIG *conf) {
69 OPENPTS_CONTEXT *ctx = NULL;
70 PTS_IF_M_Attribute *read_tlv = NULL;
75 rc = getRmSetDir(conf);
76 if (rc != PTS_SUCCESS) {
77 ERROR("collector() - getRmSetDir() was failed\n");
78 return PTS_INTERNAL_ERROR;
81 rc = getNewRmSetDir(conf);
82 if (rc != PTS_SUCCESS) {
84 DEBUG("collector() - getNewRmSetDir() was failed - never mind\n");
88 INFO("start collector (System UUID=%s, RM UUID = %s, timeout=%d)\n",
89 conf->uuid->str, conf->rm_uuid->str, conf->ifm_timeout);
91 /* Collector <-> Verifier - handshake loop */
93 INFO("open IF-M PTS connection\n");
95 ctx = newPtsContext(conf);
97 // TODO new ctx for the new connection
103 read_tlv = readPtsTlv(STDIN); // ifm.c, malloc tlv
104 if (read_tlv == NULL) {
105 INFO("close IF-M PTS connection\n");
106 /* free current context */
110 if (count >= conf->ifm_timeout) { // 5sec
112 TODO("collector2 terminate\n");
118 if (read_tlv->type == 0)
121 if (read_tlv->length > 0 && read_tlv->value == NULL)
124 INFO("IF-M read type = 0x%X, len %d\n",
129 switch (read_tlv->type) {
130 case OPENPTS_CAPABILITIES:
131 // TODO define CAPABILITIES structure
132 TODO("IF-M OPENPTS_CAPABILITIES\n");
134 if (read_tlv->length != sizeof(OPENPTS_IF_M_Capability)) { // TODO use defined name
135 ERROR("Bad PTS_CAPABILITIES, len = %d != 32\n", read_tlv->length);
137 OPENPTS_IF_M_Capability *cap;
138 cap = (OPENPTS_IF_M_Capability *) read_tlv->value;
141 /* get verifier's UUID */
142 ctx->uuid = malloc(sizeof(PTS_UUID));
143 memcpy(ctx->uuid, &cap->platform_uuid, 16);
144 ctx->str_uuid = getStringOfUuid(ctx->uuid);
147 INFO("verifier (UUID=%s)\n", ctx->str_uuid);
149 /* send PTS_CAPABILITIES msg. to verifier (=UUID) */
150 len = writePtsTlv(ctx, STDOUT, OPENPTS_CAPABILITIES);
152 ERROR("send OPENPTS_CAPABILITIES was failed\n");
154 TODO("IF-M OPENPTS_CAPABILITIES rc=%d (0x%x)\n", rc, rc);
158 case DH_NONCE_PARAMETERS_REQUEST:
159 TODO("IF-M DH_NONCE_PARAMETERS_REQUEST\n");
161 if (read_tlv->length != 4) {
162 ERROR("Bad DH_NONCE_PARAMETERS_REQUEST, len = %d != 4\n", read_tlv->length);
165 ctx->nonce->req->reserved = read_tlv->value[0];
166 ctx->nonce->req->min_nonce_len = read_tlv->value[1];
168 ctx->nonce->req->dh_group_set = (read_tlv->value[2]<<8) | read_tlv->value[3];
170 rc = getDhResponce(ctx->nonce);
174 ctx, STDOUT, DH_NONCE_PARAMETORS_RESPONSE);
176 ERROR("send DH_NONCE_PARAMETORS_RESPONSE was failed\n");
180 case DH_NONCE_FINISH:
181 TODO("IF-M DH_NONCE_FINISH\n");
183 if (read_tlv->length != 152) { // TODO how to calc this size?
184 ERROR("Bad DH_NONCE_FINISH, len = %d != 152\n", read_tlv->length);
187 ctx->nonce->fin->reserved = read_tlv->value[0];
188 ctx->nonce->fin->nonce_length = read_tlv->value[1];
190 ctx->nonce->fin->selected_hash_alg = (read_tlv->value[2]<<8) | read_tlv->value[3];
193 ctx->nonce->fin->dh_initiator_public = malloc(ctx->nonce->pubkey_length);
195 ctx->nonce->fin->dh_initiator_public,
197 ctx->nonce->pubkey_length);
200 ctx->nonce->fin->dh_initiator_nonce = malloc(ctx->nonce->fin->nonce_length);
202 ctx->nonce->fin->dh_initiator_nonce,
203 &read_tlv->value[4 + ctx->nonce->pubkey_length],
204 ctx->nonce->fin->nonce_length);
206 rc = calcDhFin(ctx->nonce);
211 case REQUEST_RIMM_SET: // 5
212 TODO("IF-M REQUEST_RIMM_SET\n");
214 if (read_tlv->length != 0) {
215 ERROR("Bad REQUEST__RIMM_SET, len = %d != 0\n", read_tlv->length);
218 ctx, STDOUT, RIMM_SET);
220 ERROR("send RIMM_SET was failed\n");
224 case REQUEST_NEW_RIMM_SET:
225 TODO("IF-M REQUEST_NEW_RIMM_SET\n");
227 if (read_tlv->length != 0) {
228 ERROR("Bad REQUEST_NEW_RIMM_SET, len = %d != 0\n", read_tlv->length);
231 ctx, STDOUT, NEW_RIMM_SET);
233 ERROR("sendNEW_RIMM_SET was failed\n");
235 TODO("IF-M REQUEST_NEW_RIMM_SET, len = %d\n", rc);
238 case REQUEST_INTEGRITY_REPORT:
239 TODO("IF-M REQUEST_INTEGRITY_REPORT\n");
241 if (read_tlv->length != 0) {
242 ERROR("Bad REQUEST_INTEGRITY_REPORT, len = %d != 0\n", read_tlv->length);
244 len = writePtsTlv(ctx, STDOUT, INTEGRITY_REPORT);
246 ERROR("send INTEGRITY_REPORT was failed\n");
248 TODO("IF-M INTEGRITY_REPORT len=%d (0x%x)\n", rc, rc);
251 case VERIFICATION_RESULT:
253 INFO("IF-M VERIFICATION_RESULT => terminate\n");
254 DEBUG_IFM("finish\n");
255 terminate = 1; // TODO add TERMINATE MSG
258 case REQUEST_AIDE_DATABASE:
259 INFO("IF-M REQUEST_AIDE_DATABASE\n");
261 if (read_tlv->length != 0) {
262 ERROR("Bad REQUEST_AIDE_DATABASE, len = %d != 0\n", read_tlv->length);
264 len = writePtsTlv(ctx, STDOUT, AIDE_DATABASE);
266 ERROR("send AIDE_DATABASE was failed\n");
271 case REQUEST_TPM_PUBKEY:
273 if (read_tlv->length != 0) {
274 ERROR("Bad REQUEST_TPM_PUBKEY, len = %d != 0\n", read_tlv->length);
276 len = writePtsTlv(ctx, STDOUT, TPM_PUBKEY); // ifm.c
278 ERROR("send TPM_PUBKEY was failed\n");
284 if (read_tlv->length != 20) {
285 ERROR("Bad NONCE, len = %d != 20\n", read_tlv->length);
288 ctx->nonce->nonce_length = 20;
289 if (ctx->nonce->nonce != NULL) {
290 free(ctx->nonce->nonce);
292 ctx->nonce->nonce = malloc(20);
293 memcpy(ctx->nonce->nonce, read_tlv->value, 20);
294 DEBUG_IFM("nonce[%d] : \n", ctx->nonce->nonce_length);
298 ERROR("verifier returns error, termnate\n");
302 ERROR("PTS IF-M type 0x%08x is not supported\n", read_tlv->type);
303 INFO("send OPENPTS_ERROR msg to verifier, then terminate the conenction");
304 ctx->ifm_errno = PTS_UNRECOGNIZED_COMMAND;
305 if (ctx->ifm_strerror != NULL) free(ctx->ifm_strerror);
306 ctx->ifm_strerror = smalloc("Unknown message type");
308 len = writePtsTlv(ctx, STDOUT, OPENPTS_ERROR); // ifm.c
310 ERROR("send OPENPTS_ERROR was failed\n");
317 if (read_tlv != NULL) {
318 freePtsTlv(read_tlv);
322 /* free TLV for break out */
323 if (read_tlv != NULL) {
324 freePtsTlv(read_tlv);
326 } while (terminate == 0);
337 fprintf(stderr, NLS(1, 1, "OpenPTS Collector\n\n"));
338 fprintf(stderr, NLS(1, 2, "Usage: ptsc [options] [command]\n\n"));
339 fprintf(stderr, NLS(1, 3, "Commands: (forgrand)\n"));
340 fprintf(stderr, NLS(1, 4, " -i Initialize PTS collector\n"));
341 fprintf(stderr, NLS(1, 5, " -t Self test (attestation)\n"));
342 fprintf(stderr, NLS(1, 6, " -s Startup (selftest + timestamp)\n"));
343 fprintf(stderr, NLS(1, 7, " -u Update the RM\n"));
344 #ifdef CONFIG_AUTO_RM_UPDATE
345 fprintf(stderr, NLS(1, 8, " -U Update the RM (auto)\n"));
347 fprintf(stderr, NLS(1, 9, " -D Display the configuration\n"));
348 fprintf(stderr, NLS(1, 10, " -m IF-M mode\n"));
349 fprintf(stderr, "\n");
350 fprintf(stderr, NLS(1, 11, "Miscellaneous:\n"));
351 fprintf(stderr, NLS(1, 12, " -h Show this help message\n"));
352 fprintf(stderr, NLS(1, 13, " -v Verbose mode. Multiple -v options increase the verbosity.\n"));
353 fprintf(stderr, "\n");
354 fprintf(stderr, NLS(1, 14, "Options:\n"));
355 fprintf(stderr, NLS(1, 15, " -c configfile Set configuration file. defalt is %s\n"), PTSC_CONFIG_FILE);
356 // fprintf(stderr, NLS(1, 14, " -f foreground, run in the foreground."));
357 // fprintf(stderr, NLS(1, 15, " Logging goes to stderr " "instead of syslog.\n"));
358 fprintf(stderr, NLS(1, 16, " -P name=value Set properties.\n"));
359 fprintf(stderr, NLS(1, 17, " -R Remove RMs\n"));
360 fprintf(stderr, NLS(1, 18, " -z Use the SRK secret to all zeros (20 bytes of zeros)"));
361 // fprintf(stderr, " -d dirname Debug\n");
363 fprintf(stderr, "\n");
373 #ifdef CONFIG_AUTO_RM_UPDATE
381 OPENPTS_PROPERTY *getPropertyFromArg(char *arg) {
385 OPENPTS_PROPERTY *prop;
387 if ((eq = strstr(arg, "=")) != NULL) {
393 prop = newProperty(name, value);
396 fprintf(stderr, "bad property %s\n", arg);
402 static int preparePriv() {
404 struct group *ptsc_grp;
408 if ((ptscd_pwd = getpwnam(PTSCD_USER_NAME)) == NULL) {
409 ERROR("Looking up for user %s", PTSCD_USER_NAME);
415 ptsc_grp = getgrnam(PTSC_GROUP_NAME); // TODO use getgrnam_r
416 if (ptsc_grp == NULL) {
417 ERROR("Looking up for group %s", PTSC_GROUP_NAME);
422 rc = setgid(ptsc_grp->gr_gid);
424 // TODO do not need for IF-M access (read only)
425 ERROR("Switching group fail. %s\n", strerror(errno));
430 if (setuid(ptscd_pwd->pw_uid) == -1) {
431 ERROR("Switching to user %s", PTSCD_USER_NAME);
442 * dir group => PTSC_GROUP_NAME
444 * flag 0:read, 1:read/write
446 static int chmodDir(char *dirpath, int flag) {
448 struct group *ptsc_grp;
451 ptsc_grp = getgrnam(PTSC_GROUP_NAME); // TODO use getgrnam_r
452 if (ptsc_grp == NULL) {
453 ERROR("Looking up for group %s", PTSC_GROUP_NAME);
469 S_IRUSR | S_IWUSR | S_IXUSR |
477 S_IRUSR | S_IWUSR | S_IXUSR |
478 S_IRGRP | S_IWGRP | S_IXGRP);
490 int main(int argc, char *argv[]) {
493 OPENPTS_CONFIG *conf = NULL;
494 char *config_filename = NULL;
495 int command = COMMAND_STATUS;
497 #ifdef CONFIG_AUTO_RM_UPDATE
501 /* properties by cmdline */
502 OPENPTS_PROPERTY *prop;
508 catd = catopen("ptscd", 0);
511 setlocale(LC_ALL, "");
512 bindtextdomain(PACKAGE, LOCALEDIR);
520 if (rc != PTS_SUCCESS) {
521 ERROR("preparePriv fail\n");
525 conf = newPtsConfig();
527 ERROR("internal error\n"); // TODO(munetoh)
532 while ((c = getopt(argc, argv, "ic:uUDtsmvP:Rzh")) != EOF) {
535 command = COMMAND_INIT;
538 command = COMMAND_UPDATE;
541 #ifdef CONFIG_AUTO_RM_UPDATE
542 command = COMMAND_AUTO_UPDATE;
546 command = COMMAND_STATUS;
549 command = COMMAND_SELFTEST;
552 command = COMMAND_STARTUP;
555 command = COMMAND_IFM;
556 setenv("OPENPTS_SYSLOG", "1", 1);
559 config_filename = optarg;
565 #ifdef CONFIG_AUTO_RM_UPDATE
570 conf->srk_password_mode = 1;
573 prop = getPropertyFromArg(optarg);
597 /* DEBUG level, 1,2,3 */
599 verbose = DEBUG_FLAG | DEBUG_FSM_FLAG | DEBUG_IFM_FLAG;
600 INFO("verbose mode 3");
601 } else if (debug > 1) {
602 verbose = DEBUG_FLAG | DEBUG_IFM_FLAG;
603 INFO("verbose mode 2");
604 } else if (debug > 0) {
605 verbose = DEBUG_FLAG;
606 INFO("verbose mode 1");
609 // verbose = DEBUG_FLAG | DEBUG_IFM_FLAG;
612 if (config_filename == NULL) {
613 DEBUG("config file : %s\n", PTSC_CONFIG_FILE);
614 rc = readPtsConfig(conf, PTSC_CONFIG_FILE);
615 if (rc != PTS_SUCCESS) {
616 ERROR("read config file, '%s' was failed - abort\n", PTSC_CONFIG_FILE);
620 DEBUG("config file : %s\n", config_filename);
621 rc = readPtsConfig(conf, config_filename);
622 if (rc != PTS_SUCCESS) {
623 ERROR("read config file, '%s' was failed - abort\n", config_filename);
632 if (checkDir(conf->ir_dir) != PTS_SUCCESS) {
633 rc = makeDir(conf->ir_dir);
634 if (rc != PTS_SUCCESS) {
635 ERROR("Can not create the dir to store IR, %s\n", conf->ir_dir);
638 rc = chmodDir(conf->ir_dir, 1);
639 if (rc != PTS_SUCCESS) {
640 ERROR("Can not create the dir to store IR, %s\n", conf->ir_dir);
645 /* initialize the collector */
646 if (command == COMMAND_INIT) {
647 DEBUG("Initialize Reference Manifest\n");
648 rc = init(conf, prop_num, start, end);
654 rc = readOpenptsUuidFile(conf->rm_uuid);
655 if (rc != PTS_SUCCESS) {
656 ERROR("read RM UUID file %s was failed, initialize ptscd first\n", conf->rm_uuid->filename);
659 DEBUG("conf->str_rm_uuid : %s\n", conf->rm_uuid->str);
663 rc = readOpenptsUuidFile(conf->newrm_uuid);
664 if (rc != PTS_SUCCESS) {
665 DEBUG("conf->str_newrm_uuid : missing (file:%s)\n", conf->newrm_uuid->filename);
668 DEBUG("conf->str_newrm_uuid : %s (for next boot)\n", conf->newrm_uuid->str);
671 /* load RSA PUB key */
672 // TODO single key => multiple keys?
674 TODO("CONFIG_NO_TSS, no TPM_PUBKEY\n");
675 conf->pubkey_length = 0;
681 conf->aik_storage_type, // TSS_PS_TYPE_SYSTEM,
682 conf->srk_password_mode,
683 conf->tpm_resetdalock,
684 conf->aik_storage_filename, // NULL,
686 &conf->pubkey_length,
688 if (rc != TSS_SUCCESS) {
689 ERROR("getTssPubKey() fail rc=0x%x srk password mode=%d, key =%s\n",
690 rc, conf->srk_password_mode, conf->uuid->str);
696 #ifdef CONFIG_AUTO_RM_UPDATE
697 case COMMAND_AUTO_UPDATE:
698 /* update by command, but HUP is better */
699 DEBUG("Update Reference Manifest\n");
701 rc = update(conf, prop_num, start, end, remove);
702 if (rc != PTS_SUCCESS) {
703 printf("update was fail\n");
708 rc = printCollectorStatus(conf);
710 case COMMAND_SELFTEST:
711 rc = selftest(conf, prop_num, start, end);
712 if (rc == OPENPTS_SELFTEST_SUCCESS) {
713 printf("selftest - OK\n");
714 } else if (rc == OPENPTS_SELFTEST_RENEWED) {
715 printf("selftest - Renewed\n");
716 } else if (rc == OPENPTS_SELFTEST_FALLBACK) {
717 printf("selftest -> fallback - TBD\n");
718 } else if (rc == OPENPTS_SELFTEST_FAILED) {
719 printf("selftest -> fail\n");
724 case COMMAND_STARTUP:
725 rc = selftest(conf, prop_num, start, end);
726 if (rc == OPENPTS_SELFTEST_SUCCESS) {
727 INFO("selftest - OK\n");
729 extendEvCollectorStart(conf); // collector.c
730 } else if (rc == OPENPTS_SELFTEST_RENEWED) {
731 INFO("selftest - Renewed\n");
733 extendEvCollectorStart(conf);
734 } else if (rc == OPENPTS_SELFTEST_FALLBACK) {
735 INFO("selftest -> fallback - TBD\n");
737 extendEvCollectorStart(conf);
738 } else if (rc == OPENPTS_SELFTEST_FAILED) {
739 INFO("selftest -> fail\n");
740 if (conf->autoupdate == 1) {
741 TODO("selftest was failed, Try to generate new manifest\n");
743 conf->rm_uuid->status = OPENPTS_UUID_FILENAME_ONLY;
744 if (conf->rm_uuid->uuid != NULL) freeUuid(conf->rm_uuid->uuid);
745 if (conf->rm_uuid->str != NULL) free(conf->rm_uuid->str);
746 if (conf->rm_uuid->time != NULL) free(conf->rm_uuid->time);
747 conf->rm_uuid->uuid = NULL;
748 conf->rm_uuid->str = NULL;
749 conf->rm_uuid->time = NULL;
751 /* gen new RM_UUID and RM */
752 rc = newrm(conf, prop_num, start, end);
753 if (rc != PTS_SUCCESS) {
754 ERROR("newrm() fail\n");
757 rc = selftest(conf, prop_num, start, end);
758 if (rc == OPENPTS_SELFTEST_SUCCESS) {
759 DEBUG("selftest - OK\n");
760 INFO("selftest was faild, new manifests has been generated\n");
761 } else if (rc == OPENPTS_SELFTEST_RENEWED) {
762 DEBUG("selftest - Renewed\n");
767 INFO("selftest was faild, but keep existing manifests\n");
775 conf->rm_uuid->status = OPENPTS_UUID_FILENAME_ONLY;
776 if (conf->rm_uuid->uuid != NULL) freeUuid(conf->rm_uuid->uuid);
777 if (conf->rm_uuid->str != NULL) free(conf->rm_uuid->str);
778 if (conf->rm_uuid->time != NULL) free(conf->rm_uuid->time);
779 conf->rm_uuid->uuid = NULL;
780 conf->rm_uuid->str = NULL;
781 conf->rm_uuid->time = NULL;
783 /* gen new RM_UUID and RM */
784 rc = newrm(conf, prop_num, start, end);
785 if (rc != PTS_SUCCESS) {
786 ERROR("newrm() fail\n");
791 rc = selftest(conf, prop_num, start, end);
792 if (rc == OPENPTS_SELFTEST_SUCCESS) {
793 INFO("manifest generation - success\n");
794 } else if (rc == OPENPTS_SELFTEST_RENEWED) {
801 /* run colelctor IF-M */
802 rc = collector2(conf);
805 ERROR("bad command\n");