200de1e191770145f3865315b590a6be93073d3f
[strongswan.git] / src / libpts / plugins / imv_attestation / imv_attestation_state.c
1 /*
2 * Copyright (C) 2011-2012 Sansar Choinyambuu
3 * Copyright (C) 2011-2013 Andreas Steffen
4 * HSR Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "imv_attestation_state.h"
18
19 #include <libpts.h>
20
21 #include <imv/imv_lang_string.h>
22 #include "imv/imv_reason_string.h"
23
24 #include <tncif_policy.h>
25
26 #include <collections/linked_list.h>
27 #include <utils/debug.h>
28
29 typedef struct private_imv_attestation_state_t private_imv_attestation_state_t;
30 typedef struct file_meas_request_t file_meas_request_t;
31 typedef struct func_comp_t func_comp_t;
32
33 /**
34 * Private data of an imv_attestation_state_t object.
35 */
36 struct 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;
52
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
63 /**
64 * Maximum PA-TNC message size for this TNCCS connection
65 */
66 u_int32_t max_msg_len;
67
68 /**
69 * Flags set for completed actions
70 */
71 u_int32_t action_flags;
72
73 /**
74 * Access Requestor ID Type
75 */
76 u_int32_t ar_id_type;
77
78 /**
79 * Access Requestor ID Value
80 */
81 chunk_t ar_id_value;
82
83 /**
84 * IMV database session associated with TNCCS connection
85 */
86 imv_session_t *session;
87
88 /**
89 * IMV Attestation handshake state
90 */
91 imv_attestation_handshake_state_t handshake_state;
92
93 /**
94 * IMV action recommendation
95 */
96 TNC_IMV_Action_Recommendation rec;
97
98 /**
99 * IMV evaluation result
100 */
101 TNC_IMV_Evaluation_Result eval;
102
103 /**
104 * List of Functional Components
105 */
106 linked_list_t *components;
107
108 /**
109 * PTS object
110 */
111 pts_t *pts;
112
113 /**
114 * Measurement error flags
115 */
116 u_int32_t measurement_error;
117
118 /**
119 * TNC Reason String
120 */
121 imv_reason_string_t *reason_string;
122
123 };
124
125 /**
126 * PTS Functional Component entry
127 */
128 struct func_comp_t {
129 pts_component_t *comp;
130 u_int8_t qualifier;
131 };
132
133 /**
134 * Frees a func_comp_t object
135 */
136 static void free_func_comp(func_comp_t *this)
137 {
138 this->comp->destroy(this->comp);
139 free(this);
140 }
141
142 /**
143 * Supported languages
144 */
145 static char* languages[] = { "en", "de", "mn" };
146
147 /**
148 * Table of reason strings
149 */
150 static imv_lang_string_t reason_file_meas_fail[] = {
151 { "en", "Incorrect file measurement" },
152 { "de", "Falsche Dateimessung" },
153 { "mn", "Буруу байгаа файл" },
154 { NULL, NULL }
155 };
156
157 static imv_lang_string_t reason_file_meas_pend[] = {
158 { "en", "Pending file measurement" },
159 { "de", "Ausstehende Dateimessung" },
160 { "mn", "Xүлээгдэж байгаа файл" },
161 { NULL, NULL }
162 };
163
164 static imv_lang_string_t reason_comp_evid_fail[] = {
165 { "en", "Incorrect component evidence" },
166 { "de", "Falsche Komponenten-Evidenz" },
167 { "mn", "Буруу компонент хэмжилт" },
168 { NULL, NULL }
169 };
170
171 static imv_lang_string_t reason_comp_evid_pend[] = {
172 { "en", "Pending component evidence" },
173 { "de", "Ausstehende Komponenten-Evidenz" },
174 { "mn", "Xүлээгдэж компонент хэмжилт" },
175 { NULL, NULL }
176 };
177
178 static imv_lang_string_t reason_tpm_quote_fail[] = {
179 { "en", "Invalid TPM Quote signature received" },
180 { "de", "Falsche TPM Quote Signature erhalten" },
181 { "mn", "Буруу TPM Quote гарын үсэг" },
182 { NULL, NULL }
183 };
184
185 METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
186 private_imv_attestation_state_t *this)
187 {
188 return this->connection_id;
189 }
190
191 METHOD(imv_state_t, has_long, bool,
192 private_imv_attestation_state_t *this)
193 {
194 return this->has_long;
195 }
196
197 METHOD(imv_state_t, has_excl, bool,
198 private_imv_attestation_state_t *this)
199 {
200 return this->has_excl;
201 }
202
203 METHOD(imv_state_t, set_flags, void,
204 private_imv_attestation_state_t *this, bool has_long, bool has_excl)
205 {
206 this->has_long = has_long;
207 this->has_excl = has_excl;
208 }
209
210 METHOD(imv_state_t, set_max_msg_len, void,
211 private_imv_attestation_state_t *this, u_int32_t max_msg_len)
212 {
213 this->max_msg_len = max_msg_len;
214 }
215
216 METHOD(imv_state_t, get_max_msg_len, u_int32_t,
217 private_imv_attestation_state_t *this)
218 {
219 return this->max_msg_len;
220 }
221
222 METHOD(imv_state_t, set_action_flags, void,
223 private_imv_attestation_state_t *this, u_int32_t flags)
224 {
225 this->action_flags |= flags;
226 }
227
228 METHOD(imv_state_t, get_action_flags, u_int32_t,
229 private_imv_attestation_state_t *this)
230 {
231 return this->action_flags;
232 }
233
234 METHOD(imv_state_t, set_ar_id, void,
235 private_imv_attestation_state_t *this, u_int32_t id_type, chunk_t id_value)
236 {
237 this->ar_id_type = id_type;
238 this->ar_id_value = chunk_clone(id_value);
239 }
240
241 METHOD(imv_state_t, get_ar_id, chunk_t,
242 private_imv_attestation_state_t *this, u_int32_t *id_type)
243 {
244 if (id_type)
245 {
246 *id_type = this->ar_id_type;
247 }
248 return this->ar_id_value;
249 }
250
251 METHOD(imv_state_t, set_session, void,
252 private_imv_attestation_state_t *this, imv_session_t *session)
253 {
254 this->session = session;
255 }
256
257 METHOD(imv_state_t, get_session, imv_session_t*,
258 private_imv_attestation_state_t *this)
259 {
260 return this->session;
261 }
262
263 METHOD(imv_state_t, change_state, void,
264 private_imv_attestation_state_t *this, TNC_ConnectionState new_state)
265 {
266 this->state = new_state;
267 }
268
269 METHOD(imv_state_t, get_recommendation, void,
270 private_imv_attestation_state_t *this, TNC_IMV_Action_Recommendation *rec,
271 TNC_IMV_Evaluation_Result *eval)
272 {
273 *rec = this->rec;
274 *eval = this->eval;
275 }
276
277 METHOD(imv_state_t, set_recommendation, void,
278 private_imv_attestation_state_t *this, TNC_IMV_Action_Recommendation rec,
279 TNC_IMV_Evaluation_Result eval)
280 {
281 this->rec = rec;
282 this->eval = eval;
283 }
284
285 METHOD(imv_state_t, update_recommendation, void,
286 private_imv_attestation_state_t *this, TNC_IMV_Action_Recommendation rec,
287 TNC_IMV_Evaluation_Result eval)
288 {
289 this->rec = tncif_policy_update_recommendation(this->rec, rec);
290 this->eval = tncif_policy_update_evaluation(this->eval, eval);
291 }
292
293 METHOD(imv_attestation_state_t, add_file_meas_reasons, void,
294 private_imv_attestation_state_t *this, imv_reason_string_t *reason_string)
295 {
296 if (this->measurement_error & IMV_ATTESTATION_ERROR_FILE_MEAS_FAIL)
297 {
298 reason_string->add_reason(reason_string, reason_file_meas_fail);
299 }
300 if (this->measurement_error & IMV_ATTESTATION_ERROR_FILE_MEAS_PEND)
301 {
302 reason_string->add_reason(reason_string, reason_file_meas_pend);
303 }
304 }
305
306 METHOD(imv_attestation_state_t, add_comp_evid_reasons, void,
307 private_imv_attestation_state_t *this, imv_reason_string_t *reason_string)
308 {
309 if (this->measurement_error & IMV_ATTESTATION_ERROR_COMP_EVID_FAIL)
310 {
311 reason_string->add_reason(reason_string, reason_comp_evid_fail);
312 }
313 if (this->measurement_error & IMV_ATTESTATION_ERROR_COMP_EVID_PEND)
314 {
315 reason_string->add_reason(reason_string, reason_comp_evid_pend);
316 }
317 if (this->measurement_error & IMV_ATTESTATION_ERROR_TPM_QUOTE_FAIL)
318 {
319 reason_string->add_reason(reason_string, reason_tpm_quote_fail);
320 }
321 }
322
323 METHOD(imv_state_t, get_reason_string, bool,
324 private_imv_attestation_state_t *this, enumerator_t *language_enumerator,
325 chunk_t *reason_string, char **reason_language)
326 {
327 *reason_language = imv_lang_string_select_lang(language_enumerator,
328 languages, countof(languages));
329
330 /* Instantiate a TNC Reason String object */
331 DESTROY_IF(this->reason_string);
332 this->reason_string = imv_reason_string_create(*reason_language, "\n");
333 add_file_meas_reasons(this, this->reason_string);
334 add_comp_evid_reasons(this, this->reason_string);
335 *reason_string = this->reason_string->get_encoding(this->reason_string);
336
337 return TRUE;
338 }
339
340 METHOD(imv_state_t, get_remediation_instructions, bool,
341 private_imv_attestation_state_t *this, enumerator_t *language_enumerator,
342 chunk_t *string, char **lang_code, char **uri)
343 {
344 return FALSE;
345 }
346
347 METHOD(imv_state_t, destroy, void,
348 private_imv_attestation_state_t *this)
349 {
350 DESTROY_IF(this->session);
351 DESTROY_IF(this->reason_string);
352 this->components->destroy_function(this->components, (void *)free_func_comp);
353 this->pts->destroy(this->pts);
354 free(this->ar_id_value.ptr);
355 free(this);
356 }
357
358 METHOD(imv_attestation_state_t, get_handshake_state,
359 imv_attestation_handshake_state_t, private_imv_attestation_state_t *this)
360 {
361 return this->handshake_state;
362 }
363
364 METHOD(imv_attestation_state_t, set_handshake_state, void,
365 private_imv_attestation_state_t *this,
366 imv_attestation_handshake_state_t new_state)
367 {
368 this->handshake_state = new_state;
369 }
370
371 METHOD(imv_attestation_state_t, get_pts, pts_t*,
372 private_imv_attestation_state_t *this)
373 {
374 return this->pts;
375 }
376
377 METHOD(imv_attestation_state_t, create_component, pts_component_t*,
378 private_imv_attestation_state_t *this, pts_comp_func_name_t *name,
379 u_int32_t depth, pts_database_t *pts_db)
380 {
381 enumerator_t *enumerator;
382 func_comp_t *entry, *new_entry;
383 pts_component_t *component;
384 bool found = FALSE;
385
386 enumerator = this->components->create_enumerator(this->components);
387 while (enumerator->enumerate(enumerator, &entry))
388 {
389 if (name->equals(name, entry->comp->get_comp_func_name(entry->comp)))
390 {
391 found = TRUE;
392 break;
393 }
394 }
395 enumerator->destroy(enumerator);
396
397 if (found)
398 {
399 if (name->get_qualifier(name) == entry->qualifier)
400 {
401 /* duplicate entry */
402 return NULL;
403 }
404 new_entry = malloc_thing(func_comp_t);
405 new_entry->qualifier = name->get_qualifier(name);
406 new_entry->comp = entry->comp->get_ref(entry->comp);
407 this->components->insert_last(this->components, new_entry);
408 return entry->comp;
409 }
410 else
411 {
412 component = pts_components->create(pts_components, name, depth, pts_db);
413 if (!component)
414 {
415 /* unsupported component */
416 return NULL;
417 }
418 new_entry = malloc_thing(func_comp_t);
419 new_entry->qualifier = name->get_qualifier(name);
420 new_entry->comp = component;
421 this->components->insert_last(this->components, new_entry);
422 return component;
423 }
424 }
425
426 METHOD(imv_attestation_state_t, get_component, pts_component_t*,
427 private_imv_attestation_state_t *this, pts_comp_func_name_t *name)
428 {
429 enumerator_t *enumerator;
430 func_comp_t *entry;
431 pts_component_t *found = NULL;
432
433 enumerator = this->components->create_enumerator(this->components);
434 while (enumerator->enumerate(enumerator, &entry))
435 {
436 if (name->equals(name, entry->comp->get_comp_func_name(entry->comp)) &&
437 name->get_qualifier(name) == entry->qualifier)
438 {
439 found = entry->comp;
440 break;
441 }
442 }
443 enumerator->destroy(enumerator);
444 return found;
445 }
446
447 METHOD(imv_attestation_state_t, get_measurement_error, u_int32_t,
448 private_imv_attestation_state_t *this)
449 {
450 return this->measurement_error;
451 }
452
453 METHOD(imv_attestation_state_t, set_measurement_error, void,
454 private_imv_attestation_state_t *this, u_int32_t error)
455 {
456 this->measurement_error |= error;
457 }
458
459 METHOD(imv_attestation_state_t, finalize_components, void,
460 private_imv_attestation_state_t *this)
461 {
462 func_comp_t *entry;
463
464 while (this->components->remove_last(this->components,
465 (void**)&entry) == SUCCESS)
466 {
467 if (!entry->comp->finalize(entry->comp, entry->qualifier))
468 {
469 set_measurement_error(this, IMV_ATTESTATION_ERROR_COMP_EVID_PEND);
470 }
471 free_func_comp(entry);
472 }
473 }
474
475 METHOD(imv_attestation_state_t, components_finalized, bool,
476 private_imv_attestation_state_t *this)
477 {
478 return this->components->get_count(this->components) == 0;
479 }
480
481 /**
482 * Described in header.
483 */
484 imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id)
485 {
486 private_imv_attestation_state_t *this;
487
488 INIT(this,
489 .public = {
490 .interface = {
491 .get_connection_id = _get_connection_id,
492 .has_long = _has_long,
493 .has_excl = _has_excl,
494 .set_flags = _set_flags,
495 .set_max_msg_len = _set_max_msg_len,
496 .get_max_msg_len = _get_max_msg_len,
497 .set_action_flags = _set_action_flags,
498 .get_action_flags = _get_action_flags,
499 .set_ar_id = _set_ar_id,
500 .get_ar_id = _get_ar_id,
501 .set_session = _set_session,
502 .get_session = _get_session,
503 .change_state = _change_state,
504 .get_recommendation = _get_recommendation,
505 .set_recommendation = _set_recommendation,
506 .update_recommendation = _update_recommendation,
507 .get_reason_string = _get_reason_string,
508 .get_remediation_instructions = _get_remediation_instructions,
509 .destroy = _destroy,
510 },
511 .get_handshake_state = _get_handshake_state,
512 .set_handshake_state = _set_handshake_state,
513 .get_pts = _get_pts,
514 .create_component = _create_component,
515 .get_component = _get_component,
516 .finalize_components = _finalize_components,
517 .components_finalized = _components_finalized,
518 .get_measurement_error = _get_measurement_error,
519 .set_measurement_error = _set_measurement_error,
520 .add_file_meas_reasons = _add_file_meas_reasons,
521 .add_comp_evid_reasons = _add_comp_evid_reasons,
522 },
523 .connection_id = connection_id,
524 .state = TNC_CONNECTION_STATE_CREATE,
525 .handshake_state = IMV_ATTESTATION_STATE_INIT,
526 .rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
527 .eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
528 .components = linked_list_create(),
529 .pts = pts_create(FALSE),
530 );
531
532 return &this->public.interface;
533 }