Philipp Deppenwiese (zaolin.daisuki@googlemail.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/16328
-gerrit
commit 802366eaaa89674c58c2ba416f9cf13d84672c13 Author: Philipp Deppenwiese zaolin@das-labor.org Date: Fri Aug 26 02:10:51 2016 +0200
util/intelmetool: Add bootguard information dump support
With this implementation it's possible to detect the state of bootguard in intel based systems. Currently it's WIP and in a testphase. Handle it with care!
Change-Id: Ifeec8e20fa8efc35d7db4c6a84be1f118dccfc4a Signed-off-by: Philipp Deppenwiese zaolin@das-labor.org --- util/intelmetool/Makefile | 2 +- util/intelmetool/intelmetool.c | 121 +++++++++++++++++++++++++++++------------ util/intelmetool/msr.c | 98 +++++++++++++++++++++++++++++++++ util/intelmetool/msr.h | 43 +++++++++++++++ 4 files changed, 228 insertions(+), 36 deletions(-)
diff --git a/util/intelmetool/Makefile b/util/intelmetool/Makefile index 4461f86..4ea5c0f 100644 --- a/util/intelmetool/Makefile +++ b/util/intelmetool/Makefile @@ -20,7 +20,7 @@ PREFIX ?= /usr/local CFLAGS ?= -O0 -g -Wall -W -Wno-unused-parameter -Wno-unused-but-set-variable -Wno-sign-compare -Wno-unused-function LDFLAGS += -lpci -lz
-OBJS = intelmetool.o me.o me_status.o mmap.o +OBJS = intelmetool.o me.o me_status.o mmap.o msr.o
OS_ARCH = $(shell uname) ifeq ($(OS_ARCH), Darwin) diff --git a/util/intelmetool/intelmetool.c b/util/intelmetool/intelmetool.c index aec0715..ce24727 100644 --- a/util/intelmetool/intelmetool.c +++ b/util/intelmetool/intelmetool.c @@ -16,6 +16,7 @@ #include <stdlib.h> #include <getopt.h> #include <unistd.h> +#include <string.h>
#ifdef __NetBSD__ #include <machine/sysarch.h> @@ -23,6 +24,7 @@
#include "me.h" #include "mmap.h" +#include "msr.h" #include "intelmetool.h"
#define FD2 0x3428 @@ -34,6 +36,7 @@ int debug = 0; static uint32_t fd2 = 0; static const int size = 0x4000; static volatile uint8_t *rcba; +static unsigned manufactor_mode = 0;
static void dumpmem(uint8_t *phys, uint32_t size) { @@ -117,7 +120,7 @@ static int pci_platform_scan() { for (dev=pacc->devices; dev; dev=dev->next) { pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_CLASS); name = pci_lookup_name(pacc, namebuf, sizeof(namebuf), - PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id); + PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id); if (dev->vendor_id == 0x8086) { if (PCI_DEV_HAS_ME_DISABLE(dev->device_id)) { printf(CGRN "Good news, you have a `%s` so ME is present but can be disabled, continuing...\n\n" RESET, name); @@ -138,9 +141,9 @@ static int pci_platform_scan() { }
if (!PCI_DEV_HAS_ME_DISABLE(dev->device_id) && - !PCI_DEV_HAS_ME_DIFFICULT(dev->device_id) && - !PCI_DEV_CAN_DISABLE_ME_IF_PRESENT(dev->device_id) && - !PCI_DEV_ME_NOT_SURE(dev->device_id)) { + !PCI_DEV_HAS_ME_DIFFICULT(dev->device_id) && + !PCI_DEV_CAN_DISABLE_ME_IF_PRESENT(dev->device_id) && + !PCI_DEV_ME_NOT_SURE(dev->device_id)) { printf(CCYN "ME is not present on your board or unkown\n\n" RESET); pci_cleanup(pacc); return 1; @@ -166,7 +169,7 @@ static struct pci_dev *pci_me_interface_scan(char **name) { for (dev=pacc->devices; dev; dev=dev->next) { pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_CLASS); *name = pci_lookup_name(pacc, namebuf, sizeof(namebuf), - PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id); + PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id); if (dev->vendor_id == 0x8086) { if (PCI_DEV_HAS_SUPPORTED_ME(dev->device_id)) { me = 1; @@ -255,6 +258,10 @@ static void dump_me_info() { printf("ME: has a broken implementation on your board with this BIOS\n"); }
+ if ((stat & 0x10) >> 4) { + manufactor_mode = 1; + } + intel_mei_setup(dev); usleep(ME_COMMAND_DELAY); mei_reset(); @@ -271,6 +278,42 @@ static void dump_me_info() { munmap((void*)rcba, size); }
+static void dump_bootguard_info() { + int result = 0; + uint64_t bootguard = msr_bootguard(&result); + + if(result < 0) { + return; + } + + printf(CYEL "Beware this feature is WIP and not stable!\n\n" RESET); + + if(BOOTGUARD_CAPABILITY(bootguard)) { + printf("ME BootGuard Capability: YES\n"); + if (manufactor_mode) { + printf(CRED "Your southbridge configuration is insecure!! BootGuard keys can be overwritten or wiped.\n" RESET); + } + switch(bootguard) { + case BOOTGUARD_DISABLED: + printf("ME BootGuard Mode: Disabled\n"); + printf(CGRN "Your system is bootguard ready but your vendor disabled it. You can flash other firmware!\n" RESET); + break; + case BOOTGUARD_ENABLED_COMBI_MODE: + printf("ME BootGuard Mode: Verified & Measured Boot\n"); + break; + case BOOTGUARD_ENABLED_MEASUREMENT_MODE: + printf("ME BootGuard Mode: Measured Boot\n"); + break; + case BOOTGUARD_ENABLED_VERIFIED_MODE: + printf("ME BootGuard Mode: Verified Boot\n"); + break; + } + } else { + printf("ME BootGuard Capability: NO\n"); + printf(CGRN "Your system isn't bootguard ready. You can flash other firmware!\n" RESET); + } +} + static void print_version(void) { printf("intelmetool v%s -- ", INTELMETOOL_VERSION); @@ -289,11 +332,12 @@ static void print_usage(const char *name) { printf("usage: %s [-vh?sd]\n", name); printf("\n" - " -v | --version: print the version\n" - " -h | --help: print this help\n\n" - " -s | --show: dump all me information on console\n" - " -d | --debug: enable debug output\n" - "\n"); + " -v | --version: print the version\n" + " -h | --help: print this help\n\n" + " -s | --show: dump all me information on console\n" + " -b | --bootguard dump bootguard state of platform\n" + " -d | --debug: enable debug output\n" + "\n"); exit(1); }
@@ -306,13 +350,14 @@ int main(int argc, char *argv[]) {"version", 0, 0, 'v'}, {"help", 0, 0, 'h'}, {"show", 0, 0, 's'}, + {"bootguard", 0, 0, 'b'}, {"debug", 0, 0, 'd'}, {0, 0, 0, 0} };
- while ((opt = getopt_long(argc, argv, "vh?sd", - long_options, &option_index)) != EOF) { - switch (opt) { + while ((opt = getopt_long(argc, argv, "vh?sdb", + long_options, &option_index)) != EOF) { + switch (opt) { case 'v': print_version(); exit(0); @@ -320,6 +365,9 @@ int main(int argc, char *argv[]) case 's': cmd_exec = 1; break; + case 'b': + cmd_exec = 2; + break; case 'd': debug = 1; break; @@ -329,42 +377,45 @@ int main(int argc, char *argv[]) print_usage(argv[0]); exit(0); break; - } } + }
#if defined(__FreeBSD__) - if (open("/dev/io", O_RDWR) < 0) { - perror("/dev/io"); + if (open("/dev/io", O_RDWR) < 0) { + perror("/dev/io"); #elif defined(__NetBSD__) # ifdef __i386__ - if (i386_iopl(3)) { - perror("iopl"); + if (i386_iopl(3)) { + perror("iopl"); # else - if (x86_64_iopl(3)) { - perror("iopl"); + if (x86_64_iopl(3)) { + perror("iopl"); # endif #else - if (iopl(3)) { - perror("iopl"); + if (iopl(3)) { + perror("iopl"); #endif - printf("You need to be root.\n"); - exit(1); - } + printf("You need to be root.\n"); + exit(1); + }
#ifndef __DARWIN__ - if ((fd_mem = open("/dev/mem", O_RDWR)) < 0) { - perror("Can not open /dev/mem"); - exit(1); - } + if ((fd_mem = open("/dev/mem", O_RDWR)) < 0) { + perror("Can not open /dev/mem"); + exit(1); + } #endif
switch(cmd_exec) { - case 1: - dump_me_info(); - break; - default: - print_usage(argv[0]); - break; + case 1: + dump_me_info(); + break; + case 2: + dump_bootguard_info(); + break; + default: + print_usage(argv[0]); + break; }
return 0; diff --git a/util/intelmetool/msr.c b/util/intelmetool/msr.c new file mode 100644 index 0000000..e890aa2 --- /dev/null +++ b/util/intelmetool/msr.c @@ -0,0 +1,98 @@ +/* intelmetool + * + * Copyright (C) 2013-2016 Philipp Deppenwiese zaolin@das-labor.org, Alexander Couzens lynxis@fe80.eu + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <cpuid.h> + +#include "msr.h" + +#define CPU_ID_SIZE 13 + +#ifndef __DARWIN__ +int fd_msr = 0; + +static void get_cpu_id(char *id) { + cpu_t cpu; + unsigned int level = 0; + unsigned int eax = 0; + + __get_cpuid(level, &eax, &cpu.ebx, &cpu.ecx, &cpu.edx); + + memcpy(id, (char*)&cpu, CPU_ID_SIZE); +} + +static uint64_t rdmsr(int addr) +{ + uint32_t buf[2]; + uint64_t msr = 0; + + if (lseek(fd_msr, (off_t) addr, SEEK_SET) == -1) { + perror("Could not lseek() to MSR"); + close(fd_msr); + return -1; + } + + if (read(fd_msr, buf, 8) == 8) { + msr = buf[0]; + msr <<= 32; + msr |= buf[1]; + close(fd_msr); + return msr; + } + + if (errno == 5) { + close(fd_msr); + return -2; + } else { + perror("Could not read() MSR"); + close(fd_msr); + return -1; + } + + return msr; +} +#endif + +uint64_t msr_bootguard(int *result) { + uint64_t msr = 0; + char cpu_id[CPU_ID_SIZE] = { 0 }; + + get_cpu_id(cpu_id); + if(!strncmp(cpu_id, "GenuineIntel", CPU_ID_SIZE)) { + perror("Error CPU is not from Intel."); + *result = -1; + return 0; + } + +#ifndef __DARWIN__ + fd_msr = open("/dev/cpu/0/msr", O_RDWR); + if (fd_msr < 0) { + perror("Error while opening /dev/cpu/0/msr"); + printf("Did you run 'modprobe msr'?\n"); + *result = -2; + return 0; + } +#endif + + msr = rdmsr(MSR_BOOTGUARD); + msr &= ~0xff; + + return msr; +} diff --git a/util/intelmetool/msr.h b/util/intelmetool/msr.h new file mode 100644 index 0000000..c76206b --- /dev/null +++ b/util/intelmetool/msr.h @@ -0,0 +1,43 @@ +/* intelmetool + * + * Copyright (C) 2013-2016 Philipp Deppenwiese zaolin@das-labor.org, Alexander Couzens lynxis@fe80.eu + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <inttypes.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <stdio.h> + +#define MSR_BOOTGUARD 0x13A + +#define BOOTGUARD_DISABLED 0x400000000 +#define BOOTGUARD_ENABLED_VERIFIED_MODE 0x100000000 +#define BOOTGUARD_ENABLED_MEASUREMENT_MODE 0x200000000 +#define BOOTGUARD_ENABLED_COMBI_MODE 0x300000000 +#define BOOTGUARD_CAPABILITY(x) ( \ + ( (x) == BOOTGUARD_DISABLED ) || \ + ( (x) == BOOTGUARD_ENABLED_VERIFIED_MODE ) || \ + ( (x) == BOOTGUARD_ENABLED_MEASUREMENT_MODE ) || \ + ( (x) == BOOTGUARD_ENABLED_COMBI_MODE )) + +#ifndef __DARWIN__ + +typedef struct { + unsigned int ebx; + unsigned int edx; + unsigned int ecx; +} cpu_t; + +extern uint64_t msr_bootguard(int *result); +#endif