]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libimcv/plugins/imv_attestation/imv_attestation_state.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libimcv / plugins / imv_attestation / imv_attestation_state.c
CommitLineData
4a492a8d 1/*
a498c7a9 2 * Copyright (C) 2011-2012 Sansar Choinyambuu
fbddf52c 3 * Copyright (C) 2011-2014 Andreas Steffen
19ef2aec
TB
4 *
5 * Copyright (C) secunet Security Networks AG
4a492a8d
AS
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18#include "imv_attestation_state.h"
19
d6fb2cc6 20#include <imcv.h>
ee6aeca8
AS
21#include <imv/imv_lang_string.h>
22#include "imv/imv_reason_string.h"
23
a6266485
AS
24#include <tncif_policy.h>
25
12642a68 26#include <collections/linked_list.h>
f05b4272 27#include <utils/debug.h>
4a492a8d
AS
28
29typedef struct private_imv_attestation_state_t private_imv_attestation_state_t;
413922ff 30typedef struct file_meas_request_t file_meas_request_t;
af8354da 31typedef struct func_comp_t func_comp_t;
4a492a8d
AS
32
33/**
34 * Private data of an imv_attestation_state_t object.
35 */
36struct private_imv_attestation_state_t {
37
38 /**
39 * Public members of imv_attestation_state_t
40 */
41 imv_attestation_state_t public;
42
43 /**
44 * TNCCS connection ID
45 */
46 TNC_ConnectionID connection_id;
47
48 /**
49 * TNCCS connection state
50 */
51 TNC_ConnectionState state;
12642a68 52
e4e291d4
AS
53 /**
54 * Does the TNCCS connection support long message types?
55 */
56 bool has_long;
57
58 /**
59 * Does the TNCCS connection support exclusive delivery?
60 */
61 bool has_excl;
62
968c83cd
AS
63 /**
64 * Maximum PA-TNC message size for this TNCCS connection
65 */
4894bfa2 66 uint32_t max_msg_len;
968c83cd 67
b1da8368
AS
68 /**
69 * Flags set for completed actions
70 */
4894bfa2 71 uint32_t action_flags;
a498c7a9 72
b8db66de 73 /**
a6266485 74 * IMV database session associated with TNCCS connection
4f9aabbf 75 */
a6266485 76 imv_session_t *session;
4f9aabbf 77
f5096897
AS
78 /**
79 * PA-TNC attribute segmentation contracts associated with TNCCS connection
80 */
81 seg_contract_manager_t *contracts;
82
12c0a261
SC
83 /**
84 * IMV Attestation handshake state
85 */
86 imv_attestation_handshake_state_t handshake_state;
4a492a8d
AS
87
88 /**
89 * IMV action recommendation
90 */
91 TNC_IMV_Action_Recommendation rec;
92
93 /**
94 * IMV evaluation result
95 */
96 TNC_IMV_Evaluation_Result eval;
8a2482c7 97
413922ff 98 /**
a1ac4d5e 99 * List of Functional Components
413922ff 100 */
a1ac4d5e 101 linked_list_t *components;
8a2482c7 102
e9fd8b4b 103 /**
925f54d3 104 * PTS object
e9fd8b4b 105 */
925f54d3 106 pts_t *pts;
e9fd8b4b 107
350f855c 108 /**
b8f0bf00 109 * Measurement error flags
350f855c 110 */
4894bfa2 111 uint32_t measurement_error;
350f855c 112
ee6aeca8
AS
113 /**
114 * TNC Reason String
115 */
116 imv_reason_string_t *reason_string;
117
4a492a8d
AS
118};
119
af8354da
AS
120/**
121 * PTS Functional Component entry
122 */
123struct func_comp_t {
124 pts_component_t *comp;
fbddf52c 125 pts_comp_func_name_t* name;
af8354da
AS
126};
127
128/**
129 * Frees a func_comp_t object
130 */
131static void free_func_comp(func_comp_t *this)
132{
133 this->comp->destroy(this->comp);
fbddf52c 134 this->name->destroy(this->name);
af8354da
AS
135 free(this);
136}
137
4a492a8d 138/**
ee6aeca8 139 * Supported languages
4a492a8d 140 */
e8a491c0 141static char* languages[] = { "en", "de", "mn" };
4a492a8d
AS
142
143/**
ee6aeca8 144 * Table of reason strings
4a492a8d 145 */
b8f0bf00
AS
146static imv_lang_string_t reason_file_meas_fail[] = {
147 { "en", "Incorrect file measurement" },
148 { "de", "Falsche Dateimessung" },
149 { "mn", "Буруу байгаа файл" },
150 { NULL, NULL }
151};
152
153static imv_lang_string_t reason_file_meas_pend[] = {
154 { "en", "Pending file measurement" },
155 { "de", "Ausstehende Dateimessung" },
156 { "mn", "Xүлээгдэж байгаа файл" },
157 { NULL, NULL }
158};
159
8b36021b
AS
160static imv_lang_string_t reason_no_trusted_aik[] = {
161 { "en", "No trusted AIK available" },
162 { "de", "Kein vetrauenswürdiger AIK verfügbar" },
163 { NULL, NULL }
164};
165
b8f0bf00
AS
166static imv_lang_string_t reason_comp_evid_fail[] = {
167 { "en", "Incorrect component evidence" },
168 { "de", "Falsche Komponenten-Evidenz" },
169 { "mn", "Буруу компонент хэмжилт" },
170 { NULL, NULL }
171};
172
173static imv_lang_string_t reason_comp_evid_pend[] = {
174 { "en", "Pending component evidence" },
175 { "de", "Ausstehende Komponenten-Evidenz" },
176 { "mn", "Xүлээгдэж компонент хэмжилт" },
177 { NULL, NULL }
178};
179
180static imv_lang_string_t reason_tpm_quote_fail[] = {
181 { "en", "Invalid TPM Quote signature received" },
182 { "de", "Falsche TPM Quote Signature erhalten" },
183 { "mn", "Буруу TPM Quote гарын үсэг" },
ee6aeca8 184 { NULL, NULL }
4a492a8d
AS
185};
186
187METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
188 private_imv_attestation_state_t *this)
189{
190 return this->connection_id;
191}
192
e4e291d4
AS
193METHOD(imv_state_t, has_long, bool,
194 private_imv_attestation_state_t *this)
195{
196 return this->has_long;
197}
198
199METHOD(imv_state_t, has_excl, bool,
200 private_imv_attestation_state_t *this)
201{
202 return this->has_excl;
203}
204
205METHOD(imv_state_t, set_flags, void,
206 private_imv_attestation_state_t *this, bool has_long, bool has_excl)
207{
208 this->has_long = has_long;
209 this->has_excl = has_excl;
210}
211
968c83cd 212METHOD(imv_state_t, set_max_msg_len, void,
4894bfa2 213 private_imv_attestation_state_t *this, uint32_t max_msg_len)
968c83cd
AS
214{
215 this->max_msg_len = max_msg_len;
216}
217
4894bfa2 218METHOD(imv_state_t, get_max_msg_len, uint32_t,
968c83cd
AS
219 private_imv_attestation_state_t *this)
220{
221 return this->max_msg_len;
222}
223
b1da8368 224METHOD(imv_state_t, set_action_flags, void,
4894bfa2 225 private_imv_attestation_state_t *this, uint32_t flags)
b1da8368
AS
226{
227 this->action_flags |= flags;
228}
229
4894bfa2 230METHOD(imv_state_t, get_action_flags, uint32_t,
b1da8368
AS
231 private_imv_attestation_state_t *this)
232{
233 return this->action_flags;
234}
235
a6266485
AS
236METHOD(imv_state_t, set_session, void,
237 private_imv_attestation_state_t *this, imv_session_t *session)
4f9aabbf 238{
a6266485 239 this->session = session;
4f9aabbf
AS
240}
241
a6266485 242METHOD(imv_state_t, get_session, imv_session_t*,
4f9aabbf
AS
243 private_imv_attestation_state_t *this)
244{
a6266485 245 return this->session;
4f9aabbf
AS
246}
247
f5096897
AS
248METHOD(imv_state_t, get_contracts, seg_contract_manager_t*,
249 private_imv_attestation_state_t *this)
250{
251 return this->contracts;
252}
253
25973c03 254METHOD(imv_state_t, change_state, TNC_ConnectionState,
4a492a8d
AS
255 private_imv_attestation_state_t *this, TNC_ConnectionState new_state)
256{
25973c03
AS
257 TNC_ConnectionState old_state;
258
259 old_state = this->state;
4a492a8d 260 this->state = new_state;
25973c03 261 return old_state;
4a492a8d
AS
262}
263
264METHOD(imv_state_t, get_recommendation, void,
265 private_imv_attestation_state_t *this, TNC_IMV_Action_Recommendation *rec,
a6266485 266 TNC_IMV_Evaluation_Result *eval)
4a492a8d
AS
267{
268 *rec = this->rec;
269 *eval = this->eval;
270}
271
272METHOD(imv_state_t, set_recommendation, void,
273 private_imv_attestation_state_t *this, TNC_IMV_Action_Recommendation rec,
a6266485 274 TNC_IMV_Evaluation_Result eval)
4a492a8d
AS
275{
276 this->rec = rec;
277 this->eval = eval;
278}
279
a6266485
AS
280METHOD(imv_state_t, update_recommendation, void,
281 private_imv_attestation_state_t *this, TNC_IMV_Action_Recommendation rec,
282 TNC_IMV_Evaluation_Result eval)
283{
284 this->rec = tncif_policy_update_recommendation(this->rec, rec);
285 this->eval = tncif_policy_update_evaluation(this->eval, eval);
286}
287
81d49c5c
AS
288METHOD(imv_attestation_state_t, add_file_meas_reasons, void,
289 private_imv_attestation_state_t *this, imv_reason_string_t *reason_string)
4a492a8d 290{
b8f0bf00
AS
291 if (this->measurement_error & IMV_ATTESTATION_ERROR_FILE_MEAS_FAIL)
292 {
81d49c5c 293 reason_string->add_reason(reason_string, reason_file_meas_fail);
b8f0bf00
AS
294 }
295 if (this->measurement_error & IMV_ATTESTATION_ERROR_FILE_MEAS_PEND)
296 {
81d49c5c 297 reason_string->add_reason(reason_string, reason_file_meas_pend);
b8f0bf00 298 }
81d49c5c
AS
299}
300
301METHOD(imv_attestation_state_t, add_comp_evid_reasons, void,
302 private_imv_attestation_state_t *this, imv_reason_string_t *reason_string)
303{
8b36021b
AS
304 if (this->measurement_error & IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK)
305 {
306 reason_string->add_reason(reason_string, reason_no_trusted_aik);
307 }
b8f0bf00
AS
308 if (this->measurement_error & IMV_ATTESTATION_ERROR_COMP_EVID_FAIL)
309 {
81d49c5c 310 reason_string->add_reason(reason_string, reason_comp_evid_fail);
b8f0bf00
AS
311 }
312 if (this->measurement_error & IMV_ATTESTATION_ERROR_COMP_EVID_PEND)
313 {
81d49c5c 314 reason_string->add_reason(reason_string, reason_comp_evid_pend);
b8f0bf00
AS
315 }
316 if (this->measurement_error & IMV_ATTESTATION_ERROR_TPM_QUOTE_FAIL)
317 {
81d49c5c 318 reason_string->add_reason(reason_string, reason_tpm_quote_fail);
b8f0bf00 319 }
81d49c5c
AS
320}
321
322METHOD(imv_state_t, get_reason_string, bool,
323 private_imv_attestation_state_t *this, enumerator_t *language_enumerator,
324 chunk_t *reason_string, char **reason_language)
325{
326 *reason_language = imv_lang_string_select_lang(language_enumerator,
327 languages, countof(languages));
328
329 /* Instantiate a TNC Reason String object */
330 DESTROY_IF(this->reason_string);
331 this->reason_string = imv_reason_string_create(*reason_language, "\n");
332 add_file_meas_reasons(this, this->reason_string);
333 add_comp_evid_reasons(this, this->reason_string);
ee6aeca8 334 *reason_string = this->reason_string->get_encoding(this->reason_string);
4a492a8d 335
4a492a8d
AS
336 return TRUE;
337}
338
af83700f
AS
339METHOD(imv_state_t, get_remediation_instructions, bool,
340 private_imv_attestation_state_t *this, enumerator_t *language_enumerator,
ee6aeca8 341 chunk_t *string, char **lang_code, char **uri)
af83700f
AS
342{
343 return FALSE;
344}
345
25973c03
AS
346METHOD(imv_state_t, reset, void,
347 private_imv_attestation_state_t *this)
348{
349 DESTROY_IF(this->reason_string);
350 this->reason_string = NULL;
351 this->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
352 this->eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
353
354 this->action_flags = 0;
355
356 this->handshake_state = IMV_ATTESTATION_STATE_INIT;
357 this->measurement_error = 0;
358 this->components->destroy_function(this->components, (void *)free_func_comp);
359 this->components = linked_list_create();
360 this->pts->destroy(this->pts);
361 this->pts = pts_create(FALSE);
362}
363
4a492a8d
AS
364METHOD(imv_state_t, destroy, void,
365 private_imv_attestation_state_t *this)
366{
a6266485 367 DESTROY_IF(this->session);
ee6aeca8 368 DESTROY_IF(this->reason_string);
af8354da 369 this->components->destroy_function(this->components, (void *)free_func_comp);
8a2482c7 370 this->pts->destroy(this->pts);
f5096897 371 this->contracts->destroy(this->contracts);
4a492a8d
AS
372 free(this);
373}
374
b8017b5e
SC
375METHOD(imv_attestation_state_t, get_handshake_state,
376 imv_attestation_handshake_state_t, private_imv_attestation_state_t *this)
12c0a261
SC
377{
378 return this->handshake_state;
379}
380
381METHOD(imv_attestation_state_t, set_handshake_state, void,
b8017b5e
SC
382 private_imv_attestation_state_t *this,
383 imv_attestation_handshake_state_t new_state)
12c0a261
SC
384{
385 this->handshake_state = new_state;
386}
387
8a2482c7
AS
388METHOD(imv_attestation_state_t, get_pts, pts_t*,
389 private_imv_attestation_state_t *this)
390{
391 return this->pts;
392}
393
af8354da
AS
394METHOD(imv_attestation_state_t, create_component, pts_component_t*,
395 private_imv_attestation_state_t *this, pts_comp_func_name_t *name,
4894bfa2 396 uint32_t depth, pts_database_t *pts_db)
413922ff 397{
af8354da
AS
398 enumerator_t *enumerator;
399 func_comp_t *entry, *new_entry;
400 pts_component_t *component;
401 bool found = FALSE;
402
403 enumerator = this->components->create_enumerator(this->components);
404 while (enumerator->enumerate(enumerator, &entry))
405 {
406 if (name->equals(name, entry->comp->get_comp_func_name(entry->comp)))
407 {
408 found = TRUE;
409 break;
410 }
411 }
412 enumerator->destroy(enumerator);
413
414 if (found)
415 {
fbddf52c 416 if (name->equals(name, entry->name))
af8354da
AS
417 {
418 /* duplicate entry */
419 return NULL;
420 }
421 new_entry = malloc_thing(func_comp_t);
fbddf52c 422 new_entry->name = name->clone(name);
af8354da
AS
423 new_entry->comp = entry->comp->get_ref(entry->comp);
424 this->components->insert_last(this->components, new_entry);
425 return entry->comp;
426 }
427 else
428 {
d6fb2cc6
AS
429 component = imcv_pts_components->create(imcv_pts_components,
430 name, depth, pts_db);
af8354da
AS
431 if (!component)
432 {
433 /* unsupported component */
434 return NULL;
435 }
436 new_entry = malloc_thing(func_comp_t);
fbddf52c 437 new_entry->name = name->clone(name);
af8354da
AS
438 new_entry->comp = component;
439 this->components->insert_last(this->components, new_entry);
440 return component;
441 }
413922ff
SC
442}
443
525cc46c
TB
444CALLBACK(entry_filter, bool,
445 void *null, enumerator_t *orig, va_list args)
fbddf52c 446{
525cc46c
TB
447 func_comp_t *entry;
448 pts_comp_func_name_t **comp_name;
449 uint32_t *depth;
450 uint8_t *flags;
fbddf52c 451
525cc46c 452 VA_ARGS_VGET(args, flags, depth, comp_name);
fbddf52c 453
525cc46c
TB
454 if (orig->enumerate(orig, &entry))
455 {
456 *flags = entry->comp->get_evidence_flags(entry->comp);
457 *depth = entry->comp->get_depth(entry->comp);
458 *comp_name = entry->name;
459 return TRUE;
460 }
461 return FALSE;
fbddf52c
AS
462}
463
464METHOD(imv_attestation_state_t, create_component_enumerator, enumerator_t*,
465 private_imv_attestation_state_t *this)
466{
467 return enumerator_create_filter(
468 this->components->create_enumerator(this->components),
525cc46c 469 entry_filter, NULL, NULL);
fbddf52c
AS
470}
471
ddafcda4 472METHOD(imv_attestation_state_t, get_component, pts_component_t*,
051dfbd6 473 private_imv_attestation_state_t *this, pts_comp_func_name_t *name)
413922ff
SC
474{
475 enumerator_t *enumerator;
af8354da
AS
476 func_comp_t *entry;
477 pts_component_t *found = NULL;
413922ff 478
a1ac4d5e
AS
479 enumerator = this->components->create_enumerator(this->components);
480 while (enumerator->enumerate(enumerator, &entry))
413922ff 481 {
fbddf52c 482 if (name->equals(name, entry->name))
413922ff 483 {
af8354da 484 found = entry->comp;
925f54d3
AS
485 break;
486 }
e9fd8b4b 487 }
925f54d3
AS
488 enumerator->destroy(enumerator);
489 return found;
e9fd8b4b
SC
490}
491
4894bfa2 492METHOD(imv_attestation_state_t, get_measurement_error, uint32_t,
db087023
AS
493 private_imv_attestation_state_t *this)
494{
ddafcda4 495 return this->measurement_error;
db087023
AS
496}
497
ddafcda4 498METHOD(imv_attestation_state_t, set_measurement_error, void,
4894bfa2 499 private_imv_attestation_state_t *this, uint32_t error)
e9fd8b4b 500{
b8f0bf00 501 this->measurement_error |= error;
e9fd8b4b
SC
502}
503
ddafcda4 504METHOD(imv_attestation_state_t, finalize_components, void,
975472e4 505 private_imv_attestation_state_t *this, bio_writer_t *result)
350f855c 506{
af8354da 507 func_comp_t *entry;
975472e4 508 bool first = TRUE;
350f855c 509
ddafcda4
AS
510 while (this->components->remove_last(this->components,
511 (void**)&entry) == SUCCESS)
512 {
975472e4
AS
513 if (first)
514 {
515 first = FALSE;
516 }
517 else
518 {
519 result->write_data(result, chunk_from_str("; "));
520 }
fbddf52c 521 if (!entry->comp->finalize(entry->comp,
975472e4
AS
522 entry->name->get_qualifier(entry->name),
523 result))
ddafcda4 524 {
b8f0bf00 525 set_measurement_error(this, IMV_ATTESTATION_ERROR_COMP_EVID_PEND);
ddafcda4 526 }
af8354da 527 free_func_comp(entry);
ddafcda4 528 }
350f855c
AS
529}
530
4a492a8d
AS
531/**
532 * Described in header.
533 */
534imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id)
535{
536 private_imv_attestation_state_t *this;
537
538 INIT(this,
539 .public = {
540 .interface = {
541 .get_connection_id = _get_connection_id,
e4e291d4
AS
542 .has_long = _has_long,
543 .has_excl = _has_excl,
544 .set_flags = _set_flags,
968c83cd
AS
545 .set_max_msg_len = _set_max_msg_len,
546 .get_max_msg_len = _get_max_msg_len,
b1da8368
AS
547 .set_action_flags = _set_action_flags,
548 .get_action_flags = _get_action_flags,
a6266485
AS
549 .set_session = _set_session,
550 .get_session = _get_session,
f5096897 551 .get_contracts = _get_contracts,
4a492a8d
AS
552 .change_state = _change_state,
553 .get_recommendation = _get_recommendation,
554 .set_recommendation = _set_recommendation,
a6266485 555 .update_recommendation = _update_recommendation,
4a492a8d 556 .get_reason_string = _get_reason_string,
af83700f 557 .get_remediation_instructions = _get_remediation_instructions,
25973c03 558 .reset = _reset,
4a492a8d
AS
559 .destroy = _destroy,
560 },
12c0a261
SC
561 .get_handshake_state = _get_handshake_state,
562 .set_handshake_state = _set_handshake_state,
8a2482c7 563 .get_pts = _get_pts,
af8354da 564 .create_component = _create_component,
fbddf52c 565 .create_component_enumerator = _create_component_enumerator,
ddafcda4
AS
566 .get_component = _get_component,
567 .finalize_components = _finalize_components,
350f855c
AS
568 .get_measurement_error = _get_measurement_error,
569 .set_measurement_error = _set_measurement_error,
81d49c5c
AS
570 .add_file_meas_reasons = _add_file_meas_reasons,
571 .add_comp_evid_reasons = _add_comp_evid_reasons,
4a492a8d 572 },
8a2482c7 573 .connection_id = connection_id,
4a492a8d 574 .state = TNC_CONNECTION_STATE_CREATE,
ad4866e8 575 .handshake_state = IMV_ATTESTATION_STATE_INIT,
4a492a8d
AS
576 .rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
577 .eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
f5096897 578 .contracts = seg_contract_manager_create(),
a1ac4d5e 579 .components = linked_list_create(),
01e069b6 580 .pts = pts_create(FALSE),
4a492a8d 581 );
d2f49c3d 582
4a492a8d
AS
583 return &this->public.interface;
584}