Re: Trusted Boot with OpenBSD

2020-03-26 Thread Julius Zint


>> I can't tell from the instructions how the FDE encryption key is stored -- 
>> do we manually seal it to the TPM and then manually unseal and copy/paste it 
>> every time we boot? Or is it assumed the user will write a script to handle 
>> this -- a script which itself will have to be measured by the TPM?
> 
> This is not possible with the current version. The Masterthesis was
> about answering this Question: Did unencrypted software change since 
> the last time the user operated this system.
> 
> What exactly is your use case? Do you want a system with FDE that does
> not prompt you for the encryption key or do you want to improve the
> security by storing a part of the key material inside the TPM while the
> other half is provided by a user password?
> 
> There are a lot of possibilities with a available TPM on boot, so if
> you have a specific use case we can tailor that right in.
> 
> Before we do that i think it is important to make this feature a lot
> easier to install. Following this manual, patching and compiling source
> code and updating the MBR and biosboot is not something the user should
> have to worry about.
> 
> The problem is, in order to make space for this feature in the MBR as
> well as in biosboot i had to remove the code responsible for loading a
> block from disk via CHS. This is obviously not acceptable if this should
> be integrated back into OpenBSD.
> 
> One possible solution would be to let the MBR and biosboot grow bigger
> than 512 byte and let installboot(8) figure out what the user needs and
> remove code paths that are not used to get the binary back to 512 byte.
> 
> Everything else i thought of involves recompiling.



Trusted Boot with OpenBSD

2020-02-24 Thread Julius Zint
As part of my master thesis i wrote code to enable a trusted boot
with OpenBSD. This short manual is for everyone who wants to try it.
Feedback on the code and the feature itself is also appreciated.

Requirements:
1: OpenBSD 6.5 (might also work with 6.6 but only tested with 6.5)
2: Default installation with Full Disk Encryption (FDE)
3: Clean sys source code in /usr/src/sys/**
4: Firmware with Logical Block Adressing (LBA) support
5: 64-Bit Processor
6: System with a dedicated TPM 1.2 Chip
7: Downloaded all attachments to this email in /tmp
8: Adventurous mindset (this might brick your installation)



1: Updating the MBR startprogram to measure biosboot(8)
The following commands are meant to be inserted one by one by the user
and need adjustments depending on the system.

cd /usr/src/sys/arch/amd64/stand/mbr/

# patch the source code and compile the new MBR
patch mbr.S /tmp/mbr.patch
make CPPFLAGS+=-DTPM_MEASURE CPPFLAGS+=-DNO_CHS

# updating MBR on disk (replace X with drive). To preserve partition
# table copy existing, overwrite startprogram and write back
dd if=/dev/rsdXc of=mbr.img bs=512 count=1
dd if=mbr of=mbr.img bs=440 count=1 conv=notrunc
dd if=mbr.img of=/dev/rsdXc bs=512 count=1
rm mbr.img



2: Updating biosboot(8) and boot(8)
Same as in the first step. These commands contain absolute paths and
drive numbers that need to be changed by the user.

cd /usr/src/sys/arch/amd64/stand/biosboot/

# patch the biosboot(8) source code and compile
patch biosboot.S /tmp/biosboot.patch
make DEBUGFLAGS+=-DNO_CHS DEBUGFLAGS+=-DTPM_MEASURE

# patch the boot(8) source code and compile
cd /usr/src/sys/arch/amd64/stand
patch ./boot/Makefile /tmp/makefile.patch

# this fix got already included in the OpenBSD source but did not make
# it in 6.6
patch ./libsa/gidt.S /tmp/boot/gidt.patch

patch ./libsa/cmd_i386.c /tmp/cmd_i386.patch
cp /tmp/tpm.c ./libsa/
cp /tmp/tpm.h ./libsa/
cd ./boot
make

# install biosboot(8) and boot(8)
# replace X with the drive number of the virtual softraid device
cd /usr/src/sys/arch/amd64/stand
installboot sdX  ./biosboot/biosboot ./boot/boot

If every step finished successfully, your system extends the measurement
chain from a small immutable piece of firmware up to boot(8). The
updated mbr(8) measures biosboot(8) and biosboot(8) measures boot(8).




The TPM has to be initialized bevor any of the tpm commands will work.
To perform the initialization:
1: reset the TPM in the firmware
2: create a bootable Fedora USB-Stick
3: start the system with it
4: and execute the following commands:
sudo dnf install tpm-tools
tpm_takeownership -z -y

boot(8) supports the machine specific command "tpm". This allows a
user to:

1: read the current contents of the Platform Control Registers (PCR)
   with the "pcr" parameter

   machine tpm p[cr]

2: seal a user supplied secret to the current PCR values and store it
   in the second block on a disk, that can be altered via a parameter.
   WARNING: If there is any other data in this block, it will be
   overwritten without asking again.

   machine tpm s[eal] secret [DiskNumber]

3: unseal a previously sealed secrent and display it to the user. This
   command just reads the second block of the disk that can be
   specified by the user and unseals it via the TPM

   machine tpm u[nseal] [DiskNumber]


Lets hope everything works as it does on my machine :). I will now be
away from my computer for a month. So if this feature is something the
OpenBSD would welcome, i would put in the other 90% it takes to bring
this feature from a prototype to something that could actually be
merged.

Kind Regards

Julius



tpm.h
Description: Binary data


tpm.c
Description: Binary data


biosboot.patch
Description: Binary data


cmd_i386.patch
Description: Binary data


gidt.patch
Description: Binary data


makefile.patch
Description: Binary data


mbr.patch
Description: Binary data


Re: Full disk encryption including /boot, excluding bootloader?

2020-02-18 Thread Julius Zint


> Are there any downsides though?  For example, would resume from
> hibernation still work for such a setup?

It should work with hibernation without any problems, but i did
not test this extensively.

> 
> More so, for the less knowledgeable of us, how does this relate to
> UEFI's "Secure Boot"?  I can only hope OpenBSD will support it some
> day, at least for amd64.  Debian has implemented it for the last major
> release, Debian 10.

Secure Boot as defined by the UEFI specification works with cryptographic
signatures instead of just measuring. Meaning there is also a Chain in which
every component has to verify the Signature of the next one.

The downside of this approach is, that in order to verify any signature, you
need some keys that you trust. If your name is Microsoft, than you can get
every vendor to include your keys inside the firmware and your bootloader
can be verified. This is obviously very convenient for the user.

If you are not Microsoft and your signature key is not included in the firmware,
than users have to sign the boot components manually and add their keys to the
firmware.

To sum it up. I think that SecureBoot was the right choice for Microsoft but
for FOSS the TPM approach is less hassle for the user. Also measuring can
not only be done for the executable itself, but also for the data it uses.
That way buffer overflow attacks can also be detected. The signature based
approach can not do that.

In the next few days i will write a email to misc containing a small manual
and all the source code.

Best Regards

Julius




Re: Full disk encryption including /boot, excluding bootloader?

2020-02-17 Thread Julius Zint


> I'm not really in a position to reflash my machine but I would still be
> curious for details.

There is no need to reflash your firmware if the system has a integrated
and supported TPM 1.2 chip.

The prototype uses a Static Root of Trust for Measurment (SRTM) approach
where the Chain of Trust is extended from a small immutable firmware part
up to boot(8). Every component in the boot chain is responsible for measuring
the components, that it hands control over the system. Measuring just means
calculating the hash and sending it to the TPM. The following example is the
Chain of Trust from my test system Lenovo Thinkpad X240 with OpenBSD.

1: Core Static Root of Trust for Measurment (C-SRTM) (immutable part of the 
Firmware)
2: Firmware (including OptionROMS)
3: MBR (mbr(8))
4: PBR (biosboot(8))
5: boot(8) (residing in the softraid(4) metadata when FDE is enabled)

I changed the mbr(8) and biosboot(8) to support measuring their next component.
Because there is very little available space left in the 440 byte of the mbr(8)
startprogram, you have to choose between CHS and measurement support at compile 
time.

boot(8) got support via a machine specific command to seal and unseal a secret 
of
your choosing to any drive. Sealing and unsealing means encrypting/decrypting
data depending on the state of the Platform Control Registers (PCR). PCRs are in
the TPM NVRAM and store the measurements.

With the laptop being in a trusted state, you can seal a secret and store it on 
a
usb drive. When you want to verify, that the software components are unchanged, 
you
plug in the usb drive and unseal the secret. If the output shows the correct 
secret
and you were the only person knowing it, than there is a very high chance that 
the
early boot components are unchanged.

Some feedback from the OpenBSD community on this would also be appreciated. Are 
there
enought people interessted in a Trusted Boot with OpenBSD?

Best Regards

Julius



Re: Full disk encryption including /boot, excluding bootloader?

2020-02-17 Thread Julius Zint


> 
> If an evil made came by and got access to my machine, they would still
> be able to tamper with the bootloader code to harvest the FDE password
> when I returned.
> 
> I want to put the whole bootloader (including the code used to decrypt
> the softraid-FDE-encrypted root-partition-containing media) on a USB
> disk.
> 
> This way the evil maid would have nothing to tamper with.

I recently finished my masterthesis that solves this problem by including
the Trusted Platform Module (TPM) in the bootprocess of OpenBSD.

It extends the Chain of Trust up to boot(8) and allows you to seal a
secret of your choice to the platform state.

To check wether the unencrypted bootcomponents got tampered with, you
can unseal and verify the secret to ensure that the contents of the
MBR, PBR and boot(8) are unchanged.

it is not exactly the solution you were looking for but it should solves
the problem that you describe. Does this sound like something you were
willing to try and does your machine have a TPM 1.2 Chip?

Best regards

Julius





Re: Value of eax register after BIOS interrupt call from boot(8)

2019-11-09 Thread Julius Zint
> 
> Index: arch/amd64/stand/libsa/gidt.S
> ===
> RCS file: /cvs/src/sys/arch/amd64/stand/libsa/gidt.S,v
> retrieving revision 1.11
> diff -u -p -u -r1.11 gidt.S
> --- arch/amd64/stand/libsa/gidt.S 27 Oct 2012 15:43:42 -  1.11
> +++ arch/amd64/stand/libsa/gidt.S 9 Nov 2019 06:50:57 -
> @@ -423,14 +423,6 @@ intno= . - 1
>   movl%edx, 0x9*4(%esp)
>   movb%bh , 0xe*4(%esp)
> 
> - /* clear NT flag in eflags */
> - /* Martin Fredriksson  */
> - pushf
> - pop %eax
> - and $0xbfff, %eax
> - push%eax
> - popf
> -
>   /* save registers into save area */
>   movl%eax, _C_LABEL(BIOS_regs)+BIOSR_AX
>   movl%ecx, _C_LABEL(BIOS_regs)+BIOSR_CX
> @@ -438,6 +430,13 @@ intno= . - 1
>   movl%ebp, _C_LABEL(BIOS_regs)+BIOSR_BP
>   movl%esi, _C_LABEL(BIOS_regs)+BIOSR_SI
>   movl%edi, _C_LABEL(BIOS_regs)+BIOSR_DI
> +
> + /* clear NT flag in eflags */
> + pushf
> + pop %eax
> + and $0xbfff, %eax
> + push%eax
> + popf
> 
>   pop %gs
>   pop %fs
> Index: arch/i386/stand/libsa/gidt.S
> ===
> RCS file: /cvs/src/sys/arch/i386/stand/libsa/gidt.S,v
> retrieving revision 1.36
> diff -u -p -u -r1.36 gidt.S
> --- arch/i386/stand/libsa/gidt.S  31 Oct 2012 13:55:58 -  1.36
> +++ arch/i386/stand/libsa/gidt.S  9 Nov 2019 06:51:29 -
> @@ -426,14 +426,6 @@ intno= . - 1
>   movl%edx, 0x9*4(%esp)
>   movb%bh , 0xe*4(%esp)
> 
> - /* clear NT flag in eflags */
> - /* Martin Fredriksson  */
> - pushf
> - pop %eax
> - and $0xbfff, %eax
> - push%eax
> - popf
> -
>   /* save registers into save area */
>   movl%eax, _C_LABEL(BIOS_regs)+BIOSR_AX
>   movl%ecx, _C_LABEL(BIOS_regs)+BIOSR_CX
> @@ -441,6 +433,13 @@ intno= . - 1
>   movl%ebp, _C_LABEL(BIOS_regs)+BIOSR_BP
>   movl%esi, _C_LABEL(BIOS_regs)+BIOSR_SI
>   movl%edi, _C_LABEL(BIOS_regs)+BIOSR_DI
> +
> + /* clear NT flag in eflags */
> + pushf
> + pop %eax
> + and $0xbfff, %eax
> + push%eax
> + popf
> 
>   pop %gs
>   pop %fs

These changes work for me. As part of my Masterthesis im working on a
measured boot with OpenBSD and to communicate with the TPM from within boot
(8) BIOS calls are a convenient way to do so.

Thanks for the fast response

Julius




Value of eax register after BIOS interrupt call from boot(8)

2019-11-07 Thread Julius Zint
Hi misc,

the following code snipped is from sys/arch/amd64/stand/libsa/gidt.S

/* pass BIOS return values back to caller */
movl%eax, 0xb*4(%esp)
movl%ecx, 0xa*4(%esp)
movl%edx, 0x9*4(%esp)
movb%bh , 0xe*4(%esp)

/* clear NT flag in eflags */
/* Martin Fredriksson  */
pushf
pop %eax
and $0xbfff, %eax
push%eax
popf

/* save registers into save area */
movl%eax, _C_LABEL(BIOS_regs)+BIOSR_AX
movl%ecx, _C_LABEL(BIOS_regs)+BIOSR_CX
movl%edx, _C_LABEL(BIOS_regs)+BIOSR_DX
movl%ebp, _C_LABEL(BIOS_regs)+BIOSR_BP
movl%esi, _C_LABEL(BIOS_regs)+BIOSR_SI
movl%edi, _C_LABEL(BIOS_regs)+BIOSR_DI

These instructions are being executed after a BIOS interrupt. If i read
correctly, than (BIOS_regs)+BIOSR_AX contains the contents of the eflags
processor register and not of %eax. Is this intended or should it contain
the value of %eax?

Kind regards

Julius