Implemented Diffie Hellman Nonce attributes
[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_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>
48
49 #include <tncif_pa_subtypes.h>
50
51 #include <pen/pen.h>
52 #include <debug.h>
53 #include <credentials/credential_manager.h>
54
55 /* IMV definitions */
56
57 static const char imv_name[] = "Attestation";
58
59 #define IMV_VENDOR_ID PEN_TCG
60 #define IMV_SUBTYPE PA_SUBTYPE_TCG_PTS
61
62 static imv_agent_t *imv_attestation;
63
64 /**
65 * Supported PTS measurement algorithms
66 */
67 static pts_meas_algorithms_t supported_algorithms = 0;
68
69 /**
70 * PTS file measurement database
71 */
72 static pts_database_t *pts_db;
73
74 /**
75 * PTS credentials
76 */
77 static pts_creds_t *pts_creds;
78
79 /**
80 * PTS credential manager
81 */
82 static credential_manager_t *pts_credmgr;
83
84 /**
85 * see section 3.7.1 of TCG TNC IF-IMV Specification 1.2
86 */
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)
91 {
92 char *hash_alg, *uri, *cadir;
93
94 if (imv_attestation)
95 {
96 DBG1(DBG_IMV, "IMV \"%s\" has already been initialized", imv_name);
97 return TNC_RESULT_ALREADY_INITIALIZED;
98 }
99 if (!pts_meas_probe_algorithms(&supported_algorithms))
100 {
101 return TNC_RESULT_FATAL;
102 }
103 imv_attestation = imv_agent_create(imv_name, IMV_VENDOR_ID, IMV_SUBTYPE,
104 imv_id, actual_version);
105 if (!imv_attestation)
106 {
107 return TNC_RESULT_FATAL;
108 }
109
110 libpts_init();
111
112 if (min_version > TNC_IFIMV_VERSION_1 || max_version < TNC_IFIMV_VERSION_1)
113 {
114 DBG1(DBG_IMV, "no common IF-IMV version");
115 return TNC_RESULT_NO_COMMON_VERSION;
116 }
117
118 /**
119 * Specify supported PTS measurement algorithms
120 *
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
124 *
125 * we expect the PTS-IMC to select the strongest supported algorithm
126 */
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"))
130 {
131 /* remove SHA384 algorithm */
132 supported_algorithms &= ~PTS_MEAS_ALGO_SHA384;
133 }
134 if (strcaseeq(hash_alg, "sha1"))
135 {
136 /* remove SHA256 algorithm */
137 supported_algorithms &= ~PTS_MEAS_ALGO_SHA256;
138 }
139
140 /* create a PTS credential manager */
141 pts_credmgr = credential_manager_create();
142
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);
147 if (pts_creds)
148 {
149 pts_credmgr->add_set(pts_credmgr, pts_creds->get_set(pts_creds));
150 }
151
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);
156
157 return TNC_RESULT_SUCCESS;
158 }
159
160 /**
161 * see section 3.7.2 of TCG TNC IF-IMV Specification 1.2
162 */
163 TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
164 TNC_ConnectionID connection_id,
165 TNC_ConnectionState new_state)
166 {
167 imv_state_t *state;
168 imv_attestation_state_t *attestation_state;
169 TNC_Result result;
170
171 if (!imv_attestation)
172 {
173 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
174 return TNC_RESULT_NOT_INITIALIZED;
175 }
176 switch (new_state)
177 {
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,
185 new_state, &state);
186 if (result != TNC_RESULT_SUCCESS)
187 {
188 return result;
189 }
190 attestation_state = (imv_attestation_state_t*)state;
191
192 /* TODO: Get some configurations */
193
194 return TNC_RESULT_SUCCESS;
195 default:
196 return imv_attestation->change_state(imv_attestation, connection_id,
197 new_state, NULL);
198 }
199 }
200
201 static TNC_Result send_message(TNC_ConnectionID connection_id)
202 {
203 pa_tnc_msg_t *msg;
204 pa_tnc_attr_t *attr;
205 pts_t *pts;
206 imv_state_t *state;
207 imv_attestation_state_t *attestation_state;
208 imv_attestation_handshake_state_t handshake_state;
209 TNC_Result result;
210
211 if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
212 {
213 return TNC_RESULT_FATAL;
214 }
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);
218
219 msg = pa_tnc_msg_create();
220
221
222 /* Switch on the attribute type IMV has received */
223 switch (handshake_state)
224 {
225 case IMV_ATTESTATION_STATE_INIT:
226 {
227 pts_proto_caps_flag_t flags;
228
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);
234
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);
239
240 attestation_state->set_handshake_state(attestation_state,
241 IMV_ATTESTATION_STATE_MEAS);
242 break;
243 }
244
245 case IMV_ATTESTATION_STATE_MEAS:
246 {
247 enumerator_t *enumerator;
248 u_int32_t delimiter = SOLIDUS_UTF;
249 char *platform_info, *pathname;
250 u_int16_t request_id;
251 int id, type;
252 bool is_dir;
253
254 attestation_state->set_handshake_state(attestation_state,
255 IMV_ATTESTATION_STATE_COMP_EVID);
256
257 /* Does the PTS-IMC have TPM support? */
258 if (pts->get_proto_caps(pts) & PTS_PROTO_CAPS_T)
259 {
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);
264
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);
269 }
270
271 /* Get Platform and OS of the PTS-IMC */
272 platform_info = pts->get_platform_info(pts);
273
274 if (!pts_db || !platform_info)
275 {
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");
280 break;
281 }
282 DBG1(DBG_IMV, "platform is '%s'", platform_info);
283
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);
288
289 /* Send Request File Measurement attribute */
290 enumerator = pts_db->create_file_enumerator(pts_db, platform_info);
291 if (!enumerator)
292 {
293 break;
294 }
295 while (enumerator->enumerate(enumerator, &id, &type, &pathname))
296 {
297 is_dir = (type != 0);
298 request_id = attestation_state->add_request(attestation_state,
299 id, is_dir);
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);
306 }
307 enumerator->destroy(enumerator);
308 break;
309 }
310 case IMV_ATTESTATION_STATE_COMP_EVID:
311 {
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;
316
317 attestation_state->set_handshake_state(attestation_state,
318 IMV_ATTESTATION_STATE_END);
319
320 flags = PTS_REQ_FUNC_COMP_FLAG_PCR;
321 sub_comp_depth = 1;
322 qualifier.kernel = FALSE;
323 qualifier.sub_component = FALSE;
324 qualifier.type = PTS_FUNC_COMP_TYPE_ALL;
325 name = PTS_FUNC_COMP_NAME_BIOS;
326
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);
336
337 break;
338 }
339 case IMV_ATTESTATION_STATE_IML:
340 DBG1(DBG_IMV, "Attestation IMV has nothing to send: \"%s\"",
341 handshake_state);
342 return TNC_RESULT_FATAL;
343 default:
344 DBG1(DBG_IMV, "Attestation IMV is in unknown state: \"%s\"",
345 handshake_state);
346 return TNC_RESULT_FATAL;
347 }
348
349 msg->build(msg);
350 result = imv_attestation->send_message(imv_attestation, connection_id,
351 msg->get_encoding(msg));
352 msg->destroy(msg);
353
354 return result;
355 }
356
357 /**
358 * see section 3.7.3 of TCG TNC IF-IMV Specification 1.2
359 */
360 TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
361 TNC_ConnectionID connection_id,
362 TNC_BufferReference msg,
363 TNC_UInt32 msg_len,
364 TNC_MessageType msg_type)
365 {
366 pa_tnc_msg_t *pa_tnc_msg;
367 pa_tnc_attr_t *attr;
368 imv_state_t *state;
369 imv_attestation_state_t *attestation_state;
370 pts_t *pts;
371 enumerator_t *enumerator;
372 TNC_Result result;
373 bool fatal_error = FALSE;
374 bool measurement_error = FALSE;
375
376 if (!imv_attestation)
377 {
378 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
379 return TNC_RESULT_NOT_INITIALIZED;
380 }
381
382 /* get current IMV state */
383 if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
384 {
385 return TNC_RESULT_FATAL;
386 }
387 attestation_state = (imv_attestation_state_t*)state;
388 pts = attestation_state->get_pts(attestation_state);
389
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,
393 &pa_tnc_msg);
394
395 /* no parsed PA-TNC attributes available if an error occurred */
396 if (!pa_tnc_msg)
397 {
398 return result;
399 }
400
401 /* analyze PA-TNC attributes */
402 enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
403 while (enumerator->enumerate(enumerator, &attr))
404 {
405 if (attr->get_vendor_id(attr) == PEN_IETF)
406 {
407 if (attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR)
408 {
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;
413 u_int32_t offset;
414
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);
419
420 if (error_vendor_id == PEN_IETF)
421 {
422 DBG1(DBG_IMV, "received PA-TNC error '%N' "
423 "concerning message %#B",
424 pa_tnc_error_code_names, error_code, &msg_info);
425
426 switch (error_code)
427 {
428 case PA_ERROR_INVALID_PARAMETER:
429 offset = error_attr->get_offset(error_attr);
430 DBG1(DBG_IMV, " occurred at offset of %u bytes",
431 offset);
432 break;
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",
436 &attr_info);
437 break;
438 default:
439 break;
440 }
441 }
442 else if (error_vendor_id == PEN_TCG)
443 {
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);
447 }
448 fatal_error = TRUE;
449 }
450 else if (attr->get_type(attr) == IETF_ATTR_PRODUCT_INFORMATION)
451 {
452 ietf_attr_product_info_t *attr_cast;
453 char *platform_info;
454
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);
458 }
459 }
460 else if (attr->get_vendor_id(attr) == PEN_TCG)
461 {
462 switch (attr->get_type(attr))
463 {
464 case TCG_PTS_PROTO_CAPS:
465 {
466 tcg_pts_attr_proto_caps_t *attr_cast;
467 pts_proto_caps_flag_t flags;
468
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);
472 break;
473 }
474 case TCG_PTS_MEAS_ALGO_SELECTION:
475 {
476 tcg_pts_attr_meas_algo_t *attr_cast;
477 pts_meas_algorithms_t selected_algorithm;
478
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);
482 break;
483 }
484 case TCG_PTS_TPM_VERSION_INFO:
485 {
486 tcg_pts_attr_tpm_version_info_t *attr_cast;
487 chunk_t tpm_version_info;
488
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);
492 break;
493 }
494 case TCG_PTS_AIK:
495 {
496 tcg_pts_attr_aik_t *attr_cast;
497 certificate_t *aik, *issuer;
498 enumerator_t *e;
499 bool trusted = FALSE;
500
501 attr_cast = (tcg_pts_attr_aik_t*)attr;
502 aik = attr_cast->get_aik(attr_cast);
503 if (!aik)
504 {
505 /* TODO generate error attribute */
506 break;
507 }
508 if (aik->get_type(aik) == CERT_X509)
509 {
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))
514 {
515 if (aik->issued_by(aik, issuer))
516 {
517 trusted = TRUE;
518 break;
519 }
520 }
521 e->destroy(e);
522 DBG1(DBG_IMV, "AIK certificate is %strusted",
523 trusted ? "" : "not ");
524 }
525 pts->set_aik(pts, aik);
526 break;
527 }
528
529 /* PTS-based Attestation Evidence */
530 case TCG_PTS_SIMPLE_COMP_EVID:
531 {
532 /** TODO: Implement saving the PCR number, Hash Algo = communicated one,
533 * PCR transform (truncate SHA256, SHA384), PCR before and after values
534 */
535 break;
536 }
537
538 case TCG_PTS_SIMPLE_EVID_FINAL:
539 {
540 /** TODO: Implement construct Quote structure over saved values from
541 * TCG_PTS_SIMPLE_COMP_EVID and compare with received one
542 */
543 break;
544 }
545
546 case TCG_PTS_FILE_MEAS:
547 {
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;
553 char *platform_info;
554 enumerator_t *e_hash;
555 bool is_dir;
556
557 platform_info = pts->get_platform_info(pts);
558 if (!pts_db || !platform_info)
559 {
560 break;
561 }
562
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);
568
569 DBG1(DBG_IMV, "measurement request %d returned %d file%s:",
570 request_id, file_count, (file_count == 1) ? "":"s");
571
572 if (!attestation_state->check_off_request(attestation_state,
573 request_id, &file_id, &is_dir))
574 {
575 DBG1(DBG_IMV, " no entry found for this request");
576 break;
577 }
578
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))
583 {
584 measurement_error = TRUE;
585 }
586 e_hash->destroy(e_hash);
587 break;
588 }
589 case TCG_PTS_UNIX_FILE_META:
590 {
591 tcg_pts_attr_file_meta_t *attr_cast;
592 int file_count;
593 pts_file_meta_t *metadata;
594 enumerator_t *e;
595 pts_file_metadata_t *entry;
596
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);
600
601 DBG1(DBG_IMV, "metadata request returned %d file%s:",
602 file_count, (file_count == 1) ? "":"s");
603
604 e = metadata->create_enumerator(metadata);
605 while(e->enumerate(e, &entry))
606 {
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);
615 }
616
617 e->destroy(e);
618
619 break;
620 }
621
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:
629 /* On Windows only*/
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:
646 default:
647 DBG1(DBG_IMV, "received unsupported attribute '%N'",
648 tcg_attr_names, attr->get_type(attr));
649 break;
650 }
651 }
652 }
653 enumerator->destroy(enumerator);
654 pa_tnc_msg->destroy(pa_tnc_msg);
655
656
657 if (fatal_error)
658 {
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,
663 connection_id);
664 }
665
666 if (attestation_state->get_handshake_state(attestation_state) &
667 IMV_ATTESTATION_STATE_END)
668 {
669 if (attestation_state->get_request_count(attestation_state))
670 {
671 DBG1(DBG_IMV, "failure due to %d pending file measurements",
672 attestation_state->get_request_count(attestation_state));
673 measurement_error = TRUE;
674 }
675 if (measurement_error)
676 {
677 state->set_recommendation(state,
678 TNC_IMV_ACTION_RECOMMENDATION_ISOLATE,
679 TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR);
680 }
681 else
682 {
683 state->set_recommendation(state,
684 TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
685 TNC_IMV_EVALUATION_RESULT_COMPLIANT);
686 }
687 return imv_attestation->provide_recommendation(imv_attestation,
688 connection_id);
689 }
690
691 return send_message(connection_id);
692 }
693
694 /**
695 * see section 3.7.4 of TCG TNC IF-IMV Specification 1.2
696 */
697 TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
698 TNC_ConnectionID connection_id)
699 {
700 if (!imv_attestation)
701 {
702 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
703 return TNC_RESULT_NOT_INITIALIZED;
704 }
705 return imv_attestation->provide_recommendation(imv_attestation, connection_id);
706 }
707
708 /**
709 * see section 3.7.5 of TCG TNC IF-IMV Specification 1.2
710 */
711 TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id,
712 TNC_ConnectionID connection_id)
713 {
714 imv_state_t *state;
715 imv_attestation_state_t *attestation_state;
716
717 if (!imv_attestation)
718 {
719 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
720 return TNC_RESULT_NOT_INITIALIZED;
721 }
722 /* get current IMV state */
723 if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
724 {
725 return TNC_RESULT_FATAL;
726 }
727 attestation_state = (imv_attestation_state_t*)state;
728
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)
732 {
733 return send_message(connection_id);
734 }
735 return TNC_RESULT_SUCCESS;
736 }
737
738 /**
739 * see section 3.7.6 of TCG TNC IF-IMV Specification 1.2
740 */
741 TNC_Result TNC_IMV_Terminate(TNC_IMVID imv_id)
742 {
743 if (!imv_attestation)
744 {
745 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
746 return TNC_RESULT_NOT_INITIALIZED;
747 }
748 if (pts_creds)
749 {
750 pts_credmgr->remove_set(pts_credmgr, pts_creds->get_set(pts_creds));
751 pts_creds->destroy(pts_creds);
752 }
753 DESTROY_IF(pts_db);
754 DESTROY_IF(pts_credmgr);
755
756 libpts_deinit();
757
758 imv_attestation->destroy(imv_attestation);
759 imv_attestation = NULL;
760
761 return TNC_RESULT_SUCCESS;
762 }
763
764 /**
765 * see section 4.2.8.1 of TCG TNC IF-IMV Specification 1.2
766 */
767 TNC_Result TNC_IMV_ProvideBindFunction(TNC_IMVID imv_id,
768 TNC_TNCS_BindFunctionPointer bind_function)
769 {
770 if (!imv_attestation)
771 {
772 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
773 return TNC_RESULT_NOT_INITIALIZED;
774 }
775 return imv_attestation->bind_functions(imv_attestation, bind_function);
776 }