2 * Copyright (C) 2011-2014 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
16 #include "pts_ima_bios_list.h"
18 #include <utils/debug.h>
20 #include <sys/types.h>
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 typedef enum event_type_t event_type_t
;
31 /* BIOS Events (TCG PC Client Specification for Convential BIOS 1.21) */
32 EV_PREBOOT_CERT
= 0x00000000,
33 EV_POST_CODE
= 0x00000001,
34 EV_UNUSED
= 0x00000002,
35 EV_NO_ACTION
= 0x00000003,
36 EV_SEPARATOR
= 0x00000004,
37 EV_ACTION
= 0x00000005,
38 EV_EVENT_TAG
= 0x00000006,
39 EV_S_CRTM_CONTENTS
= 0x00000007,
40 EV_S_CRTM_VERSION
= 0x00000008,
41 EV_CPU_MICROCODE
= 0x00000009,
42 EV_PLATFORM_CONFIG_FLAGS
= 0x0000000A,
43 EV_TABLE_OF_DEVICES
= 0x0000000B,
44 EV_COMPACT_HASH
= 0x0000000C,
46 EV_IPL_PARTITION_DATA
= 0x0000000E,
47 EV_NONHOST_CODE
= 0x0000000F,
48 EV_NONHOST_CONFIG
= 0x00000010,
49 EV_NONHOST_INFO
= 0x00000011,
50 EV_OMIT_BOOT_DEVICE_EVENTS
= 0x00000012,
52 /* EFI Events (TCG EFI Platform Specification 1.22) */
53 EV_EFI_EVENT_BASE
= 0x80000000,
54 EV_EFI_VARIABLE_DRIVER_CONFIG
= 0x80000001,
55 EV_EFI_VARIABLE_BOOT
= 0x80000002,
56 EV_EFI_BOOT_SERVICES_APPLICATION
= 0x80000003,
57 EV_EFI_BOOT_SERVICES_DRIVER
= 0x80000004,
58 EV_EFI_RUNTIME_SERVICES_DRIVER
= 0x80000005,
59 EV_EFI_GPT_EVENT
= 0x80000006,
60 EV_EFI_ACTION
= 0x80000007,
61 EV_EFI_PLATFORM_FIRMWARE_BLOB
= 0x80000008,
62 EV_EFI_HANDOFF_TABLES
= 0x80000009,
64 EV_EFI_VARIABLE_AUTHORITY
= 0x800000E0
67 ENUM_BEGIN(event_type_names
, EV_PREBOOT_CERT
, EV_OMIT_BOOT_DEVICE_EVENTS
,
78 "Platform Config Flags",
86 "Omit Boot Device Events"
89 ENUM_NEXT(event_type_names
, EV_EFI_EVENT_BASE
, EV_EFI_HANDOFF_TABLES
,
90 EV_OMIT_BOOT_DEVICE_EVENTS
,
92 "EFI Variable Driver Config",
94 "EFI Boot Services Application",
95 "EFI Boot Services Driver",
96 "EFI Runtime Services Driver",
99 "EFI Platform Firmware Blob",
102 ENUM_NEXT(event_type_names
, EV_EFI_VARIABLE_AUTHORITY
, EV_EFI_VARIABLE_AUTHORITY
,
103 EV_EFI_HANDOFF_TABLES
,
104 "EFI Variable Authority"
106 ENUM_END(event_type_names
, EV_EFI_VARIABLE_AUTHORITY
);
109 * Private data of a pts_ima_bios_list_t object.
112 struct private_pts_ima_bios_list_t
{
115 * Public pts_ima_bios_list_t interface.
117 pts_ima_bios_list_t
public;
120 * List of BIOS measurement entries
125 * Time when BIOS measurements were taken
127 time_t creation_time
;
132 * Linux IMA BIOS measurement entry
134 struct bios_entry_t
{
142 * SHA1 measurement hash
148 * Free a bios_entry_t object
150 static void free_bios_entry(bios_entry_t
*this)
152 free(this->measurement
.ptr
);
156 METHOD(pts_ima_bios_list_t
, get_time
, time_t,
157 private_pts_ima_bios_list_t
*this)
159 return this->creation_time
;
162 METHOD(pts_ima_bios_list_t
, get_count
, int,
163 private_pts_ima_bios_list_t
*this)
165 return this->list
->get_count(this->list
);
168 METHOD(pts_ima_bios_list_t
, get_next
, status_t
,
169 private_pts_ima_bios_list_t
*this, uint32_t *pcr
, chunk_t
*measurement
)
174 status
= this->list
->remove_first(this->list
, (void**)&entry
);
176 *measurement
= entry
->measurement
;
182 METHOD(pts_ima_bios_list_t
, destroy
, void,
183 private_pts_ima_bios_list_t
*this)
185 this->list
->destroy_function(this->list
, (void *)free_bios_entry
);
192 pts_ima_bios_list_t
* pts_ima_bios_list_create(char *file
)
194 private_pts_ima_bios_list_t
*this;
195 uint32_t pcr
, event_type
, event_len
, seek_len
;
196 uint32_t buf_len
= 2048;
197 uint8_t event_buf
[buf_len
];
204 fd
= open(file
, O_RDONLY
);
207 DBG1(DBG_PTS
, "opening '%s' failed: %s", file
, strerror(errno
));
211 if (fstat(fd
, &st
) == -1)
213 DBG1(DBG_PTS
, "getting statistics of '%s' failed: %s", file
,
221 .get_time
= _get_time
,
222 .get_count
= _get_count
,
223 .get_next
= _get_next
,
226 .creation_time
= st
.st_ctime
,
227 .list
= linked_list_create(),
230 DBG2(DBG_PTS
, "PCR Event Type (Size)");
233 res
= read(fd
, &pcr
, 4);
236 DBG2(DBG_PTS
, "loaded bios measurements '%s' (%d entries)",
237 file
, this->list
->get_count(this->list
));
239 return &this->public;
242 entry
= malloc_thing(bios_entry_t
);
244 entry
->measurement
= chunk_alloc(HASH_SIZE_SHA1
);
250 if (read(fd
, &event_type
, 4) != 4)
254 if (read(fd
, entry
->measurement
.ptr
, HASH_SIZE_SHA1
) != HASH_SIZE_SHA1
)
258 if (read(fd
, &event_len
, 4) != 4)
262 DBG2(DBG_PTS
, "%2u %N (%u bytes)", pcr
, event_type_names
, event_type
,
265 seek_len
= (event_len
> buf_len
) ? event_len
- buf_len
: 0;
266 event_len
-= seek_len
;
268 if (read(fd
, event_buf
, event_len
) != event_len
)
272 event
= chunk_create(event_buf
, event_len
);
273 DBG3(DBG_PTS
,"%B", &event
);
275 if (event_type
== EV_ACTION
|| event_type
== EV_EFI_ACTION
)
277 DBG2(DBG_PTS
, " '%.*s'", event_len
, event_buf
);
280 if (seek_len
> 0 && lseek(fd
, seek_len
, SEEK_CUR
) == -1)
284 this->list
->insert_last(this->list
, entry
);
287 DBG1(DBG_PTS
, "loading bios measurements '%s' failed: %s", file
,
289 free_bios_entry(entry
);