UEFI SecureBoot mini-HOWTO
From ALT Linux Wiki
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 Michael Shigorin for ALT Linux; 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.
- prepare the assets
- obtain shim.efi signed by UEFI CA
- wire the rest of the distro to make use of it
Subject: ALT Linux Rescue
Hello everybody out there needing rescue -
I've implemented a CD/Flash, BIOS/UEFI hybrid rescue image that
can stand SecureBoot and still help you get your system to just boot.
It's been brewing for a few years and actually works for me now.
Being a part of weekly regular builds, it's ever-relevant since
these images are baked from "current" ALT Linux Sisyphus repository.
You will need:
- $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)
The suggested steps are:
- start obtaining Symantec certificate for a company (or private person)
- prepare the binary builds of a signing tool, shim and grub2 (or another bootloader)
- bring up a distribution-specific certification authority and create a pair of certificate+key pairs (CA and Signer)
- build and test shim.efi containing the public part of your CA cert
- build and test at least one EFI capable bootloader signed by your Signer key
The result should be "ready to start approaching UEFI CA".
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.
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.
Get the certificate+private key obtained from Import Export software into a standalone file:
- Options > Content > Certificates > Personal
- choose the certificate
- click Export
- 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.
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.
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.
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.
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. :)
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.
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:
We use refind and elilo either but grub2 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.
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.
It is recommended to use efikeygen(1) utility from pesign package as it will set up the NSS DB as intended with minimal hassle:
mkdir ~/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
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.
Deliverable: a password-protected NSS database holding cacert and signer cert with corresponding private keys.
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.
pesign -s -n ~/ca/signer -c "ALT Linux UEFI SB Signer" -i grub.efi -o grub-signed.efi
Example of manual debug start:
# pesign -D -N -v -n /path/to/ca/signer
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:
- obtain a live.com account
- authenticate/link the company to that account
- read and accept Microsoft's agreements
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:
- create a certificate database with Symantec certificates imported into that
- download winqualexe.zip from sysdev.microsoft.com, unpack and pesign it
- 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
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.
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:
- prepare shim.efi for submission
- upload shim.cab to sysdev.microsoft.com
- send a questionnaire to email@example.com
- wait and check both inbox and spambox of the account used periodically
- 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.
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 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:
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.
- boot that Windows host/VM up
- start a web browser with Silverlight plugin available
- log into sysdev.microsoft.com
- go to Hardware Certification > Create UEFI submission
- choose the prepared shim.cab file
- enter something like "shim.efi (upstream 0.7)" as a Name
Deliverable: submission ID.
Posting the answers
You can expect a query from firstname.lastname@example.org 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:
- Does your company have an external URL? If so, please provide an external link to the website.
- Does the UEFI submission contain product quality code?
- Include a brief statement on the purpose or goal for the UEFI submission.
- Is the UEFI submission associated with another program?
- Does the UEFI submission include license terms that would mandate the transmission of keys used for signing? (i.e., GPLv3 or similar)
- 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 email@example.com referring to that submission id
It took three weeks in our case as we didn't know about that questionnaire yet.
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:
- bootx64.efi or shim.efi (shim)
- grubx64.efi (some primary bootmanager/bootloader)
- 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.
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.
Note that you might need to teach grub-install script to:
- 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.
- 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
- ↑ those implementing are advised to have a look at introduction into UEFI boot process; the topic is clearly out of this document's scope, a separate HOWTO of comparable size could be written if available distributions wiki pages are not enough
- ↑ as in missing "access denied" with no apparent way around it
- ↑ there's a single UEFI Certification Authority currently and it's Microsoft Corp, incidentally; by a chance, Microsoft's "Windows 8 Logo" certification for hardware results in SecureBoot enabled by default with Microsoft's certificate enrolled into firmware as well as Fast Boot enabled which can pose another serious issue (5 second press?)
- ↑ even worse for kernels as the review process does take time and sometimes updates are urgent
- ↑ shim.efi: a program that can be built with a distribution's certificate embedded to be able to verify the binaries signed with it and that can be further signed with Microsoft's key so that generic PC hardware will agree to run it
- ↑ shim also enables the user to sign binaries with their own Machine Owner Keys (MOK), you're encouraged to read up on that and provide your users with corresponding tools and/or documentation
- ↑ see also Fedora SecureBoot feature page
- ↑ Matthew Garrett notes that "you can do this as an individual" regarding creating the new company account
- ↑ at $99/year instead of the usual $499+; you may need to renew the certificate with standard fees, depending on the validity of the certificate
- ↑ that doesn't mean Firefox, strangely enough
- ↑ note that options might be quite hard to reverse-translate in case of localized Windows, you're likely to end up doing LC_MESSAGES=C windows-way
- ↑ here's archive.org copy just in case
- ↑ ...which might involve something like prolonged MSDN subscription
- ↑ and yet another check method as compared to the two cases described above and by Matthew (but we're a company indeed)
- ↑ let's call these entities this way, substitute whatever form of deliverables your distribution uses
- ↑ ...until you want to work out a scheme booting the kernels directly
- ↑ this should also make testing/deploying new gnu-efi versions somewhat easier
- ↑ you're still free to examine more docs and use/write whatever you like of course
- ↑ I didn't really try my hand at LF's PreLoader finding it somewhat less apt than shim for ALT's purposes
- ↑ in alphabetic order
- ↑ ...so that signing certificates can be changed without having to change CA certificate and corresponding loss of ability to verify the trust chain up to the deployed one
- ↑ The cheapest smartcard/USB/etc HSMs you can buy satisfy this requirement, it's basically "you can lock a private key on a card and never be able to extract it"
- ↑ we've settled with pesign, those interested in sbsigntools are advised to have a look at openSUSE documentation
- ↑ ...or at least that Symantec says so
- ↑ instead of asking for that interactively by default, what a shame for security related utility
- ↑ it's not explained at all and should rather be named "Description" actually
- ↑ it is specifically not covered in this document, another one of similar volume can be written regarding this topic
- ↑ this name gets hardcoded into shim binary at build time
- ↑ ...but you knew that already, right?
- ↑ feasible with shim < 0.5