OSDN Git Service

Re-organize console out and logging out
[openpts/openpts.git] / src / imc.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/imc.c
26  * \brief TCG TNC IF-IMC v1.2 R8
27  * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
28  * @date 2010-05-07
29  * cleanup 2011-12-31 SM
30  *
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
33  *
34  *
35  * this library is not a thread safe.
36  *  just one IMC<-(IFM)->IMV conenction.
37  * 
38  *  handshake
39  *    0 IMC -> IMV hello
40  *    1 IMC <- IMV capability 
41  *    2 IMC -> IMV capability
42  *
43  *    3 IMC <- IMV DH-nonce param req
44  *    4 IMC -> IMV DH-nonce param res
45  *    5 IMC <- IMV DH-nonce done
46  *    6 IMC -> IMV ack
47  *
48  *    7 IMC <- IMV template RIMM req
49  *    8 IMC -> IMV RIMM
50  *    9 IMC <- IMV template IR req
51  *   10 IMC -> IMV IR
52  */
53
54 #include <stdio.h>
55 #include <string.h>
56
57 #include <tncifimc.h>
58 #include <openpts.h>
59
60 // ifm.c
61 char* getPtsTlvMessage(OPENPTS_CONTEXT *ctx, int type, int *len);
62
63 /* global variables */
64 static int initialized = 0;
65 static TNC_IMCID id = -1;
66 static TNC_ConnectionID cid = -1;
67
68 static TNC_TNCC_ReportMessageTypesPointer    reportMessageTypesPtr;
69 static TNC_TNCC_RequestHandshakeRetryPointer requestHandshakeRetryPtr;
70 static TNC_TNCC_SendMessagePointer           sendMessagePtr;
71
72 static OPENPTS_CONFIG *conf = NULL;
73 static OPENPTS_CONTEXT *ctx = NULL;
74
75 // int verbose = 0;
76 // int verbose = DEBUG_IFM_FLAG;
77 // int verbose = DEBUG_FLAG | DEBUG_IFM_FLAG;
78
79
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);
86
87
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
92 };
93
94
95 /******************************************************************************/
96 /*  IMC Functions                                                             */
97 /******************************************************************************/
98 /**
99  * TNC_IMC_Initialize (MANDATORY) 
100  * 
101  * TODO share the code with ptsc.c
102  */
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) {
108     int rc;
109
110     DEBUG("TNC_IMC_Initialize() - imcID=%d, minVersion=%d maxVersion=%d\n",
111         imcID, minVersion, maxVersion);
112
113     if (initialized) {
114         LOG(LOG_ERR, "not initialized");
115         return TNC_RESULT_ALREADY_INITIALIZED;
116     }
117
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;
123     }
124
125     /* OK */
126     *pOutActualVersion = TNC_IFIMC_VERSION_1;
127     id = imcID;
128
129     /* initialize PTS Collector */
130     conf = newPtsConfig();
131     if (conf == NULL) {
132         LOG(LOG_ERR, "no memory");
133         rc = TNC_RESULT_FATAL;
134         goto error;
135     }
136     ctx =  newPtsContext(conf);
137     if (ctx == NULL) {
138         LOG(LOG_ERR, "no memory\n");
139         rc = TNC_RESULT_FATAL;
140         goto error;
141     }
142
143     DEBUG_IFM("config file  : %s\n", PTSC_CONFIG_FILE);
144
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;
150         goto error;
151     }
152
153     /* check IR dir */
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;
157         goto error;
158     }
159
160     /* RM UUID */
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;
165         goto error;
166     } else {
167         DEBUG("conf->str_rm_uuid         : %s\n", conf->rm_uuid->str);
168     }
169
170     /* NEWRM UUID */
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);
174         // May not exist
175     } else {
176         DEBUG("conf->str_newrm_uuid      : %s (for next boot)\n", conf->newrm_uuid->str);
177     }
178
179     /* load RSA PUB key */
180     // TODO single key => multiple keys?
181     /* get PUBKEY */
182     rc = getTssPubKey(
183             conf->uuid->uuid,
184             conf->aik_storage_type,
185             conf->srk_password_mode,
186             conf->tpm_resetdalock,
187             conf->aik_storage_filename,
188             conf->aik_auth_type,
189             &conf->pubkey_length,
190             &conf->pubkey);
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;
195         goto error;
196     }
197
198     /* PUBKEY ? */
199
200     initialized++;
201     return TNC_RESULT_SUCCESS;
202
203   error:
204     if (ctx != NULL) {
205         freePtsContext(ctx);
206         ctx = NULL;
207     }
208     if (conf != NULL) {
209         freePtsConfig(conf);
210         conf = NULL;
211     }
212
213     return rc;
214 }
215
216
217 /**
218  * TNC_IMC_NotifyConnectionChange (OPTIONAL)
219  * TODO(munetoh) dummy 
220  */
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");
226
227     /* check internal status */
228     if (!initialized) {
229         LOG(LOG_ERR, "not initialized");
230         return TNC_RESULT_NOT_INITIALIZED;
231     }
232
233     /* check ID */
234     if (imcID != id) {
235         LOG(LOG_ERR, "BAD id");
236         return TNC_RESULT_INVALID_PARAMETER;
237     }
238
239     /*  ID */
240     cid = connectionID;
241
242     return TNC_RESULT_SUCCESS;
243 }
244
245 /**
246  * TNC_IMC_BeginHandshake (MANDATORY)
247  */
248 TNC_IMC_API TNC_Result TNC_IMC_BeginHandshake(
249 /*in*/  TNC_IMCID imcID,
250 /*in*/  TNC_ConnectionID connectionID) {
251     int rc = 0;
252     char* msg;
253     int len;
254
255     DEBUG("TNC_IMC_BeginHandshake - imcID=%d, connectionID=%d\n",
256             (int)imcID, (int)connectionID);
257
258     /* check internal status */
259     if (!initialized) {
260         LOG(LOG_ERR, "not initialized");
261         return TNC_RESULT_NOT_INITIALIZED;
262     }
263
264     /* check ID */
265     if (imcID != id) {
266         LOG(LOG_ERR, "bad id");
267         return TNC_RESULT_INVALID_PARAMETER;
268     }
269
270     /* connection ID */
271     cid = connectionID;
272
273     /* just send OPENPTS_CAPABILITIES to verifier */
274     msg = getPtsTlvMessage(ctx, OPENPTS_CAPABILITIES, &len);
275
276     DEBUG_IFM("[C->V] OPENPTS_CAPABILITIES[%d]\n", len);
277
278     rc = sendMessage(
279         imcID,
280         connectionID,
281         (TNC_BufferReference) msg,
282         len,
283         ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
284
285     return rc;
286 }
287
288 /**
289  * TNC_IMC_ReceiveMessage (OPTIONAL)
290  */
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;
298     UINT32 type;
299     int length;
300     int rc = 0;
301     BYTE *value;
302     int len = 0;
303     char* msg;
304
305     // DEBUG("TNC_IMC_ReceiveMessage msg=%s\n", messageBuffer);
306
307     /* check internal status */
308     if (!initialized) {
309         LOG(LOG_ERR, "not initialized");
310         return TNC_RESULT_NOT_INITIALIZED;
311     }
312
313     /* check ID */
314     if (imcID != id) {
315         LOG(LOG_ERR, "bad id");
316         return TNC_RESULT_INVALID_PARAMETER;
317     }
318
319     /* connection ID */
320     if (connectionID != cid) {
321         LOG(LOG_ERR, "bad cid");
322         return TNC_RESULT_INVALID_PARAMETER;
323     }
324
325     /* */
326     DEBUG_IFM("[C<-V] imcID=%d, connectionID=%d, type=0x%x, msg[%d]\n",
327         (int)imcID, (int)connectionID, (int)messageType, (int)messageLength);
328
329     /* handshake */
330     if (messageType == ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS)) {
331         /* 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;
337         }
338
339         /* check VID */
340         // TODO read_tlv->
341         type = ntohl(read_tlv->type);
342         length = ntohl(read_tlv->length);
343         value = (BYTE*)&messageBuffer[12];
344
345         // DEBUG_IFM("[C->V]  type=%08X, length=%d\n", type, length);
346
347         switch (type) {
348         case OPENPTS_CAPABILITIES:
349             /* Check Verifier */
350             DEBUG_IFM("[C<-V] OPENPTS_CAPABILITIES[%d]\n", 12 + length);
351             // TODO check the verifier's UUID?
352             break;
353
354         case REQUEST_TPM_PUBKEY:
355             DEBUG_IFM("[C<-V] REQUEST_TPM_PUBKEY[%d]\n", 12 + length);
356
357             /* send TPM_PUBKEY */
358             msg = getPtsTlvMessage(ctx, TPM_PUBKEY, &len);
359             if (msg == NULL) {
360                 LOG(LOG_ERR, "return  OPENPTS_ERROR");
361                 msg = getPtsTlvMessage(ctx, OPENPTS_ERROR, &len);
362             }
363
364             rc = sendMessage(
365                 imcID,
366                 connectionID,
367                 (TNC_BufferReference) msg,
368                 len,
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;
373             } else {
374                 DEBUG_IFM("[C->V] TPM_PUBKEY[%d]\n", len);
375             }
376             break;
377
378         case REQUEST_RIMM_SET:
379             DEBUG_IFM("[C<-V]  REQUEST_RIMM_SET[%d]\n", 12 + length);
380
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;
386             }
387
388             /* send RIMM_SET */
389             msg = getPtsTlvMessage(ctx, RIMM_SET, &len);
390             if (msg == NULL) {
391                 LOG(LOG_ERR, "Get RIMM_SET message was faild, return  OPENPTS_ERROR");
392                 msg = getPtsTlvMessage(ctx, OPENPTS_ERROR, &len);
393             }
394
395             rc = sendMessage(
396                 imcID,
397                 connectionID,
398                 (TNC_BufferReference) msg,
399                 len,
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;
404             } else {
405                 DEBUG_IFM("[C->V] RIMM_SET[%d]\n", len);
406             }
407             break;
408
409         case NONCE:
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);
414             break;
415
416         case REQUEST_INTEGRITY_REPORT:
417             DEBUG_IFM("[C<-V]  REQUEST_INTEGRITY_REPORT[%d]\n", 12 + length);
418
419             /* send INTEGRITY_REPORT */
420             msg = getPtsTlvMessage(ctx, INTEGRITY_REPORT, &len);
421             if (msg == NULL) {
422                 LOG(LOG_ERR, "return  OPENPTS_ERROR");
423                 msg = getPtsTlvMessage(ctx, OPENPTS_ERROR, &len);
424             }
425
426             rc = sendMessage(
427                 imcID,
428                 connectionID,
429                 (TNC_BufferReference) msg,
430                 len,
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;
435             } else {
436                 DEBUG_IFM("[C->V] INTEGRITY_REPORT[%d]\n", len);
437             }
438             break;
439
440         default:
441             LOG(LOG_ERR, "Unknown type %08X", type);
442             break;
443         }
444         return rc;
445     } else if (messageType == ((TNC_VENDORID_TCG_PEN << 8) | TNC_SUBTYPE_TCG_PTS)) {
446         /* TCG */
447         LOG(LOG_ERR, "TBD\n");
448         return TNC_RESULT_FATAL;
449     } else {
450         LOG(LOG_ERR, "bad msg from collector");
451         return TNC_RESULT_FATAL;
452     }
453
454     return TNC_RESULT_SUCCESS;
455 }
456
457 /**
458  * TNC_IMC_BatchEnding (OPTIONAL)
459  */
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");
464
465     /* check internal status */
466     if (!initialized) {
467         LOG(LOG_ERR, "not initialized");
468         return TNC_RESULT_NOT_INITIALIZED;
469     }
470
471     /* check ID */
472     if (imcID != id) {
473         LOG(LOG_ERR, "bad id");
474         return TNC_RESULT_INVALID_PARAMETER;
475     }
476
477     /* connection ID */
478     if (connectionID != cid) {
479         LOG(LOG_ERR, "bad cid");
480         return TNC_RESULT_INVALID_PARAMETER;
481     }
482
483     DEBUG_IFM("C    imcID=%d, connectionID=%d - TNC_IMC_BatchEnding\n", (int)imcID, (int)connectionID);
484
485     return TNC_RESULT_SUCCESS;
486 }
487
488 /**
489  * TNC_IMC_Terminate (OPTIONAL)
490  */
491 TNC_IMC_API TNC_Result TNC_IMC_Terminate(
492 /*in*/  TNC_IMCID imcID) {
493     DEBUG("TNC_IMC_Terminate\n");
494
495     /* check internal status */
496     if (!initialized) {
497         LOG(LOG_ERR, "not initialized");
498         return TNC_RESULT_NOT_INITIALIZED;
499     }
500
501     /* check ID */
502     if (imcID != id) {
503         LOG(LOG_ERR, "bad id");
504         return TNC_RESULT_INVALID_PARAMETER;
505     }
506
507     /* connection ID */
508     // TODO(munetoh)
509
510     /* Free PTS contexts */
511     freePtsContext(ctx);
512     freePtsConfig(conf);
513
514     DEBUG_IFM("C    imcID=%d - TNC_IMC_Terminate\n", (int)imcID);
515
516     return TNC_RESULT_SUCCESS;
517 }
518
519
520 /* TNC Client Functions */
521
522 /**
523  * Call TNC_TNCC_ReportMessageTypes (MANDATORY) in the TNCC
524  */
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);
531
532     if (!reportMessageTypesPtr) {
533         LOG(LOG_ERR, "null input");
534         return TNC_RESULT_FATAL;
535     }
536
537     return (*reportMessageTypesPtr)(
538         imcID,
539         supportedTypes,
540         typeCount);
541 }
542
543 #if 1
544 /**
545  * Call TNC_TNCC_SendMessage (MANDATORY) in the TNCC
546  */
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);
555
556     if (!sendMessagePtr) {
557         LOG(LOG_ERR, "null input");
558         return TNC_RESULT_FATAL;
559     }
560
561     DEBUG_IFM("[C->V] imcID=%d, connectionID=%d, type=0x%x, msg[%d]\n",
562         (int)imcID, (int)connectionID, (int)messageType, (int)messageLength);
563
564     return (*sendMessagePtr)(imcID,
565                               connectionID,
566                               message,
567                               messageLength,
568                               messageType);
569 }
570 #endif
571
572 #if 0
573 // F12 imc.c:277: error: â€˜requestHandshakeRetry’ defined but not used
574 /**
575  * Call TNC_TNCC_RequestHandshakeRetry (MANDATORY) in the TNCC
576  */
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");
582
583     if (!requestHandshakeRetryPtr)
584         return TNC_RESULT_FATAL;
585
586     return (*requestHandshakeRetryPtr)(imcID, connectionID, reason);
587 }
588 #endif
589
590
591 /* Platform-Specific IMC Functions */
592
593 /**
594  * TNC_IMC_ProvideBindFunction (MANDATORY)
595  * 
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.
600  *
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.
605  *
606  * @param imcID - IMC ID assigned by TNCC
607  * @param bindFunction - Pointer to TNC_TNCC_BindFunction
608  */
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;
613
614     DEBUG("TNC_IMC_ProvideBindFunction() - imcID=%d\n", imcID);
615
616     /* check internal status */
617     if (!initialized) {
618         LOG(LOG_ERR, "not initialized");
619         return TNC_RESULT_NOT_INITIALIZED;
620     }
621
622     /* check ID */
623     if (imcID != id) {
624         LOG(LOG_ERR, "bad id");
625         return TNC_RESULT_INVALID_PARAMETER;
626     }
627
628     /* Bind  */
629     if (bindFunction) {
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;
636             return rc;
637         }
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;
644             return rc;
645         }
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;
652             return rc;
653         }
654     }
655
656     rc = reportMessageTypes(
657             imcID,
658             messageTypes,
659             sizeof(messageTypes) / sizeof(TNC_MessageType));
660
661     return rc;
662 }