Annotation of embedaddon/strongswan/src/libimcv/pts/pts_ima_bios_list.c, revision 1.1.1.1

1.1       misho       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: typedef enum event_type_t event_type_t;
                     29: 
                     30: enum event_type_t {
                     31:        /* BIOS Events (TCG PC Client Specification for Conventional 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,
                     45:        EV_IPL =                           0x0000000D,
                     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,
                     51: 
                     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,
                     63: 
                     64:        EV_EFI_HCRTM_EVENT =               0x80000010,
                     65: 
                     66:        EV_EFI_VARIABLE_AUTHORITY =        0x800000E0
                     67: };
                     68: 
                     69: ENUM_BEGIN(event_type_names, EV_PREBOOT_CERT, EV_OMIT_BOOT_DEVICE_EVENTS,
                     70:        "Preboot Cert",
                     71:        "POST Code",
                     72:        "Unused",
                     73:        "No Action",
                     74:        "Separator",
                     75:        "Action",
                     76:        "Event Tag",
                     77:        "S-CRTM Contents",
                     78:        "S-CRTM Version",
                     79:        "CPU Microcode",
                     80:        "Platform Config Flags",
                     81:        "Table of Devices",
                     82:        "Compact Hash",
                     83:        "IPL",
                     84:        "IPL Partition Data",
                     85:        "Nonhost Code",
                     86:        "Nonhost Config",
                     87:        "Nonhost Info",
                     88:        "Omit Boot Device Events"
                     89: );
                     90: ENUM_NEXT(event_type_names, EV_EFI_EVENT_BASE, EV_EFI_HANDOFF_TABLES,
                     91:                                                        EV_OMIT_BOOT_DEVICE_EVENTS,
                     92:        "EFI Event Base",
                     93:        "EFI Variable Driver Config",
                     94:        "EFI Variable Boot",
                     95:        "EFI Boot Services Application",
                     96:        "EFI Boot Services Driver",
                     97:        "EFI Runtime Services Driver",
                     98:        "EFI GPT Event",
                     99:        "EFI Action",
                    100:        "EFI Platform Firmware Blob",
                    101:        "EFI Handoff Tables"
                    102: );
                    103: ENUM_NEXT(event_type_names, EV_EFI_HCRTM_EVENT, EV_EFI_HCRTM_EVENT,
                    104:                                                        EV_EFI_HANDOFF_TABLES,
                    105:        "EFI HCRTM Event"
                    106: );
                    107: ENUM_NEXT(event_type_names, EV_EFI_VARIABLE_AUTHORITY, EV_EFI_VARIABLE_AUTHORITY,
                    108:                                                        EV_EFI_HCRTM_EVENT,
                    109:        "EFI Variable Authority"
                    110: );
                    111: ENUM_END(event_type_names, EV_EFI_VARIABLE_AUTHORITY);
                    112: 
                    113: /**
                    114:  * Private data of a pts_ima_bios_list_t object.
                    115:  *
                    116:  */
                    117: struct private_pts_ima_bios_list_t {
                    118: 
                    119:        /**
                    120:         * Public pts_ima_bios_list_t interface.
                    121:         */
                    122:        pts_ima_bios_list_t public;
                    123: 
                    124:        /**
                    125:         * List of BIOS measurement entries
                    126:         */
                    127:        linked_list_t *list;
                    128: 
                    129:        /**
                    130:         * Time when BIOS measurements were taken
                    131:         */
                    132:        time_t creation_time;
                    133: 
                    134: };
                    135: 
                    136: /**
                    137:  * Linux IMA BIOS measurement entry
                    138:  */
                    139: struct bios_entry_t {
                    140: 
                    141:        /**
                    142:         * PCR register
                    143:         */
                    144:        uint32_t pcr;
                    145: 
                    146:        /**
                    147:         * SHA1 measurement hash
                    148:         */
                    149:        chunk_t measurement;
                    150: };
                    151: 
                    152: /**
                    153:  * Free a bios_entry_t object
                    154:  */
                    155: static void free_bios_entry(bios_entry_t *this)
                    156: {
                    157:        free(this->measurement.ptr);
                    158:        free(this);
                    159: }
                    160: 
                    161: METHOD(pts_ima_bios_list_t, get_time, time_t,
                    162:        private_pts_ima_bios_list_t *this)
                    163: {
                    164:        return this->creation_time;
                    165: }
                    166: 
                    167: METHOD(pts_ima_bios_list_t, get_count, int,
                    168:        private_pts_ima_bios_list_t *this)
                    169: {
                    170:        return this->list->get_count(this->list);
                    171: }
                    172: 
                    173: METHOD(pts_ima_bios_list_t, get_next, status_t,
                    174:        private_pts_ima_bios_list_t *this, uint32_t *pcr, chunk_t *measurement)
                    175: {
                    176:        bios_entry_t *entry;
                    177:        status_t status;
                    178: 
                    179:        status = this->list->remove_first(this->list, (void**)&entry);
                    180:        *pcr = entry->pcr;
                    181:        *measurement = entry->measurement;
                    182:        free(entry);
                    183: 
                    184:        return status;
                    185: }
                    186: 
                    187: METHOD(pts_ima_bios_list_t, destroy, void,
                    188:        private_pts_ima_bios_list_t *this)
                    189: {
                    190:        this->list->destroy_function(this->list, (void *)free_bios_entry);
                    191:        free(this);
                    192: }
                    193: 
                    194: /**
                    195:  * See header
                    196:  */
                    197: pts_ima_bios_list_t* pts_ima_bios_list_create(char *file)
                    198: {
                    199:        private_pts_ima_bios_list_t *this;
                    200:        uint32_t pcr, event_type, event_len, seek_len;
                    201:        uint32_t buf_len = 2048;
                    202:        uint8_t event_buf[buf_len];
                    203:        chunk_t event;
                    204:        bios_entry_t *entry;
                    205:        struct stat st;
                    206:        ssize_t res;
                    207:        int fd;
                    208: 
                    209:        fd = open(file, O_RDONLY);
                    210:        if (fd == -1)
                    211:        {
                    212:                DBG1(DBG_PTS, "opening '%s' failed: %s", file, strerror(errno));
                    213:                return NULL;
                    214:        }
                    215: 
                    216:        if (fstat(fd, &st) == -1)
                    217:        {
                    218:                DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file,
                    219:                         strerror(errno));
                    220:                close(fd);
                    221:                return FALSE;
                    222:        }
                    223: 
                    224:        INIT(this,
                    225:                .public = {
                    226:                        .get_time = _get_time,
                    227:                        .get_count = _get_count,
                    228:                        .get_next = _get_next,
                    229:                        .destroy = _destroy,
                    230:                },
                    231:                .creation_time = st.st_ctime,
                    232:                .list = linked_list_create(),
                    233:        );
                    234: 
                    235:        DBG2(DBG_PTS, "PCR Event Type  (Size)");
                    236:        while (TRUE)
                    237:        {
                    238:                res = read(fd, &pcr, 4);
                    239:                if (res == 0)
                    240:                {
                    241:                        DBG2(DBG_PTS, "loaded bios measurements '%s' (%d entries)",
                    242:                                 file, this->list->get_count(this->list));
                    243:                        close(fd);
                    244:                        return &this->public;
                    245:                }
                    246: 
                    247:                entry = malloc_thing(bios_entry_t);
                    248:                entry->pcr = pcr;
                    249:                entry->measurement = chunk_alloc(HASH_SIZE_SHA1);
                    250: 
                    251:                if (res != 4)
                    252:                {
                    253:                        break;
                    254:                }
                    255:                if (read(fd, &event_type, 4) != 4)
                    256:                {
                    257:                        break;
                    258:                }
                    259:                if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1)
                    260:                {
                    261:                        break;
                    262:                }
                    263:                if (read(fd, &event_len, 4) != 4)
                    264:                {
                    265:                        break;
                    266:                }
                    267:                DBG2(DBG_PTS, "%2u  %N  (%u bytes)", pcr, event_type_names, event_type,
                    268:                                                                                         event_len);
                    269: 
                    270:                seek_len = (event_len > buf_len) ? event_len - buf_len : 0;
                    271:                event_len -= seek_len;
                    272: 
                    273:                if (read(fd, event_buf, event_len) != event_len)
                    274:                {
                    275:                        break;
                    276:                }
                    277:                event = chunk_create(event_buf, event_len);
                    278:                DBG3(DBG_PTS,"%B", &event);
                    279: 
                    280:                if (event_type == EV_ACTION || event_type == EV_EFI_ACTION)
                    281:                {
                    282:                        DBG2(DBG_PTS, "     '%.*s'", event_len, event_buf);
                    283:                }
                    284: 
                    285:                if (seek_len > 0 && lseek(fd, seek_len, SEEK_CUR) == -1)
                    286:                {
                    287:                                break;
                    288:                }
                    289:                this->list->insert_last(this->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:        destroy(this);
                    297: 
                    298:        return NULL;
                    299: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>