Replaced DH_NONCE state with TPM_INIT state
[strongswan.git] / src / libimcv / plugins / imc_attestation / imc_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 "imc_attestation_state.h"
17
18 #include <imc/imc_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_error.h>
27
28 #include <tcg/tcg_pts_attr_proto_caps.h>
29 #include <tcg/tcg_pts_attr_dh_nonce_params_req.h>
30 #include <tcg/tcg_pts_attr_dh_nonce_params_resp.h>
31 #include <tcg/tcg_pts_attr_dh_nonce_finish.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 #include <tcg/tcg_pts_attr_req_file_meta.h>
44 #include <tcg/tcg_pts_attr_unix_file_meta.h>
45
46 #include <tncif_pa_subtypes.h>
47
48 #include <pen/pen.h>
49 #include <debug.h>
50 #include <utils/linked_list.h>
51
52 /* IMC definitions */
53
54 static const char imc_name[] = "Attestation";
55
56 #define IMC_VENDOR_ID PEN_TCG
57 #define IMC_SUBTYPE PA_SUBTYPE_TCG_PTS
58
59 static imc_agent_t *imc_attestation;
60
61 /**
62 * Supported PTS measurement algorithms
63 */
64 static pts_meas_algorithms_t supported_algorithms = 0;
65
66 /**
67 * Supported PTS Diffie Hellman Groups
68 */
69 static pts_dh_group_t supported_dh_groups = 0;
70
71 /**
72 * see section 3.7.1 of TCG TNC IF-IMC Specification 1.2
73 */
74 TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id,
75 TNC_Version min_version,
76 TNC_Version max_version,
77 TNC_Version *actual_version)
78 {
79 if (imc_attestation)
80 {
81 DBG1(DBG_IMC, "IMC \"%s\" has already been initialized", imc_name);
82 return TNC_RESULT_ALREADY_INITIALIZED;
83 }
84 if (!pts_meas_probe_algorithms(&supported_algorithms))
85 {
86 return TNC_RESULT_FATAL;
87 }
88 if (!pts_probe_dh_groups(&supported_dh_groups))
89 {
90 return TNC_RESULT_FATAL;
91 }
92 imc_attestation = imc_agent_create(imc_name, IMC_VENDOR_ID, IMC_SUBTYPE,
93 imc_id, actual_version);
94 if (!imc_attestation)
95 {
96 return TNC_RESULT_FATAL;
97 }
98
99 libpts_init();
100
101 if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1)
102 {
103 DBG1(DBG_IMC, "no common IF-IMC version");
104 return TNC_RESULT_NO_COMMON_VERSION;
105 }
106 return TNC_RESULT_SUCCESS;
107 }
108
109 /**
110 * see section 3.7.2 of TCG TNC IF-IMC Specification 1.2
111 */
112 TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
113 TNC_ConnectionID connection_id,
114 TNC_ConnectionState new_state)
115 {
116 imc_state_t *state;
117 /* TODO: Not used so far */
118 //imc_attestation_state_t *attestation_state;
119
120 if (!imc_attestation)
121 {
122 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
123 return TNC_RESULT_NOT_INITIALIZED;
124 }
125 switch (new_state)
126 {
127 case TNC_CONNECTION_STATE_CREATE:
128 state = imc_attestation_state_create(connection_id);
129 return imc_attestation->create_state(imc_attestation, state);
130 case TNC_CONNECTION_STATE_DELETE:
131 return imc_attestation->delete_state(imc_attestation, connection_id);
132 case TNC_CONNECTION_STATE_HANDSHAKE:
133 case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
134 case TNC_CONNECTION_STATE_ACCESS_NONE:
135 default:
136 return imc_attestation->change_state(imc_attestation, connection_id,
137 new_state, NULL);
138 }
139 }
140
141
142 /**
143 * see section 3.7.3 of TCG TNC IF-IMC Specification 1.2
144 */
145 TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
146 TNC_ConnectionID connection_id)
147 {
148 imc_state_t *state;
149 imc_attestation_state_t *attestation_state;
150 pts_t *pts;
151 char *platform_info;
152 TNC_Result result = TNC_RESULT_SUCCESS;
153
154 if (!imc_attestation)
155 {
156 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
157 return TNC_RESULT_NOT_INITIALIZED;
158 }
159
160 /* get current IMC state */
161 if (!imc_attestation->get_state(imc_attestation, connection_id, &state))
162 {
163 return TNC_RESULT_FATAL;
164 }
165 attestation_state = (imc_attestation_state_t*)state;
166 pts = attestation_state->get_pts(attestation_state);
167
168 platform_info = pts->get_platform_info(pts);
169 if (platform_info)
170 {
171 pa_tnc_msg_t *pa_tnc_msg;
172 pa_tnc_attr_t *attr;
173
174 pa_tnc_msg = pa_tnc_msg_create();
175 attr = ietf_attr_product_info_create(0, 0, platform_info);
176 pa_tnc_msg->add_attribute(pa_tnc_msg, attr);
177 pa_tnc_msg->build(pa_tnc_msg);
178 result = imc_attestation->send_message(imc_attestation, connection_id,
179 pa_tnc_msg->get_encoding(pa_tnc_msg));
180 pa_tnc_msg->destroy(pa_tnc_msg);
181 }
182
183 return result;
184 }
185
186 /**
187 * see section 3.7.4 of TCG TNC IF-IMC Specification 1.2
188 */
189 TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
190 TNC_ConnectionID connection_id,
191 TNC_BufferReference msg,
192 TNC_UInt32 msg_len,
193 TNC_MessageType msg_type)
194 {
195 pa_tnc_msg_t *pa_tnc_msg;
196 pa_tnc_attr_t *attr;
197 linked_list_t *attr_list;
198 imc_state_t *state;
199 imc_attestation_state_t *attestation_state;
200 enumerator_t *enumerator;
201 pts_t *pts;
202 TNC_Result result;
203 bool fatal_error = FALSE;
204 chunk_t attr_info;
205 pts_error_code_t pts_error;
206 bool valid_path;
207
208 if (!imc_attestation)
209 {
210 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
211 return TNC_RESULT_NOT_INITIALIZED;
212 }
213
214 /* get current IMC state */
215 if (!imc_attestation->get_state(imc_attestation, connection_id, &state))
216 {
217 return TNC_RESULT_FATAL;
218 }
219 attestation_state = (imc_attestation_state_t*)state;
220 pts = attestation_state->get_pts(attestation_state);
221
222 /* parse received PA-TNC message and automatically handle any errors */
223 result = imc_attestation->receive_message(imc_attestation, connection_id,
224 chunk_create(msg, msg_len), msg_type,
225 &pa_tnc_msg);
226
227 /* no parsed PA-TNC attributes available if an error occurred */
228 if (!pa_tnc_msg)
229 {
230 return result;
231 }
232
233 attr_list = linked_list_create();
234
235 /* analyze PA-TNC attributes */
236 enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
237 while (enumerator->enumerate(enumerator, &attr))
238 {
239 if (attr->get_vendor_id(attr) == PEN_IETF &&
240 attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR)
241 {
242 ietf_attr_pa_tnc_error_t *error_attr;
243 pa_tnc_error_code_t error_code;
244 chunk_t msg_info, attr_info;
245 u_int32_t offset;
246
247 error_attr = (ietf_attr_pa_tnc_error_t*)attr;
248 error_code = error_attr->get_error_code(error_attr);
249 msg_info = error_attr->get_msg_info(error_attr);
250
251 DBG1(DBG_IMC, "received PA-TNC error '%N' concerning message %#B",
252 pa_tnc_error_code_names, error_code, &msg_info);
253 switch (error_code)
254 {
255 case PA_ERROR_INVALID_PARAMETER:
256 offset = error_attr->get_offset(error_attr);
257 DBG1(DBG_IMC, " occurred at offset of %u bytes", offset);
258 break;
259 case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
260 attr_info = error_attr->get_attr_info(error_attr);
261 DBG1(DBG_IMC, " unsupported attribute %#B", &attr_info);
262 break;
263 default:
264 break;
265 }
266 fatal_error = TRUE;
267 }
268 else if (attr->get_vendor_id(attr) == PEN_TCG)
269 {
270 switch (attr->get_type(attr))
271 {
272 case TCG_PTS_REQ_PROTO_CAPS:
273 {
274 tcg_pts_attr_proto_caps_t *attr_cast;
275 pts_proto_caps_flag_t imc_caps, imv_caps;
276
277 attr_cast = (tcg_pts_attr_proto_caps_t*)attr;
278 imv_caps = attr_cast->get_flags(attr_cast);
279 imc_caps = pts->get_proto_caps(pts);
280 pts->set_proto_caps(pts, imc_caps & imv_caps);
281
282 /* Send PTS Protocol Capabilities attribute */
283 attr = tcg_pts_attr_proto_caps_create(imc_caps & imv_caps,
284 FALSE);
285 attr_list->insert_last(attr_list, attr);
286 break;
287 }
288 case TCG_PTS_DH_NONCE_PARAMS_REQ:
289 {
290 tcg_pts_attr_dh_nonce_params_req_t *attr_cast;
291 u_int8_t min_nonce_len;
292 pts_dh_group_t offered_dh_groups, selected_dh_group;
293
294 attr_cast = (tcg_pts_attr_dh_nonce_params_req_t*)attr;
295 min_nonce_len = attr_cast->get_min_nonce_len(attr_cast);
296 offered_dh_groups = attr_cast->get_dh_groups(attr_cast);
297
298 if ((supported_dh_groups & PTS_DH_GROUP_IKE20) &&
299 (offered_dh_groups & PTS_DH_GROUP_IKE20))
300 {
301 pts->set_dh_group(pts, PTS_DH_GROUP_IKE20);
302 }
303 else if ((supported_dh_groups & PTS_DH_GROUP_IKE19) &&
304 (offered_dh_groups & PTS_DH_GROUP_IKE19))
305 {
306 pts->set_dh_group(pts, PTS_DH_GROUP_IKE19);
307 }
308 else if ((supported_dh_groups & PTS_DH_GROUP_IKE14) &&
309 (offered_dh_groups & PTS_DH_GROUP_IKE14))
310 {
311 pts->set_dh_group(pts, PTS_DH_GROUP_IKE14);
312 }
313 else if ((supported_dh_groups & PTS_DH_GROUP_IKE5) &&
314 (offered_dh_groups & PTS_DH_GROUP_IKE5))
315 {
316 pts->set_dh_group(pts, PTS_DH_GROUP_IKE5);
317 }
318 else if ((supported_dh_groups & PTS_DH_GROUP_IKE2) &&
319 (offered_dh_groups & PTS_DH_GROUP_IKE2))
320 {
321 pts->set_dh_group(pts, PTS_DH_GROUP_IKE2);
322 }
323 else
324 {
325 attr_info = attr->get_value(attr);
326 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
327 TCG_PTS_DH_GRPS_NOT_SUPPORTED, attr_info);
328 attr_list->insert_last(attr_list, attr);
329 break;
330 }
331
332 /* Send DH Nonce Parameters Response attribute */
333 selected_dh_group = pts->get_dh_group(pts);
334 /* TODO: Implement */
335
336 break;
337 }
338 case TCG_PTS_DH_NONCE_FINISH:
339 {
340 /* TODO: Implement */
341 break;
342 }
343 case TCG_PTS_MEAS_ALGO:
344 {
345 tcg_pts_attr_meas_algo_t *attr_cast;
346 pts_meas_algorithms_t offered_algorithms, selected_algorithm;
347
348 attr_cast = (tcg_pts_attr_meas_algo_t*)attr;
349 offered_algorithms = attr_cast->get_algorithms(attr_cast);
350
351 if ((supported_algorithms & PTS_MEAS_ALGO_SHA384) &&
352 (offered_algorithms & PTS_MEAS_ALGO_SHA384))
353 {
354 pts->set_meas_algorithm(pts, PTS_MEAS_ALGO_SHA384);
355 }
356 else if ((supported_algorithms & PTS_MEAS_ALGO_SHA256) &&
357 (offered_algorithms & PTS_MEAS_ALGO_SHA256))
358 {
359 pts->set_meas_algorithm(pts, PTS_MEAS_ALGO_SHA256);
360 }
361
362 else if ((supported_algorithms & PTS_MEAS_ALGO_SHA1) &&
363 (offered_algorithms & PTS_MEAS_ALGO_SHA1))
364 {
365 pts->set_meas_algorithm(pts, PTS_MEAS_ALGO_SHA1);
366 }
367 else
368 {
369 attr = pts_hash_alg_error_create(supported_algorithms);
370 attr_list->insert_last(attr_list, attr);
371 break;
372 }
373
374 /* Send Measurement Algorithm Selection attribute */
375 selected_algorithm = pts->get_meas_algorithm(pts);
376 attr = tcg_pts_attr_meas_algo_create(selected_algorithm,
377 TRUE);
378 attr_list->insert_last(attr_list, attr);
379 break;
380 }
381
382 case TCG_PTS_GET_TPM_VERSION_INFO:
383 {
384 chunk_t tpm_version_info, attr_info;
385
386 if (!pts->get_tpm_version_info(pts, &tpm_version_info))
387 {
388 attr_info = attr->get_value(attr);
389 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
390 TCG_PTS_TPM_VERS_NOT_SUPPORTED, attr_info);
391 attr_list->insert_last(attr_list, attr);
392 break;
393 }
394
395 /* Send TPM Version Info attribute */
396 attr = tcg_pts_attr_tpm_version_info_create(tpm_version_info);
397 attr_list->insert_last(attr_list, attr);
398 break;
399 }
400
401 case TCG_PTS_GET_AIK:
402 {
403 certificate_t *aik;
404
405 aik = pts->get_aik(pts);
406 if (!aik)
407 {
408 DBG1(DBG_IMC, "no AIK certificate or public key available");
409 break;
410 }
411
412 /* Send AIK attribute */
413 attr = tcg_pts_attr_aik_create(aik);
414 attr_list->insert_last(attr_list, attr);
415 break;
416 }
417
418 /* PTS-based Attestation Evidence */
419 case TCG_PTS_REQ_FUNCT_COMP_EVID:
420 {
421 tcg_pts_attr_req_funct_comp_evid_t *attr_cast;
422 pts_proto_caps_flag_t negotiated_caps;
423 pts_attr_req_funct_comp_evid_flag_t flags;
424 u_int32_t sub_comp_depth;
425 u_int32_t comp_name_vendor_id;
426 u_int8_t family;
427 pts_qualifier_t qualifier;
428 pts_funct_comp_name_t name;
429
430 attr_info = attr->get_value(attr);
431 attr_cast = (tcg_pts_attr_req_funct_comp_evid_t*)attr;
432 negotiated_caps = pts->get_proto_caps(pts);
433 flags = attr_cast->get_flags(attr_cast);
434
435 if (flags & PTS_REQ_FUNC_COMP_FLAG_TTC)
436 {
437 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
438 TCG_PTS_UNABLE_DET_TTC, attr_info);
439 attr_list->insert_last(attr_list, attr);
440 break;
441 }
442 if (flags & PTS_REQ_FUNC_COMP_FLAG_VER &&
443 !(negotiated_caps & PTS_PROTO_CAPS_V))
444 {
445 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
446 TCG_PTS_UNABLE_LOCAL_VAL, attr_info);
447 attr_list->insert_last(attr_list, attr);
448 break;
449 }
450 if (flags & PTS_REQ_FUNC_COMP_FLAG_CURR &&
451 !(negotiated_caps & PTS_PROTO_CAPS_C))
452 {
453 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
454 TCG_PTS_UNABLE_CUR_EVID, attr_info);
455 attr_list->insert_last(attr_list, attr);
456 break;
457 }
458 if (flags & PTS_REQ_FUNC_COMP_FLAG_PCR &&
459 !(negotiated_caps & PTS_PROTO_CAPS_T))
460 {
461 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
462 TCG_PTS_UNABLE_DET_PCR, attr_info);
463 attr_list->insert_last(attr_list, attr);
464 break;
465 }
466
467 sub_comp_depth = attr_cast->get_sub_component_depth(attr_cast);
468 /* TODO: Implement checking of components with its sub-components */
469 if (sub_comp_depth != 1)
470 {
471 DBG1(DBG_IMC, "Current version of Attestation IMC does not support"
472 "sub component measurement deeper than 1. "
473 "Measuring top level component only.");
474 }
475
476 comp_name_vendor_id = attr_cast->get_comp_funct_name_vendor_id(attr_cast);
477 if (comp_name_vendor_id != PEN_TCG)
478 {
479 DBG1(DBG_IMC, "Current version of Attestation IMC supports"
480 "only functional component namings by TCG ");
481 break;
482 }
483
484 family = attr_cast->get_family(attr_cast);
485 if (family)
486 {
487 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
488 TCG_PTS_INVALID_NAME_FAM, attr_info);
489 attr_list->insert_last(attr_list, attr);
490 break;
491 }
492
493 qualifier = attr_cast->get_qualifier(attr_cast);
494 /* Check if Unknown or Wildcard was set for qualifier */
495 if (qualifier.kernel && qualifier.sub_component &&
496 (qualifier.type & PTS_FUNC_COMP_TYPE_ALL))
497 {
498 DBG2(DBG_IMC, "Wildcard was set for the qualifier of functional"
499 " component. Identifying the component with name binary enumeration");
500 }
501 else if (!qualifier.kernel && !qualifier.sub_component &&
502 (qualifier.type & PTS_FUNC_COMP_TYPE_UNKNOWN))
503 {
504 DBG2(DBG_IMC, "Unknown was set for the qualifier of functional"
505 " component. Identifying the component with name binary enumeration");
506 }
507 else
508 {
509 /* TODO: Implement what todo with received qualifier */
510 }
511
512 name = attr_cast->get_comp_funct_name(attr_cast);
513 switch (name)
514 {
515 case PTS_FUNC_COMP_NAME_BIOS:
516 {
517 /* TODO: Implement BIOS measurement */
518 DBG1(DBG_IMC, "TODO: Implement BIOS measurement");
519 break;
520 }
521 case PTS_FUNC_COMP_NAME_IGNORE:
522 case PTS_FUNC_COMP_NAME_CRTM:
523 case PTS_FUNC_COMP_NAME_PLATFORM_EXT:
524 case PTS_FUNC_COMP_NAME_BOARD:
525 case PTS_FUNC_COMP_NAME_INIT_LOADER:
526 case PTS_FUNC_COMP_NAME_OPT_ROMS:
527 default:
528 {
529 DBG1(DBG_IMC, "Unsupported Functional Component Name");
530 break;
531 }
532 }
533
534 break;
535 }
536 case TCG_PTS_GEN_ATTEST_EVID:
537 {
538 pts_simple_evid_final_flag_t flags;
539 /* TODO: TPM quote operation over included PCR's */
540
541 /* Send Simple Evidence Final attribute */
542 flags = PTS_SIMPLE_EVID_FINAL_FLAG_NO;
543 attr = tcg_pts_attr_simple_evid_final_create(flags, 0,
544 chunk_empty, chunk_empty, chunk_empty);
545 attr_list->insert_last(attr_list, attr);
546 break;
547 }
548 case TCG_PTS_REQ_FILE_META:
549 {
550 tcg_pts_attr_req_file_meta_t *attr_cast;
551 char *pathname;
552 bool is_directory;
553 u_int8_t delimiter;
554 pts_file_meta_t *metadata;
555
556 attr_info = attr->get_value(attr);
557 attr_cast = (tcg_pts_attr_req_file_meta_t*)attr;
558 is_directory = attr_cast->get_directory_flag(attr_cast);
559 delimiter = attr_cast->get_delimiter(attr_cast);
560 pathname = attr_cast->get_pathname(attr_cast);
561
562 valid_path = pts->is_path_valid(pts, pathname, &pts_error);
563 if (valid_path && pts_error)
564 {
565 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
566 pts_error, attr_info);
567 attr_list->insert_last(attr_list, attr);
568 break;
569 }
570 else if (!valid_path)
571 {
572 break;
573 }
574 if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF)
575 {
576 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
577 TCG_PTS_INVALID_DELIMITER, attr_info);
578 attr_list->insert_last(attr_list, attr);
579 break;
580 }
581 /* Get File Metadata and send them to PTS-IMV */
582 DBG2(DBG_IMC, "metadata request for %s '%s'",
583 is_directory ? "directory" : "file",
584 pathname);
585 metadata = pts->get_metadata(pts, pathname, is_directory);
586
587 if (!metadata)
588 {
589 /* TODO handle error codes from measurements */
590 return TNC_RESULT_FATAL;
591 }
592 attr = tcg_pts_attr_unix_file_meta_create(metadata);
593 attr->set_noskip_flag(attr, TRUE);
594 attr_list->insert_last(attr_list, attr);
595
596 break;
597 }
598 case TCG_PTS_REQ_FILE_MEAS:
599 {
600 tcg_pts_attr_req_file_meas_t *attr_cast;
601 char *pathname;
602 u_int16_t request_id;
603 bool is_directory;
604 u_int32_t delimiter;
605 pts_file_meas_t *measurements;
606
607 attr_info = attr->get_value(attr);
608 attr_cast = (tcg_pts_attr_req_file_meas_t*)attr;
609 is_directory = attr_cast->get_directory_flag(attr_cast);
610 request_id = attr_cast->get_request_id(attr_cast);
611 delimiter = attr_cast->get_delimiter(attr_cast);
612 pathname = attr_cast->get_pathname(attr_cast);
613 valid_path = pts->is_path_valid(pts, pathname, &pts_error);
614
615 if (valid_path && pts_error)
616 {
617 attr_info = attr->get_value(attr);
618 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
619 pts_error, attr_info);
620 attr_list->insert_last(attr_list, attr);
621 break;
622 }
623 else if (!valid_path)
624 {
625 break;
626 }
627
628 if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF)
629 {
630 attr_info = attr->get_value(attr);
631 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
632 TCG_PTS_INVALID_DELIMITER, attr_info);
633 attr_list->insert_last(attr_list, attr);
634 break;
635 }
636
637 /* Do PTS File Measurements and send them to PTS-IMV */
638 DBG2(DBG_IMC, "measurement request %d for %s '%s'",
639 request_id, is_directory ? "directory" : "file",
640 pathname);
641 measurements = pts->do_measurements(pts, request_id,
642 pathname, is_directory);
643 if (!measurements)
644 {
645 /* TODO handle error codes from measurements */
646 return TNC_RESULT_FATAL;
647 }
648 attr = tcg_pts_attr_file_meas_create(measurements);
649 attr->set_noskip_flag(attr, TRUE);
650 attr_list->insert_last(attr_list, attr);
651 break;
652 }
653 /* TODO: Not implemented yet */
654 case TCG_PTS_REQ_INTEG_MEAS_LOG:
655 /* Attributes using XML */
656 case TCG_PTS_REQ_TEMPL_REF_MANI_SET_META:
657 case TCG_PTS_UPDATE_TEMPL_REF_MANI:
658 /* On Windows only*/
659 case TCG_PTS_REQ_REGISTRY_VALUE:
660 /* Received on IMV side only*/
661 case TCG_PTS_PROTO_CAPS:
662 case TCG_PTS_DH_NONCE_PARAMS_RESP:
663 case TCG_PTS_MEAS_ALGO_SELECTION:
664 case TCG_PTS_TPM_VERSION_INFO:
665 case TCG_PTS_TEMPL_REF_MANI_SET_META:
666 case TCG_PTS_AIK:
667 case TCG_PTS_SIMPLE_COMP_EVID:
668 case TCG_PTS_SIMPLE_EVID_FINAL:
669 case TCG_PTS_VERIFICATION_RESULT:
670 case TCG_PTS_INTEG_REPORT:
671 case TCG_PTS_UNIX_FILE_META:
672 case TCG_PTS_FILE_MEAS:
673 case TCG_PTS_INTEG_MEAS_LOG:
674 default:
675 DBG1(DBG_IMC, "received unsupported attribute '%N'",
676 tcg_attr_names, attr->get_type(attr));
677 break;
678 }
679 }
680 }
681 enumerator->destroy(enumerator);
682 pa_tnc_msg->destroy(pa_tnc_msg);
683
684 result = TNC_RESULT_SUCCESS;
685
686 if (attr_list->get_count(attr_list))
687 {
688 pa_tnc_msg = pa_tnc_msg_create();
689
690 enumerator = attr_list->create_enumerator(attr_list);
691 while (enumerator->enumerate(enumerator, &attr))
692 {
693 pa_tnc_msg->add_attribute(pa_tnc_msg, attr);
694 }
695 enumerator->destroy(enumerator);
696
697 pa_tnc_msg->build(pa_tnc_msg);
698 result = imc_attestation->send_message(imc_attestation, connection_id,
699 pa_tnc_msg->get_encoding(pa_tnc_msg));
700 pa_tnc_msg->destroy(pa_tnc_msg);
701 }
702 attr_list->destroy(attr_list);
703
704 return result;
705 }
706
707 /**
708 * see section 3.7.5 of TCG TNC IF-IMC Specification 1.2
709 */
710 TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id,
711 TNC_ConnectionID connection_id)
712 {
713 if (!imc_attestation)
714 {
715 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
716 return TNC_RESULT_NOT_INITIALIZED;
717 }
718 return TNC_RESULT_SUCCESS;
719 }
720
721 /**
722 * see section 3.7.6 of TCG TNC IF-IMC Specification 1.2
723 */
724 TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id)
725 {
726 if (!imc_attestation)
727 {
728 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
729 return TNC_RESULT_NOT_INITIALIZED;
730 }
731
732 libpts_deinit();
733
734 imc_attestation->destroy(imc_attestation);
735 imc_attestation = NULL;
736
737 return TNC_RESULT_SUCCESS;
738 }
739
740 /**
741 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.2
742 */
743 TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
744 TNC_TNCC_BindFunctionPointer bind_function)
745 {
746 if (!imc_attestation)
747 {
748 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
749 return TNC_RESULT_NOT_INITIALIZED;
750 }
751 return imc_attestation->bind_functions(imc_attestation, bind_function);
752 }