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