UEFI SecureBoot mini-HOWTO update 2018

= Disclaimer =

The article is based on an original [UEFI SecureBoot mini-HOWTO] by Michael Shigorin and is intended to cover changes in the process introduced as time passed by... NOTE: The article is under development and not ready to serve as a complete solution.

= Introduction =

This document aims to help Linux distributions cope with UEFI SecureBoot; it focuses on SecureBoot part primarily although working implementation of plain UEFI boot support is required in the first place.

Getting seamless boot on x86 systems with SecureBoot enabled out-of-box basically requires dealing with UEFI CA. They offer to sign EFI binaries which have passed their review with "Microsoft Windows UEFI Driver Publisher" key for 3rd party drivers.

As it would be highly impractical at best to have to sign bootloaders this way though, the nice folks at Red Hat and SUSE have developed UEFI shim which makes the review/sign process much more rare but it still has to be done at least once.

This document relates to ALT Linux case and thus has some inevitable peculiarities. We hope that it will be helpful to those willing to take the trouble for their users though.

You should also comprehend FSF statement on the problem: "We reject the recommendation that others join the Microsoft developer program".

Thanks go to:
 * Peter Jones (Red Hat) -- for his kind replies and implementation advice ;
 * Matthew Garrett (Red Hat->Nebula) -- for this terse walkthrough and the many articles;
 * Gary Ching-Pang Lin (SUSE) -- for MOK concept implementation;
 * all of them for the resulting shim and other code required;
 * Roderick Smith -- for his solid documentation and beautiful refind bootloader;
 * Suhas Manangi (Microsoft) -- for patient CA-side explanations.

This document has been written by [mailto:nickelaltlinux.org Nikolai Kostrigin] for ; feel free to provide criticism, suggestions, feedback but please understand that I can't answer every single question, especially within areas not trodden during this work.

= The Plan =


 * 1) prepare the assets
 * 2) obtain shim<%EFI_ARCH>.efi signed by UEFI CA
 * 3) wire the rest of the distro to make use of it

Assets
You will need:

As was:
 * $99+, several days to a few weeks, and a Windows host/VM
 * hardware or KVM stand with SB-capable firmware
 * some more packages (or whatever you do)

As is: As of the fall 2018 there is no more opportunity to get a certificate from a CA for $99. Moreover, Microsoft requires using EV Code Sign Certificate to sign all UEFI CA submissions.

As was: The suggested steps are:
 * 1) start obtaining Symantec certificate for a company (or private person)
 * 2) prepare the binary builds of a signing tool, shim and grub2 (or another bootloader)
 * 3) bring up a distribution-specific certification authority and create a pair of certificate+key pairs (CA and Signer)
 * 4) build and test shim.efi containing the public part of your CA cert
 * 5) build and test at least one EFI capable bootloader signed by your Signer key

The result should be "ready to start approaching UEFI CA".

As is: The suggested steps are:
 * 1) before obtaining a certificate one may want to register company's publicly accessible unique identifier for business (like D-U-N-S or similar) as this may be a requirement from CA.
 * 2) start obtaining a suitable certificate for a company (private person can not obtain EV Code Sign certificate)
 * 3) prepare the binary builds of a signing tool, shim and grub2 (or another bootloader)
 * 4) bring up a distribution-specific certification authority and create a pair of certificate+key pairs (CA and Signer)
 * 5) build and test shim.efi containing the public part of your CA cert
 * 6) build and test at least one EFI capable bootloader signed by your Signer key
 * 7) create a Microsoft Hardware Dev Center account
 * 8) provide your shim binaries (with a reproducible rebuild recipe and tools) and bootloader's source code for review to Shim Review Board;

The result should be "ready to start approaching UEFI CA".

Why
This one is needed once to authorize the company when registering at UEFI CA portal and then each time you prepare the upload to be reviewed and signed. It's an Authenticode class 3 certificate; one can be obtained with discount via Windows Dev Center.

How
The process requires IE7+ with a peculiar setup of ActiveX to get a certificate generated and imported to be exported into a file. See the walkthrough. Do not dispose of that host/VM at once, you will need it later.

It took three business days for us.

Where to
Get the certificate+private key obtained from Import Export software into a standalone file:
 * 1) Options > Content > Certificates > Personal
 * 2) choose the certificate
 * 3) click Export
 * 4) choose "Yes, export the private key" and "Personal Information Exchange - PKCS #12 (.PFX)"

The password should be strong enough but care not to lose it (reasonable offline storage like a paper in an envelope inside a safe is recommended backup). Backup the file and keep it in safe dry location as well.

Deliverable: .pfx file including the private key exported to PKCS#12 form.

Testing facility
This could be a notebook, desktop, server or barebone/improvised system which is declared to be "Windows 8 Ready" which means it supports UEFI 2.3.1 spec version or later. We chose a notebook shipping with Windows 8 to be able to test dualboot as well.

This could also be a Linux KVM instance booted with TianoCore firmware build supporting that spec version; virtualized approach has both upsides (ease of reversion) and downsides (burden of re-initialization) but one can use both real and virtual stands after all.

Deliverable: something that can boot PE binaries or refuse to due to the "wrong" signature or the lack thereof.

Specific software
You need to make sure that several packages are available: signing utilities, UEFI shim and a EFI capable bootloader ; nss-utils will and openssl might come handy too but you should be able to just install these.

A few more utilities are needed each time to prepare shim for upload and to prepare winqual.exe once as well.

Deliverables: at least the working binaries for initial experiments; proper packages are highly preferred for reproducibility.

winqual and shim related
cabextract is probably there already; you will most likely still need to build osslsigncode and lcab.

gnu-efi
Your distribution might be carrying this toolchain already, most likely so if it does support UEFI. In case it does not, take a look at 3.0r and 3.0u: 3.0s and 3.0t have known regressions while earlier versions had other kinks not worked out yet, this tends to result in EFI binaries hanging upon the start; my 3.1 experiments weren't successful so far either.

Sticking with 3.0r for bootloaders looks good so far, 3.0u gets some interesting CWD handling differences in resulting binaries for me. Fedora RPM spec here.

I've built shim binaries with 3.0u before having discovered those differences and have settled for multiple gnu-efi versions available in repository ; YMMV.

pesign
We'll discuss Fedora's pesign which is more capable and versatile than Ubuntu's sbsigntools. It can do client/server and provides a few more useful tools like efikeygen.

Grab pesign source and make sure you have 0.106 to 0.109 (as of today) built and working. Fedora spec is here. I chose to leave Red Hat Test Certificate as the default packaged one to avoid needless duplication and to give some extra credit. :)

shim
Basically there are two flavours of EFI shim : <0.5 and >0.5.

0.5 itself is broken (it won't work on UEFI firmware without SecureBoot implementation) so you'll likely choose 0.7 or later which also implement further restrictions on subsequent bootloader basically blowing it up if the bootloader doesn't verify a signature. This ends up requiring at least the kernel images to be signed as well.

0.4 lacks this kind of behaviour but there's no warranty that these builds will get signed.

You want as few patches as possible, ideally just clean upstream commits. If using 0.7 or later, the upstream-recommended procedure is:

git checkout 0.7 make test-archive

...and to use the resulting tarball; this will cause the output of

git log -1 --pretty=format:%H > /tmp/shim-$(VERSION)/commit

to exist in the tarball, which will make the commit ID show up in an ident string. This should greatly aid the CA's efforts in knowing what's being signed and might come handy to you too.

grub2
You can choose between several implementations that share the ability to be built as EFI binaries and to start other EFI binaries passing the commandline to Linux kernels :


 * efilinux
 * elilo
 * grub2
 * refind

We use refind and elilo</tt> either but grub2</tt> is the most "generic" layer of code that can also boot something else on occasion.

You want 2.00 with considerable number of patches or later versions if/when these get released and work for you.

The most important choice is whether you will get it to verify the kernel's signature (required by recent shim versions). I chose not to but we've got shim-0.4 build signed.

Your CA
The method covered here is a pretty standard basic CA scheme: there's one self-signed CA certificated (cacert) and at least one signing certificate which is signed by that one. Other methods were not considered reasonable.

You need to generate and store those in a reasonably safe manner so that private key material leak is not feasible. It is strongly recommended that everybody use FIPS 140-2 Level 2 hardware security modules for all key storage.

These should be RSA2048/SHA256 X.509 certificates.

It is recommended to use efikeygen(1)</tt> utility from pesign package as it will set up the NSS DB as intended with minimal hassle:

mkdir -p ~/ca/altlinux certutil -d ~/ca/altlinux -N efikeygen -d ~/ca/altlinux \ --ca --self-sign \ --nickname='ALT Linux UEFI SB CA' \ --common-name='CN=ALT UEFI SB CA 2013,OU=ALT Certification Authority,O=ALT Linux Team,C=RU' \ --url='http://altlinux.org/UEFI' --serial=00 efikeygen -d ~/ca/altlinux \ --signer='ALT Linux UEFI SB CA' \ --nickname='ALT Linux UEFI SB Signer' \ --common-name='CN=ALT UEFI SB Signer 2013,OU=ALT Certification Authority,O=ALT Linux Team,C=RU' \ --url='http://altlinux.org/UEFI' --serial=01 pk12util -d ~/ca/altlinux -o signer.p12 -n 'ALT Linux UEFI SB Signer' mkdir ~/ca/signer certutil -d ~/ca/signer -N pk12util -d ~/ca/signer -i signer.p12 shred signer.p12

One will also need CA cert exported as DER file to build it into shim later, so:

certutil -d ~/ca/altlinux -L -n "ALT Linux UEFI SB CA" -r > altlinux-ca.cer

Examine the result if interested:

derdump -i altlinux-ca.cer | less

You might want to read up a bit: SSL Certificates HOWTO, OpenSSL Certificate HOWTO, Mozilla's Glossary.

[http://blog.hansenpartnership.com/uefi-secure-boot/ Note that when the UEFI spec says “key”, it doesn’t mean the same as an openssl key. In UEFI parlance, the “key” or “public key” means the public part (i.e. the X509 certificate); openssl uses the term key to mean the private key used to sign stuff with.]

Deliverables: a password-protected NSS database holding cacert and signer cert with corresponding private keys; a DER-encoded CA certificate file.

Signing EFI binaries
pesign can work in both standalone and client/server modes; the process doing the actual signing (pesign) must be given at least read-only access to the NSS database directory containing the Signer certificate or a smart card token capable of signing.

standalone
pesign -s -n ~/ca/signer -c "ALT Linux UEFI SB Signer" -i grub.efi -o grub-signed.efi

server
Example of manual debug start:


 * 1) pesign -D -N -v -n /path/to/ca/signer

client
Running client/server requires that the client process is started by a user with enough permissions to access /var/run/pesign/socket.

$ pesign-client -u $ pesign-client -s -c "ALT Linux UEFI SB Signer" -i grub.efi -o grub-signed.efi

The former command asks for the NSS DB password and provided the correct one triggers unlocking the database; the latter command feeds the binary to the server to get it signed.

Preparing sysdev account
You will need once:
 * Windows host/VM
 * Symantec/Verisign certificate
 * live.com account
 * several days to a few months

The suggested steps are:
 * 1) obtain a live.com account
 * 2) authenticate/link the company to that account
 * 3) read and accept Microsoft's agreements

Logging in
sysdev.microsoft.com requires a live.com account to work with it so you're forced to obtain one.

Authenticating the company
This process is set up by means of signing a test binary with Symantec/Verisign provided certificate and needs to be done once.

You will have to:
 * 1) create a certificate database with Symantec certificates imported into that
 * 2) download winqualexe.zip from sysdev.microsoft.com, unpack and pesign it
 * 3) upload the signed winqual.exe back to sysdev.microsoft.com

Preparing NSS database
Our file holding the exported certificate+private key in PKCS#12 form is referred to as "altlinux.pfx" below, adjust as appropriate.

Additionally, save Symantec intermediate certificates into primary.crt and secondary.crt files.

Then import these into a separate certificate database:

mkdir -p ~/ca/symantec certutil -N -d ~/ca/symantec certutil -A -n 'Symantec primary' -d ~/ca/symantec -t CT,CT,CT -i primary.crt certutil -A -n 'Symantec secondary' -d ~/ca/symantec -t CT,CT,CT -i secondary.crt pk12util -A -n 'ALT Linux (authenticode)' -d ~/ca/symantec -i altlinux.pfx certutil -L -d ~/ca/symantec

The last command should list the three certificates with the last one having xx-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx form of certificate nickname and "u,u,u" trust attributes.

Obtaining the test binary
See this MSDN article, download winqualexe.zip and unzip it.

Signing with Symantec certificate
Use that last certificate nickname to sign the downloaded binary:

pesign -n ~/ca/symantec -c xx-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \ -s -i ~/unsigned/winqual.exe -o ~/signed/winqual.exe

This one is to be uploaded to confirm that the registered company name relates to a real company.

Legal Agreements
These are "Windows Logo Program Testing Agreement V3" and "UEFI Firmware Agreement" as of autumn 2013.

You'll need to give permissions to sign agreements to the account used (which is administrative) or another user's one if there are several involved:
 * Dev Center - Hardware > Administration > Legal agreements

Getting your shim signed
You will need this each time you build new production shim:
 * Windows host/VM with Silverlight available
 * shim.efi containing your cacert's public part and verified to work generally
 * Symantec certificate to sign the submission
 * sysdev account with UEFI signing permission
 * several days to several weeks

The suggested steps are:
 * 1) prepare shim.efi for submission
 * 2) upload shim.cab to sysdev.microsoft.com
 * 3) send a questionnaire to [mailto:sysdev@microsoft.com sysdev@microsoft.com]
 * 4) wait and check both inbox and spambox of the account used periodically
 * 5) download the signed binary if/when completed

You might choose to further sign the obtained binary with the Signer key to have two signatures thus supporting the case when firmware is clean of Microsoft's ones but yours is enrolled; note that some firmware implementations will not accept dual signatures.

Preparing the upload
The EFI binary to be signed by UEFI CA has to be extracted from the package you have built already, wrapped up as a CAB file and signed:

lcab shim.efi shim-unsigned.cab

osslsigncode</tt> is weird enough to only accept the password via the commandline ; so don't forget to prevent it to be stored in shell history in its entirety, e.g. for bash</tt>:

export HISTCONTROL=$HISTCONTROL:ignorespace osslsigncode sign -pkcs12 altlinux.pfx -pass xxxx -in shim-unsigned.cab -out shim.cab

Deliverable: shim.cab file ready for upload.

Uploading shim

 * 1) boot that Windows host/VM up
 * 2) start a web browser with Silverlight plugin available
 * 3) log into sysdev.microsoft.com
 * 4) go to Hardware Certification > Create UEFI submission
 * 5) choose the prepared shim.cab file
 * 6) enter something like "shim.efi (upstream 0.7)" as a Name
 * 7) submit

Deliverable: submission ID.

Posting the answers
You can expect a query from sysdev@microsoft.com for some additional details or care to provide these beforehand with a reference to the obtained submission ID in Subject: line. The questions to be expected are:


 * 1) Does your company have an external URL?  If so, please provide an external link to the website.
 * 2) Does the UEFI submission contain product quality code?
 * 3) Include a brief statement on the purpose or goal for the UEFI submission.
 * 4) Is the UEFI submission associated with another program?
 * 5) Does the UEFI submission include license terms that would mandate the transmission of keys used for signing? (i.e., GPLv3 or similar)
 * 6) Does your submission load and execute any other code prior to ExitBootServices? If so, please explain how the code is loaded, authorized, and executed.  For example, All images are loaded by EFI LoadImage and executed by EFI StartImage, and a prompt is displayed to the user requesting authorization.

A long wait
Looks like the sysdev guys are going through the queue once or twice a week; expect at least three days of normal silence, if that's longer than a week or so:
 * query Hardware certification > Manage submissions page for the status
 * re-check the spambox
 * ask sysdev@microsoft.com referring to that submission id

It took three weeks in our case as we didn't know about that questionnaire yet.

Downloading shim
UEFI CA will send a notification email including the download link with Subject: including "UEFI Submission Processing Complete" to the email address of live.com account which has done the submission -- provided that the binary has passed the review and ended up with "Approved" status.

The cabextracted binary should manifest a signature:

$ pesign -S -i shim.efi - certificate address is 0x7f5ec2a4a8e8 Content was not encrypted. Content is detached; signature cannot be verified. The signer's common name is Microsoft Windows UEFI Driver Publisher No signer email address. No signing time included. There were certs or crls included. -

Deliverable: the precious shim binary :-|

Re-fit boot bits together
You will need:
 * hardware or virtual stand with SecureBoot enabled
 * existing support for UEFI boot/install
 * further patience to tweak the already working parts

In a nutshell
You have to ensure that there's a verified boot chain when SecureBoot is enabled for both install/live media and the installed operating system:


 * 1) bootx64.efi or shim.efi (shim)
 * 2) grubx64.efi (some primary bootmanager/bootloader)
 * 3) vmlinuz (kernel) or some secondary bootloader

This chain can vary after shim but the main principles stay:
 * shim is verified by a key that is available to firmware via KEK/DB and further verifies the loaded binary via its embedded certificate, MOK or firmware;
 * the subsequent bootloaders can communicate to shim to make use of your certificate information embedded into it and of MOKs added by the user of a particular machine.

Trying your hand at plain FAT-formatted USB flash drive first is recommended.

ALT way
Your implementation may vary significantly; ALT Linux one is:


 * shim -> refind -> elilo -> vmlinuz for install/live/rescue media
 * shim -> grub2 -> vmlinuz for installed system

refind is a wonderful piece of software of the same high quality as Rod Smith's manuals are; we use it as a comprehensive boot manager for media as some UEFI implementations have inferior ones or even lack a proper boot manager completely.

elilo acts as a "filter" to only allow Linux kernels to be booted; we need that as we want to give our users the ability to boot non-signed kernels still not to provide a gaping way to boot unsigned anything.

GRUB
Note that you might need to teach grub-install script to: ALT Linux way of doing that is a simplified version of Ubuntu/Debian patch for GRUB 2.00.
 * avoid rebuilding EFI binary image if SecureBoot is enabled but rather to copy over the prebuilt signed binary;
 * install signed shim,

You might also prefer to review Debian, openSUSE and PLD patches; Fedora package is somewhat hard to follow by now as it contains 9-bit number of patches at the moment which rather look as upstream git presented as patch series.

= References =

Overviews

 * Free Software Foundation recommendations for free operating system distributions considering Secure Boot
 * Matthew Garrett's terse shim signing walkthrough
 * James Bottomley's Adventures in Microsoft UEFI Signing
 * Getting a Code Signing Certificate
 * Managing EFI Boot Loaders for Linux: Dealing with Secure Boot
 * The Meaning of all the UEFI Keys

Project pages

 * Fedora 18 UEFI Secure Boot Guide
 * openSUSE:UEFI
 * SUSE and Secure Boot: The Details
 * SecureBoot