Discussion:
Trusted Boot with OpenBSD
podolica
2021-04-21 08:26:18 UTC
Permalink
Hi all,

I have tested if the trusted boot implementation
of Julius Zint for OpenBSD 6.5
(https://marc.info/?l=openbsd-misc&m=158255450604977&w=2)
is still working in OpenBSD 6.8.

Despite of some patch files that had to be updated,
all changes needed to be applied can be applied and
Trusted Boot can be used.
(Tested with an external hard drive and an amd64
ThinkPad with TPM module version 1.2)

Here are the new patch files. I did not provide them as
attachments because the netiquette says only the bugs,
ports and the tech mailing list are supporting
attachments although it was allowed when Julius Zint
made it's initial post. The files are beginning after
the ``` and are ending before the next ``` just like
in Markdown.


# gidt.S.patch
```
--- gidt.S.orig Mon Apr 19 13:22:32 2021
+++ gidt.S Mon Apr 19 13:22:32 2021
@@ -432,11 +432,13 @@
movl %edi, _C_LABEL(BIOS_regs)+BIOSR_DI

/* clear NT flag in eflags */
- pushf
+ push %eax
+ pushf
pop %eax
and $0xffffbfff, %eax
push %eax
popf
+ pop %eax

pop %gs
pop %fs

```

# cmd_i386.c.patch
```
--- cmd_i386.c.orig Mon Apr 19 13:23:44 2021
+++ cmd_i386.c Mon Apr 19 13:23:44 2021
@@ -36,6 +36,7 @@
#include "biosdev.h"
#include "libsa.h"
#include <cmd.h>
+#include <tpm.h>

extern const char version[];

@@ -44,6 +45,7 @@
int Xdiskinfo(void);
int Xmemory(void);
int Xregs(void);
+int Xtpm(void);

/* From gidt.S */
int bootbuf(void *, int);
@@ -53,11 +55,155 @@
{ "comaddr", CMDT_CMD, Xcomaddr },
{ "diskinfo", CMDT_CMD, Xdiskinfo },
{ "memory", CMDT_CMD, Xmemory },
+ { "tpm", CMDT_CMD, Xtpm },
#ifdef DEBUG
{ "regs", CMDT_CMD, Xregs },
#endif
{ NULL, 0 }
};
+
+/**
+ * print_memory - debugging functionality to dump memory region to screen
+ * @buf: memory location to begin dump
+ * @rows: rows to print
+ * @columns: columns to print
+ *
+ * Remarks: total bytes dumped = rows * columns
+ */
+void
+print_memory(void* buf, uint32_t rows, uint32_t columns)
+{
+ uint8_t* iter = buf;
+ for(int i = 0; i < rows; i++) {
+ printf("%03x:", i * columns);
+ for(int k = 0; k < columns; k++) {
+ printf(" %02x", *iter);
+ iter++;
+ }
+ printf("\n");
+ }
+}
+
+#define SECRET_BLK_OFF 1
+
+int
+Xtpm(void)
+{
+ int rc;
+ uint8_t major = 0;
+ uint8_t minor = 0;
+ rc = tpm_statuscheck(&major, &minor);
+ if(rc != 0) {
+ printf("No TCG compliant BIOS available.\n");
+ }
+ else if(major != 1 && minor != 2) {
+ printf("Incompatible TCG BIOS version: %u.%u\n", major, minor);
+ }
+ if (cmd.argc < 2) {
+ printf("machine tpm r[andom]|p[cr]|u[nseal] [DiskNumber]|s[eal] secret [DiskNumber]\n");
+ printf("strlen(secret) <= 100\n");
+ return 0;
+ }
+ switch(cmd.argv[1][0]) {
+ case 'r': {
+ char random_buf[20];
+ tpm_random(random_buf, 20);
+ print_memory(random_buf, 2, 10);
+ } break;
+ case 'p': {
+ tpm_printpcr(0, 15);
+ } break;
+ case 'u': {
+ // load secret disk block
+ int disk_number = 0x80;
+ if(cmd.argc == 3) {
+ disk_number = (int)strtol(cmd.argv[2], NULL, 0);
+ }
+ unsigned char* secret_disk_block = alloc(512);
+ memset(secret_disk_block, 0x00, 512);
+ struct diskinfo * disk_info = dklookup(disk_number);
+ if(disk_info == NULL) {
+ printf("IO Error - Disk %x not found\n", disk_number);
+ goto unseal_end;
+ }
+ rc = biosd_diskio(F_READ, disk_info, SECRET_BLK_OFF, 1, secret_disk_block);
+ if(rc != 0) {
+ printf("IO Error \n");
+ goto unseal_end;
+ }
+ if (secret_disk_block[0] != 'A' ||
+ secret_disk_block[1] != 'E' ||
+ secret_disk_block[2] != 'M' ||
+ secret_disk_block[3] != 'S')
+ {
+ printf("No sealed secret found on disk");
+ goto unseal_end;
+ }
+ uint32_t sealed_size = *((uint32_t*)(secret_disk_block + 4));
+ unsigned char* sealed_data = secret_disk_block + 8;
+ if(sealed_size > 512) {
+ printf("Invalid size for sealed data\n");
+ goto unseal_end;
+ }
+
+ // unseal data
+ char unsealed_secret[100];
+ uint32_t unsealed_size = 100;
+ memset(unsealed_secret, 0x00, 100);
+ rc = tpm_unsealdata(
+ sealed_data,
+ sealed_size,
+ unsealed_secret,
+ &unsealed_size);
+ if(rc == 0) {
+ printf("Secret: %s \n", unsealed_secret);
+ }
+unseal_end:
+ free(secret_disk_block, 512);
+ secret_disk_block = NULL;
+ } break;
+ case 's': {
+ if(cmd.argc < 3) {
+ printf("no secret specified to seal\n");
+ }
+ int disk_number = 0x80;
+ if(cmd.argc == 4) {
+ disk_number = (int)strtol(cmd.argv[3], NULL, 0);
+ }
+ unsigned char* secret_disk_block = alloc(512);
+ memset(secret_disk_block, 0x00, 512);
+
+ char* secret = cmd.argv[2];
+ uint32_t secret_length = strlen(secret);
+ uint32_t sealed_size = 512;
+ char* sealed_data = secret_disk_block + 8;
+ rc = tpm_sealdata(secret, secret_length, sealed_data, &sealed_size);
+ if(rc != 0) {
+ goto seal_end;
+ }
+ secret_disk_block[0] = 'A';
+ secret_disk_block[1] = 'E';
+ secret_disk_block[2] = 'M';
+ secret_disk_block[3] = 'S';
+ memcpy(secret_disk_block + 4, &sealed_size, sizeof(uint32_t));
+
+ struct diskinfo * disk_info = dklookup(disk_number);
+ if(disk_info == NULL) {
+ printf("IO Error - Disk 0x%x not found\n", disk_number);
+ goto seal_end;
+ }
+ rc = biosd_diskio(F_WRITE, disk_info, 1, 1, secret_disk_block);
+ if(rc != 0) {
+ printf("IO Error \n");
+ goto seal_end;
+ }
+seal_end:
+ free(secret_disk_block, 512);
+ secret_disk_block = NULL;
+ } break;
+ }
+ return 0;
+}

int
Xdiskinfo(void)

```
t***@danwin1210.me
2021-04-21 19:17:50 UTC
Permalink
That's very interesting, and good work patching the assembly code.
Post by podolica
Hi all,
I have tested if the trusted boot implementation
of Julius Zint for OpenBSD 6.5
(https://marc.info/?l=openbsd-misc&m=158255450604977&w=2)
is still working in OpenBSD 6.8.
Despite of some patch files that had to be updated,
all changes needed to be applied can be applied and
Trusted Boot can be used.
(Tested with an external hard drive and an amd64
ThinkPad with TPM module version 1.2)
Here are the new patch files. I did not provide them as
attachments because the netiquette says only the bugs,
ports and the tech mailing list are supporting
attachments although it was allowed when Julius Zint
made it's initial post. The files are beginning after
the ``` and are ending before the next ``` just like
in Markdown.
# gidt.S.patch
```
--- gidt.S.orig Mon Apr 19 13:22:32 2021
+++ gidt.S Mon Apr 19 13:22:32 2021
@@ -432,11 +432,13 @@
movl %edi, _C_LABEL(BIOS_regs)+BIOSR_DI
/* clear NT flag in eflags */
- pushf
+ push %eax
+ pushf
pop %eax
and $0xffffbfff, %eax
push %eax
popf
+ pop %eax
pop %gs
pop %fs
```
# cmd_i386.c.patch
```
--- cmd_i386.c.orig Mon Apr 19 13:23:44 2021
+++ cmd_i386.c Mon Apr 19 13:23:44 2021
@@ -36,6 +36,7 @@
#include "biosdev.h"
#include "libsa.h"
#include <cmd.h>
+#include <tpm.h>
extern const char version[];
@@ -44,6 +45,7 @@
int Xdiskinfo(void);
int Xmemory(void);
int Xregs(void);
+int Xtpm(void);
/* From gidt.S */
int bootbuf(void *, int);
@@ -53,11 +55,155 @@
{ "comaddr", CMDT_CMD, Xcomaddr },
{ "diskinfo", CMDT_CMD, Xdiskinfo },
{ "memory", CMDT_CMD, Xmemory },
+ { "tpm", CMDT_CMD, Xtpm },
#ifdef DEBUG
{ "regs", CMDT_CMD, Xregs },
#endif
{ NULL, 0 }
};
+
+/**
+ * print_memory - debugging functionality to dump memory region to screen
+ *
+ * Remarks: total bytes dumped = rows * columns
+ */
+void
+print_memory(void* buf, uint32_t rows, uint32_t columns)
+{
+ uint8_t* iter = buf;
+ for(int i = 0; i < rows; i++) {
+ printf("%03x:", i * columns);
+ for(int k = 0; k < columns; k++) {
+ printf(" %02x", *iter);
+ iter++;
+ }
+ printf("\n");
+ }
+}
+
+#define SECRET_BLK_OFF 1
+
+int
+Xtpm(void)
+{
+ int rc;
+ uint8_t major = 0;
+ uint8_t minor = 0;
+ rc = tpm_statuscheck(&major, &minor);
+ if(rc != 0) {
+ printf("No TCG compliant BIOS available.\n");
+ }
+ else if(major != 1 && minor != 2) {
+ printf("Incompatible TCG BIOS version: %u.%u\n", major, minor);
+ }
+ if (cmd.argc < 2) {
+ printf("machine tpm r[andom]|p[cr]|u[nseal] [DiskNumber]|s[eal] secret [DiskNumber]\n");
+ printf("strlen(secret) <= 100\n");
+ return 0;
+ }
+ switch(cmd.argv[1][0]) {
+ case 'r': {
+ char random_buf[20];
+ tpm_random(random_buf, 20);
+ print_memory(random_buf, 2, 10);
+ } break;
+ case 'p': {
+ tpm_printpcr(0, 15);
+ } break;
+ case 'u': {
+ // load secret disk block
+ int disk_number = 0x80;
+ if(cmd.argc == 3) {
+ disk_number = (int)strtol(cmd.argv[2], NULL, 0);
+ }
+ unsigned char* secret_disk_block = alloc(512);
+ memset(secret_disk_block, 0x00, 512);
+ struct diskinfo * disk_info = dklookup(disk_number);
+ if(disk_info == NULL) {
+ printf("IO Error - Disk %x not found\n", disk_number);
+ goto unseal_end;
+ }
+ rc = biosd_diskio(F_READ, disk_info, SECRET_BLK_OFF, 1, secret_disk_block);
+ if(rc != 0) {
+ printf("IO Error \n");
+ goto unseal_end;
+ }
+ if (secret_disk_block[0] != 'A' ||
+ secret_disk_block[1] != 'E' ||
+ secret_disk_block[2] != 'M' ||
+ secret_disk_block[3] != 'S')
+ {
+ printf("No sealed secret found on disk");
+ goto unseal_end;
+ }
+ uint32_t sealed_size = *((uint32_t*)(secret_disk_block + 4));
+ unsigned char* sealed_data = secret_disk_block + 8;
+ if(sealed_size > 512) {
+ printf("Invalid size for sealed data\n");
+ goto unseal_end;
+ }
+
+ // unseal data
+ char unsealed_secret[100];
+ uint32_t unsealed_size = 100;
+ memset(unsealed_secret, 0x00, 100);
+ rc = tpm_unsealdata(
+ sealed_data,
+ sealed_size,
+ unsealed_secret,
+ &unsealed_size);
+ if(rc == 0) {
+ printf("Secret: %s \n", unsealed_secret);
+ }
+ free(secret_disk_block, 512);
+ secret_disk_block = NULL;
+ } break;
+ case 's': {
+ if(cmd.argc < 3) {
+ printf("no secret specified to seal\n");
+ }
+ int disk_number = 0x80;
+ if(cmd.argc == 4) {
+ disk_number = (int)strtol(cmd.argv[3], NULL, 0);
+ }
+ unsigned char* secret_disk_block = alloc(512);
+ memset(secret_disk_block, 0x00, 512);
+
+ char* secret = cmd.argv[2];
+ uint32_t secret_length = strlen(secret);
+ uint32_t sealed_size = 512;
+ char* sealed_data = secret_disk_block + 8;
+ rc = tpm_sealdata(secret, secret_length, sealed_data, &sealed_size);
+ if(rc != 0) {
+ goto seal_end;
+ }
+ secret_disk_block[0] = 'A';
+ secret_disk_block[1] = 'E';
+ secret_disk_block[2] = 'M';
+ secret_disk_block[3] = 'S';
+ memcpy(secret_disk_block + 4, &sealed_size, sizeof(uint32_t));
+
+ struct diskinfo * disk_info = dklookup(disk_number);
+ if(disk_info == NULL) {
+ printf("IO Error - Disk 0x%x not found\n", disk_number);
+ goto seal_end;
+ }
+ rc = biosd_diskio(F_WRITE, disk_info, 1, 1, secret_disk_block);
+ if(rc != 0) {
+ printf("IO Error \n");
+ goto seal_end;
+ }
+ free(secret_disk_block, 512);
+ secret_disk_block = NULL;
+ } break;
+ }
+ return 0;
+}
int
Xdiskinfo(void)
```
podolica
2021-04-22 06:03:32 UTC
Permalink
Patching the assembly code is the work of Julius Zint -
not my work. I have only patched the patch files because
some of the old one doesn't work anymore. This is because
of some changes of OpenBSDs source code which are preventing
the patch util to find the lines to change.

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
Post by t***@danwin1210.me
That's very interesting, and good work patching the assembly code.
Post by podolica
Hi all,
I have tested if the trusted boot implementation
of Julius Zint for OpenBSD 6.5
(https://marc.info/?l=openbsd-misc&m=158255450604977&w=2)
is still working in OpenBSD 6.8.
Despite of some patch files that had to be updated,
all changes needed to be applied can be applied and
Trusted Boot can be used.
(Tested with an external hard drive and an amd64
ThinkPad with TPM module version 1.2)
Here are the new patch files. I did not provide them as
attachments because the netiquette says only the bugs,
ports and the tech mailing list are supporting
attachments although it was allowed when Julius Zint
made it's initial post. The files are beginning after
the `and are ending before the next` just like
in Markdown.
gidt.S.patch
=============
--- gidt.S.orig Mon Apr 19 13:22:32 2021
+++ gidt.S Mon Apr 19 13:22:32 2021
@@ -432,11 +432,13 @@
movl %edi, _C_LABEL(BIOS_regs)+BIOSR_DI
/* clear NT flag in eflags */
- pushf
+ push %eax
+ pushf
pop %eax
and $0xffffbfff, %eax
push %eax
popf
+ pop %eax
pop %gs
pop %fs
cmd_i386.c.patch
=================
--- cmd_i386.c.orig Mon Apr 19 13:23:44 2021
+++ cmd_i386.c Mon Apr 19 13:23:44 2021
@@ -36,6 +36,7 @@
#include "biosdev.h"
#include "libsa.h"
#include <cmd.h>
+#include <tpm.h>
extern const char version[];
@@ -44,6 +45,7 @@
int Xdiskinfo(void);
int Xmemory(void);
int Xregs(void);
+int Xtpm(void);
/* From gidt.S */
int bootbuf(void *, int);
@@ -53,11 +55,155 @@
{ "comaddr", CMDT_CMD, Xcomaddr },
{ "diskinfo", CMDT_CMD, Xdiskinfo },
{ "memory", CMDT_CMD, Xmemory },
+ { "tpm", CMDT_CMD, Xtpm },
#ifdef DEBUG
{ "regs", CMDT_CMD, Xregs },
#endif
{ NULL, 0 }
};
+
+/**
+ * print_memory - debugging functionality to dump memory region to screen
+ *
+ * Remarks: total bytes dumped = rows * columns
+ */
+void
+print_memory(void* buf, uint32_t rows, uint32_t columns)
+{
+ uint8_t* iter = buf;
+ for(int i = 0; i < rows; i++) {
+ printf("%03x:", i * columns);
+ for(int k = 0; k < columns; k++) {
+ printf(" %02x", *iter);
+ iter++;
+ }
+ printf("\\n");
+ }
+}
+
+#define SECRET_BLK_OFF 1
+
+int
+Xtpm(void)
+{
+ int rc;
+ uint8_t major = 0;
+ uint8_t minor = 0;
+ rc = tpm_statuscheck(&major, &minor);
+ if(rc != 0) {
+ printf("No TCG compliant BIOS available.\\n");
+ }
+ else if(major != 1 && minor != 2) {
+ printf("Incompatible TCG BIOS version: %u.%u\\n", major, minor);
+ }
+ if (cmd.argc < 2) {
+ printf("machine tpm r[andom]|p[cr]|u[nseal] [DiskNumber]|s[eal] secret [DiskNumber]\\n");
+ printf("strlen(secret) <= 100\\n");
+ return 0;
+ }
+ switch(cmd.argv[1][0]) {
+ case 'r': {
+ char random_buf[20];
+ tpm_random(random_buf, 20);
+ print_memory(random_buf, 2, 10);
+ } break;
+ case 'p': {
+ tpm_printpcr(0, 15);
+ } break;
+ case 'u': {
+ // load secret disk block
+ int disk_number = 0x80;
+ if(cmd.argc == 3) {
+ disk_number = (int)strtol(cmd.argv[2], NULL, 0);
+ }
+ unsigned char* secret_disk_block = alloc(512);
+ memset(secret_disk_block, 0x00, 512);
+ struct diskinfo * disk_info = dklookup(disk_number);
+ if(disk_info == NULL) {
+ printf("IO Error - Disk %x not found\\n", disk_number);
+ goto unseal_end;
+ }
+ rc = biosd_diskio(F_READ, disk_info, SECRET_BLK_OFF, 1, secret_disk_block);
+ if(rc != 0) {
+ printf("IO Error \\n");
+ goto unseal_end;
+ }
+ if (secret_disk_block[0] != 'A' ||
+ secret_disk_block[1] != 'E' ||
+ secret_disk_block[2] != 'M' ||
+ secret_disk_block[3] != 'S')
+ {
+ printf("No sealed secret found on disk");
+ goto unseal_end;
+ }
+ uint32_t sealed_size = *((uint32_t*)(secret_disk_block + 4));
+ unsigned char* sealed_data = secret_disk_block + 8;
+ if(sealed_size > 512) {
+ printf("Invalid size for sealed data\\n");
+ goto unseal_end;
+ }
+
+ // unseal data
+ char unsealed_secret[100];
+ uint32_t unsealed_size = 100;
+ memset(unsealed_secret, 0x00, 100);
+ rc = tpm_unsealdata(
+ sealed_data,
+ sealed_size,
+ unsealed_secret,
+ &unsealed_size);
+ if(rc == 0) {
+ printf("Secret: %s \\n", unsealed_secret);
+ }
+ free(secret_disk_block, 512);
+ secret_disk_block = NULL;
+ } break;
+ case 's': {
+ if(cmd.argc < 3) {
+ printf("no secret specified to seal\\n");
+ }
+ int disk_number = 0x80;
+ if(cmd.argc == 4) {
+ disk_number = (int)strtol(cmd.argv[3], NULL, 0);
+ }
+ unsigned char* secret_disk_block = alloc(512);
+ memset(secret_disk_block, 0x00, 512);
+
+ char* secret = cmd.argv[2];
+ uint32_t secret_length = strlen(secret);
+ uint32_t sealed_size = 512;
+ char* sealed_data = secret_disk_block + 8;
+ rc = tpm_sealdata(secret, secret_length, sealed_data, &sealed_size);
+ if(rc != 0) {
+ goto seal_end;
+ }
+ secret_disk_block[0] = 'A';
+ secret_disk_block[1] = 'E';
+ secret_disk_block[2] = 'M';
+ secret_disk_block[3] = 'S';
+ memcpy(secret_disk_block + 4, &sealed_size, sizeof(uint32_t));
+
+ struct diskinfo * disk_info = dklookup(disk_number);
+ if(disk_info == NULL) {
+ printf("IO Error - Disk 0x%x not found\\n", disk_number);
+ goto seal_end;
+ }
+ rc = biosd_diskio(F_WRITE, disk_info, 1, 1, secret_disk_block);
+ if(rc != 0) {
+ printf("IO Error \\n");
+ goto seal_end;
+ }
+ free(secret_disk_block, 512);
+ secret_disk_block = NULL;
+ } break;
+ }
+ return 0;
+}
int
Xdiskinfo(void)
Loading...