Moved BIOS and IMA measurement lists into classes of their own
[strongswan.git] / src / libpts / pts / components / ita / ita_comp_ima.c
1 /*
2 * Copyright (C) 2011-2014 Andreas Steffen
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 #include "ita_comp_ima.h"
17 #include "ita_comp_func_name.h"
18
19 #include "libpts.h"
20 #include "pts/pts_pcr.h"
21 #include "pts/pts_ima_bios_list.h"
22 #include "pts/pts_ima_event_list.h"
23 #include "pts/components/pts_component.h"
24
25 #include <utils/debug.h>
26 #include <crypto/hashers/hasher.h>
27 #include <pen/pen.h>
28
29 #define SECURITY_DIR "/sys/kernel/security/"
30 #define IMA_BIOS_MEASUREMENTS SECURITY_DIR "tpm0/binary_bios_measurements"
31 #define IMA_RUNTIME_MEASUREMENTS SECURITY_DIR "ima/binary_runtime_measurements"
32 #define IMA_FILENAME_LEN_MAX 255
33
34 typedef struct pts_ita_comp_ima_t pts_ita_comp_ima_t;
35 typedef enum ima_state_t ima_state_t;
36
37 enum ima_state_t {
38 IMA_STATE_INIT,
39 IMA_STATE_BIOS,
40 IMA_STATE_BOOT_AGGREGATE,
41 IMA_STATE_RUNTIME,
42 IMA_STATE_END
43 };
44
45 /**
46 * Private data of a pts_ita_comp_ima_t object.
47 *
48 */
49 struct pts_ita_comp_ima_t {
50
51 /**
52 * Public pts_component_t interface.
53 */
54 pts_component_t public;
55
56 /**
57 * Component Functional Name
58 */
59 pts_comp_func_name_t *name;
60
61 /**
62 * Sub-component depth
63 */
64 uint32_t depth;
65
66 /**
67 * PTS measurement database
68 */
69 pts_database_t *pts_db;
70
71 /**
72 * Primary key for AIK database entry
73 */
74 int aik_id;
75
76 /**
77 * Primary key for IMA BIOS Component Functional Name database entry
78 */
79 int bios_cid;
80
81 /**
82 * Primary key for IMA Runtime Component Functional Name database entry
83 */
84 int ima_cid;
85
86 /**
87 * Component is registering IMA BIOS measurements
88 */
89 bool is_bios_registering;
90
91 /**
92 * Component is registering IMA boot aggregate measurement
93 */
94 bool is_ima_registering;
95
96 /**
97 * Measurement sequence number
98 */
99 int seq_no;
100
101 /**
102 * Expected IMA BIOS measurement count
103 */
104 int bios_count;
105
106 /**
107 * IMA BIOS measurements
108 */
109 pts_ima_bios_list_t *bios_list;
110
111 /**
112 * IMA runtime file measurements
113 */
114 pts_ima_event_list_t *ima_list;
115
116 /**
117 * Whether to send pcr_before and pcr_after info
118 */
119 bool pcr_info;
120
121 /**
122 * Creation time of measurement
123 */
124 time_t creation_time;
125
126 /**
127 * IMA state machine
128 */
129 ima_state_t state;
130
131 /**
132 * Total number of component measurements
133 */
134 int count;
135
136 /**
137 * Number of successful component measurements
138 */
139 int count_ok;
140
141 /**
142 * Number of unknown component measurements
143 */
144 int count_unknown;
145
146 /**
147 * Number of differing component measurements
148 */
149 int count_differ;
150
151 /**
152 * Number of failed component measurements
153 */
154 int count_failed;
155
156 /**
157 * Reference count
158 */
159 refcount_t ref;
160
161 };
162
163 /**
164 * Extend measurement into PCR and create evidence
165 */
166 static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
167 uint8_t qualifier, pts_pcr_t *pcrs,
168 uint32_t pcr, chunk_t measurement)
169 {
170 size_t pcr_len;
171 pts_pcr_transform_t pcr_transform;
172 pts_meas_algorithms_t hash_algo;
173 pts_comp_func_name_t *name;
174 pts_comp_evidence_t *evidence;
175 chunk_t pcr_before = chunk_empty, pcr_after = chunk_empty;
176
177 hash_algo = PTS_MEAS_ALGO_SHA1;
178 pcr_len = HASH_SIZE_SHA1;
179 pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
180
181 if (this->pcr_info)
182 {
183 pcr_before = chunk_clone(pcrs->get(pcrs, pcr));
184 }
185 pcr_after = pcrs->extend(pcrs, pcr, measurement);
186 if (!pcr_after.ptr)
187 {
188 free(pcr_before.ptr);
189 return NULL;
190 }
191 name = this->name->clone(this->name);
192 name->set_qualifier(name, qualifier);
193 evidence = pts_comp_evidence_create(name, this->depth, pcr, hash_algo,
194 pcr_transform, this->creation_time, measurement);
195 if (this->pcr_info)
196 {
197 pcr_after =chunk_clone(pcrs->get(pcrs, pcr));
198 evidence->set_pcr_info(evidence, pcr_before, pcr_after);
199 }
200 return evidence;
201 }
202
203 /**
204 * Generate an IMA or IMA-NG hash from an event digest and event name
205 *
206 * @param digest event digest
207 * @param ima_algo hash algorithm string ("sha1:", "sha256:", etc.)
208 * @param ima_name event name
209 * @param little_endian endianness of client platform
210 * @param algo hash algorithm used by TPM
211 * @param hash_buf hash value to be compared with TPM measurement
212 */
213 static bool ima_hash(chunk_t digest, char *ima_algo, char *ima_name,
214 bool little_endian, pts_meas_algorithms_t algo,
215 char *hash_buf)
216 {
217 hash_algorithm_t hash_alg;
218 hasher_t *hasher;
219 bool success;
220
221 hash_alg = pts_meas_algo_to_hash(algo);
222 hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
223 if (!hasher)
224 {
225 DBG1(DBG_PTS, "%N hasher could not be created",
226 hash_algorithm_short_names, hash_alg);
227 return FALSE;
228 }
229
230 if (ima_algo)
231 {
232 uint32_t d_len, n_len;
233 chunk_t algo_name, event_name, digest_len, name_len;
234
235 /* IMA-NG hash */
236 algo_name = chunk_create(ima_algo, strlen(ima_algo) + 1);
237 event_name = chunk_create(ima_name, strlen(ima_name) + 1);
238
239 d_len = algo_name.len + digest.len;
240 digest_len = chunk_create((uint8_t*)&d_len, sizeof(d_len));
241 /* TODO handle endianness of both client and server platforms */
242
243 n_len = event_name.len;
244 name_len = chunk_create((uint8_t*)&n_len, sizeof(n_len));
245 /* TODO handle endianness of both client and server platforms */
246
247 success = hasher->get_hash(hasher, digest_len, NULL) &&
248 hasher->get_hash(hasher, algo_name, NULL) &&
249 hasher->get_hash(hasher, digest, NULL) &&
250 hasher->get_hash(hasher, name_len, NULL) &&
251 hasher->get_hash(hasher, event_name, hash_buf);
252 }
253 else
254 {
255 u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1];
256 chunk_t file_name;
257
258 /* IMA legacy hash */
259 memset(filename_buffer, 0, sizeof(filename_buffer));
260 strncpy(filename_buffer, ima_name, IMA_FILENAME_LEN_MAX);
261 file_name = chunk_create (filename_buffer, sizeof(filename_buffer));
262
263 success = hasher->get_hash(hasher, digest, NULL) &&
264 hasher->get_hash(hasher, file_name, hash_buf);
265 }
266 hasher->destroy(hasher);
267
268 return success;
269 }
270
271 /**
272 * Compute and check boot aggregate value by hashing PCR0 to PCR7
273 */
274 static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement,
275 char *algo)
276 {
277 u_char pcr_buffer[HASH_SIZE_SHA1];
278 chunk_t boot_aggregate;
279 hasher_t *hasher;
280 uint32_t i;
281 bool success, pcr_ok = TRUE;
282
283 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
284 if (!hasher)
285 {
286 DBG1(DBG_PTS, "%N hasher could not be created",
287 hash_algorithm_short_names, HASH_SHA1);
288 return FALSE;
289 }
290 for (i = 0; i < 8 && pcr_ok; i++)
291 {
292 pcr_ok = hasher->get_hash(hasher, pcrs->get(pcrs, i), NULL);
293 }
294 if (pcr_ok)
295 {
296 pcr_ok = hasher->get_hash(hasher, chunk_empty, pcr_buffer);
297 }
298 hasher->destroy(hasher);
299
300 if (pcr_ok)
301 {
302 boot_aggregate = chunk_create(pcr_buffer, sizeof(pcr_buffer));
303
304 /* TODO handle endianness of client platform */
305 pcr_ok = ima_hash(boot_aggregate, algo, "boot_aggregate",
306 TRUE, PTS_MEAS_ALGO_SHA1, pcr_buffer);
307 }
308 if (pcr_ok)
309 {
310 success = chunk_equals(boot_aggregate, measurement);
311 DBG1(DBG_PTS, "boot aggregate value is %scorrect",
312 success ? "":"in");
313 return success;
314 }
315 else
316 {
317 DBG1(DBG_PTS, "failed to compute boot aggregate value");
318 return FALSE;
319 }
320 }
321
322 METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
323 pts_ita_comp_ima_t *this)
324 {
325 return this->name;
326 }
327
328 METHOD(pts_component_t, get_evidence_flags, uint8_t,
329 pts_ita_comp_ima_t *this)
330 {
331 return PTS_REQ_FUNC_COMP_EVID_PCR;
332 }
333
334 METHOD(pts_component_t, get_depth, uint32_t,
335 pts_ita_comp_ima_t *this)
336 {
337 return this->depth;
338 }
339
340 METHOD(pts_component_t, measure, status_t,
341 pts_ita_comp_ima_t *this, uint8_t qualifier, pts_t *pts,
342 pts_comp_evidence_t **evidence)
343 {
344 pts_pcr_t *pcrs;
345 pts_comp_evidence_t *evid = NULL;
346 size_t algo_len, name_len;
347 chunk_t measurement;
348 char *uri, *algo, *name;
349 uint32_t pcr;
350 status_t status;
351
352 pcrs = pts->get_pcrs(pts);
353
354 if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
355 PTS_ITA_QUALIFIER_TYPE_TRUSTED))
356 {
357 switch (this->state)
358 {
359 case IMA_STATE_INIT:
360 this->bios_list = pts_ima_bios_list_create(
361 IMA_BIOS_MEASUREMENTS);
362 if (!this->bios_list)
363 {
364 return FAILED;
365 }
366 this->creation_time = this->bios_list->get_time(this->bios_list);
367 this->bios_count = this->bios_list->get_count(this->bios_list);
368 this->state = IMA_STATE_BIOS;
369 /* fall through to next state */
370 case IMA_STATE_BIOS:
371 status = this->bios_list->get_next(this->bios_list, &pcr,
372 &measurement);
373 if (status != SUCCESS)
374 {
375 DBG1(DBG_PTS, "could not retrieve bios measurement entry");
376 return status;
377 }
378 evid = extend_pcr(this, qualifier, pcrs, pcr, measurement);
379
380 this->state = this->bios_list->get_count(this->bios_list) ?
381 IMA_STATE_BIOS : IMA_STATE_INIT;
382 break;
383 default:
384 return FAILED;
385 }
386 }
387 else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
388 PTS_ITA_QUALIFIER_TYPE_OS))
389 {
390 switch (this->state)
391 {
392 case IMA_STATE_INIT:
393 this->ima_list = pts_ima_event_list_create(
394 IMA_RUNTIME_MEASUREMENTS);
395 if (!this->ima_list)
396 {
397 return FAILED;
398 }
399 this->creation_time = this->ima_list->get_time(this->ima_list);
400 this->count = this->ima_list->get_count(this->ima_list);
401 this->state = IMA_STATE_BOOT_AGGREGATE;
402 /* fall through to next state */
403 case IMA_STATE_BOOT_AGGREGATE:
404 case IMA_STATE_RUNTIME:
405 status = this->ima_list->get_next(this->ima_list, &measurement,
406 &algo, &name);
407 if (status != SUCCESS)
408 {
409 DBG1(DBG_PTS, "could not retrieve ima measurement entry");
410 return status;
411 }
412 if (this->state == IMA_STATE_BOOT_AGGREGATE && this->bios_count)
413 {
414 if (!check_boot_aggregate(pcrs, measurement, algo))
415 {
416 return FAILED;
417 }
418 }
419 evid = extend_pcr(this, qualifier, pcrs, IMA_PCR,
420 measurement);
421 if (evid)
422 {
423 if (algo)
424 {
425 algo_len = strlen(algo);
426 name_len = strlen(name);
427 uri = malloc(algo_len + name_len + 1);
428 memcpy(uri, algo, algo_len);
429 strcpy(uri + algo_len, name);
430 }
431 else
432 {
433 uri = strdup(name);
434 }
435 evid->set_validation(evid, PTS_COMP_EVID_VALIDATION_PASSED,
436 uri);
437 free(uri);
438 }
439 free(name);
440 free(algo);
441
442 this->state = this->ima_list->get_count(this->ima_list) ?
443 IMA_STATE_RUNTIME : IMA_STATE_END;
444 break;
445 default:
446 return FAILED;
447 }
448 }
449 else
450 {
451 DBG1(DBG_PTS, "unsupported functional component name qualifier");
452 return FAILED;
453 }
454
455 *evidence = evid;
456 if (!evid)
457 {
458 return FAILED;
459 }
460
461 return (this->state == IMA_STATE_INIT || this->state == IMA_STATE_END) ?
462 SUCCESS : NEED_MORE;
463 }
464
465 /**
466 * Parse a validation URI of the form <hash algorithm>:<event name>
467 * into its components
468 */
469 static pts_meas_algorithms_t parse_validation_uri(pts_comp_evidence_t *evidence,
470 char **ima_name, char **ima_algo, char *algo_buf)
471 {
472 pts_meas_algorithms_t hash_algo;
473 char *uri, *pos, *algo, *name;
474
475 evidence->get_validation(evidence, &uri);
476
477 /* IMA-NG format? */
478 pos = strchr(uri, ':');
479 if (pos && (pos - uri + 1) < IMA_ALGO_LEN_MAX)
480 {
481 memset(algo_buf, '\0', IMA_ALGO_LEN_MAX);
482 memcpy(algo_buf, uri, pos - uri + 1);
483 algo = algo_buf;
484 name = pos + 1;
485
486 if (streq(algo, "sha1:") || streq(algo, ":"))
487 {
488 hash_algo = PTS_MEAS_ALGO_SHA1;
489 }
490 else if (streq(algo, "sha256:"))
491 {
492 hash_algo = PTS_MEAS_ALGO_SHA256;
493 }
494 else if (streq(algo, "sha384:"))
495 {
496 hash_algo = PTS_MEAS_ALGO_SHA384;
497 }
498 else
499 {
500 hash_algo = PTS_MEAS_ALGO_NONE;
501 }
502 }
503 else
504 {
505 algo = NULL;
506 name = uri;
507 hash_algo = PTS_MEAS_ALGO_SHA1;
508 }
509
510 if (ima_name)
511 {
512 *ima_name = name;
513 }
514 if (ima_algo)
515 {
516 *ima_algo = algo;
517 }
518
519 return hash_algo;
520 }
521
522 METHOD(pts_component_t, verify, status_t,
523 pts_ita_comp_ima_t *this, uint8_t qualifier, pts_t *pts,
524 pts_comp_evidence_t *evidence)
525 {
526 bool has_pcr_info;
527 uint32_t pcr;
528 pts_meas_algorithms_t algo;
529 pts_pcr_transform_t transform;
530 pts_pcr_t *pcrs;
531 time_t creation_time;
532 chunk_t measurement, pcr_before, pcr_after;
533 status_t status = NOT_FOUND;
534
535 this->aik_id = pts->get_aik_id(pts);
536 pcrs = pts->get_pcrs(pts);
537 measurement = evidence->get_measurement(evidence, &pcr, &algo, &transform,
538 &creation_time);
539
540 if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
541 PTS_ITA_QUALIFIER_TYPE_TRUSTED))
542 {
543 switch (this->state)
544 {
545 case IMA_STATE_INIT:
546 this->name->set_qualifier(this->name, qualifier);
547 status = this->pts_db->get_comp_measurement_count(this->pts_db,
548 this->name, this->aik_id, algo,
549 &this->bios_cid, &this->bios_count);
550 this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
551 if (status != SUCCESS)
552 {
553 return status;
554 }
555
556 if (this->bios_count)
557 {
558 DBG1(DBG_PTS, "checking %d BIOS evidence measurements",
559 this->bios_count);
560 }
561 else
562 {
563 DBG1(DBG_PTS, "registering BIOS evidence measurements");
564 this->is_bios_registering = TRUE;
565 }
566
567 this->state = IMA_STATE_BIOS;
568 /* fall through to next state */
569 case IMA_STATE_BIOS:
570 if (this->is_bios_registering)
571 {
572 status = this->pts_db->insert_comp_measurement(this->pts_db,
573 measurement, this->bios_cid, this->aik_id,
574 ++this->seq_no, pcr, algo);
575 if (status != SUCCESS)
576 {
577 return status;
578 }
579 this->bios_count = this->seq_no + 1;
580 }
581 else
582 {
583 status = this->pts_db->check_comp_measurement(this->pts_db,
584 measurement, this->bios_cid, this->aik_id,
585 ++this->seq_no, pcr, algo);
586 if (status == FAILED)
587 {
588 return status;
589 }
590 }
591 break;
592 default:
593 return FAILED;
594 }
595 }
596 else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
597 PTS_ITA_QUALIFIER_TYPE_OS))
598 {
599 int ima_count;
600 char *ima_algo, *ima_name;
601 char algo_buf[IMA_ALGO_LEN_MAX];
602 pts_meas_algorithms_t hash_algo;
603
604 hash_algo = parse_validation_uri(evidence, &ima_name, &ima_algo,
605 algo_buf);
606
607 switch (this->state)
608 {
609 case IMA_STATE_BIOS:
610 this->state = IMA_STATE_RUNTIME;
611
612 if (!streq(ima_name, "boot_aggregate"))
613 {
614 DBG1(DBG_PTS, "ima: name must be 'boot_aggregate' "
615 "but is '%s'", ima_name);
616 return FAILED;
617 }
618 if (hash_algo != PTS_MEAS_ALGO_SHA1)
619 {
620 DBG1(DBG_PTS, "ima: boot_aggregate algorithm must be %N "
621 "but is %N",
622 pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1,
623 pts_meas_algorithm_names, hash_algo);
624 return FAILED;
625 }
626 if (!check_boot_aggregate(pcrs, measurement, ima_algo))
627 {
628 return FAILED;
629 }
630 this->state = IMA_STATE_INIT;
631 /* fall through to next state */
632 case IMA_STATE_INIT:
633 this->name->set_qualifier(this->name, qualifier);
634 status = this->pts_db->get_comp_measurement_count(this->pts_db,
635 this->name, this->aik_id, algo,
636 &this->ima_cid, &ima_count);
637 this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
638 if (status != SUCCESS)
639 {
640 return status;
641 }
642
643 if (ima_count)
644 {
645 DBG1(DBG_PTS, "checking boot aggregate evidence "
646 "measurement");
647 status = this->pts_db->check_comp_measurement(this->pts_db,
648 measurement, this->ima_cid,
649 this->aik_id, 1, pcr, algo);
650 }
651 else
652 {
653 DBG1(DBG_PTS, "registering boot aggregate evidence "
654 "measurement");
655 this->is_ima_registering = TRUE;
656 status = this->pts_db->insert_comp_measurement(this->pts_db,
657 measurement, this->ima_cid,
658 this->aik_id, 1, pcr, algo);
659 }
660 this->state = IMA_STATE_RUNTIME;
661
662 if (status != SUCCESS)
663 {
664 return status;
665 }
666 break;
667 case IMA_STATE_RUNTIME:
668 {
669 uint8_t hash_buf[HASH_SIZE_SHA512];
670 chunk_t digest, hash;
671 enumerator_t *e;
672
673 this->count++;
674 if (evidence->get_validation(evidence, NULL) !=
675 PTS_COMP_EVID_VALIDATION_PASSED)
676 {
677 DBG1(DBG_PTS, "evidence validation failed");
678 this->count_failed++;
679 return FAILED;
680 }
681 hash = chunk_create(hash_buf, pts_meas_algo_hash_size(algo));
682
683 e = this->pts_db->create_file_meas_enumerator(this->pts_db,
684 pts->get_platform_id(pts),
685 hash_algo, ima_name);
686 if (e)
687 {
688 while (e->enumerate(e, &digest))
689 {
690 if (!ima_hash(digest, ima_algo, ima_name,
691 FALSE, algo, hash_buf))
692 {
693 status = FAILED;
694 break;
695 }
696 if (chunk_equals(measurement, hash))
697 {
698 status = SUCCESS;
699 break;
700 }
701 else
702 {
703 status = VERIFY_ERROR;
704 }
705 }
706 e->destroy(e);
707 }
708 else
709 {
710 status = FAILED;
711 }
712
713 switch (status)
714 {
715 case SUCCESS:
716 DBG3(DBG_PTS, "%#B for '%s' is ok",
717 &measurement, ima_name);
718 this->count_ok++;
719 break;
720 case NOT_FOUND:
721 DBG2(DBG_PTS, "%#B for '%s' not found",
722 &measurement, ima_name);
723 this->count_unknown++;
724 break;
725 case VERIFY_ERROR:
726 DBG1(DBG_PTS, "%#B for '%s' differs",
727 &measurement, ima_name);
728 this->count_differ++;
729 break;
730 case FAILED:
731 default:
732 DBG1(DBG_PTS, "%#B for '%s' failed",
733 &measurement, ima_name);
734 this->count_failed++;
735 }
736 break;
737 }
738 default:
739 return FAILED;
740 }
741 }
742 else
743 {
744 DBG1(DBG_PTS, "unsupported functional component name qualifier");
745 return FAILED;
746 }
747
748 has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
749 if (has_pcr_info)
750 {
751 if (!chunk_equals(pcr_before, pcrs->get(pcrs, pcr)))
752 {
753 DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
754 pcr);
755 }
756 if (pcrs->set(pcrs, pcr, pcr_after))
757 {
758 return status;
759 }
760 }
761 else
762 {
763 pcr_after = pcrs->extend(pcrs, pcr, measurement);
764 if (pcr_after.ptr)
765 {
766 return status;
767 }
768 }
769 return FAILED;
770 }
771
772 METHOD(pts_component_t, finalize, bool,
773 pts_ita_comp_ima_t *this, uint8_t qualifier, bio_writer_t *result)
774 {
775 char result_buf[BUF_LEN];
776 char *pos = result_buf;
777 size_t len = BUF_LEN;
778 int written;
779 bool success = TRUE;
780
781 this->name->set_qualifier(this->name, qualifier);
782
783 if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
784 PTS_ITA_QUALIFIER_TYPE_TRUSTED))
785 {
786 /* finalize BIOS measurements */
787 if (this->is_bios_registering)
788 {
789 /* close registration */
790 this->is_bios_registering = FALSE;
791
792 snprintf(pos, len, "registered %d BIOS evidence measurements",
793 this->seq_no);
794 }
795 else if (this->seq_no < this->bios_count)
796 {
797 snprintf(pos, len, "%d of %d BIOS evidence measurements missing",
798 this->bios_count - this->seq_no, this->bios_count);
799 success = FALSE;
800 }
801 else
802 {
803 snprintf(pos, len, "%d BIOS evidence measurements are ok",
804 this->bios_count);
805 }
806 }
807 else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
808 PTS_ITA_QUALIFIER_TYPE_OS))
809 {
810 /* finalize IMA file measurements */
811 if (this->is_ima_registering)
812 {
813 /* close registration */
814 this->is_ima_registering = FALSE;
815
816 written = snprintf(pos, len, "registered IMA boot aggregate "
817 "evidence measurement; ");
818 pos += written;
819 len -= written;
820 }
821 if (this->count)
822 {
823 snprintf(pos, len, "processed %d IMA file evidence measurements: "
824 "%d ok, %d unknown, %d differ, %d failed",
825 this->count, this->count_ok, this->count_unknown,
826 this->count_differ, this->count_failed);
827 }
828 else
829 {
830 snprintf(pos, len, "no IMA file evidence measurements");
831 success = FALSE;
832 }
833 }
834 else
835 {
836 snprintf(pos, len, "unsupported functional component name qualifier");
837 success = FALSE;
838 }
839 this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
840
841 DBG1(DBG_PTS, "%s", result_buf);
842 result->write_data(result, chunk_from_str(result_buf));
843
844 return success;
845 }
846
847 METHOD(pts_component_t, get_ref, pts_component_t*,
848 pts_ita_comp_ima_t *this)
849 {
850 ref_get(&this->ref);
851 return &this->public;
852 }
853
854 METHOD(pts_component_t, destroy, void,
855 pts_ita_comp_ima_t *this)
856 {
857 int count;
858
859 if (ref_put(&this->ref))
860 {
861
862 if (this->is_bios_registering)
863 {
864 count = this->pts_db->delete_comp_measurements(this->pts_db,
865 this->bios_cid, this->aik_id);
866 DBG1(DBG_PTS, "deleted %d registered BIOS evidence measurements",
867 count);
868 }
869 if (this->is_ima_registering)
870 {
871 count = this->pts_db->delete_comp_measurements(this->pts_db,
872 this->ima_cid, this->aik_id);
873 DBG1(DBG_PTS, "deleted registered boot aggregate evidence "
874 "measurement");
875 }
876 DESTROY_IF(this->bios_list);
877 DESTROY_IF(this->ima_list);
878 this->name->destroy(this->name);
879
880 free(this);
881 }
882 }
883
884 /**
885 * See header
886 */
887 pts_component_t *pts_ita_comp_ima_create(uint32_t depth,
888 pts_database_t *pts_db)
889 {
890 pts_ita_comp_ima_t *this;
891
892 INIT(this,
893 .public = {
894 .get_comp_func_name = _get_comp_func_name,
895 .get_evidence_flags = _get_evidence_flags,
896 .get_depth = _get_depth,
897 .measure = _measure,
898 .verify = _verify,
899 .finalize = _finalize,
900 .get_ref = _get_ref,
901 .destroy = _destroy,
902 },
903 .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_IMA,
904 PTS_QUALIFIER_UNKNOWN),
905 .depth = depth,
906 .pts_db = pts_db,
907 .pcr_info = lib->settings->get_bool(lib->settings,
908 "%s.plugins.imc-attestation.pcr_info", TRUE, lib->ns),
909 .ref = 1,
910 );
911
912 return &this->public;
913 }
914