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