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