From Fedora Project Wiki
 
(7 intermediate revisions by the same user not shown)
Line 11: Line 11:
** the linux kernel from whatever distro you're using.
** the linux kernel from whatever distro you're using.
** pesign - https://github.com/vathpela/pesign/releases/download/0.110/pesign-0.110.tar.bz2
** pesign - https://github.com/vathpela/pesign/releases/download/0.110/pesign-0.110.tar.bz2
** efitools - https://git.kernel.org/cgit/linux/kernel/git/jejb/efitools.git/


== Steps ==
== Steps ==
= Create signing keys =
= Create signing keys =


This is pretty easy on a modern Linux distro when you've got pesign installed, though it is recommended to use a hardware security mechanism like a smart card or USB FIPS 140 Level 2 conforming device to generate and store the cryptographic keys.  There's a short tutorial on that <a href="https://fedoraproject.org/wiki/User:Pjones/SecureBootSmartCardDeployment">here</a>, though for these purposes you don't really need a CA key.  Assuming you've got the device itself set up and its modules added to the nss db in /etc/pki/pesign, and it is represented with a token in your pesign nss database named "fred", you need to create the keypaid and certificates:
This is pretty easy on a modern Linux distro when you've got pesign installed, though it is recommended to use a hardware security mechanism like a smart card or USB FIPS 140 Level 2 conforming device to generate and store the cryptographic keys.  There's a short tutorial on that over at [[User:Pjones/SecureBootSmartCardDeployment]], though for these purposes you don't really need a separate CA key; a single self-signed key should do.  Assuming you've got the device itself set up and its modules added to the nss db in /etc/pki/pesign, and it presents a token in your pesign nss database named "fred", you need to create the key pair and certificates:
<pre>efikeygen -t fred -S -n jrh-signer -c "CN=J.Random Hacker's Code Signing Authority and Amalgamated Distillates, Inc." -u "https://example.com/jrh-signer-info"</pre>
<pre>efikeygen -t fred -S -n jrh-signer -c "CN=J.Random Hacker's Code Signing Authority and Amalgamated Distillates, Inc." -u "https://example.com/jrh-signer-info"</pre>


Line 24: Line 25:
jrh-machine:~/shim-0.8$ pesign -t fred -c jrh-signer -s -i fallback.efi -o fallback-signed.efi
jrh-machine:~/shim-0.8$ pesign -t fred -c jrh-signer -s -i fallback.efi -o fallback-signed.efi
jrh-machine:~/shim-0.8$ pesign -t fred -c jrh-signer -s -i MokManager.efi -o MokManager-signed.efi</pre>
jrh-machine:~/shim-0.8$ pesign -t fred -c jrh-signer -s -i MokManager.efi -o MokManager-signed.efi</pre>
Here we're assuming the bootloader will be installed as "EFI/jrh/grubx64.efi" on the ESP.


Assuming the EFI system partition is mounted on /boot/efi/, you'll also need to copy the files into place.  Don't just change -o above to point there; you may hit <a href="https://github.com/vathpela/fuzzy-lana">this problem</a> and find yourself having a very confusing week.<pre>mkdir -p /boot/efi/EFI/jrh/ /boot/efi/EFI/BOOT
Assuming the EFI system partition is mounted on /boot/efi/, you'll also need to copy the files into place.  Don't just change -o above to point there; you may hit [https://github.com/vathpela/fuzzy-lana this problem] and find yourself having a very confusing week.<pre>mkdir -p /boot/efi/EFI/jrh/ /boot/efi/EFI/BOOT
cp shim-signed.efi /boot/efi/EFI/jrh/shim.efi
cp shim-signed.efi /boot/efi/EFI/jrh/shim.efi
cp MokManager-signed.efi /boot/efi/EFI/jrh/MokManager.efi
cp MokManager-signed.efi /boot/efi/EFI/jrh/MokManager.efi
Line 33: Line 35:
You'll also want to make a BOOT.CSV for fallback to find in EFI\jrh\ ; it's a UCS-2 LE file, so do something like:<pre>echo -n "shim.efi,JRH-OS,,This is the boot entry for JRH-OS" | ( printf "\xff\xfe" ; sed 's/./&\x00/g') > /boot/efi/EFI/jrh/BOOT.CSV</pre>
You'll also want to make a BOOT.CSV for fallback to find in EFI\jrh\ ; it's a UCS-2 LE file, so do something like:<pre>echo -n "shim.efi,JRH-OS,,This is the boot entry for JRH-OS" | ( printf "\xff\xfe" ; sed 's/./&\x00/g') > /boot/efi/EFI/jrh/BOOT.CSV</pre>


At this point you need to build the bootloader, including using "grub-mkimage" to make a reasonable grubx64.efi image.  If your distro already has that, all you really need to do is make sure it's signed with your signature:<pre>jrh-machine:~/tmp$ pesign -i grub-2.02/grub.efi -o grub.efi -r -u 0
jrh-machine:~/tmp$ pesign -t fred -c jrh-signer -s -i -i grub.efi -o grub-signed.efi
jrh-machine:~/tmp$ cp grub-signed.efi /boot/efi/EFI/jrh/grubx64.efi</pre>


And do the same with the kernel: <pre>jrh-machine:~/tmp$ pesign -i /boot/vmlinuz-3.15.6-200.fc20.x86_64 -o vmlinuz-unsigned -r -u 0
jrh-machine:~/tmp$ pesign -t fred -c jrh-signer -s -i -i vmlinuz-unsigned.efi -o vmlinuz-signed
jrh-machine:~/tmp$ cp vmlinuz-signed /boot/vmlinuz-3.15.6-200.fc20.x86_64</pre>
Again, don't sign things on /boot, it'll make you likely to hit [https://github.com/vathpela/fuzzy-lana this pit of dispair].


You'll need to re-do grub and the kernel any time you upgrade them.  If you have a reasonable level of minor paranoia about protecting keys and you've used an HSM with a pin code or at the least kept the keys on e.g. a USB stick that's not normally mounted on the machine you're doing signing for, then you probably can't really automate it.  Sorry.


...
= build LoadKeys.efi =
You're going to have to get these keys loaded somehow. One of the easiest ways to do so is to build efitools' LoadKeys.efi with your keys built in as db.
Clone a copy of efitools and do this:<pre>jrh-machine:~/tmp/efitools$ certutil -d /etc/pki/pesign -h fred -L -n jrh-signer -r > jrh-signer.cer
jrh-machine:~/tmp/efitools$ openssl x509 -in jrhsigner.cer -inform DER -out DB.auth -outform PEM
jrh-machine:~/tmp/efitools$ make LockDown.efi
# lots o' stuff here
jrh-machine:~/tmp/efitools$ cp LockDown.efi /boot/efi/LockDown.efi</pre>
 
= set up the machine to actually use this stuff =
Finally, you need to actually configure the machine to be using all this:<pre>jrh-machine:~$ efibootmgr -b 1010 -c -d /dev/sda -L JRH-OS -l '\LockDown.efi'
jrh-machine:~$ efibootmgr -b 1011 -c -d /dev/sda -L JRH-OS -l '\EFI\jrh\shim.efi'
jrh-machine:~$ efibootmgr -n 1010 -o 1011
</pre>
 
Now reboot, interrupt boot to go into the firmware setup menus, find the Secure Boot option, and put it in "setup mode".  Then reboot again.
This should run LockDown.efi (because we configured it as BootNext with efibootmgr above), which will install the keys on the machine.  Another reboot will use shim.efi ; you may need to re-enable secure boot after installing keys, but on most machines you shouldn't need to.

Latest revision as of 20:04, 4 November 2014

Self Signing For Secure Boot

Here's how to do your own signing for use with Secure Boot!

Stuff you need

Steps

Create signing keys

This is pretty easy on a modern Linux distro when you've got pesign installed, though it is recommended to use a hardware security mechanism like a smart card or USB FIPS 140 Level 2 conforming device to generate and store the cryptographic keys. There's a short tutorial on that over at User:Pjones/SecureBootSmartCardDeployment, though for these purposes you don't really need a separate CA key; a single self-signed key should do. Assuming you've got the device itself set up and its modules added to the nss db in /etc/pki/pesign, and it presents a token in your pesign nss database named "fred", you need to create the key pair and certificates:

efikeygen -t fred -S -n jrh-signer -c "CN=J.Random Hacker's Code Signing Authority and Amalgamated Distillates, Inc." -u "https://example.com/jrh-signer-info"

Build shim with your key built in to it

At the least, you need some things from shim signed, and you need to build it with your keys built in. Basically this:

jrh-machine:~/shim-0.8$ certutil -d /etc/pki/pesign -h fred -L -n jrh-signer -r > jrh-signer.cer
jrh-machine:~/shim-0.8$ make 'DEFAULT_LOADER=\\\\grubx64.efi' VENDOR_CERT_FILE=jrh-signer.cer shim.efi MokManager.efi fallback.efi
jrh-machine:~/shim-0.8$ pesign -t fred -c jrh-signer -s -i shim.efi -o shim-signed.efi
jrh-machine:~/shim-0.8$ pesign -t fred -c jrh-signer -s -i fallback.efi -o fallback-signed.efi
jrh-machine:~/shim-0.8$ pesign -t fred -c jrh-signer -s -i MokManager.efi -o MokManager-signed.efi

Here we're assuming the bootloader will be installed as "EFI/jrh/grubx64.efi" on the ESP.

Assuming the EFI system partition is mounted on /boot/efi/, you'll also need to copy the files into place. Don't just change -o above to point there; you may hit this problem and find yourself having a very confusing week.

mkdir -p /boot/efi/EFI/jrh/ /boot/efi/EFI/BOOT
cp shim-signed.efi /boot/efi/EFI/jrh/shim.efi
cp MokManager-signed.efi /boot/efi/EFI/jrh/MokManager.efi
cp shim-signed.efi /boot/efi/EFI/BOOTX64.EFI
cp fallback.efi /boot/efi/EFI/BOOT/fallback.efi

You'll also want to make a BOOT.CSV for fallback to find in EFI\jrh\ ; it's a UCS-2 LE file, so do something like:

echo -n "shim.efi,JRH-OS,,This is the boot entry for JRH-OS" | ( printf "\xff\xfe" ; sed 's/./&\x00/g') > /boot/efi/EFI/jrh/BOOT.CSV

At this point you need to build the bootloader, including using "grub-mkimage" to make a reasonable grubx64.efi image. If your distro already has that, all you really need to do is make sure it's signed with your signature:

jrh-machine:~/tmp$ pesign -i grub-2.02/grub.efi -o grub.efi -r -u 0
jrh-machine:~/tmp$ pesign -t fred -c jrh-signer -s -i -i grub.efi -o grub-signed.efi
jrh-machine:~/tmp$ cp grub-signed.efi /boot/efi/EFI/jrh/grubx64.efi

And do the same with the kernel:

jrh-machine:~/tmp$ pesign -i /boot/vmlinuz-3.15.6-200.fc20.x86_64 -o vmlinuz-unsigned -r -u 0
jrh-machine:~/tmp$ pesign -t fred -c jrh-signer -s -i -i vmlinuz-unsigned.efi -o vmlinuz-signed
jrh-machine:~/tmp$ cp vmlinuz-signed /boot/vmlinuz-3.15.6-200.fc20.x86_64

Again, don't sign things on /boot, it'll make you likely to hit this pit of dispair.

You'll need to re-do grub and the kernel any time you upgrade them. If you have a reasonable level of minor paranoia about protecting keys and you've used an HSM with a pin code or at the least kept the keys on e.g. a USB stick that's not normally mounted on the machine you're doing signing for, then you probably can't really automate it. Sorry.

build LoadKeys.efi

You're going to have to get these keys loaded somehow. One of the easiest ways to do so is to build efitools' LoadKeys.efi with your keys built in as db.

Clone a copy of efitools and do this:

jrh-machine:~/tmp/efitools$ certutil -d /etc/pki/pesign -h fred -L -n jrh-signer -r > jrh-signer.cer
jrh-machine:~/tmp/efitools$ openssl x509 -in jrhsigner.cer -inform DER -out DB.auth -outform PEM
jrh-machine:~/tmp/efitools$ make LockDown.efi
# lots o' stuff here
jrh-machine:~/tmp/efitools$ cp LockDown.efi /boot/efi/LockDown.efi

set up the machine to actually use this stuff

Finally, you need to actually configure the machine to be using all this:

jrh-machine:~$ efibootmgr -b 1010 -c -d /dev/sda -L JRH-OS -l '\LockDown.efi'
jrh-machine:~$ efibootmgr -b 1011 -c -d /dev/sda -L JRH-OS -l '\EFI\jrh\shim.efi'
jrh-machine:~$ efibootmgr -n 1010 -o 1011

Now reboot, interrupt boot to go into the firmware setup menus, find the Secure Boot option, and put it in "setup mode". Then reboot again. This should run LockDown.efi (because we configured it as BootNext with efibootmgr above), which will install the keys on the machine. Another reboot will use shim.efi ; you may need to re-enable secure boot after installing keys, but on most machines you shouldn't need to.