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