Moved BIOS and IMA measurement lists into classes of their own
[strongswan.git] / src / libpts / pts / pts_ima_bios_list.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 "pts_ima_bios_list.h"
17
18 #include <utils/debug.h>
19
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <errno.h>
25
26 typedef struct private_pts_ima_bios_list_t private_pts_ima_bios_list_t;
27 typedef struct bios_entry_t bios_entry_t;
28
29 /**
30 * Private data of a pts_ima_bios_list_t object.
31 *
32 */
33 struct private_pts_ima_bios_list_t {
34
35 /**
36 * Public pts_ima_bios_list_t interface.
37 */
38 pts_ima_bios_list_t public;
39
40 /**
41 * List of BIOS measurement entries
42 */
43 linked_list_t *list;
44
45 /**
46 * Time when BIOS measurements were taken
47 */
48 time_t creation_time;
49
50 };
51
52 /**
53 * Linux IMA BIOS measurement entry
54 */
55 struct bios_entry_t {
56
57 /**
58 * PCR register
59 */
60 uint32_t pcr;
61
62 /**
63 * SHA1 measurement hash
64 */
65 chunk_t measurement;
66 };
67
68 /**
69 * Free a bios_entry_t object
70 */
71 static void free_bios_entry(bios_entry_t *this)
72 {
73 free(this->measurement.ptr);
74 free(this);
75 }
76
77 METHOD(pts_ima_bios_list_t, get_time, time_t,
78 private_pts_ima_bios_list_t *this)
79 {
80 return this->creation_time;
81 }
82
83 METHOD(pts_ima_bios_list_t, get_count, int,
84 private_pts_ima_bios_list_t *this)
85 {
86 return this->list->get_count(this->list);
87 }
88
89 METHOD(pts_ima_bios_list_t, get_next, status_t,
90 private_pts_ima_bios_list_t *this, uint32_t *pcr, chunk_t *measurement)
91 {
92 bios_entry_t *entry;
93 status_t status;
94
95 status = this->list->remove_first(this->list, (void**)&entry);
96 *pcr = entry->pcr;
97 *measurement = entry->measurement;
98 free(entry);
99
100 return status;
101 }
102
103 METHOD(pts_ima_bios_list_t, destroy, void,
104 private_pts_ima_bios_list_t *this)
105 {
106 this->list->destroy_function(this->list, (void *)free_bios_entry);
107 free(this);
108 }
109
110 /**
111 * See header
112 */
113 pts_ima_bios_list_t* pts_ima_bios_list_create(char *file)
114 {
115 private_pts_ima_bios_list_t *this;
116 uint32_t pcr, num, len;
117 bios_entry_t *entry;
118 struct stat st;
119 ssize_t res;
120 int fd;
121
122 fd = open(file, O_RDONLY);
123 if (fd == -1)
124 {
125 DBG1(DBG_PTS, "opening '%s' failed: %s", file, strerror(errno));
126 return NULL;
127 }
128
129 if (fstat(fd, &st) == -1)
130 {
131 DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file,
132 strerror(errno));
133 close(fd);
134 return FALSE;
135 }
136
137 INIT(this,
138 .public = {
139 .get_time = _get_time,
140 .get_count = _get_count,
141 .get_next = _get_next,
142 .destroy = _destroy,
143 },
144 .creation_time = st.st_ctime,
145 .list = linked_list_create(),
146 );
147
148 while (TRUE)
149 {
150 res = read(fd, &pcr, 4);
151 if (res == 0)
152 {
153 DBG2(DBG_PTS, "loaded bios measurements '%s' (%d entries)",
154 file, this->list->get_count(this->list));
155 close(fd);
156 return &this->public;
157 }
158
159 entry = malloc_thing(bios_entry_t);
160 entry->pcr = pcr;
161 entry->measurement = chunk_alloc(HASH_SIZE_SHA1);
162
163 if (res != 4)
164 {
165 break;
166 }
167 if (read(fd, &num, 4) != 4)
168 {
169 break;
170 }
171 if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1)
172 {
173 break;
174 }
175 if (read(fd, &len, 4) != 4)
176 {
177 break;
178 }
179 if (lseek(fd, len, SEEK_CUR) == -1)
180 {
181 break;
182 }
183 this->list->insert_last(this->list, entry);
184 }
185
186 DBG1(DBG_PTS, "loading bios measurements '%s' failed: %s", file,
187 strerror(errno));
188 free_bios_entry(entry);
189 close(fd);
190 destroy(this);
191
192 return NULL;
193 }