* SMBIOS-provided encryption key patch
@ 2008-09-21 12:35 W. Michael Petullo
2008-09-21 15:04 ` Felix Zielcke
2008-09-24 9:57 ` Robert Millan
0 siblings, 2 replies; 3+ messages in thread
From: W. Michael Petullo @ 2008-09-21 12:35 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 894 bytes --]
I have attached a patch that implements reading an encryption key
from a SMBIOS record. This is useful for hardware that provides a key
to a system using SMBIOS when a physical token is attached to a
system. This patch is dependent on Michael Gorven's encryption patch
[1].
My system is written to use the SMBIOS BIOS vendor field for testing.
Presently, this needs to be changed to the appropriate field for a
given device. Also, there are a lot of grub_printf statements that
would be removed in a production environment. The patch adds the
command "dmiloadkey" to GRUB. This command sets the "passphrase"
environment variable that will then be picked up by Michael's
encryption functions.
I wanted to make this project available in its current state to
determine if anyone is interested in it.
[1] http://lists.gnu.org/archive/html/grub-devel/2008-05/msg00127.html
[-- Attachment #2: grub-1.96-20080813-dmi.patch --]
[-- Type: application/octet-stream, Size: 11712 bytes --]
diff -u --recursive --new-file grub2-20080813-luks-vanilla/ChangeLog grub2-20080813-dmi/ChangeLog
--- grub2-20080813-luks-vanilla/ChangeLog 2008-08-24 08:46:48.000000000 -0400
+++ grub2-20080813-dmi/ChangeLog 2008-08-24 08:54:15.000000000 -0400
@@ -1,3 +1,8 @@
+2008-08-23 W. Michael Petullo <mike@flyn.org>
+
+ * commands/rmi.c: New file
+ * conf/common.rmk: Add rmi.mod
+
2008-08-13 Robert Millan <rmh@aybabtu.com>
* docs/grub.cfg: Remove `/dev/' prefix in GNU/Hurd boot entry.
diff -u --recursive --new-file grub2-20080813-luks-vanilla/commands/dmi.c grub2-20080813-dmi/commands/dmi.c
--- grub2-20080813-luks-vanilla/commands/dmi.c 1969-12-31 19:00:00.000000000 -0500
+++ grub2-20080813-dmi/commands/dmi.c 2008-08-26 19:43:38.000000000 -0400
@@ -0,0 +1,305 @@
+/*
+ * dmi.c - Read information from BIOS's DMI data
+ * Copyright (C) 2008 W. Michael Petullo <mike@flyn.org>
+ */
+
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2007 Free Software Foundation, Inc.
+ *
+ * GRUB 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+#include <grub/err.h>
+
+/* See the "System Management BIOS (SMBIOS) Reference Specification"
+ * for details on the following structures
+ */
+
+typedef struct smbios_entry_point {
+ unsigned char anchor[4];
+ unsigned char checksum;
+ unsigned char length;
+ unsigned char bios_major_version;
+ unsigned char bios_minor_version;
+ unsigned short max_struct_size;
+ unsigned char revision;
+ unsigned char formatted_area[5];
+ unsigned char intermediate_anchor[5];
+ unsigned char intermediate_checksum;
+ unsigned short structure_table_length;
+ unsigned int structure_table_address;
+ unsigned short num_structures;
+ unsigned char bcd_version;
+} smbios_entry_point_t;
+
+typedef struct smbios_generic_header {
+ unsigned char type;
+ unsigned char length;
+ unsigned short handle;
+} smbios_generic_header_t;
+
+/* NOTE: there are more fields in the specification. However, the
+ * fields beginning with "BIOS Characteristics Extension Bytes" are
+ * not included because this field has a variable number of bytes.
+ */
+typedef struct smbios_bios_information {
+ unsigned char type;
+ unsigned char length;
+ unsigned short handle;
+ unsigned char vendor;
+ unsigned char version;
+ unsigned short start_addr;
+ unsigned char release_date;
+ unsigned char rom_size;
+ unsigned long long characteristics;
+} smbios_bios_information_t;
+
+typedef struct smbios_system_information {
+ unsigned char type;
+ unsigned char length;
+ unsigned short handle;
+ unsigned char manufacturer;
+ unsigned char product;
+ unsigned char version;
+ unsigned char serial_number;
+ unsigned char uuid[16];
+ unsigned char wakeup_time;
+ unsigned char sku;
+ unsigned char family;
+} smbios_system_information_t;
+
+static const struct grub_arg_option options[] = {
+ {0, 0, 0, 0, 0, 0}
+};
+
+static int grub_dmi_checksum (char *ptr, int length)
+{
+ unsigned char sum = 0;
+ length--;
+ while(length >= 0) {
+ sum += ptr[length--];
+ }
+ return sum;
+}
+
+static char *
+grub_dmi_get_string (char *ptr, char n)
+/* Given ptr to beginning of SMBIOS structure and structure length,
+ * print nth string, if n is too big, will return pointer to 0x00
+ * that terminates string list (empty string).
+ */
+{
+ ptr += *(ptr + 1); /* Skip header, ptr + 1 byte is header length */
+ /* String numbering starts at 1, so --n */
+ while (--n > 0 && *ptr != 0x00) {
+ ptr += grub_strlen(ptr) + 1;
+ }
+ return ptr;
+}
+
+static void
+grub_dmi_read_generic_header (char *ptr)
+{
+ ptr += *(ptr + 1); /* Skip header, ptr + 1 byte is header length */
+
+ /* If we see a 0x00 here, it's the second one, as we've already
+ * incremented past the null terminator with ptr += ... below.
+ * The empty string is indicated by a 0 in the SMBIOS structure
+ * above, so we won't see one here.
+ */
+ while (*ptr != 0x00) {
+ grub_printf("%s\n", ptr);
+ ptr += grub_strlen(ptr) + 1;
+ }
+}
+
+static void
+grub_dmi_read_bios_information (char *ptr)
+{
+ smbios_bios_information_t bios_information;
+ grub_memcpy(&bios_information, ptr, sizeof(smbios_bios_information_t));
+
+ grub_printf("Length: %d\n", bios_information.length);
+ grub_printf("Handle: 0x%x\n", bios_information.handle);
+ grub_printf("Vendor: %s\n",
+ grub_dmi_get_string(ptr, bios_information.vendor));
+ grub_printf("Version: %s\n",
+ grub_dmi_get_string(ptr, bios_information.version));
+ grub_printf("BIOS Addr.: 0x%x\n", bios_information.start_addr);
+ grub_printf("Rel. Date: %s\n",
+ grub_dmi_get_string(ptr, bios_information.release_date));
+ grub_printf("BIOS ROM Size: %d\n", bios_information.rom_size);
+
+ if (grub_env_get("passphrase") == 0x00) {
+ grub_env_set("passphrase", grub_dmi_get_string(ptr, bios_information.vendor));
+ } else {
+ grub_printf("Env. var. passphrase already set!\n");
+ }
+}
+
+static void
+grub_dmi_read_system_information (char *ptr)
+{
+ smbios_system_information_t system_information;
+ grub_memcpy(&system_information, ptr, sizeof(smbios_system_information_t));
+
+ grub_printf("Length: %d\n", system_information.length);
+ grub_printf("Handle: 0x%x\n", system_information.handle);
+ grub_printf("Manufacturer: %s\n",
+ grub_dmi_get_string(ptr, system_information.manufacturer));
+ grub_printf("Product: %s\n",
+ grub_dmi_get_string(ptr, system_information.product));
+ grub_printf("Version: 0x%s\n",
+ grub_dmi_get_string(ptr, system_information.version));
+ grub_printf("Serial Num: %s\n",
+ grub_dmi_get_string(ptr, system_information.serial_number));
+ grub_printf("Wake-up Time: %x\n", system_information.wakeup_time);
+ grub_printf("SKU: %s\n",
+ grub_dmi_get_string(ptr, system_information.sku));
+ grub_printf("Family: %s\n",
+ grub_dmi_get_string(ptr, system_information.family));
+}
+
+static grub_err_t
+grub_cmd_dmiloadkey (struct grub_arg_list *state, int argc, char **args)
+{
+ char *ptr;
+ grub_err_t err = GRUB_ERR_NONE;
+
+ for (ptr = (char *) 0x000f0000; ptr < (char *) 0x000fffff; ptr++) {
+ if (0 == grub_strncmp("_SM_", ptr, 4)) {
+ int i;
+ smbios_entry_point_t entry_point;
+
+ grub_printf("Found '_SM_' at 0x%x\n", (unsigned int) ptr);
+
+ if (0 != grub_dmi_checksum(ptr, *(ptr + 0x05))) {
+ grub_printf("Checksum failed!\n");
+ continue;
+ } else {
+ grub_printf("Checksum passed\n");
+ }
+
+ grub_memcpy(&entry_point, ptr, sizeof(smbios_entry_point_t));
+
+ if (0 != grub_strncmp("_DMI_", entry_point.intermediate_anchor, 5)) {
+ grub_printf("Missing '_DMI_'!\n");
+ continue;
+ }
+
+ if (0 != grub_dmi_checksum((char *) &(entry_point.intermediate_anchor), 0x0F)) {
+ grub_printf("Intermediate checksum failed!\n");
+ continue;
+ } else {
+ grub_printf("Intermediate checksum passed\n");
+ }
+
+ for (i = 0; i < entry_point.length; i+=2) {
+ grub_printf("0x%x", ptr[i]);
+ grub_printf("%x ", ptr[i+1]);
+ if (i % 8 == 0) {
+ grub_printf("\n");
+ }
+ }
+
+ grub_printf("Table Length: %d\n", entry_point.structure_table_length);
+ grub_printf("Table Address: 0x%x\n", entry_point.structure_table_address);
+
+ ptr = (char *) entry_point.structure_table_address;
+
+ do {
+ smbios_generic_header_t generic_header;
+ grub_memcpy(&generic_header, ptr, sizeof(smbios_generic_header_t));
+
+ switch (*ptr) {
+ case 0:
+ grub_printf("Found BIOS information struct at 0x%x\n",
+ (unsigned int) ptr);
+ grub_dmi_read_bios_information (ptr);
+ break;
+ case 1:
+ grub_printf("Found system information struct at 0x%x\n",
+ (unsigned int) ptr);
+ grub_dmi_read_system_information (ptr);
+ break;
+ default:
+ grub_printf("Unknown information stuct (%d) at 0x%x\n", *ptr,
+ (unsigned int) ptr);
+ grub_dmi_read_generic_header (ptr);
+ break;
+ }
+
+ grub_printf("Advance past struct (%d)\n", generic_header.length);
+ ptr += generic_header.length; /* Advance past struct to strings */
+
+ do { /* Advance past strings: */
+ grub_printf("Advance past string (%d)\n", grub_strlen(ptr) + 1);
+ ptr += grub_strlen(ptr) + 1;
+ } while (*ptr != 0x00);
+ /* This is a do...while instead of a while because:
+ *
+ * a. if there is a string it will be advanced over and the
+ * string's null may be the first of the double null terminator
+ *
+ * b. if there are no strings at all, the first null of the
+ * double null terminator will be advanced over as if it were
+ * part of an empty string
+ *
+ * If we see a 0x00 here, it's the second one, as we've already
+ * incremented past the null terminator with ptr += ... above.
+ * The empty string is indicated by a 0 in the SMBIOS structure
+ * above, so we won't see one here.
+ */
+
+ grub_printf("Advance one more\n");
+ ptr++; /* Advance past second 0x00 that signifies end of strings */
+
+ grub_millisleep(1000);
+
+ } while (ptr < (char *) entry_point.structure_table_address + entry_point.structure_table_length);
+
+ break;
+ }
+ }
+
+ if (ptr == (char *) 0x000fffff) {
+ grub_printf("Did not find DMI data!\n");
+ err = GRUB_ERR_READ_ERROR;
+ goto _return;
+ }
+_return:
+ return err;
+}
+
+GRUB_MOD_INIT(dmi)
+{
+ grub_register_command ("dmiloadkey", grub_cmd_dmiloadkey,
+ GRUB_COMMAND_FLAG_BOTH,
+ "dmiloadkey",
+ "Read data from DMI.",
+ options);
+}
+
+GRUB_MOD_FINI(dmi)
+{
+ grub_unregister_command("dmiloadkey");
+}
+
+/* vi: set et sw=2 sts=2: */
diff -u --recursive --new-file grub2-20080813-luks-vanilla/conf/common.rmk grub2-20080813-dmi/conf/common.rmk
--- grub2-20080813-luks-vanilla/conf/common.rmk 2008-08-24 08:46:48.000000000 -0400
+++ grub2-20080813-dmi/conf/common.rmk 2008-08-24 08:55:04.000000000 -0400
@@ -281,7 +281,7 @@
cmp.mod cat.mod help.mod font.mod search.mod \
loopback.mod fs_uuid.mod configfile.mod echo.mod \
terminfo.mod test.mod blocklist.mod hexdump.mod \
- read.mod sleep.mod loadenv.mod crc.mod
+ read.mod sleep.mod loadenv.mod crc.mod dmi.mod
# For hello.mod.
hello_mod_SOURCES = hello/hello.c
@@ -460,6 +460,11 @@
crc_mod_CFLAGS = $(COMMON_CFLAGS)
crc_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For dmi.mod.
+dmi_mod_SOURCES = commands/dmi.c
+dmi_mod_CFLAGS = $(COMMON_CFLAGS)
+dmi_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
# Misc.
pkglib_MODULES += gzio.mod bufio.mod elf.mod
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: SMBIOS-provided encryption key patch
2008-09-21 12:35 SMBIOS-provided encryption key patch W. Michael Petullo
@ 2008-09-21 15:04 ` Felix Zielcke
2008-09-24 9:57 ` Robert Millan
1 sibling, 0 replies; 3+ messages in thread
From: Felix Zielcke @ 2008-09-21 15:04 UTC (permalink / raw)
To: The development of GRUB 2
Am Sonntag, den 21.09.2008, 08:35 -0400 schrieb W. Michael Petullo:
Hi,
> Also, there are a lot of grub_printf statements that
> would be removed in a production environment.
Instead of grub_printf you could just use grub_dprintf ("dmi", ...)
and then they get shown with `set debug=dmi' command in real GRUB.
--
Felix Zielcke
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: SMBIOS-provided encryption key patch
2008-09-21 12:35 SMBIOS-provided encryption key patch W. Michael Petullo
2008-09-21 15:04 ` Felix Zielcke
@ 2008-09-24 9:57 ` Robert Millan
1 sibling, 0 replies; 3+ messages in thread
From: Robert Millan @ 2008-09-24 9:57 UTC (permalink / raw)
To: The development of GRUB 2; +Cc: Yoshinori K. Okuji
On Sun, Sep 21, 2008 at 08:35:52AM -0400, W. Michael Petullo wrote:
> I have attached a patch that implements reading an encryption key
> from a SMBIOS record. This is useful for hardware that provides a key
> to a system using SMBIOS when a physical token is attached to a
> system.
Can you be more specific about the application of this? (e.g. with an
example use case)
> This patch is dependent on Michael Gorven's encryption patch
> [1].
Unfortunately we haven't sorted out that patch yet. Although I expect we're
almost there... we need some response from Marco or Okuji.
--
Robert Millan
The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
how) you may access your data; but nobody's threatening your freedom: we
still allow you to remove your data and not access it at all."
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2008-09-24 9:59 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-21 12:35 SMBIOS-provided encryption key patch W. Michael Petullo
2008-09-21 15:04 ` Felix Zielcke
2008-09-24 9:57 ` Robert Millan
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.