This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Systemtap and UEFI Secure Boot


One of the things I've been asked to look at is how systemtap will work
on systems using Secure Boot. Secure boot is a setup using UEFI (Unified
Extensible Firmware Interface) firmware to check cryptographic
signatures on the bootloader and associated OS kernel to ensure they
have not been tampered with or bypassed in the boot process. For more
background, see <https://fedoraproject.org/wiki/Secureboot>

I finally got a systemtap module running by hand on a secure boot
system, here's how I did it.


Creating a Secure Boot VM
=========================

One of my first problems here was that I don't have a system that
supports UEFI or secure boot. But, the good news is that you can create
a virtual machine to test secure boot with KVM and OVMF (Open Virtual
Machine Firmware). OVMF is basically UEFI for KVM. Here's a link that
describes creating a F18 Secure Boot VM (virtual machine):

<https://fedoraproject.org/wiki/Testing_secureboot_with_KVM>

Originally I created a F19 VM using those instructions, but after lots
of problems realized that F19 doesn't have a new enough version of the
'shim' rpm. The version of 'shim' must be at least 1.5 for the following
procedure to work. So, I created a rawhide VM with OVMF.

Basically I combined the above Secure Boot VM instructions with the
"Point installer to Rawhide" section of the following link to create the
rawhide VM:

<https://fedoraproject.org/wiki/Releases/Rawhide?rd=Rawhide>

Note that OVMF makes the VM run slower, so the install will take longer
than normal.

Also note that the secure boot VM instructions state that you must enter
some commands on every reboot. That isn't quite true. The OVMF firmware
by default runs a script called 'startup.nsh'. After booting your VM,
you can create the script in /boot/efi/startup.nsh. Here's what mine
looks like:

====
fs0:
echo "Loading Lockdown_ms.efi..."
\EFI\fedora\Lockdown_ms.efi
echo "Loading shim.efi..."
\EFI\fedora\shim.efi
====


Verifying Secure Boot Operation
===============================

To make sure your system was booted in secure mode, you can do the
following:

# dmesg | grep 'Secure boot'
[    0.000000] Secure boot enabled

OK, now that we've got a secure boot machine, let's try to run a
systemtap module.

# stap -m hello -e 'probe begin { printf("hello\n"); exit() }'
# staprun hello.ko
ERROR: Couldn't insert module 'hello.ko': Required key not available

This is to be expected. On a secure boot system, the kernel and all
kernel modules have to be signed with a key that has been installed in
the bios.


Creating a Signing Key
======================

We need to create a key that we can use to sign the systemtap modules.
First, create a config file that looks like the following:

====
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
prompt = no
x509_extensions = myexts

[ req_distinguished_name ]
O = Systemtap
CN = Systemtap module signing key

[ myexts ]
basicConstraints=critical,CA:FALSE
keyUsage=digitalSignature
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
====

The above is based on the kernel's key config file. Once we have the
config file (which I called 'x509.genkey'), we can create the public and
private key files:

====
# openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \
	-config x509.genkey -outform DER -out signing_key.x509 \
	-keyout signing_key.priv
Generating a 4096 bit RSA private key
..............................................................................................................................++
.....................................................................................................................++
writing new private key to 'signing_key.priv'
-----
====

This creates the public key in 'signing_key.x590' and the private key in
'signing_key.priv'.


Signing the Systemtap Module
============================

Now we can sign the systemtap module, using a script from kernel-devel:

====
# /usr/src/kernels/`uname -r`/scripts/sign-file sha512 signing_key.priv
signing_key.x509 hello.ko
====

Let's see if we can insert this signed systemtap module:

====
# staprun hello.ko
ERROR: Couldn't insert module 'hello.ko': Required key not available
====

Even though the module is signed, the UEFI bios knows nothing of this
signing key. If you'll look in /var/log/messages, you'll see something
like this:

kernel: [ 4790.187663] Request for unknown module key 'Systemtap module
signing key: 56825d793f2636788a68c7fb6fa957a552c009e3' err -11


Adding the Signing Key to the BIOS
==================================

There are actually several different keys sets involved in Secure Boot.
We're going to add the public key we created earlier to the MOK (Machine
Owner Keys) database using mokutil:

====
# mokutil --import signing_key.x509
====

When you run the above, if you haven't set a password on your MOK
database, it will ask for one. At this point the key isn't "enrolled"
in the MOK database, it is just marked as ready to be enrolled. To
fully enroll the key, you have to reboot your system.

When you reboot the system, the fedora shim.efi will automatically run
MokManager.efi to allow you to enroll the new key. After enrolling the
key, the system will reboot again.

After the system comes up, mokutil can be used to list the enrolled
keys.

====
# mokutil --list-enrolled
[key 1]
SHA1 Fingerprint:
1c:24:05:9c:d4:03:b9:f1:60:5d:15:e9:ed:fb:d8:d9:d4:84:38:9a
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 17787941542718095415 (0xf6db7696ab204037)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: O=Systemtap, CN=Systemtap module signing key
...
====

There's the public key we created.


Running the Signed Systemtap Module
===================================

Our new key got enrolled. Now, let's run the signed module:

====
# staprun hello.ko
hello
====

Success! Once the key is enrolled, running the signed module is
"normal", there is nothing extra to do. Even after a reboot, the key is
still enrolled in the MOK database and the signed module can be run
without a problem.


Development Questions
=====================

The secure boot environment creates several questions for systemtap.
Here are the top two floating around in my head:

- How do we keep the private key secure? The kernel documentation file
called 'module-signing.txt' contains the following text:

====
Since the private key is used to sign modules, malware can use
the private key to sign modules and compromise the operating system.
The private key must be moved to a secure location and not kept in
the root node of the kernel source tree.
====

The fedora kernel build handles this by creating the key, building the
kernel and all modules, signing everything, then deleting the private
key. Systemtap doesn't have this option, we'll have to keep our private
key around so that we can continue to sign modules. This brings up lots
of security concerns/questions, like:

   - Where will we keep the public/private keys?

   - Who will have access to these keys? (At first I thought it would be
root only, but then how would a member of the 'stapdev' group get a
module signed at build time?)

- When does a module get signed - at build time or when staprun inserts
the module? If at build time, then you can't copy modules between
systems anymore (using stap-server or 'stap --remote') - unless the
systems use the exact same public/private keys. If the module gets
signed when staprun inserts the module, this would make running a
systemtap module early in the boot process difficult, if not impossible.

-- 
David Smith
dsmith@redhat.com
Red Hat
http://www.redhat.com
256.217.0141 (direct)
256.837.0057 (fax)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]