8748202029aef610f695a23f614bc59de2bddac2
[strongswan.git] / src / libimcv / plugins / imc_attestation / imc_attestation_process.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 #define _GNU_SOURCE
17
18 #include <stdio.h>
19
20 #include "imc_attestation_process.h"
21
22 #include <ietf/ietf_attr_pa_tnc_error.h>
23 #include <pts/pts.h>
24
25 #include <tcg/tcg_pts_attr_proto_caps.h>
26 #include <tcg/tcg_pts_attr_meas_algo.h>
27 #include <tcg/tcg_pts_attr_dh_nonce_params_req.h>
28 #include <tcg/tcg_pts_attr_dh_nonce_params_resp.h>
29 #include <tcg/tcg_pts_attr_dh_nonce_finish.h>
30 #include <tcg/tcg_pts_attr_get_tpm_version_info.h>
31 #include <tcg/tcg_pts_attr_tpm_version_info.h>
32 #include <tcg/tcg_pts_attr_get_aik.h>
33 #include <tcg/tcg_pts_attr_aik.h>
34 #include <tcg/tcg_pts_attr_req_funct_comp_evid.h>
35 #include <tcg/tcg_pts_attr_gen_attest_evid.h>
36 #include <tcg/tcg_pts_attr_simple_comp_evid.h>
37 #include <tcg/tcg_pts_attr_simple_evid_final.h>
38 #include <tcg/tcg_pts_attr_req_file_meas.h>
39 #include <tcg/tcg_pts_attr_file_meas.h>
40 #include <tcg/tcg_pts_attr_req_file_meta.h>
41 #include <tcg/tcg_pts_attr_unix_file_meta.h>
42
43 #include <debug.h>
44
45 #define DEFAULT_NONCE_LEN 20
46 #define EXTEND_PCR 16
47
48 bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
49 imc_attestation_state_t *attestation_state,
50 pts_meas_algorithms_t supported_algorithms,
51 pts_dh_group_t supported_dh_groups,
52 linked_list_t *evidences)
53 {
54 chunk_t attr_info;
55 pts_t *pts;
56 pts_error_code_t pts_error;
57 bool valid_path;
58
59 pts = attestation_state->get_pts(attestation_state);
60 switch (attr->get_type(attr))
61 {
62 case TCG_PTS_REQ_PROTO_CAPS:
63 {
64 tcg_pts_attr_proto_caps_t *attr_cast;
65 pts_proto_caps_flag_t imc_caps, imv_caps;
66
67 attr_cast = (tcg_pts_attr_proto_caps_t*)attr;
68 imv_caps = attr_cast->get_flags(attr_cast);
69 imc_caps = pts->get_proto_caps(pts);
70 pts->set_proto_caps(pts, imc_caps & imv_caps);
71
72 /* Send PTS Protocol Capabilities attribute */
73 attr = tcg_pts_attr_proto_caps_create(imc_caps & imv_caps, FALSE);
74 attr_list->insert_last(attr_list, attr);
75 break;
76 }
77 case TCG_PTS_MEAS_ALGO:
78 {
79 tcg_pts_attr_meas_algo_t *attr_cast;
80 pts_meas_algorithms_t offered_algorithms, selected_algorithm;
81
82 attr_cast = (tcg_pts_attr_meas_algo_t*)attr;
83 offered_algorithms = attr_cast->get_algorithms(attr_cast);
84 selected_algorithm = pts_meas_algo_select(supported_algorithms,
85 offered_algorithms);
86 if (selected_algorithm == PTS_MEAS_ALGO_NONE)
87 {
88 attr = pts_hash_alg_error_create(supported_algorithms);
89 attr_list->insert_last(attr_list, attr);
90 break;
91 }
92
93 /* Send Measurement Algorithm Selection attribute */
94 pts->set_meas_algorithm(pts, selected_algorithm);
95 attr = tcg_pts_attr_meas_algo_create(selected_algorithm, TRUE);
96 attr_list->insert_last(attr_list, attr);
97 break;
98 }
99 case TCG_PTS_DH_NONCE_PARAMS_REQ:
100 {
101 tcg_pts_attr_dh_nonce_params_req_t *attr_cast;
102 pts_dh_group_t offered_dh_groups, selected_dh_group;
103 chunk_t responder_value, responder_nonce;
104 int nonce_len, min_nonce_len;
105
106 nonce_len = lib->settings->get_int(lib->settings,
107 "libimcv.plugins.imc-attestation.nonce_len",
108 DEFAULT_NONCE_LEN);
109
110 attr_cast = (tcg_pts_attr_dh_nonce_params_req_t*)attr;
111 min_nonce_len = attr_cast->get_min_nonce_len(attr_cast);
112 if (nonce_len < PTS_MIN_NONCE_LEN ||
113 (min_nonce_len > 0 && nonce_len < min_nonce_len))
114 {
115 attr = pts_dh_nonce_error_create(nonce_len, PTS_MAX_NONCE_LEN);
116 attr_list->insert_last(attr_list, attr);
117 break;
118 }
119
120 offered_dh_groups = attr_cast->get_dh_groups(attr_cast);
121 selected_dh_group = pts_dh_group_select(supported_dh_groups,
122 offered_dh_groups);
123 if (selected_dh_group == PTS_DH_GROUP_NONE)
124 {
125 attr = pts_dh_group_error_create(supported_dh_groups);
126 attr_list->insert_last(attr_list, attr);
127 break;
128 }
129
130 /* Create own DH factor and nonce */
131 if (!pts->create_dh_nonce(pts, selected_dh_group, nonce_len))
132 {
133 return FALSE;
134 }
135 pts->get_my_public_value(pts, &responder_value, &responder_nonce);
136
137 /* Send DH Nonce Parameters Response attribute */
138 attr = tcg_pts_attr_dh_nonce_params_resp_create(selected_dh_group,
139 supported_algorithms, responder_nonce, responder_value);
140 attr_list->insert_last(attr_list, attr);
141 break;
142 }
143 case TCG_PTS_DH_NONCE_FINISH:
144 {
145 tcg_pts_attr_dh_nonce_finish_t *attr_cast;
146 pts_meas_algorithms_t selected_algorithm;
147 chunk_t initiator_nonce, initiator_value;
148 int nonce_len;
149
150 attr_cast = (tcg_pts_attr_dh_nonce_finish_t*)attr;
151 selected_algorithm = attr_cast->get_hash_algo(attr_cast);
152 if (!(selected_algorithm & supported_algorithms))
153 {
154 DBG1(DBG_IMC, "PTS-IMV selected unsupported DH hash algorithm");
155 return FALSE;
156 }
157 pts->set_dh_hash_algorithm(pts, selected_algorithm);
158
159 initiator_value = attr_cast->get_initiator_value(attr_cast);
160 initiator_nonce = attr_cast->get_initiator_nonce(attr_cast);
161
162 nonce_len = lib->settings->get_int(lib->settings,
163 "libimcv.plugins.imc-attestation.nonce_len",
164 DEFAULT_NONCE_LEN);
165 if (nonce_len != initiator_nonce.len)
166 {
167 DBG1(DBG_IMC, "initiator and responder DH nonces "
168 "have differing lengths");
169 return FALSE;
170 }
171
172 pts->set_peer_public_value(pts, initiator_value, initiator_nonce);
173 if (!pts->calculate_secret(pts))
174 {
175 return FALSE;
176 }
177 break;
178 }
179 case TCG_PTS_GET_TPM_VERSION_INFO:
180 {
181 chunk_t tpm_version_info, attr_info;
182
183 if (!pts->get_tpm_version_info(pts, &tpm_version_info))
184 {
185 attr_info = attr->get_value(attr);
186 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
187 TCG_PTS_TPM_VERS_NOT_SUPPORTED, attr_info);
188 attr_list->insert_last(attr_list, attr);
189 break;
190 }
191
192 /* Send TPM Version Info attribute */
193 attr = tcg_pts_attr_tpm_version_info_create(tpm_version_info);
194 attr_list->insert_last(attr_list, attr);
195 break;
196 }
197 case TCG_PTS_GET_AIK:
198 {
199 certificate_t *aik;
200
201 aik = pts->get_aik(pts);
202 if (!aik)
203 {
204 DBG1(DBG_IMC, "no AIK certificate or public key available");
205 break;
206 }
207
208 /* Send AIK attribute */
209 attr = tcg_pts_attr_aik_create(aik);
210 attr_list->insert_last(attr_list, attr);
211 break;
212 }
213 case TCG_PTS_REQ_FUNCT_COMP_EVID:
214 {
215 tcg_pts_attr_req_funct_comp_evid_t *attr_cast;
216 pts_proto_caps_flag_t negotiated_caps;
217 pts_attr_req_funct_comp_evid_flag_t flags;
218 u_int32_t sub_comp_depth;
219 u_int32_t comp_name_vendor_id;
220 u_int8_t family;
221 pts_qualifier_t qualifier;
222 pts_funct_comp_name_t name;
223
224 attr_info = attr->get_value(attr);
225 attr_cast = (tcg_pts_attr_req_funct_comp_evid_t*)attr;
226 negotiated_caps = pts->get_proto_caps(pts);
227 flags = attr_cast->get_flags(attr_cast);
228
229 if (flags & PTS_REQ_FUNC_COMP_FLAG_TTC)
230 {
231 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
232 TCG_PTS_UNABLE_DET_TTC, attr_info);
233 attr_list->insert_last(attr_list, attr);
234 break;
235 }
236 if (flags & PTS_REQ_FUNC_COMP_FLAG_VER &&
237 !(negotiated_caps & PTS_PROTO_CAPS_V))
238 {
239 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
240 TCG_PTS_UNABLE_LOCAL_VAL, attr_info);
241 attr_list->insert_last(attr_list, attr);
242 break;
243 }
244 if (flags & PTS_REQ_FUNC_COMP_FLAG_CURR &&
245 !(negotiated_caps & PTS_PROTO_CAPS_C))
246 {
247 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
248 TCG_PTS_UNABLE_CUR_EVID, attr_info);
249 attr_list->insert_last(attr_list, attr);
250 break;
251 }
252 if (flags & PTS_REQ_FUNC_COMP_FLAG_PCR &&
253 !(negotiated_caps & PTS_PROTO_CAPS_T))
254 {
255 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
256 TCG_PTS_UNABLE_DET_PCR, attr_info);
257 attr_list->insert_last(attr_list, attr);
258 break;
259 }
260
261 sub_comp_depth = attr_cast->get_sub_component_depth(attr_cast);
262 /* TODO: Implement checking of components with its sub-components */
263 if (sub_comp_depth != 0)
264 {
265 DBG1(DBG_IMC, "current version of Attestation IMC does not "
266 "support sub component measurement deeper than "
267 "zero. Measuring top level component only.");
268 }
269
270 comp_name_vendor_id = attr_cast->get_comp_funct_name_vendor_id(
271 attr_cast);
272 if (comp_name_vendor_id != PEN_TCG)
273 {
274 DBG1(DBG_IMC, "current version of Attestation IMC supports"
275 "only functional component namings by TCG ");
276 break;
277 }
278
279 family = attr_cast->get_family(attr_cast);
280 if (family)
281 {
282 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
283 TCG_PTS_INVALID_NAME_FAM, attr_info);
284 attr_list->insert_last(attr_list, attr);
285 break;
286 }
287
288 qualifier = attr_cast->get_qualifier(attr_cast);
289
290 /* Check if Unknown or Wildcard was set for qualifier */
291 if (qualifier.kernel && qualifier.sub_component &&
292 (qualifier.type & PTS_FUNC_COMP_TYPE_ALL))
293 {
294 DBG2(DBG_IMC, "wildcard was set for the qualifier of functional"
295 " component. Identifying the component with "
296 "name binary enumeration");
297 }
298 else if (!qualifier.kernel && !qualifier.sub_component &&
299 (qualifier.type & PTS_FUNC_COMP_TYPE_UNKNOWN))
300 {
301 DBG2(DBG_IMC, "unknown was set for the qualifier of functional"
302 " component. Identifying the component with "
303 "name binary enumeration");
304 }
305 else
306 {
307 /* TODO: Implement what todo with received qualifier */
308 }
309
310 name = attr_cast->get_comp_funct_name(attr_cast);
311 switch (name)
312 {
313 case PTS_FUNC_COMP_NAME_BIOS:
314 {
315 tcg_pts_attr_simple_comp_evid_params_t params;
316 pts_qualifier_t qualifier;
317 time_t measurement_time_t;
318 struct tm *time_now;
319 char *utc_time;
320 hasher_t *hasher;
321 u_char hash_output[HASH_SIZE_SHA384];
322 hash_algorithm_t hash_alg;
323
324 /* TODO: Implement BIOS measurement */
325 DBG1(DBG_IMC, "experimental implementation:"
326 " Extend TPM with etc/tnc_config file");
327 params.pcr_info_included = TRUE;
328 params.flags = PTS_SIMPLE_COMP_EVID_FLAG_NO_VALID;
329 params.depth = 0;
330 params.vendor_id = PEN_TCG;
331
332 qualifier.kernel = FALSE;
333 qualifier.sub_component = FALSE;
334 qualifier.type = PTS_FUNC_COMP_TYPE_TNC;
335 params.qualifier = qualifier;
336
337 params.name = PTS_FUNC_COMP_NAME_BIOS;
338 params.extended_pcr = EXTEND_PCR;
339 params.hash_algorithm = pts->get_meas_algorithm(pts);
340
341 if (!params.pcr_info_included)
342 {
343 params.transformation = PTS_PCR_TRANSFORM_NO;
344 }
345 else if (pts->get_meas_algorithm(pts) & PTS_MEAS_ALGO_SHA1)
346 {
347 params.transformation = PTS_PCR_TRANSFORM_MATCH;
348 }
349 else if (pts->get_meas_algorithm(pts) & PTS_MEAS_ALGO_SHA256)
350 {
351 params.transformation = PTS_PCR_TRANSFORM_LONG;
352 }
353
354 /* Create a hasher */
355 hash_alg = pts_meas_algo_to_hash(pts->get_meas_algorithm(pts));
356 hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
357 if (!hasher)
358 {
359 DBG1(DBG_IMC, " hasher %N not available",
360 hash_algorithm_names, hash_alg);
361 return FALSE;
362 }
363
364 if (!pts->hash_file(pts, hasher, "/etc/tnc_config",
365 hash_output))
366 {
367 hasher->destroy(hasher);
368 return FALSE;
369 }
370
371 measurement_time_t = time(NULL);
372 if (!measurement_time_t)
373 {
374 params.measurement_time = chunk_create(
375 "0000-00-00T00:00:00Z", 20);
376 }
377 else
378 {
379 time_now = localtime(&measurement_time_t);
380 if (asprintf(&utc_time,
381 "%d-%2.2d-%2.2dT%2.2d:%2.2d:%2.2dZ",
382 time_now->tm_year + 1900,
383 time_now->tm_mon + 1,
384 time_now->tm_mday,
385 time_now->tm_hour,
386 time_now->tm_min,
387 time_now->tm_sec) < 0)
388 {
389 DBG1(DBG_IMC, "could not format local time to UTC");
390 hasher->destroy(hasher);
391 return FALSE;
392 }
393 params.measurement_time = chunk_create(utc_time, 20);
394 params.measurement_time = chunk_clone(
395 params.measurement_time);
396 free(utc_time);
397
398 }
399
400 params.measurement = chunk_create(hash_output,
401 hasher->get_hash_size(hasher));
402 hasher->destroy(hasher);
403
404 params.policy_uri = chunk_empty;
405 if (!pts->read_pcr(pts, EXTEND_PCR, &params.pcr_before))
406 {
407 DBG1(DBG_IMC, "error occured while reading PCR: %d",
408 EXTEND_PCR);
409 return FALSE;
410 }
411
412 if (!pts->extend_pcr(pts, EXTEND_PCR,
413 params.measurement, &params.pcr_after))
414 {
415 DBG1(DBG_IMC, "error occured while extending PCR: %d",
416 EXTEND_PCR);
417 return FALSE;
418 }
419
420 /* Buffer Simple Component Evidence attribute */
421 attr = tcg_pts_attr_simple_comp_evid_create(params);
422 evidences->insert_last(evidences, attr);
423
424 break;
425 }
426 case PTS_FUNC_COMP_NAME_IGNORE:
427 case PTS_FUNC_COMP_NAME_CRTM:
428 case PTS_FUNC_COMP_NAME_PLATFORM_EXT:
429 case PTS_FUNC_COMP_NAME_BOARD:
430 case PTS_FUNC_COMP_NAME_INIT_LOADER:
431 case PTS_FUNC_COMP_NAME_OPT_ROMS:
432 default:
433 {
434 DBG1(DBG_IMC, "unsupported Functional Component Name");
435 break;
436 }
437 }
438 break;
439 }
440 case TCG_PTS_GEN_ATTEST_EVID:
441 {
442 enumerator_t *e;
443 pts_simple_evid_final_flag_t flags;
444 pts_meas_algorithms_t composite_algorithm = 0;
445 chunk_t pcr_composite, quote_signature;
446 u_int32_t num_of_evidences, i = 0;
447 u_int32_t *pcrs;
448
449 /* Send buffered Simple Component Evidences */
450 num_of_evidences = evidences->get_count(evidences);
451 pcrs = (u_int32_t*)malloc(sizeof(u_int32_t)*num_of_evidences);
452
453 e = evidences->create_enumerator(evidences);
454 while (e->enumerate(e, &attr))
455 {
456 tcg_pts_attr_simple_comp_evid_t *attr_cast;
457 u_int32_t extended_pcr;
458
459 attr_cast = (tcg_pts_attr_simple_comp_evid_t*)attr;
460 extended_pcr = attr_cast->get_extended_pcr(attr_cast);
461
462 /* Add extended PCR number to PCR list to quote */
463 /* Duplicated PCR numbers have no influence */
464 pcrs[i] = extended_pcr;
465 i++;
466 /* Send Simple Compoenent Evidence */
467 attr_list->insert_last(attr_list, attr);
468 }
469
470 /* Quote */
471 if (!pts->quote_tpm(pts, pcrs, num_of_evidences,
472 &pcr_composite, &quote_signature))
473 {
474 DBG1(DBG_IMC, "error occured during TPM quote operation");
475 DESTROY_IF(e);
476 DESTROY_IF(evidences);
477 return FALSE;
478 }
479
480 /* Send Simple Evidence Final attribute */
481 flags = PTS_SIMPLE_EVID_FINAL_FLAG_TPM_QUOTE_INFO;
482 composite_algorithm |= PTS_MEAS_ALGO_SHA1;
483
484 attr = tcg_pts_attr_simple_evid_final_create(FALSE, flags,
485 composite_algorithm, pcr_composite,
486 quote_signature, chunk_empty);
487 attr_list->insert_last(attr_list, attr);
488
489 DESTROY_IF(e);
490 DESTROY_IF(evidences);
491
492 break;
493 }
494 case TCG_PTS_REQ_FILE_META:
495 {
496 tcg_pts_attr_req_file_meta_t *attr_cast;
497 char *pathname;
498 bool is_directory;
499 u_int8_t delimiter;
500 pts_file_meta_t *metadata;
501
502 attr_info = attr->get_value(attr);
503 attr_cast = (tcg_pts_attr_req_file_meta_t*)attr;
504 is_directory = attr_cast->get_directory_flag(attr_cast);
505 delimiter = attr_cast->get_delimiter(attr_cast);
506 pathname = attr_cast->get_pathname(attr_cast);
507
508 valid_path = pts->is_path_valid(pts, pathname, &pts_error);
509 if (valid_path && pts_error)
510 {
511 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
512 pts_error, attr_info);
513 attr_list->insert_last(attr_list, attr);
514 break;
515 }
516 else if (!valid_path)
517 {
518 break;
519 }
520 if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF)
521 {
522 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
523 TCG_PTS_INVALID_DELIMITER, attr_info);
524 attr_list->insert_last(attr_list, attr);
525 break;
526 }
527 /* Get File Metadata and send them to PTS-IMV */
528 DBG2(DBG_IMC, "metadata request for %s '%s'",
529 is_directory ? "directory" : "file",
530 pathname);
531 metadata = pts->get_metadata(pts, pathname, is_directory);
532
533 if (!metadata)
534 {
535 /* TODO handle error codes from measurements */
536 return FALSE;
537 }
538 attr = tcg_pts_attr_unix_file_meta_create(metadata);
539 attr->set_noskip_flag(attr, TRUE);
540 attr_list->insert_last(attr_list, attr);
541
542 break;
543 }
544 case TCG_PTS_REQ_FILE_MEAS:
545 {
546 tcg_pts_attr_req_file_meas_t *attr_cast;
547 char *pathname;
548 u_int16_t request_id;
549 bool is_directory;
550 u_int32_t delimiter;
551 pts_file_meas_t *measurements;
552
553 attr_info = attr->get_value(attr);
554 attr_cast = (tcg_pts_attr_req_file_meas_t*)attr;
555 is_directory = attr_cast->get_directory_flag(attr_cast);
556 request_id = attr_cast->get_request_id(attr_cast);
557 delimiter = attr_cast->get_delimiter(attr_cast);
558 pathname = attr_cast->get_pathname(attr_cast);
559 valid_path = pts->is_path_valid(pts, pathname, &pts_error);
560
561 if (valid_path && pts_error)
562 {
563 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
564 pts_error, attr_info);
565 attr_list->insert_last(attr_list, attr);
566 break;
567 }
568 else if (!valid_path)
569 {
570 break;
571 }
572
573 if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF)
574 {
575 attr = ietf_attr_pa_tnc_error_create(PEN_TCG,
576 TCG_PTS_INVALID_DELIMITER, attr_info);
577 attr_list->insert_last(attr_list, attr);
578 break;
579 }
580
581 /* Do PTS File Measurements and send them to PTS-IMV */
582 DBG2(DBG_IMC, "measurement request %d for %s '%s'",
583 request_id, is_directory ? "directory" : "file",
584 pathname);
585 measurements = pts->do_measurements(pts, request_id,
586 pathname, is_directory);
587 if (!measurements)
588 {
589 /* TODO handle error codes from measurements */
590 return FALSE;
591 }
592 attr = tcg_pts_attr_file_meas_create(measurements);
593 attr->set_noskip_flag(attr, TRUE);
594 attr_list->insert_last(attr_list, attr);
595 break;
596 }
597 /* TODO: Not implemented yet */
598 case TCG_PTS_REQ_INTEG_MEAS_LOG:
599 /* Attributes using XML */
600 case TCG_PTS_REQ_TEMPL_REF_MANI_SET_META:
601 case TCG_PTS_UPDATE_TEMPL_REF_MANI:
602 /* On Windows only*/
603 case TCG_PTS_REQ_REGISTRY_VALUE:
604 /* Received on IMV side only*/
605 case TCG_PTS_PROTO_CAPS:
606 case TCG_PTS_DH_NONCE_PARAMS_RESP:
607 case TCG_PTS_MEAS_ALGO_SELECTION:
608 case TCG_PTS_TPM_VERSION_INFO:
609 case TCG_PTS_TEMPL_REF_MANI_SET_META:
610 case TCG_PTS_AIK:
611 case TCG_PTS_SIMPLE_COMP_EVID:
612 case TCG_PTS_SIMPLE_EVID_FINAL:
613 case TCG_PTS_VERIFICATION_RESULT:
614 case TCG_PTS_INTEG_REPORT:
615 case TCG_PTS_UNIX_FILE_META:
616 case TCG_PTS_FILE_MEAS:
617 case TCG_PTS_INTEG_MEAS_LOG:
618 default:
619 DBG1(DBG_IMC, "received unsupported attribute '%N'",
620 tcg_attr_names, attr->get_type(attr));
621 break;
622 }
623 return TRUE;
624 }