UEFI SecureBoot mini-HOWTO update 2018

From ALT Linux Wiki

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[1].

Getting seamless boot[2] on x86 systems with SecureBoot enabled out-of-box basically requires dealing with UEFI CA[3]. 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[4], the nice folks at Red Hat and SUSE have developed UEFI shim[5] which makes the review/sign process much more rare but it still has to be done at least once[6].

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[7];
  • 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 Nikolai Kostrigin for [1]; 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".

Verisign/Symantec certificate

Why

This one is needed once to authorize the company[8] 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[9] via Windows Dev Center.

How

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

It took three business days for us[14].

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[15] are available: signing utilities, UEFI shim and a EFI capable bootloader[16]; 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[17]; YMMV.

pesign

We'll discuss Fedora's pesign which is more capable and versatile than Ubuntu's sbsigntools[18]. 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[19]: <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[20]:

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.

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[21]. 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[22] for all key storage.

These should be RSA2048/SHA256 X.509 certificates.

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 -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.

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[23] 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:

# 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[24].

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 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[25].

Preparing the upload

The EFI binary to be signed by UEFI CA has to be extracted from the package you have built already[26], 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[27]; 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.

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[28]
  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[29]
  • 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[30] (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[31].

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[32] 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:

  • avoid rebuilding EFI binary image if SecureBoot is enabled but rather to copy over the prebuilt signed binary;
  • install signed shim,

ALT Linux way of doing that is a simplified version of Ubuntu/Debian patch for GRUB 2.00.

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

Project pages

Footnotes

  1. 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
  2. as in missing "access denied" with no apparent way around it
  3. 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?)
  4. even worse for kernels as the review process does take time and sometimes updates are urgent
  5. 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
  6. 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
  7. see also Fedora SecureBoot feature page
  8. Matthew Garrett notes that "you can do this as an individual" regarding creating the new company account
  9. 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
  10. that doesn't mean Firefox, strangely enough
  11. 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
  12. here's archive.org copy just in case
  13. ...which might involve something like prolonged MSDN subscription
  14. and yet another check method as compared to the two cases described above and by Matthew (but we're a company indeed)
  15. let's call these entities this way, substitute whatever form of deliverables your distribution uses
  16. ...until you want to work out a scheme booting the kernels directly
  17. this should also make testing/deploying new gnu-efi versions somewhat easier
  18. you're still free to examine more docs and use/write whatever you like of course
  19. I didn't really try my hand at LF's PreLoader finding it somewhat less apt than shim for ALT's purposes
  20. in alphabetic order
  21. ...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
  22. 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"
  23. we've settled with pesign, those interested in sbsigntools are advised to have a look at openSUSE documentation
  24. ...or at least that Symantec says so
  25. looks like this is the reason for Ubuntu to ship with Microsoft's signature only; Fedora, openSUSE and ALT Linux ship with both Microsoft's and distribution's signatures
  26. ...probably based on Fedora package with appropriate change of certificate file in DER form passed via VENDOR_CERT_FILE]
  27. instead of asking for that interactively by default, what a shame for security related utility
  28. it's not explained at all and should rather be named "Description" actually
  29. it is specifically not covered in this document, another one of similar volume can be written regarding this topic
  30. this name gets hardcoded into shim binary at build time
  31. ...but you knew that already, right?
  32. feasible with shim < 0.5