used request ID in message request output
[strongswan.git] / src / libimcv / plugins / imv_attestation / imv_attestation.c
1 /*
2 * Copyright (C) 2011 Sansar Choinyambuu
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "imv_attestation_state.h"
17
18 #include <imv/imv_agent.h>
19 #include <pa_tnc/pa_tnc_msg.h>
20 #include <ietf/ietf_attr.h>
21 #include <ietf/ietf_attr_pa_tnc_error.h>
22 #include <ietf/ietf_attr_product_info.h>
23
24 #include <libpts.h>
25
26 #include <pts/pts_database.h>
27 #include <pts/pts_creds.h>
28 #include <pts/pts_error.h>
29
30 #include <tcg/tcg_attr.h>
31 #include <tcg/tcg_pts_attr_proto_caps.h>
32 #include <tcg/tcg_pts_attr_meas_algo.h>
33 #include <tcg/tcg_pts_attr_get_tpm_version_info.h>
34 #include <tcg/tcg_pts_attr_tpm_version_info.h>
35 #include <tcg/tcg_pts_attr_get_aik.h>
36 #include <tcg/tcg_pts_attr_aik.h>
37 #include <tcg/tcg_pts_attr_req_funct_comp_evid.h>
38 #include <tcg/tcg_pts_attr_gen_attest_evid.h>
39 #include <tcg/tcg_pts_attr_simple_comp_evid.h>
40 #include <tcg/tcg_pts_attr_simple_evid_final.h>
41 #include <tcg/tcg_pts_attr_req_file_meas.h>
42 #include <tcg/tcg_pts_attr_file_meas.h>
43
44 #include <tncif_pa_subtypes.h>
45
46 #include <pen/pen.h>
47 #include <debug.h>
48 #include <credentials/credential_manager.h>
49
50 /* IMV definitions */
51
52 static const char imv_name[] = "Attestation";
53
54 #define IMV_VENDOR_ID PEN_TCG
55 #define IMV_SUBTYPE PA_SUBTYPE_TCG_PTS
56
57 static imv_agent_t *imv_attestation;
58
59 /**
60 * Supported PTS measurement algorithms
61 */
62 static pts_meas_algorithms_t supported_algorithms = 0;
63
64 /**
65 * PTS file measurement database
66 */
67 static pts_database_t *pts_db;
68
69 /**
70 * PTS credentials
71 */
72 static pts_creds_t *pts_creds;
73
74 /**
75 * PTS credential manager
76 */
77 static credential_manager_t *pts_credmgr;
78
79 /**
80 * see section 3.7.1 of TCG TNC IF-IMV Specification 1.2
81 */
82 TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id,
83 TNC_Version min_version,
84 TNC_Version max_version,
85 TNC_Version *actual_version)
86 {
87 char *hash_alg, *uri, *cadir;
88
89 if (imv_attestation)
90 {
91 DBG1(DBG_IMV, "IMV \"%s\" has already been initialized", imv_name);
92 return TNC_RESULT_ALREADY_INITIALIZED;
93 }
94 if (!pts_meas_probe_algorithms(&supported_algorithms))
95 {
96 return TNC_RESULT_FATAL;
97 }
98 imv_attestation = imv_agent_create(imv_name, IMV_VENDOR_ID, IMV_SUBTYPE,
99 imv_id, actual_version);
100 if (!imv_attestation)
101 {
102 return TNC_RESULT_FATAL;
103 }
104
105 libpts_init();
106
107 if (min_version > TNC_IFIMV_VERSION_1 || max_version < TNC_IFIMV_VERSION_1)
108 {
109 DBG1(DBG_IMV, "no common IF-IMV version");
110 return TNC_RESULT_NO_COMMON_VERSION;
111 }
112
113 /**
114 * Specify supported PTS measurement algorithms
115 *
116 * sha1 : PTS_MEAS_ALGO_SHA1
117 * sha256: PTS_MEAS_ALGO_SHA1 | PTS_MEAS_ALGO_SHA256
118 * sha384: PTS_MEAS_ALGO_SHA1 | PTS_MEAS_ALGO_SHA256 | PTS_MEAS_ALGO_SHA384
119 *
120 * we expect the PTS-IMC to select the strongest supported algorithm
121 */
122 hash_alg = lib->settings->get_str(lib->settings,
123 "libimcv.plugins.imv-attestation.hash_algorithm", "sha256");
124 if (!strcaseeq(hash_alg, "sha384") && !strcaseeq(hash_alg, "sha2_384"))
125 {
126 /* remove SHA384 algorithm */
127 supported_algorithms &= ~PTS_MEAS_ALGO_SHA384;
128 }
129 if (strcaseeq(hash_alg, "sha1"))
130 {
131 /* remove SHA256 algorithm */
132 supported_algorithms &= ~PTS_MEAS_ALGO_SHA256;
133 }
134
135 /* create a PTS credential manager */
136 pts_credmgr = credential_manager_create();
137
138 /* create PTS credential set */
139 cadir = lib->settings->get_str(lib->settings,
140 "libimcv.plugins.imv-attestation.cadir", NULL);
141 pts_creds = pts_creds_create(cadir);
142 if (pts_creds)
143 {
144 pts_credmgr->add_set(pts_credmgr, pts_creds->get_set(pts_creds));
145 }
146
147 /* attach file measurement database */
148 uri = lib->settings->get_str(lib->settings,
149 "libimcv.plugins.imv-attestation.database", NULL);
150 pts_db = pts_database_create(uri);
151
152 return TNC_RESULT_SUCCESS;
153 }
154
155 /**
156 * see section 3.7.2 of TCG TNC IF-IMV Specification 1.2
157 */
158 TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
159 TNC_ConnectionID connection_id,
160 TNC_ConnectionState new_state)
161 {
162 imv_state_t *state;
163 imv_attestation_state_t *attestation_state;
164 TNC_Result result;
165
166 if (!imv_attestation)
167 {
168 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
169 return TNC_RESULT_NOT_INITIALIZED;
170 }
171 switch (new_state)
172 {
173 case TNC_CONNECTION_STATE_CREATE:
174 state = imv_attestation_state_create(connection_id);
175 return imv_attestation->create_state(imv_attestation, state);
176 case TNC_CONNECTION_STATE_DELETE:
177 return imv_attestation->delete_state(imv_attestation, connection_id);
178 case TNC_CONNECTION_STATE_HANDSHAKE:
179 result = imv_attestation->change_state(imv_attestation, connection_id,
180 new_state, &state);
181 if (result != TNC_RESULT_SUCCESS)
182 {
183 return result;
184 }
185 attestation_state = (imv_attestation_state_t*)state;
186
187 /* TODO: Get some configurations */
188
189 return TNC_RESULT_SUCCESS;
190 default:
191 return imv_attestation->change_state(imv_attestation, connection_id,
192 new_state, NULL);
193 }
194 }
195
196 static TNC_Result send_message(TNC_ConnectionID connection_id)
197 {
198 pa_tnc_msg_t *msg;
199 pa_tnc_attr_t *attr;
200 pts_t *pts;
201 imv_state_t *state;
202 imv_attestation_state_t *attestation_state;
203 imv_attestation_handshake_state_t handshake_state;
204 TNC_Result result;
205
206 if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
207 {
208 return TNC_RESULT_FATAL;
209 }
210 attestation_state = (imv_attestation_state_t*)state;
211 handshake_state = attestation_state->get_handshake_state(attestation_state);
212 pts = attestation_state->get_pts(attestation_state);
213
214 msg = pa_tnc_msg_create();
215
216
217 /* Switch on the attribute type IMV has received */
218 switch (handshake_state)
219 {
220 case IMV_ATTESTATION_STATE_INIT:
221 {
222 pts_proto_caps_flag_t flags;
223
224 /* Send Request Protocol Capabilities attribute */
225 flags = pts->get_proto_caps(pts);
226 attr = tcg_pts_attr_proto_caps_create(flags, TRUE);
227 attr->set_noskip_flag(attr, TRUE);
228 msg->add_attribute(msg, attr);
229
230 /* Send Measurement Algorithms attribute */
231 attr = tcg_pts_attr_meas_algo_create(supported_algorithms, FALSE);
232 attr->set_noskip_flag(attr, TRUE);
233 msg->add_attribute(msg, attr);
234
235 attestation_state->set_handshake_state(attestation_state,
236 IMV_ATTESTATION_STATE_MEAS);
237 break;
238 }
239
240 case IMV_ATTESTATION_STATE_MEAS:
241 {
242 enumerator_t *enumerator;
243 u_int32_t delimiter = SOLIDUS_UTF;
244 char *platform_info, *pathname;
245 u_int16_t request_id;
246 int id, type;
247 bool is_dir;
248
249 attestation_state->set_handshake_state(attestation_state,
250 IMV_ATTESTATION_STATE_END);
251
252 /* Does the PTS-IMC have TPM support? */
253 if (pts->get_proto_caps(pts) & PTS_PROTO_CAPS_T)
254 {
255 /* Send Get TPM Version attribute */
256 attr = tcg_pts_attr_get_tpm_version_info_create();
257 attr->set_noskip_flag(attr, TRUE);
258 msg->add_attribute(msg, attr);
259
260 /* Send Get AIK attribute */
261 attr = tcg_pts_attr_get_aik_create();
262 attr->set_noskip_flag(attr, TRUE);
263 msg->add_attribute(msg, attr);
264 }
265
266 /* Get Platform and OS of the PTS-IMC */
267 platform_info = pts->get_platform_info(pts);
268
269 if (!pts_db || !platform_info)
270 {
271 DBG1(DBG_IMV, "%s%s%s not available",
272 (pts_db) ? "" : "pts database",
273 (!pts_db && !platform_info) ? "and" : "",
274 (platform_info) ? "" : "platform info");
275 break;
276 }
277 DBG1(DBG_IMV, "platform is '%s'", platform_info);
278
279 /* Send Request File Measurement attribute */
280 enumerator = pts_db->create_file_enumerator(pts_db, platform_info);
281 if (!enumerator)
282 {
283 break;
284 }
285 while (enumerator->enumerate(enumerator, &id, &type, &pathname))
286 {
287 is_dir = (type != 0);
288 request_id = attestation_state->add_request(attestation_state,
289 id, is_dir);
290 DBG2(DBG_IMV, "measurement request %d for %s '%s'",
291 request_id, is_dir ? "directory" : "file", pathname);
292 attr = tcg_pts_attr_req_file_meas_create(is_dir, request_id,
293 delimiter, pathname);
294 attr->set_noskip_flag(attr, TRUE);
295 msg->add_attribute(msg, attr);
296 }
297 enumerator->destroy(enumerator);
298 break;
299 }
300 case IMV_ATTESTATION_STATE_COMP_EVID:
301 case IMV_ATTESTATION_STATE_IML:
302 DBG1(DBG_IMV, "Attestation IMV has nothing to send: \"%s\"",
303 handshake_state);
304 return TNC_RESULT_FATAL;
305 default:
306 DBG1(DBG_IMV, "Attestation IMV is in unknown state: \"%s\"",
307 handshake_state);
308 return TNC_RESULT_FATAL;
309 }
310
311 msg->build(msg);
312 result = imv_attestation->send_message(imv_attestation, connection_id,
313 msg->get_encoding(msg));
314 msg->destroy(msg);
315
316 return result;
317 }
318
319 /**
320 * see section 3.7.3 of TCG TNC IF-IMV Specification 1.2
321 */
322 TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
323 TNC_ConnectionID connection_id,
324 TNC_BufferReference msg,
325 TNC_UInt32 msg_len,
326 TNC_MessageType msg_type)
327 {
328 pa_tnc_msg_t *pa_tnc_msg;
329 pa_tnc_attr_t *attr;
330 imv_state_t *state;
331 imv_attestation_state_t *attestation_state;
332 pts_t *pts;
333 enumerator_t *enumerator;
334 TNC_Result result;
335 bool fatal_error = FALSE;
336 bool measurement_error = FALSE;
337
338 if (!imv_attestation)
339 {
340 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
341 return TNC_RESULT_NOT_INITIALIZED;
342 }
343
344 /* get current IMV state */
345 if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
346 {
347 return TNC_RESULT_FATAL;
348 }
349 attestation_state = (imv_attestation_state_t*)state;
350 pts = attestation_state->get_pts(attestation_state);
351
352 /* parse received PA-TNC message and automatically handle any errors */
353 result = imv_attestation->receive_message(imv_attestation, connection_id,
354 chunk_create(msg, msg_len), msg_type,
355 &pa_tnc_msg);
356
357 /* no parsed PA-TNC attributes available if an error occurred */
358 if (!pa_tnc_msg)
359 {
360 return result;
361 }
362
363 /* analyze PA-TNC attributes */
364 enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
365 while (enumerator->enumerate(enumerator, &attr))
366 {
367 if (attr->get_vendor_id(attr) == PEN_IETF)
368 {
369 if (attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR)
370 {
371 ietf_attr_pa_tnc_error_t *error_attr;
372 pen_t error_vendor_id;
373 pa_tnc_error_code_t error_code;
374 chunk_t msg_info, attr_info;
375 u_int32_t offset;
376
377 error_attr = (ietf_attr_pa_tnc_error_t*)attr;
378 error_vendor_id = error_attr->get_vendor_id(error_attr);
379 error_code = error_attr->get_error_code(error_attr);
380 msg_info = error_attr->get_msg_info(error_attr);
381
382 if (error_vendor_id == PEN_IETF)
383 {
384 DBG1(DBG_IMV, "received PA-TNC error '%N' "
385 "concerning message %#B",
386 pa_tnc_error_code_names, error_code, &msg_info);
387
388 switch (error_code)
389 {
390 case PA_ERROR_INVALID_PARAMETER:
391 offset = error_attr->get_offset(error_attr);
392 DBG1(DBG_IMV, " occurred at offset of %u bytes",
393 offset);
394 break;
395 case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
396 attr_info = error_attr->get_attr_info(error_attr);
397 DBG1(DBG_IMV, " unsupported attribute %#B",
398 &attr_info);
399 break;
400 default:
401 break;
402 }
403 }
404 else if (error_vendor_id == PEN_TCG)
405 {
406 DBG1(DBG_IMV, "received TCG-PTS error '%N'",
407 pts_error_code_names, error_code);
408 DBG1(DBG_IMV, "error information: %B", &msg_info);
409 }
410 fatal_error = TRUE;
411 }
412 else if (attr->get_type(attr) == IETF_ATTR_PRODUCT_INFORMATION)
413 {
414 ietf_attr_product_info_t *attr_cast;
415 char *platform_info;
416
417 attr_cast = (ietf_attr_product_info_t*)attr;
418 platform_info = attr_cast->get_info(attr_cast, NULL, NULL);
419 pts->set_platform_info(pts, platform_info);
420 }
421 }
422 else if (attr->get_vendor_id(attr) == PEN_TCG)
423 {
424 switch (attr->get_type(attr))
425 {
426 case TCG_PTS_PROTO_CAPS:
427 {
428 tcg_pts_attr_proto_caps_t *attr_cast;
429 pts_proto_caps_flag_t flags;
430
431 attr_cast = (tcg_pts_attr_proto_caps_t*)attr;
432 flags = attr_cast->get_flags(attr_cast);
433 pts->set_proto_caps(pts, flags);
434 break;
435 }
436 case TCG_PTS_MEAS_ALGO_SELECTION:
437 {
438 tcg_pts_attr_meas_algo_t *attr_cast;
439 pts_meas_algorithms_t selected_algorithm;
440
441 attr_cast = (tcg_pts_attr_meas_algo_t*)attr;
442 selected_algorithm = attr_cast->get_algorithms(attr_cast);
443 pts->set_meas_algorithm(pts, selected_algorithm);
444 break;
445 }
446 case TCG_PTS_TPM_VERSION_INFO:
447 {
448 tcg_pts_attr_tpm_version_info_t *attr_cast;
449 chunk_t tpm_version_info;
450
451 attr_cast = (tcg_pts_attr_tpm_version_info_t*)attr;
452 tpm_version_info = attr_cast->get_tpm_version_info(attr_cast);
453 pts->set_tpm_version_info(pts, tpm_version_info);
454 break;
455 }
456 case TCG_PTS_AIK:
457 {
458 tcg_pts_attr_aik_t *attr_cast;
459 certificate_t *aik, *issuer;
460 enumerator_t *e;
461 bool trusted = FALSE;
462
463 attr_cast = (tcg_pts_attr_aik_t*)attr;
464 aik = attr_cast->get_aik(attr_cast);
465 if (!aik)
466 {
467 /* TODO generate error attribute */
468 break;
469 }
470 if (aik->get_type(aik) == CERT_X509)
471 {
472 DBG1(DBG_IMV, "verifying AIK certificate");
473 e = pts_credmgr->create_trusted_enumerator(pts_credmgr,
474 KEY_ANY, aik->get_issuer(aik), FALSE);
475 while (e->enumerate(e, &issuer))
476 {
477 if (aik->issued_by(aik, issuer))
478 {
479 trusted = TRUE;
480 break;
481 }
482 }
483 e->destroy(e);
484 DBG1(DBG_IMV, "AIK certificate is %strusted",
485 trusted ? "" : "not ");
486 }
487 pts->set_aik(pts, aik);
488 break;
489 }
490
491 /* PTS-based Attestation Evidence */
492 case TCG_PTS_SIMPLE_COMP_EVID:
493 break;
494 case TCG_PTS_SIMPLE_EVID_FINAL:
495 break;
496 case TCG_PTS_FILE_MEAS:
497 {
498 tcg_pts_attr_file_meas_t *attr_cast;
499 u_int16_t request_id;
500 int file_count, file_id;
501 pts_meas_algorithms_t algo;
502 pts_file_meas_t *measurements;
503 char *platform_info;
504 enumerator_t *e_hash;
505 bool is_dir;
506
507 platform_info = pts->get_platform_info(pts);
508 if (!pts_db || !platform_info)
509 {
510 break;
511 }
512
513 attr_cast = (tcg_pts_attr_file_meas_t*)attr;
514 measurements = attr_cast->get_measurements(attr_cast);
515 algo = pts->get_meas_algorithm(pts);
516 request_id = measurements->get_request_id(measurements);
517 file_count = measurements->get_file_count(measurements);
518
519 DBG1(DBG_IMV, "measurement request %d returned %d file%s:",
520 request_id, file_count, (file_count == 1) ? "":"s");
521
522 if (!attestation_state->check_off_request(attestation_state,
523 request_id, &file_id, &is_dir))
524 {
525 DBG1(DBG_IMV, " no entry found for this request");
526 break;
527 }
528
529 /* check hashes from database against measurements */
530 e_hash = pts_db->create_hash_enumerator(pts_db,
531 platform_info, algo, file_id, is_dir);
532 if (!measurements->verify(measurements, e_hash, is_dir))
533 {
534 measurement_error = TRUE;
535 }
536 e_hash->destroy(e_hash);
537 break;
538 }
539
540 /* TODO: Not implemented yet */
541 case TCG_PTS_DH_NONCE_PARAMS_RESP:
542 case TCG_PTS_UNIX_FILE_META:
543 case TCG_PTS_INTEG_MEAS_LOG:
544 /* Attributes using XML */
545 case TCG_PTS_TEMPL_REF_MANI_SET_META:
546 case TCG_PTS_VERIFICATION_RESULT:
547 case TCG_PTS_INTEG_REPORT:
548 /* On Windows only*/
549 case TCG_PTS_WIN_FILE_META:
550 case TCG_PTS_REGISTRY_VALUE:
551 /* Received on IMC side only*/
552 case TCG_PTS_REQ_PROTO_CAPS:
553 case TCG_PTS_DH_NONCE_PARAMS_REQ:
554 case TCG_PTS_DH_NONCE_FINISH:
555 case TCG_PTS_MEAS_ALGO:
556 case TCG_PTS_GET_TPM_VERSION_INFO:
557 case TCG_PTS_REQ_TEMPL_REF_MANI_SET_META:
558 case TCG_PTS_UPDATE_TEMPL_REF_MANI:
559 case TCG_PTS_GET_AIK:
560 case TCG_PTS_REQ_FUNCT_COMP_EVID:
561 case TCG_PTS_GEN_ATTEST_EVID:
562 case TCG_PTS_REQ_FILE_META:
563 case TCG_PTS_REQ_FILE_MEAS:
564 case TCG_PTS_REQ_INTEG_MEAS_LOG:
565 default:
566 DBG1(DBG_IMV, "received unsupported attribute '%N'",
567 tcg_attr_names, attr->get_type(attr));
568 break;
569 }
570 }
571 }
572 enumerator->destroy(enumerator);
573 pa_tnc_msg->destroy(pa_tnc_msg);
574
575
576 if (fatal_error)
577 {
578 state->set_recommendation(state,
579 TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
580 TNC_IMV_EVALUATION_RESULT_ERROR);
581 return imv_attestation->provide_recommendation(imv_attestation,
582 connection_id);
583 }
584
585 if (attestation_state->get_handshake_state(attestation_state) &
586 IMV_ATTESTATION_STATE_END)
587 {
588 if (attestation_state->get_request_count(attestation_state))
589 {
590 DBG1(DBG_IMV, "failure due to %d pending file measurements",
591 attestation_state->get_request_count(attestation_state));
592 measurement_error = TRUE;
593 }
594 if (measurement_error)
595 {
596 state->set_recommendation(state,
597 TNC_IMV_ACTION_RECOMMENDATION_ISOLATE,
598 TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR);
599 }
600 else
601 {
602 state->set_recommendation(state,
603 TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
604 TNC_IMV_EVALUATION_RESULT_COMPLIANT);
605 }
606 return imv_attestation->provide_recommendation(imv_attestation,
607 connection_id);
608 }
609
610 return send_message(connection_id);
611 }
612
613 /**
614 * see section 3.7.4 of TCG TNC IF-IMV Specification 1.2
615 */
616 TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
617 TNC_ConnectionID connection_id)
618 {
619 if (!imv_attestation)
620 {
621 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
622 return TNC_RESULT_NOT_INITIALIZED;
623 }
624 return imv_attestation->provide_recommendation(imv_attestation, connection_id);
625 }
626
627 /**
628 * see section 3.7.5 of TCG TNC IF-IMV Specification 1.2
629 */
630 TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id,
631 TNC_ConnectionID connection_id)
632 {
633 imv_state_t *state;
634 imv_attestation_state_t *attestation_state;
635
636 if (!imv_attestation)
637 {
638 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
639 return TNC_RESULT_NOT_INITIALIZED;
640 }
641 /* get current IMV state */
642 if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
643 {
644 return TNC_RESULT_FATAL;
645 }
646 attestation_state = (imv_attestation_state_t*)state;
647
648 /* Check if IMV has to initiate the PA-TNC exchange */
649 if (attestation_state->get_handshake_state(attestation_state) ==
650 IMV_ATTESTATION_STATE_INIT)
651 {
652 return send_message(connection_id);
653 }
654 return TNC_RESULT_SUCCESS;
655 }
656
657 /**
658 * see section 3.7.6 of TCG TNC IF-IMV Specification 1.2
659 */
660 TNC_Result TNC_IMV_Terminate(TNC_IMVID imv_id)
661 {
662 if (!imv_attestation)
663 {
664 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
665 return TNC_RESULT_NOT_INITIALIZED;
666 }
667 if (pts_creds)
668 {
669 pts_credmgr->remove_set(pts_credmgr, pts_creds->get_set(pts_creds));
670 pts_creds->destroy(pts_creds);
671 }
672 DESTROY_IF(pts_db);
673 DESTROY_IF(pts_credmgr);
674
675 libpts_deinit();
676
677 imv_attestation->destroy(imv_attestation);
678 imv_attestation = NULL;
679
680 return TNC_RESULT_SUCCESS;
681 }
682
683 /**
684 * see section 4.2.8.1 of TCG TNC IF-IMV Specification 1.2
685 */
686 TNC_Result TNC_IMV_ProvideBindFunction(TNC_IMVID imv_id,
687 TNC_TNCS_BindFunctionPointer bind_function)
688 {
689 if (!imv_attestation)
690 {
691 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
692 return TNC_RESULT_NOT_INITIALIZED;
693 }
694 return imv_attestation->bind_functions(imv_attestation, bind_function);
695 }