2 * Copyright (C) 2011 Sansar Choinyambuu
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
16 #include "imv_attestation_state.h"
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>
26 #include <pts/pts_database.h>
27 #include <pts/pts_creds.h>
28 #include <pts/pts_error.h>
30 #include <tcg/tcg_attr.h>
31 #include <tcg/tcg_pts_attr_proto_caps.h>
32 #include <tcg/tcg_pts_attr_dh_nonce_params_req.h>
33 #include <tcg/tcg_pts_attr_dh_nonce_params_resp.h>
34 #include <tcg/tcg_pts_attr_dh_nonce_finish.h>
35 #include <tcg/tcg_pts_attr_meas_algo.h>
36 #include <tcg/tcg_pts_attr_get_tpm_version_info.h>
37 #include <tcg/tcg_pts_attr_tpm_version_info.h>
38 #include <tcg/tcg_pts_attr_get_aik.h>
39 #include <tcg/tcg_pts_attr_aik.h>
40 #include <tcg/tcg_pts_attr_req_funct_comp_evid.h>
41 #include <tcg/tcg_pts_attr_gen_attest_evid.h>
42 #include <tcg/tcg_pts_attr_simple_comp_evid.h>
43 #include <tcg/tcg_pts_attr_simple_evid_final.h>
44 #include <tcg/tcg_pts_attr_req_file_meas.h>
45 #include <tcg/tcg_pts_attr_file_meas.h>
46 #include <tcg/tcg_pts_attr_req_file_meta.h>
47 #include <tcg/tcg_pts_attr_unix_file_meta.h>
49 #include <tncif_pa_subtypes.h>
53 #include <credentials/credential_manager.h>
57 static const char imv_name
[] = "Attestation";
59 #define IMV_VENDOR_ID PEN_TCG
60 #define IMV_SUBTYPE PA_SUBTYPE_TCG_PTS
62 static imv_agent_t
*imv_attestation
;
65 * Supported PTS measurement algorithms
67 static pts_meas_algorithms_t supported_algorithms
= 0;
70 * PTS file measurement database
72 static pts_database_t
*pts_db
;
77 static pts_creds_t
*pts_creds
;
80 * PTS credential manager
82 static credential_manager_t
*pts_credmgr
;
85 * see section 3.7.1 of TCG TNC IF-IMV Specification 1.2
87 TNC_Result
TNC_IMV_Initialize(TNC_IMVID imv_id
,
88 TNC_Version min_version
,
89 TNC_Version max_version
,
90 TNC_Version
*actual_version
)
92 char *hash_alg
, *uri
, *cadir
;
96 DBG1(DBG_IMV
, "IMV \"%s\" has already been initialized", imv_name
);
97 return TNC_RESULT_ALREADY_INITIALIZED
;
99 if (!pts_meas_probe_algorithms(&supported_algorithms
))
101 return TNC_RESULT_FATAL
;
103 imv_attestation
= imv_agent_create(imv_name
, IMV_VENDOR_ID
, IMV_SUBTYPE
,
104 imv_id
, actual_version
);
105 if (!imv_attestation
)
107 return TNC_RESULT_FATAL
;
112 if (min_version
> TNC_IFIMV_VERSION_1
|| max_version
< TNC_IFIMV_VERSION_1
)
114 DBG1(DBG_IMV
, "no common IF-IMV version");
115 return TNC_RESULT_NO_COMMON_VERSION
;
119 * Specify supported PTS measurement algorithms
121 * sha1 : PTS_MEAS_ALGO_SHA1
122 * sha256: PTS_MEAS_ALGO_SHA1 | PTS_MEAS_ALGO_SHA256
123 * sha384: PTS_MEAS_ALGO_SHA1 | PTS_MEAS_ALGO_SHA256 | PTS_MEAS_ALGO_SHA384
125 * we expect the PTS-IMC to select the strongest supported algorithm
127 hash_alg
= lib
->settings
->get_str(lib
->settings
,
128 "libimcv.plugins.imv-attestation.hash_algorithm", "sha256");
129 if (!strcaseeq(hash_alg
, "sha384") && !strcaseeq(hash_alg
, "sha2_384"))
131 /* remove SHA384 algorithm */
132 supported_algorithms
&= ~PTS_MEAS_ALGO_SHA384
;
134 if (strcaseeq(hash_alg
, "sha1"))
136 /* remove SHA256 algorithm */
137 supported_algorithms
&= ~PTS_MEAS_ALGO_SHA256
;
140 /* create a PTS credential manager */
141 pts_credmgr
= credential_manager_create();
143 /* create PTS credential set */
144 cadir
= lib
->settings
->get_str(lib
->settings
,
145 "libimcv.plugins.imv-attestation.cadir", NULL
);
146 pts_creds
= pts_creds_create(cadir
);
149 pts_credmgr
->add_set(pts_credmgr
, pts_creds
->get_set(pts_creds
));
152 /* attach file measurement database */
153 uri
= lib
->settings
->get_str(lib
->settings
,
154 "libimcv.plugins.imv-attestation.database", NULL
);
155 pts_db
= pts_database_create(uri
);
157 return TNC_RESULT_SUCCESS
;
161 * see section 3.7.2 of TCG TNC IF-IMV Specification 1.2
163 TNC_Result
TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id
,
164 TNC_ConnectionID connection_id
,
165 TNC_ConnectionState new_state
)
168 imv_attestation_state_t
*attestation_state
;
171 if (!imv_attestation
)
173 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
174 return TNC_RESULT_NOT_INITIALIZED
;
178 case TNC_CONNECTION_STATE_CREATE
:
179 state
= imv_attestation_state_create(connection_id
);
180 return imv_attestation
->create_state(imv_attestation
, state
);
181 case TNC_CONNECTION_STATE_DELETE
:
182 return imv_attestation
->delete_state(imv_attestation
, connection_id
);
183 case TNC_CONNECTION_STATE_HANDSHAKE
:
184 result
= imv_attestation
->change_state(imv_attestation
, connection_id
,
186 if (result
!= TNC_RESULT_SUCCESS
)
190 attestation_state
= (imv_attestation_state_t
*)state
;
192 /* TODO: Get some configurations */
194 return TNC_RESULT_SUCCESS
;
196 return imv_attestation
->change_state(imv_attestation
, connection_id
,
201 static TNC_Result
send_message(TNC_ConnectionID connection_id
)
207 imv_attestation_state_t
*attestation_state
;
208 imv_attestation_handshake_state_t handshake_state
;
211 if (!imv_attestation
->get_state(imv_attestation
, connection_id
, &state
))
213 return TNC_RESULT_FATAL
;
215 attestation_state
= (imv_attestation_state_t
*)state
;
216 handshake_state
= attestation_state
->get_handshake_state(attestation_state
);
217 pts
= attestation_state
->get_pts(attestation_state
);
219 msg
= pa_tnc_msg_create();
222 /* Switch on the attribute type IMV has received */
223 switch (handshake_state
)
225 case IMV_ATTESTATION_STATE_INIT
:
227 pts_proto_caps_flag_t flags
;
229 /* Send Request Protocol Capabilities attribute */
230 flags
= pts
->get_proto_caps(pts
);
231 attr
= tcg_pts_attr_proto_caps_create(flags
, TRUE
);
232 attr
->set_noskip_flag(attr
, TRUE
);
233 msg
->add_attribute(msg
, attr
);
235 /* Send Measurement Algorithms attribute */
236 attr
= tcg_pts_attr_meas_algo_create(supported_algorithms
, FALSE
);
237 attr
->set_noskip_flag(attr
, TRUE
);
238 msg
->add_attribute(msg
, attr
);
240 attestation_state
->set_handshake_state(attestation_state
,
241 IMV_ATTESTATION_STATE_MEAS
);
245 case IMV_ATTESTATION_STATE_MEAS
:
247 enumerator_t
*enumerator
;
248 u_int32_t delimiter
= SOLIDUS_UTF
;
249 char *platform_info
, *pathname
;
250 u_int16_t request_id
;
254 attestation_state
->set_handshake_state(attestation_state
,
255 IMV_ATTESTATION_STATE_COMP_EVID
);
257 /* Does the PTS-IMC have TPM support? */
258 if (pts
->get_proto_caps(pts
) & PTS_PROTO_CAPS_T
)
260 /* Send Get TPM Version attribute */
261 attr
= tcg_pts_attr_get_tpm_version_info_create();
262 attr
->set_noskip_flag(attr
, TRUE
);
263 msg
->add_attribute(msg
, attr
);
265 /* Send Get AIK attribute */
266 attr
= tcg_pts_attr_get_aik_create();
267 attr
->set_noskip_flag(attr
, TRUE
);
268 msg
->add_attribute(msg
, attr
);
271 /* Get Platform and OS of the PTS-IMC */
272 platform_info
= pts
->get_platform_info(pts
);
274 if (!pts_db
|| !platform_info
)
276 DBG1(DBG_IMV
, "%s%s%s not available",
277 (pts_db
) ?
"" : "pts database",
278 (!pts_db
&& !platform_info
) ?
"and" : "",
279 (platform_info
) ?
"" : "platform info");
282 DBG1(DBG_IMV
, "platform is '%s'", platform_info
);
284 /* Send Request File Metadata attribute */
285 attr
= tcg_pts_attr_req_file_meta_create(FALSE
, SOLIDUS_UTF
, "/etc/tnc_config");
286 attr
->set_noskip_flag(attr
, TRUE
);
287 msg
->add_attribute(msg
, attr
);
289 /* Send Request File Measurement attribute */
290 enumerator
= pts_db
->create_file_enumerator(pts_db
, platform_info
);
295 while (enumerator
->enumerate(enumerator
, &id
, &type
, &pathname
))
297 is_dir
= (type
!= 0);
298 request_id
= attestation_state
->add_request(attestation_state
,
300 DBG2(DBG_IMV
, "measurement request %d for %s '%s'",
301 request_id
, is_dir ?
"directory" : "file", pathname
);
302 attr
= tcg_pts_attr_req_file_meas_create(is_dir
, request_id
,
303 delimiter
, pathname
);
304 attr
->set_noskip_flag(attr
, TRUE
);
305 msg
->add_attribute(msg
, attr
);
307 enumerator
->destroy(enumerator
);
310 case IMV_ATTESTATION_STATE_COMP_EVID
:
312 pts_attr_req_funct_comp_evid_flag_t flags
;
313 u_int32_t sub_comp_depth
;
314 pts_qualifier_t qualifier
;
315 pts_funct_comp_name_t name
;
317 attestation_state
->set_handshake_state(attestation_state
,
318 IMV_ATTESTATION_STATE_END
);
320 flags
= PTS_REQ_FUNC_COMP_FLAG_PCR
;
322 qualifier
.kernel
= FALSE
;
323 qualifier
.sub_component
= FALSE
;
324 qualifier
.type
= PTS_FUNC_COMP_TYPE_ALL
;
325 name
= PTS_FUNC_COMP_NAME_BIOS
;
327 /* Send Request Functional Component Evidence attribute */
328 attr
= tcg_pts_attr_req_funct_comp_evid_create(flags
, sub_comp_depth
,
329 PEN_TCG
, qualifier
, name
);
330 attr
->set_noskip_flag(attr
, TRUE
);
331 msg
->add_attribute(msg
, attr
);
332 /* Send Generate Attestation Evidence attribute */
333 attr
= tcg_pts_attr_gen_attest_evid_create();
334 attr
->set_noskip_flag(attr
, TRUE
);
335 msg
->add_attribute(msg
, attr
);
339 case IMV_ATTESTATION_STATE_IML
:
340 DBG1(DBG_IMV
, "Attestation IMV has nothing to send: \"%s\"",
342 return TNC_RESULT_FATAL
;
344 DBG1(DBG_IMV
, "Attestation IMV is in unknown state: \"%s\"",
346 return TNC_RESULT_FATAL
;
350 result
= imv_attestation
->send_message(imv_attestation
, connection_id
,
351 msg
->get_encoding(msg
));
358 * see section 3.7.3 of TCG TNC IF-IMV Specification 1.2
360 TNC_Result
TNC_IMV_ReceiveMessage(TNC_IMVID imv_id
,
361 TNC_ConnectionID connection_id
,
362 TNC_BufferReference msg
,
364 TNC_MessageType msg_type
)
366 pa_tnc_msg_t
*pa_tnc_msg
;
369 imv_attestation_state_t
*attestation_state
;
371 enumerator_t
*enumerator
;
373 bool fatal_error
= FALSE
;
374 bool measurement_error
= FALSE
;
376 if (!imv_attestation
)
378 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
379 return TNC_RESULT_NOT_INITIALIZED
;
382 /* get current IMV state */
383 if (!imv_attestation
->get_state(imv_attestation
, connection_id
, &state
))
385 return TNC_RESULT_FATAL
;
387 attestation_state
= (imv_attestation_state_t
*)state
;
388 pts
= attestation_state
->get_pts(attestation_state
);
390 /* parse received PA-TNC message and automatically handle any errors */
391 result
= imv_attestation
->receive_message(imv_attestation
, connection_id
,
392 chunk_create(msg
, msg_len
), msg_type
,
395 /* no parsed PA-TNC attributes available if an error occurred */
401 /* analyze PA-TNC attributes */
402 enumerator
= pa_tnc_msg
->create_attribute_enumerator(pa_tnc_msg
);
403 while (enumerator
->enumerate(enumerator
, &attr
))
405 if (attr
->get_vendor_id(attr
) == PEN_IETF
)
407 if (attr
->get_type(attr
) == IETF_ATTR_PA_TNC_ERROR
)
409 ietf_attr_pa_tnc_error_t
*error_attr
;
410 pen_t error_vendor_id
;
411 pa_tnc_error_code_t error_code
;
412 chunk_t msg_info
, attr_info
;
415 error_attr
= (ietf_attr_pa_tnc_error_t
*)attr
;
416 error_vendor_id
= error_attr
->get_vendor_id(error_attr
);
417 error_code
= error_attr
->get_error_code(error_attr
);
418 msg_info
= error_attr
->get_msg_info(error_attr
);
420 if (error_vendor_id
== PEN_IETF
)
422 DBG1(DBG_IMV
, "received PA-TNC error '%N' "
423 "concerning message %#B",
424 pa_tnc_error_code_names
, error_code
, &msg_info
);
428 case PA_ERROR_INVALID_PARAMETER
:
429 offset
= error_attr
->get_offset(error_attr
);
430 DBG1(DBG_IMV
, " occurred at offset of %u bytes",
433 case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED
:
434 attr_info
= error_attr
->get_attr_info(error_attr
);
435 DBG1(DBG_IMV
, " unsupported attribute %#B",
442 else if (error_vendor_id
== PEN_TCG
)
444 DBG1(DBG_IMV
, "received TCG-PTS error '%N'",
445 pts_error_code_names
, error_code
);
446 DBG1(DBG_IMV
, "error information: %B", &msg_info
);
450 else if (attr
->get_type(attr
) == IETF_ATTR_PRODUCT_INFORMATION
)
452 ietf_attr_product_info_t
*attr_cast
;
455 attr_cast
= (ietf_attr_product_info_t
*)attr
;
456 platform_info
= attr_cast
->get_info(attr_cast
, NULL
, NULL
);
457 pts
->set_platform_info(pts
, platform_info
);
460 else if (attr
->get_vendor_id(attr
) == PEN_TCG
)
462 switch (attr
->get_type(attr
))
464 case TCG_PTS_PROTO_CAPS
:
466 tcg_pts_attr_proto_caps_t
*attr_cast
;
467 pts_proto_caps_flag_t flags
;
469 attr_cast
= (tcg_pts_attr_proto_caps_t
*)attr
;
470 flags
= attr_cast
->get_flags(attr_cast
);
471 pts
->set_proto_caps(pts
, flags
);
474 case TCG_PTS_MEAS_ALGO_SELECTION
:
476 tcg_pts_attr_meas_algo_t
*attr_cast
;
477 pts_meas_algorithms_t selected_algorithm
;
479 attr_cast
= (tcg_pts_attr_meas_algo_t
*)attr
;
480 selected_algorithm
= attr_cast
->get_algorithms(attr_cast
);
481 pts
->set_meas_algorithm(pts
, selected_algorithm
);
484 case TCG_PTS_TPM_VERSION_INFO
:
486 tcg_pts_attr_tpm_version_info_t
*attr_cast
;
487 chunk_t tpm_version_info
;
489 attr_cast
= (tcg_pts_attr_tpm_version_info_t
*)attr
;
490 tpm_version_info
= attr_cast
->get_tpm_version_info(attr_cast
);
491 pts
->set_tpm_version_info(pts
, tpm_version_info
);
496 tcg_pts_attr_aik_t
*attr_cast
;
497 certificate_t
*aik
, *issuer
;
499 bool trusted
= FALSE
;
501 attr_cast
= (tcg_pts_attr_aik_t
*)attr
;
502 aik
= attr_cast
->get_aik(attr_cast
);
505 /* TODO generate error attribute */
508 if (aik
->get_type(aik
) == CERT_X509
)
510 DBG1(DBG_IMV
, "verifying AIK certificate");
511 e
= pts_credmgr
->create_trusted_enumerator(pts_credmgr
,
512 KEY_ANY
, aik
->get_issuer(aik
), FALSE
);
513 while (e
->enumerate(e
, &issuer
))
515 if (aik
->issued_by(aik
, issuer
))
522 DBG1(DBG_IMV
, "AIK certificate is %strusted",
523 trusted ?
"" : "not ");
525 pts
->set_aik(pts
, aik
);
529 /* PTS-based Attestation Evidence */
530 case TCG_PTS_SIMPLE_COMP_EVID
:
532 /** TODO: Implement saving the PCR number, Hash Algo = communicated one,
533 * PCR transform (truncate SHA256, SHA384), PCR before and after values
538 case TCG_PTS_SIMPLE_EVID_FINAL
:
540 /** TODO: Implement construct Quote structure over saved values from
541 * TCG_PTS_SIMPLE_COMP_EVID and compare with received one
546 case TCG_PTS_FILE_MEAS
:
548 tcg_pts_attr_file_meas_t
*attr_cast
;
549 u_int16_t request_id
;
550 int file_count
, file_id
;
551 pts_meas_algorithms_t algo
;
552 pts_file_meas_t
*measurements
;
554 enumerator_t
*e_hash
;
557 platform_info
= pts
->get_platform_info(pts
);
558 if (!pts_db
|| !platform_info
)
563 attr_cast
= (tcg_pts_attr_file_meas_t
*)attr
;
564 measurements
= attr_cast
->get_measurements(attr_cast
);
565 algo
= pts
->get_meas_algorithm(pts
);
566 request_id
= measurements
->get_request_id(measurements
);
567 file_count
= measurements
->get_file_count(measurements
);
569 DBG1(DBG_IMV
, "measurement request %d returned %d file%s:",
570 request_id
, file_count
, (file_count
== 1) ?
"":"s");
572 if (!attestation_state
->check_off_request(attestation_state
,
573 request_id
, &file_id
, &is_dir
))
575 DBG1(DBG_IMV
, " no entry found for this request");
579 /* check hashes from database against measurements */
580 e_hash
= pts_db
->create_hash_enumerator(pts_db
,
581 platform_info
, algo
, file_id
, is_dir
);
582 if (!measurements
->verify(measurements
, e_hash
, is_dir
))
584 measurement_error
= TRUE
;
586 e_hash
->destroy(e_hash
);
589 case TCG_PTS_UNIX_FILE_META
:
591 tcg_pts_attr_file_meta_t
*attr_cast
;
593 pts_file_meta_t
*metadata
;
595 pts_file_metadata_t
*entry
;
597 attr_cast
= (tcg_pts_attr_file_meta_t
*)attr
;
598 metadata
= attr_cast
->get_metadata(attr_cast
);
599 file_count
= metadata
->get_file_count(metadata
);
601 DBG1(DBG_IMV
, "metadata request returned %d file%s:",
602 file_count
, (file_count
== 1) ?
"":"s");
604 e
= metadata
->create_enumerator(metadata
);
605 while(e
->enumerate(e
, &entry
))
607 DBG1(DBG_IMV
, "File name: %s", entry
->filename
);
608 DBG1(DBG_IMV
, " type: %d", entry
->type
);
609 DBG1(DBG_IMV
, " size: %d", entry
->filesize
);
610 DBG1(DBG_IMV
, " create time: %s", ctime(&entry
->create_time
));
611 DBG1(DBG_IMV
, " last modified: %s", ctime(&entry
->last_modify_time
));
612 DBG1(DBG_IMV
, " last accessed: %s", ctime(&entry
->last_access_time
));
613 DBG1(DBG_IMV
, " owner id: %d", entry
->owner_id
);
614 DBG1(DBG_IMV
, " group id: %d", entry
->group_id
);
622 /* TODO: Not implemented yet */
623 case TCG_PTS_DH_NONCE_PARAMS_RESP
:
624 case TCG_PTS_INTEG_MEAS_LOG
:
625 /* Attributes using XML */
626 case TCG_PTS_TEMPL_REF_MANI_SET_META
:
627 case TCG_PTS_VERIFICATION_RESULT
:
628 case TCG_PTS_INTEG_REPORT
:
630 case TCG_PTS_WIN_FILE_META
:
631 case TCG_PTS_REGISTRY_VALUE
:
632 /* Received on IMC side only*/
633 case TCG_PTS_REQ_PROTO_CAPS
:
634 case TCG_PTS_DH_NONCE_PARAMS_REQ
:
635 case TCG_PTS_DH_NONCE_FINISH
:
636 case TCG_PTS_MEAS_ALGO
:
637 case TCG_PTS_GET_TPM_VERSION_INFO
:
638 case TCG_PTS_REQ_TEMPL_REF_MANI_SET_META
:
639 case TCG_PTS_UPDATE_TEMPL_REF_MANI
:
640 case TCG_PTS_GET_AIK
:
641 case TCG_PTS_REQ_FUNCT_COMP_EVID
:
642 case TCG_PTS_GEN_ATTEST_EVID
:
643 case TCG_PTS_REQ_FILE_META
:
644 case TCG_PTS_REQ_FILE_MEAS
:
645 case TCG_PTS_REQ_INTEG_MEAS_LOG
:
647 DBG1(DBG_IMV
, "received unsupported attribute '%N'",
648 tcg_attr_names
, attr
->get_type(attr
));
653 enumerator
->destroy(enumerator
);
654 pa_tnc_msg
->destroy(pa_tnc_msg
);
659 state
->set_recommendation(state
,
660 TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION
,
661 TNC_IMV_EVALUATION_RESULT_ERROR
);
662 return imv_attestation
->provide_recommendation(imv_attestation
,
666 if (attestation_state
->get_handshake_state(attestation_state
) &
667 IMV_ATTESTATION_STATE_END
)
669 if (attestation_state
->get_request_count(attestation_state
))
671 DBG1(DBG_IMV
, "failure due to %d pending file measurements",
672 attestation_state
->get_request_count(attestation_state
));
673 measurement_error
= TRUE
;
675 if (measurement_error
)
677 state
->set_recommendation(state
,
678 TNC_IMV_ACTION_RECOMMENDATION_ISOLATE
,
679 TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR
);
683 state
->set_recommendation(state
,
684 TNC_IMV_ACTION_RECOMMENDATION_ALLOW
,
685 TNC_IMV_EVALUATION_RESULT_COMPLIANT
);
687 return imv_attestation
->provide_recommendation(imv_attestation
,
691 return send_message(connection_id
);
695 * see section 3.7.4 of TCG TNC IF-IMV Specification 1.2
697 TNC_Result
TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id
,
698 TNC_ConnectionID connection_id
)
700 if (!imv_attestation
)
702 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
703 return TNC_RESULT_NOT_INITIALIZED
;
705 return imv_attestation
->provide_recommendation(imv_attestation
, connection_id
);
709 * see section 3.7.5 of TCG TNC IF-IMV Specification 1.2
711 TNC_Result
TNC_IMV_BatchEnding(TNC_IMVID imv_id
,
712 TNC_ConnectionID connection_id
)
715 imv_attestation_state_t
*attestation_state
;
717 if (!imv_attestation
)
719 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
720 return TNC_RESULT_NOT_INITIALIZED
;
722 /* get current IMV state */
723 if (!imv_attestation
->get_state(imv_attestation
, connection_id
, &state
))
725 return TNC_RESULT_FATAL
;
727 attestation_state
= (imv_attestation_state_t
*)state
;
729 /* Check if IMV has to initiate the PA-TNC exchange */
730 if (attestation_state
->get_handshake_state(attestation_state
) ==
731 IMV_ATTESTATION_STATE_INIT
)
733 return send_message(connection_id
);
735 return TNC_RESULT_SUCCESS
;
739 * see section 3.7.6 of TCG TNC IF-IMV Specification 1.2
741 TNC_Result
TNC_IMV_Terminate(TNC_IMVID imv_id
)
743 if (!imv_attestation
)
745 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
746 return TNC_RESULT_NOT_INITIALIZED
;
750 pts_credmgr
->remove_set(pts_credmgr
, pts_creds
->get_set(pts_creds
));
751 pts_creds
->destroy(pts_creds
);
754 DESTROY_IF(pts_credmgr
);
758 imv_attestation
->destroy(imv_attestation
);
759 imv_attestation
= NULL
;
761 return TNC_RESULT_SUCCESS
;
765 * see section 4.2.8.1 of TCG TNC IF-IMV Specification 1.2
767 TNC_Result
TNC_IMV_ProvideBindFunction(TNC_IMVID imv_id
,
768 TNC_TNCS_BindFunctionPointer bind_function
)
770 if (!imv_attestation
)
772 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
773 return TNC_RESULT_NOT_INITIALIZED
;
775 return imv_attestation
->bind_functions(imv_attestation
, bind_function
);