]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libpts/plugins/imc_attestation/imc_attestation_process.c
Moved debug.[ch] to utils folder
[thirdparty/strongswan.git] / src / libpts / plugins / imc_attestation / imc_attestation_process.c
CommitLineData
325704e1 1/*
af8354da 2 * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
325704e1
AS
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>
868c24b2
SC
19/* for isdigit */
20#include <ctype.h>
325704e1
AS
21
22#include "imc_attestation_process.h"
23
24#include <ietf/ietf_attr_pa_tnc_error.h>
cb3ecd5a 25
325704e1
AS
26#include <pts/pts.h>
27
28#include <tcg/tcg_pts_attr_proto_caps.h>
29#include <tcg/tcg_pts_attr_meas_algo.h>
30#include <tcg/tcg_pts_attr_dh_nonce_params_req.h>
31#include <tcg/tcg_pts_attr_dh_nonce_params_resp.h>
32#include <tcg/tcg_pts_attr_dh_nonce_finish.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>
a1ac4d5e 37#include <tcg/tcg_pts_attr_req_func_comp_evid.h>
325704e1
AS
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
f05b4272 46#include <utils/debug.h>
868c24b2 47#include <utils/lexparser.h>
325704e1
AS
48
49#define DEFAULT_NONCE_LEN 20
2aa28b16 50
f8a70254 51bool imc_attestation_process(pa_tnc_attr_t *attr, imc_msg_t *msg,
325704e1
AS
52 imc_attestation_state_t *attestation_state,
53 pts_meas_algorithms_t supported_algorithms,
cb3ecd5a 54 pts_dh_group_t supported_dh_groups)
325704e1
AS
55{
56 chunk_t attr_info;
57 pts_t *pts;
58 pts_error_code_t pts_error;
dbb7859f 59 pen_type_t attr_type;
325704e1
AS
60 bool valid_path;
61
62 pts = attestation_state->get_pts(attestation_state);
dbb7859f
AS
63 attr_type = attr->get_type(attr);
64
65 switch (attr_type.type)
325704e1
AS
66 {
67 case TCG_PTS_REQ_PROTO_CAPS:
68 {
69 tcg_pts_attr_proto_caps_t *attr_cast;
70 pts_proto_caps_flag_t imc_caps, imv_caps;
71
72 attr_cast = (tcg_pts_attr_proto_caps_t*)attr;
73 imv_caps = attr_cast->get_flags(attr_cast);
74 imc_caps = pts->get_proto_caps(pts);
75 pts->set_proto_caps(pts, imc_caps & imv_caps);
76
77 /* Send PTS Protocol Capabilities attribute */
78 attr = tcg_pts_attr_proto_caps_create(imc_caps & imv_caps, FALSE);
f8a70254 79 msg->add_attribute(msg, attr);
325704e1
AS
80 break;
81 }
82 case TCG_PTS_MEAS_ALGO:
83 {
84 tcg_pts_attr_meas_algo_t *attr_cast;
85 pts_meas_algorithms_t offered_algorithms, selected_algorithm;
86
87 attr_cast = (tcg_pts_attr_meas_algo_t*)attr;
88 offered_algorithms = attr_cast->get_algorithms(attr_cast);
89 selected_algorithm = pts_meas_algo_select(supported_algorithms,
90 offered_algorithms);
91 if (selected_algorithm == PTS_MEAS_ALGO_NONE)
92 {
93 attr = pts_hash_alg_error_create(supported_algorithms);
f8a70254 94 msg->add_attribute(msg, attr);
325704e1
AS
95 break;
96 }
97
98 /* Send Measurement Algorithm Selection attribute */
99 pts->set_meas_algorithm(pts, selected_algorithm);
100 attr = tcg_pts_attr_meas_algo_create(selected_algorithm, TRUE);
f8a70254 101 msg->add_attribute(msg, attr);
325704e1
AS
102 break;
103 }
104 case TCG_PTS_DH_NONCE_PARAMS_REQ:
105 {
106 tcg_pts_attr_dh_nonce_params_req_t *attr_cast;
107 pts_dh_group_t offered_dh_groups, selected_dh_group;
108 chunk_t responder_value, responder_nonce;
109 int nonce_len, min_nonce_len;
110
111 nonce_len = lib->settings->get_int(lib->settings,
112 "libimcv.plugins.imc-attestation.nonce_len",
113 DEFAULT_NONCE_LEN);
114
115 attr_cast = (tcg_pts_attr_dh_nonce_params_req_t*)attr;
116 min_nonce_len = attr_cast->get_min_nonce_len(attr_cast);
dc5995fb 117 if (nonce_len < PTS_MIN_NONCE_LEN ||
f557e5fc 118 (min_nonce_len > 0 && nonce_len < min_nonce_len))
325704e1 119 {
dc5995fb 120 attr = pts_dh_nonce_error_create(nonce_len, PTS_MAX_NONCE_LEN);
f8a70254 121 msg->add_attribute(msg, attr);
325704e1
AS
122 break;
123 }
124
125 offered_dh_groups = attr_cast->get_dh_groups(attr_cast);
126 selected_dh_group = pts_dh_group_select(supported_dh_groups,
127 offered_dh_groups);
128 if (selected_dh_group == PTS_DH_GROUP_NONE)
129 {
dc5995fb 130 attr = pts_dh_group_error_create(supported_dh_groups);
f8a70254 131 msg->add_attribute(msg, attr);
325704e1
AS
132 break;
133 }
134
135 /* Create own DH factor and nonce */
136 if (!pts->create_dh_nonce(pts, selected_dh_group, nonce_len))
137 {
138 return FALSE;
139 }
140 pts->get_my_public_value(pts, &responder_value, &responder_nonce);
141
142 /* Send DH Nonce Parameters Response attribute */
143 attr = tcg_pts_attr_dh_nonce_params_resp_create(selected_dh_group,
144 supported_algorithms, responder_nonce, responder_value);
f8a70254 145 msg->add_attribute(msg, attr);
325704e1
AS
146 break;
147 }
148 case TCG_PTS_DH_NONCE_FINISH:
149 {
150 tcg_pts_attr_dh_nonce_finish_t *attr_cast;
151 pts_meas_algorithms_t selected_algorithm;
152 chunk_t initiator_nonce, initiator_value;
153 int nonce_len;
154
155 attr_cast = (tcg_pts_attr_dh_nonce_finish_t*)attr;
156 selected_algorithm = attr_cast->get_hash_algo(attr_cast);
157 if (!(selected_algorithm & supported_algorithms))
158 {
159 DBG1(DBG_IMC, "PTS-IMV selected unsupported DH hash algorithm");
dc5995fb 160 return FALSE;
325704e1
AS
161 }
162 pts->set_dh_hash_algorithm(pts, selected_algorithm);
163
164 initiator_value = attr_cast->get_initiator_value(attr_cast);
165 initiator_nonce = attr_cast->get_initiator_nonce(attr_cast);
dc5995fb
AS
166
167 nonce_len = lib->settings->get_int(lib->settings,
168 "libimcv.plugins.imc-attestation.nonce_len",
169 DEFAULT_NONCE_LEN);
170 if (nonce_len != initiator_nonce.len)
325704e1 171 {
dc5995fb
AS
172 DBG1(DBG_IMC, "initiator and responder DH nonces "
173 "have differing lengths");
174 return FALSE;
325704e1 175 }
f05b4272 176
325704e1
AS
177 pts->set_peer_public_value(pts, initiator_value, initiator_nonce);
178 if (!pts->calculate_secret(pts))
179 {
180 return FALSE;
181 }
182 break;
183 }
184 case TCG_PTS_GET_TPM_VERSION_INFO:
185 {
186 chunk_t tpm_version_info, attr_info;
dbb7859f 187 pen_type_t error_code = { PEN_TCG, TCG_PTS_TPM_VERS_NOT_SUPPORTED };
325704e1
AS
188
189 if (!pts->get_tpm_version_info(pts, &tpm_version_info))
190 {
191 attr_info = attr->get_value(attr);
dbb7859f 192 attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
f8a70254 193 msg->add_attribute(msg, attr);
325704e1
AS
194 break;
195 }
196
197 /* Send TPM Version Info attribute */
198 attr = tcg_pts_attr_tpm_version_info_create(tpm_version_info);
f8a70254 199 msg->add_attribute(msg, attr);
325704e1
AS
200 break;
201 }
202 case TCG_PTS_GET_AIK:
203 {
204 certificate_t *aik;
205
206 aik = pts->get_aik(pts);
207 if (!aik)
208 {
209 DBG1(DBG_IMC, "no AIK certificate or public key available");
210 break;
211 }
212
213 /* Send AIK attribute */
214 attr = tcg_pts_attr_aik_create(aik);
f8a70254 215 msg->add_attribute(msg, attr);
325704e1
AS
216 break;
217 }
72e75049 218 case TCG_PTS_REQ_FILE_MEAS:
77cf6271 219 {
72e75049 220 tcg_pts_attr_req_file_meas_t *attr_cast;
77cf6271 221 char *pathname;
72e75049 222 u_int16_t request_id;
77cf6271 223 bool is_directory;
72e75049
SC
224 u_int32_t delimiter;
225 pts_file_meas_t *measurements;
dbb7859f 226 pen_type_t error_code;
77cf6271
SC
227
228 attr_info = attr->get_value(attr);
72e75049 229 attr_cast = (tcg_pts_attr_req_file_meas_t*)attr;
77cf6271 230 is_directory = attr_cast->get_directory_flag(attr_cast);
72e75049 231 request_id = attr_cast->get_request_id(attr_cast);
77cf6271
SC
232 delimiter = attr_cast->get_delimiter(attr_cast);
233 pathname = attr_cast->get_pathname(attr_cast);
77cf6271 234 valid_path = pts->is_path_valid(pts, pathname, &pts_error);
72e75049 235
77cf6271
SC
236 if (valid_path && pts_error)
237 {
dbb7859f
AS
238 error_code = pen_type_create(PEN_TCG, pts_error);
239 attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
f8a70254 240 msg->add_attribute(msg, attr);
77cf6271
SC
241 break;
242 }
243 else if (!valid_path)
244 {
245 break;
246 }
72e75049 247
77cf6271
SC
248 if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF)
249 {
dbb7859f
AS
250 error_code = pen_type_create(PEN_TCG,
251 TCG_PTS_INVALID_DELIMITER);
252 attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
f8a70254 253 msg->add_attribute(msg, attr);
77cf6271
SC
254 break;
255 }
77cf6271 256
72e75049
SC
257 /* Do PTS File Measurements and send them to PTS-IMV */
258 DBG2(DBG_IMC, "measurement request %d for %s '%s'",
259 request_id, is_directory ? "directory" : "file",
260 pathname);
0f236aac
AS
261 measurements = pts_file_meas_create_from_path(request_id,
262 pathname, is_directory, TRUE,
263 pts->get_meas_algorithm(pts));
72e75049 264 if (!measurements)
77cf6271
SC
265 {
266 /* TODO handle error codes from measurements */
267 return FALSE;
268 }
72e75049 269 attr = tcg_pts_attr_file_meas_create(measurements);
77cf6271 270 attr->set_noskip_flag(attr, TRUE);
f8a70254 271 msg->add_attribute(msg, attr);
77cf6271
SC
272 break;
273 }
72e75049 274 case TCG_PTS_REQ_FILE_META:
77cf6271 275 {
72e75049 276 tcg_pts_attr_req_file_meta_t *attr_cast;
77cf6271 277 char *pathname;
77cf6271 278 bool is_directory;
72e75049
SC
279 u_int8_t delimiter;
280 pts_file_meta_t *metadata;
dbb7859f 281 pen_type_t error_code;
77cf6271
SC
282
283 attr_info = attr->get_value(attr);
72e75049 284 attr_cast = (tcg_pts_attr_req_file_meta_t*)attr;
77cf6271 285 is_directory = attr_cast->get_directory_flag(attr_cast);
77cf6271
SC
286 delimiter = attr_cast->get_delimiter(attr_cast);
287 pathname = attr_cast->get_pathname(attr_cast);
77cf6271 288
72e75049 289 valid_path = pts->is_path_valid(pts, pathname, &pts_error);
77cf6271
SC
290 if (valid_path && pts_error)
291 {
dbb7859f
AS
292 error_code = pen_type_create(PEN_TCG, pts_error);
293 attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
f8a70254 294 msg->add_attribute(msg, attr);
77cf6271
SC
295 break;
296 }
297 else if (!valid_path)
298 {
299 break;
300 }
77cf6271
SC
301 if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF)
302 {
dbb7859f
AS
303 error_code = pen_type_create(PEN_TCG,
304 TCG_PTS_INVALID_DELIMITER);
305 attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
f8a70254 306 msg->add_attribute(msg, attr);
77cf6271
SC
307 break;
308 }
72e75049
SC
309 /* Get File Metadata and send them to PTS-IMV */
310 DBG2(DBG_IMC, "metadata request for %s '%s'",
311 is_directory ? "directory" : "file",
312 pathname);
313 metadata = pts->get_metadata(pts, pathname, is_directory);
77cf6271 314
72e75049 315 if (!metadata)
77cf6271
SC
316 {
317 /* TODO handle error codes from measurements */
318 return FALSE;
319 }
72e75049 320 attr = tcg_pts_attr_unix_file_meta_create(metadata);
77cf6271 321 attr->set_noskip_flag(attr, TRUE);
f8a70254 322 msg->add_attribute(msg, attr);
77cf6271
SC
323 break;
324 }
a1ac4d5e 325 case TCG_PTS_REQ_FUNC_COMP_EVID:
325704e1 326 {
a1ac4d5e 327 tcg_pts_attr_req_func_comp_evid_t *attr_cast;
325704e1 328 pts_proto_caps_flag_t negotiated_caps;
8ee7e36b 329 pts_comp_func_name_t *name;
cb3ecd5a
AS
330 pts_comp_evidence_t *evid;
331 pts_component_t *comp;
dbb7859f 332 pen_type_t error_code;
a1ac4d5e
AS
333 u_int32_t depth;
334 u_int8_t flags;
cb3ecd5a 335 status_t status;
a1ac4d5e 336 enumerator_t *e;
f05b4272 337
325704e1 338 attr_info = attr->get_value(attr);
a1ac4d5e 339 attr_cast = (tcg_pts_attr_req_func_comp_evid_t*)attr;
325704e1 340
d5bde491 341 DBG1(DBG_IMC, "evidence requested for %d functional components",
a1ac4d5e 342 attr_cast->get_count(attr_cast));
325704e1 343
a1ac4d5e
AS
344 e = attr_cast->create_enumerator(attr_cast);
345 while (e->enumerate(e, &flags, &depth, &name))
325704e1 346 {
cb3ecd5a 347 name->log(name, "* ");
72e75049
SC
348 negotiated_caps = pts->get_proto_caps(pts);
349
8d851141 350 if (flags & PTS_REQ_FUNC_COMP_EVID_TTC)
72e75049 351 {
dbb7859f 352 error_code = pen_type_create(PEN_TCG,
f05b4272 353 TCG_PTS_UNABLE_DET_TTC);
dbb7859f 354 attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
f8a70254 355 msg->add_attribute(msg, attr);
72e75049
SC
356 break;
357 }
8d851141 358 if (flags & PTS_REQ_FUNC_COMP_EVID_VER &&
72e75049
SC
359 !(negotiated_caps & PTS_PROTO_CAPS_V))
360 {
dbb7859f
AS
361 error_code = pen_type_create(PEN_TCG,
362 TCG_PTS_UNABLE_LOCAL_VAL);
363 attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
f8a70254 364 msg->add_attribute(msg, attr);
72e75049
SC
365 break;
366 }
8d851141 367 if (flags & PTS_REQ_FUNC_COMP_EVID_CURR &&
72e75049
SC
368 !(negotiated_caps & PTS_PROTO_CAPS_C))
369 {
dbb7859f
AS
370 error_code = pen_type_create(PEN_TCG,
371 TCG_PTS_UNABLE_CUR_EVID);
372 attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
f8a70254 373 msg->add_attribute(msg, attr);
72e75049
SC
374 break;
375 }
8d851141 376 if (flags & PTS_REQ_FUNC_COMP_EVID_PCR &&
72e75049
SC
377 !(negotiated_caps & PTS_PROTO_CAPS_T))
378 {
dbb7859f
AS
379 error_code = pen_type_create(PEN_TCG,
380 TCG_PTS_UNABLE_DET_PCR);
381 attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
f8a70254 382 msg->add_attribute(msg, attr);
72e75049
SC
383 break;
384 }
cb3ecd5a 385 if (depth > 0)
325704e1 386 {
cb3ecd5a
AS
387 DBG1(DBG_IMC, "the Attestation IMC currently does not "
388 "support sub component measurements");
2aa28b16 389 return FALSE;
325704e1 390 }
af8354da
AS
391 comp = attestation_state->create_component(attestation_state,
392 name, depth);
cb3ecd5a 393 if (!comp)
72e75049 394 {
cb3ecd5a 395 DBG2(DBG_IMC, " not registered: no evidence provided");
cb3ecd5a 396 continue;
72e75049 397 }
72e75049 398
ab957aac 399 /* do the component evidence measurement[s] and cache them */
cb3ecd5a
AS
400 do
401 {
af8354da
AS
402 status = comp->measure(comp, name->get_qualifier(name),
403 pts, &evid);
cb3ecd5a 404 if (status == FAILED)
72e75049 405 {
8ee7e36b 406 break;
72e75049 407 }
ab957aac 408 attestation_state->add_evidence(attestation_state, evid);
72e75049 409 }
cb3ecd5a 410 while (status == NEED_MORE);
2aa28b16 411 }
72e75049 412 e->destroy(e);
325704e1
AS
413 break;
414 }
415 case TCG_PTS_GEN_ATTEST_EVID:
416 {
325704e1 417 pts_simple_evid_final_flag_t flags;
db103fad 418 pts_meas_algorithms_t comp_hash_algorithm;
ab957aac 419 pts_comp_evidence_t *evid;
db103fad 420 chunk_t pcr_composite, quote_sig;
f6aab3cd 421 bool use_quote2;
d25b7b3d 422
ab957aac
AS
423 /* Send cached Component Evidence entries */
424 while (attestation_state->next_evidence(attestation_state, &evid))
325704e1 425 {
ab957aac 426 attr = tcg_pts_attr_simple_comp_evid_create(evid);
f8a70254 427 msg->add_attribute(msg, attr);
325704e1 428 }
f6aab3cd 429
19c956b6
AS
430 use_quote2 = lib->settings->get_bool(lib->settings,
431 "libimcv.plugins.imc-attestation.use_quote2", TRUE);
db103fad 432 if (!pts->quote_tpm(pts, use_quote2, &pcr_composite, &quote_sig))
325704e1 433 {
35a19861 434 DBG1(DBG_IMC, "error occurred during TPM quote operation");
325704e1
AS
435 return FALSE;
436 }
77cf6271 437
325704e1 438 /* Send Simple Evidence Final attribute */
db103fad
AS
439 flags = use_quote2 ? PTS_SIMPLE_EVID_FINAL_QUOTE_INFO2 :
440 PTS_SIMPLE_EVID_FINAL_QUOTE_INFO;
b2485f32 441 comp_hash_algorithm = PTS_MEAS_ALGO_SHA1;
77cf6271 442
db103fad
AS
443 attr = tcg_pts_attr_simple_evid_final_create(flags,
444 comp_hash_algorithm, pcr_composite, quote_sig);
f8a70254 445 msg->add_attribute(msg, attr);
325704e1
AS
446 break;
447 }
448 /* TODO: Not implemented yet */
449 case TCG_PTS_REQ_INTEG_MEAS_LOG:
450 /* Attributes using XML */
451 case TCG_PTS_REQ_TEMPL_REF_MANI_SET_META:
452 case TCG_PTS_UPDATE_TEMPL_REF_MANI:
453 /* On Windows only*/
454 case TCG_PTS_REQ_REGISTRY_VALUE:
455 /* Received on IMV side only*/
456 case TCG_PTS_PROTO_CAPS:
457 case TCG_PTS_DH_NONCE_PARAMS_RESP:
458 case TCG_PTS_MEAS_ALGO_SELECTION:
459 case TCG_PTS_TPM_VERSION_INFO:
460 case TCG_PTS_TEMPL_REF_MANI_SET_META:
461 case TCG_PTS_AIK:
462 case TCG_PTS_SIMPLE_COMP_EVID:
463 case TCG_PTS_SIMPLE_EVID_FINAL:
464 case TCG_PTS_VERIFICATION_RESULT:
465 case TCG_PTS_INTEG_REPORT:
466 case TCG_PTS_UNIX_FILE_META:
467 case TCG_PTS_FILE_MEAS:
468 case TCG_PTS_INTEG_MEAS_LOG:
469 default:
470 DBG1(DBG_IMC, "received unsupported attribute '%N'",
471 tcg_attr_names, attr->get_type(attr));
472 break;
473 }
474 return TRUE;
475}