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.
26 * \brief TCG TNC IF-IMC v1.2 R8
27 * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
29 * cleanup 2011-12-31 SM
31 * http://www.trustedcomputinggroup.org/resources/tnc_ifimc_specification
32 * http://www.trustedcomputinggroup.org/files/resource_files/8CB977E1-1D09-3519-AD48484530EF6639/TNC_IFIMC_v1_2_r8.pdf
35 * this library is not a thread safe.
36 * just one IMC<-(IFM)->IMV conenction.
40 * 1 IMC <- IMV capability
41 * 2 IMC -> IMV capability
43 * 3 IMC <- IMV DH-nonce param req
44 * 4 IMC -> IMV DH-nonce param res
45 * 5 IMC <- IMV DH-nonce done
48 * 7 IMC <- IMV template RIMM req
50 * 9 IMC <- IMV template IR req
61 char* getPtsTlvMessage(OPENPTS_CONTEXT *ctx, int type, int *len);
63 /* global variables */
64 static int initialized = 0;
65 static TNC_IMCID id = -1;
66 static TNC_ConnectionID cid = -1;
68 static TNC_TNCC_ReportMessageTypesPointer reportMessageTypesPtr;
69 static TNC_TNCC_RequestHandshakeRetryPointer requestHandshakeRetryPtr;
70 static TNC_TNCC_SendMessagePointer sendMessagePtr;
72 static OPENPTS_CONFIG *conf = NULL;
73 static OPENPTS_CONTEXT *ctx = NULL;
76 // int verbose = DEBUG_IFM_FLAG;
77 // int verbose = DEBUG_FLAG | DEBUG_IFM_FLAG;
80 static TNC_Result sendMessage(
81 /*in*/ TNC_IMCID imcID,
82 /*in*/ TNC_ConnectionID connectionID,
83 /*in*/ TNC_BufferReference message,
84 /*in*/ TNC_UInt32 messageLength,
85 /*in*/ TNC_MessageType messageType);
88 /* List of receive message types */
89 static TNC_MessageType messageTypes[] = {
90 ((TNC_VENDORID_TCG_PEN << 8) | TNC_SUBTYPE_TCG_PTS), // generic
91 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS) // OpenPTS
95 /******************************************************************************/
97 /******************************************************************************/
99 * TNC_IMC_Initialize (MANDATORY)
101 * TODO share the code with ptsc.c
103 TNC_IMC_API TNC_Result TNC_IMC_Initialize(
104 /*in*/ TNC_IMCID imcID,
105 /*in*/ TNC_Version minVersion,
106 /*in*/ TNC_Version maxVersion,
107 /*out*/ TNC_Version *pOutActualVersion) {
110 DEBUG("TNC_IMC_Initialize() - imcID=%d, minVersion=%d maxVersion=%d\n",
111 imcID, minVersion, maxVersion);
114 LOG(LOG_ERR, "not initialized");
115 return TNC_RESULT_ALREADY_INITIALIZED;
118 /* check version - Only support version 1 */
119 if ((minVersion < TNC_IFIMC_VERSION_1) ||
120 (maxVersion > TNC_IFIMC_VERSION_1)) {
121 LOG(LOG_ERR, "no common version");
122 return TNC_RESULT_NO_COMMON_VERSION;
126 *pOutActualVersion = TNC_IFIMC_VERSION_1;
129 /* initialize PTS Collector */
130 conf = newPtsConfig();
132 LOG(LOG_ERR, "no memory");
133 rc = TNC_RESULT_FATAL;
136 ctx = newPtsContext(conf);
138 LOG(LOG_ERR, "no memory\n");
139 rc = TNC_RESULT_FATAL;
143 DEBUG_IFM("config file : %s\n", PTSC_CONFIG_FILE);
145 /* configure PTS Collector */
146 rc = readPtsConfig(conf, PTSC_CONFIG_FILE);
147 if (rc != PTS_SUCCESS) {
148 LOG(LOG_ERR, "read config file, '%s' was failed - abort\n", PTSC_CONFIG_FILE);
149 rc = TNC_RESULT_FATAL;
154 if (checkDir(conf->ir_dir) != PTS_SUCCESS) {
155 LOG(LOG_ERR, "Initialize the IMC. e.g. ptsc -i\n");
156 rc = TNC_RESULT_FATAL;
161 rc = readOpenptsUuidFile(conf->rm_uuid);
162 if (rc != PTS_SUCCESS) {
163 LOG(LOG_ERR, "read RM UUID file %s was failed, initialize ptscd first\n", conf->rm_uuid->filename);
164 rc = TNC_RESULT_FATAL;
167 DEBUG("conf->str_rm_uuid : %s\n", conf->rm_uuid->str);
171 rc = readOpenptsUuidFile(conf->newrm_uuid);
172 if (rc != PTS_SUCCESS) {
173 DEBUG("conf->str_newrm_uuid : missing (file:%s)\n", conf->newrm_uuid->filename);
176 DEBUG("conf->str_newrm_uuid : %s (for next boot)\n", conf->newrm_uuid->str);
179 /* load RSA PUB key */
180 // TODO single key => multiple keys?
184 conf->aik_storage_type,
185 conf->srk_password_mode,
186 conf->tpm_resetdalock,
187 conf->aik_storage_filename,
189 &conf->pubkey_length,
191 if (rc != TSS_SUCCESS) {
192 LOG(LOG_ERR, "getTssPubKey() fail rc=0x%x srk password mode=%d, key =%s\n",
193 rc, conf->srk_password_mode, conf->uuid->str);
194 rc = TNC_RESULT_FATAL;
201 return TNC_RESULT_SUCCESS;
218 * TNC_IMC_NotifyConnectionChange (OPTIONAL)
219 * TODO(munetoh) dummy
221 TNC_IMC_API TNC_Result TNC_IMC_NotifyConnectionChange(
222 /*in*/ TNC_IMCID imcID,
223 /*in*/ TNC_ConnectionID connectionID,
224 /*in*/ TNC_ConnectionState newState) {
225 DEBUG("TNC_IMC_NotifyConnectionChange\n");
227 /* check internal status */
229 LOG(LOG_ERR, "not initialized");
230 return TNC_RESULT_NOT_INITIALIZED;
235 LOG(LOG_ERR, "BAD id");
236 return TNC_RESULT_INVALID_PARAMETER;
242 return TNC_RESULT_SUCCESS;
246 * TNC_IMC_BeginHandshake (MANDATORY)
248 TNC_IMC_API TNC_Result TNC_IMC_BeginHandshake(
249 /*in*/ TNC_IMCID imcID,
250 /*in*/ TNC_ConnectionID connectionID) {
255 DEBUG("TNC_IMC_BeginHandshake - imcID=%d, connectionID=%d\n",
256 (int)imcID, (int)connectionID);
258 /* check internal status */
260 LOG(LOG_ERR, "not initialized");
261 return TNC_RESULT_NOT_INITIALIZED;
266 LOG(LOG_ERR, "bad id");
267 return TNC_RESULT_INVALID_PARAMETER;
273 /* just send OPENPTS_CAPABILITIES to verifier */
274 msg = getPtsTlvMessage(ctx, OPENPTS_CAPABILITIES, &len);
276 DEBUG_IFM("[C->V] OPENPTS_CAPABILITIES[%d]\n", len);
281 (TNC_BufferReference) msg,
283 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
289 * TNC_IMC_ReceiveMessage (OPTIONAL)
291 TNC_IMC_API TNC_Result TNC_IMC_ReceiveMessage(
292 /*in*/ TNC_IMCID imcID,
293 /*in*/ TNC_ConnectionID connectionID,
294 /*in*/ TNC_BufferReference messageBuffer,
295 /*in*/ TNC_UInt32 messageLength,
296 /*in*/ TNC_MessageType messageType) {
297 PTS_IF_M_Attribute *read_tlv;
305 // DEBUG("TNC_IMC_ReceiveMessage msg=%s\n", messageBuffer);
307 /* check internal status */
309 LOG(LOG_ERR, "not initialized");
310 return TNC_RESULT_NOT_INITIALIZED;
315 LOG(LOG_ERR, "bad id");
316 return TNC_RESULT_INVALID_PARAMETER;
320 if (connectionID != cid) {
321 LOG(LOG_ERR, "bad cid");
322 return TNC_RESULT_INVALID_PARAMETER;
326 DEBUG_IFM("[C<-V] imcID=%d, connectionID=%d, type=0x%x, msg[%d]\n",
327 (int)imcID, (int)connectionID, (int)messageType, (int)messageLength);
330 if (messageType == ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS)) {
332 read_tlv = (PTS_IF_M_Attribute*)messageBuffer;
333 if (read_tlv == NULL) {
334 // TODO should send error?
335 LOG(LOG_ERR, "TLV is null");
336 return TNC_RESULT_FATAL;
341 type = ntohl(read_tlv->type);
342 length = ntohl(read_tlv->length);
343 value = (BYTE*)&messageBuffer[12];
345 // DEBUG_IFM("[C->V] type=%08X, length=%d\n", type, length);
348 case OPENPTS_CAPABILITIES:
350 DEBUG_IFM("[C<-V] OPENPTS_CAPABILITIES[%d]\n", 12 + length);
351 // TODO check the verifier's UUID?
354 case REQUEST_TPM_PUBKEY:
355 DEBUG_IFM("[C<-V] REQUEST_TPM_PUBKEY[%d]\n", 12 + length);
357 /* send TPM_PUBKEY */
358 msg = getPtsTlvMessage(ctx, TPM_PUBKEY, &len);
360 LOG(LOG_ERR, "return OPENPTS_ERROR");
361 msg = getPtsTlvMessage(ctx, OPENPTS_ERROR, &len);
367 (TNC_BufferReference) msg,
369 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
370 if (rc != TNC_RESULT_SUCCESS) {
371 LOG(LOG_ERR, "[C->V] TPM_PUBKEY[%d] fail", len);
372 return TNC_RESULT_FATAL;
374 DEBUG_IFM("[C->V] TPM_PUBKEY[%d]\n", len);
378 case REQUEST_RIMM_SET:
379 DEBUG_IFM("[C<-V] REQUEST_RIMM_SET[%d]\n", 12 + length);
381 /* set RM filename */
382 rc = getRmSetDir(conf);
383 if (rc != PTS_SUCCESS) {
384 LOG(LOG_ERR, "collector() - getRmSetDir() was failed\n");
385 return PTS_INTERNAL_ERROR;
389 msg = getPtsTlvMessage(ctx, RIMM_SET, &len);
391 LOG(LOG_ERR, "Get RIMM_SET message was faild, return OPENPTS_ERROR");
392 msg = getPtsTlvMessage(ctx, OPENPTS_ERROR, &len);
398 (TNC_BufferReference) msg,
400 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
401 if (rc != TNC_RESULT_SUCCESS) {
402 LOG(LOG_ERR, "[C->V] RIMM_SET[%d] fail\n", len);
403 return TNC_RESULT_FATAL;
405 DEBUG_IFM("[C->V] RIMM_SET[%d]\n", len);
410 DEBUG_IFM("[C<-V] NONCE[%d]\n", 12 + length);
411 ctx->nonce->nonce_length = length;
412 ctx->nonce->nonce = xmalloc_assert(length);
413 memcpy(ctx->nonce->nonce, value, length);
416 case REQUEST_INTEGRITY_REPORT:
417 DEBUG_IFM("[C<-V] REQUEST_INTEGRITY_REPORT[%d]\n", 12 + length);
419 /* send INTEGRITY_REPORT */
420 msg = getPtsTlvMessage(ctx, INTEGRITY_REPORT, &len);
422 LOG(LOG_ERR, "return OPENPTS_ERROR");
423 msg = getPtsTlvMessage(ctx, OPENPTS_ERROR, &len);
429 (TNC_BufferReference) msg,
431 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
432 if (rc != TNC_RESULT_SUCCESS) {
433 LOG(LOG_ERR, "[C->V] INTEGRITY_REPORT[%d] fail", len);
434 return TNC_RESULT_FATAL;
436 DEBUG_IFM("[C->V] INTEGRITY_REPORT[%d]\n", len);
441 LOG(LOG_ERR, "Unknown type %08X", type);
445 } else if (messageType == ((TNC_VENDORID_TCG_PEN << 8) | TNC_SUBTYPE_TCG_PTS)) {
447 LOG(LOG_ERR, "TBD\n");
448 return TNC_RESULT_FATAL;
450 LOG(LOG_ERR, "bad msg from collector");
451 return TNC_RESULT_FATAL;
454 return TNC_RESULT_SUCCESS;
458 * TNC_IMC_BatchEnding (OPTIONAL)
460 TNC_IMC_API TNC_Result TNC_IMC_BatchEnding(
461 /*in*/ TNC_IMCID imcID,
462 /*in*/ TNC_ConnectionID connectionID) {
463 DEBUG("TNC_IMC_BatchEnding\n");
465 /* check internal status */
467 LOG(LOG_ERR, "not initialized");
468 return TNC_RESULT_NOT_INITIALIZED;
473 LOG(LOG_ERR, "bad id");
474 return TNC_RESULT_INVALID_PARAMETER;
478 if (connectionID != cid) {
479 LOG(LOG_ERR, "bad cid");
480 return TNC_RESULT_INVALID_PARAMETER;
483 DEBUG_IFM("C imcID=%d, connectionID=%d - TNC_IMC_BatchEnding\n", (int)imcID, (int)connectionID);
485 return TNC_RESULT_SUCCESS;
489 * TNC_IMC_Terminate (OPTIONAL)
491 TNC_IMC_API TNC_Result TNC_IMC_Terminate(
492 /*in*/ TNC_IMCID imcID) {
493 DEBUG("TNC_IMC_Terminate\n");
495 /* check internal status */
497 LOG(LOG_ERR, "not initialized");
498 return TNC_RESULT_NOT_INITIALIZED;
503 LOG(LOG_ERR, "bad id");
504 return TNC_RESULT_INVALID_PARAMETER;
510 /* Free PTS contexts */
514 DEBUG_IFM("C imcID=%d - TNC_IMC_Terminate\n", (int)imcID);
516 return TNC_RESULT_SUCCESS;
520 /* TNC Client Functions */
523 * Call TNC_TNCC_ReportMessageTypes (MANDATORY) in the TNCC
525 static TNC_Result reportMessageTypes(
526 /*in*/ TNC_IMCID imcID,
527 /*in*/ TNC_MessageTypeList supportedTypes,
528 /*in*/ TNC_UInt32 typeCount) {
529 DEBUG("TNC_TNCC_ReportMessageTypes() - imcID=%d, supportedTypes=0x%X, typeCount=%d\n",
530 imcID, supportedTypes, typeCount);
532 if (!reportMessageTypesPtr) {
533 LOG(LOG_ERR, "null input");
534 return TNC_RESULT_FATAL;
537 return (*reportMessageTypesPtr)(
545 * Call TNC_TNCC_SendMessage (MANDATORY) in the TNCC
547 static TNC_Result sendMessage(
548 /*in*/ TNC_IMCID imcID,
549 /*in*/ TNC_ConnectionID connectionID,
550 /*in*/ TNC_BufferReference message,
551 /*in*/ TNC_UInt32 messageLength,
552 /*in*/ TNC_MessageType messageType) {
553 DEBUG("TNC_TNCC_SendMessage msg='%s' type=0x%x\n",
554 message, (int)messageType);
556 if (!sendMessagePtr) {
557 LOG(LOG_ERR, "null input");
558 return TNC_RESULT_FATAL;
561 DEBUG_IFM("[C->V] imcID=%d, connectionID=%d, type=0x%x, msg[%d]\n",
562 (int)imcID, (int)connectionID, (int)messageType, (int)messageLength);
564 return (*sendMessagePtr)(imcID,
573 // F12 imc.c:277: error: ‘requestHandshakeRetry’ defined but not used
575 * Call TNC_TNCC_RequestHandshakeRetry (MANDATORY) in the TNCC
577 static TNC_Result requestHandshakeRetry(
578 /*in*/ TNC_IMCID imcID,
579 /*in*/ TNC_ConnectionID connectionID,
580 /*in*/ TNC_RetryReason reason) {
581 DEBUG("TNC_TNCC_RequestHandshakeRetry\n");
583 if (!requestHandshakeRetryPtr)
584 return TNC_RESULT_FATAL;
586 return (*requestHandshakeRetryPtr)(imcID, connectionID, reason);
591 /* Platform-Specific IMC Functions */
594 * TNC_IMC_ProvideBindFunction (MANDATORY)
596 * IMCs implementing the UNIX/Linux Dynamic Linkage platform binding MUST define this
597 * additional platform-specific function. The TNC Client MUST call the function immediately after
598 * calling TNC_IMC_Initialize to provide a pointer to the TNCC bind function. The IMC can then
599 * use the TNCC bind function to obtain pointers to any other TNCC functions.
601 * In the imcID parameter, the TNCC MUST pass the value provided to TNC_IMC_Initialize. In
602 * the bindFunction parameter, the TNCC MUST pass a pointer to the TNCC bind function. IMCs
603 * MAY check if imcID matches the value previously passed to TNC_IMC_Initialize and return
604 * TNC_RESULT_INVALID_PARAMETER if not, but they are not required to make this check.
606 * @param imcID - IMC ID assigned by TNCC
607 * @param bindFunction - Pointer to TNC_TNCC_BindFunction
609 TNC_IMC_API TNC_Result TNC_IMC_ProvideBindFunction(
610 /*in*/ TNC_IMCID imcID,
611 /*in*/ TNC_TNCC_BindFunctionPointer bindFunction) {
612 TNC_Result rc = TNC_RESULT_SUCCESS;
614 DEBUG("TNC_IMC_ProvideBindFunction() - imcID=%d\n", imcID);
616 /* check internal status */
618 LOG(LOG_ERR, "not initialized");
619 return TNC_RESULT_NOT_INITIALIZED;
624 LOG(LOG_ERR, "bad id");
625 return TNC_RESULT_INVALID_PARAMETER;
630 if ((*bindFunction)(imcID,
631 "TNC_TNCC_ReportMessageTypes",
632 (void**)&reportMessageTypesPtr)
633 != TNC_RESULT_SUCCESS) {
634 LOG(LOG_ERR, "bind function fails -TNC_TNCC_ReportMessageTypes\n");
635 rc = TNC_RESULT_FATAL;
638 if ((*bindFunction)(imcID,
639 "TNC_TNCC_RequestHandshakeRetry",
640 (void**)&requestHandshakeRetryPtr)
641 != TNC_RESULT_SUCCESS) {
642 LOG(LOG_ERR, "bind function fails - TNC_TNCC_RequestHandshakeRetry\n");
643 rc = TNC_RESULT_FATAL;
646 if ((*bindFunction)(imcID,
647 "TNC_TNCC_SendMessage",
648 (void**)&sendMessagePtr)
649 != TNC_RESULT_SUCCESS) {
650 LOG(LOG_ERR, "bind functionfails - TNC_TNCC_SendMessage\n");
651 rc = TNC_RESULT_FATAL;
656 rc = reportMessageTypes(
659 sizeof(messageTypes) / sizeof(TNC_MessageType));