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