Introduction
UEFI secure boot is a feature described by the latest UEFI specification (2.3.1c) which is available from the UEFI Forum Site. There have also been numerous blog posts about how UEFI secure boot works (e.g. here or here), so it will not be described here further. The purpose of this site is to keep relevant information for enabling people to play with secure booting systems. The goal is to have a working qemu system with the UEFI secure boot bios as well as various repositories for efi binary signing tools. This should enable people to produce their own boot media for secure boot systems
Intel and TianoCore
Intel has produced a project called TianoCore as an open firmware reference implementation of UEFI. One of the sub projects within TianoCore is OVMF which stands for Open Virtual Machine Firmware. It is OVMF that we are using to produce the virtual machine image for qemu that will run the UEFI secure boot environment. TianoCore secure boot is only really working as of version r13466 of the svn repository. This version has not yet been released as a downloadable zip file.
Since building TianoCore can be a bit of a challenge, a version supporting secure boot has been uploaded to the openSUSE build server here. The particular package you need for the virtual machine firmware is the OVMF rpm (download).
Booting the TianoCore Virtual Machine Image
After installing the rpm, execute
qemu-system-x86_64 -L /usr/share/qemu-ovmf/bios
And the secure boot bios will come up. Unfortunately, there is currently no way to save the EFI nvram with qemu, so the platform will come up in pristine state with each new invocation of qemu.
If your platform is kvm capable, you may also use
qemu-kvm -L /usr/share/qemu-ovmf/bios
Booting Linux with TianoCore
By default, all the standard methods (elilo, grub or even native boot using the linux kernel efi stub) work. However, TianoCore itself has a problem (as of release r13478) in that the ACPI CRS tables seem to be wrong, which causes the booting kernel to remap the EFI framebuffer and consequently be unable to attach (so you basically get no output on the screen once the kernel has booted). The workarounds for this are to specify
pci=nocrs
on the kernel boot line. This causes the kernel to ignore the ACPI CRS tables and thus attach normally to the EFI framebuffer. Thanks to Peter Jones for this. Or to boot the kernel using the serial console
console=ttyS0
Playing with Secure Boot in Tianocore
By default, TianoCore boots up into Setup Mode, meaning the platform is not provisioned with any keys and the user can take control. To take control, go to the EFI menu screens (type exit if you’re at the efi boot prompt) select the “Device Manager” entry, then “Secure Boot Configuration”. Here you will see the status of the Secure Boot flag (“Attempt Secure Boot”) and the platform mode. Setting the platform from “Standard Mode” to “Custom Mode” will allow you to edit the keys. Once the platform is in “Custom Mode”, a “Custom Secure Boot Options” menu will appear and you will be able to manipulate the four sets of key databases from here. The format of all key files for openssl generated keys is DER format (by default openssl generates PEM format). Note that the KEK, db and dbx options will ask you for a GUID as well as a key file. The GUID is the platform’s way of identifying the key. It serves no purpose other than for you to tell which key is which when you delete them (it’s not used at all in signature verification). By default, since GUIDs aren’t really human readable, I just ignore this and the GUID is set to all zeros.
Because there’s no way to save the nvram area, these variables get reset on each invocation of qemu as well and entering three sets of keys with each invocation of qemu gets very old, very fast. The repository
http://git.kernel.org/?p=linux/kernel/git/jejb/efitools.git;a=summary
contains a set of tools to help with this. Note that there’s a bug in gnu-efi earlier than 3.0q so you must have this installed if you want to build efi binaries that are capable of being signed (there’s a rpm for it in the openSUSE build service UEFI project)
If you type make, it will generate a set of keys and place them into a binary called LockDown.efi. Execution of this efi binary will provision all the keys and place the platform into Secure Boot enabled User Mode (from this point on, it will only execute signed efi binaries)
UEFI Keys and openssl
The UEFI specification has several possible key types, but X509 is the most useful to us, since it’s the easiest to generate with openssl (The platform key is required to be X509 anyway). 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.
All keys (PK, and X509 keys in KEK and db) should be X509 CA keys (i.e. self signed). The reason for this is that the platform will verify a key back to its root of trust. It is possible to provision a signature chain going back to the root of trust, but it’s not easy, so starting with self signed CA certificates is easiest. Note that from the CA, you can issue signing keys, but those keys cannot themselves then be used to create subordinate signing keys because the intermediate trust certificate will be missing from the signing chain.
For more details on all the keys and how they work, see this post.
Creating UEFI CA keys
The easiest way is to use the x509 CA creation command
openssl req -new -x509 -newkey rsa:2048 -keyout PK.key -out PK.crt -days <length
> -subj “/CN=<my common name>/”
Will create two files, PK.crt (which is the public certificate we’ll use as the UEFI key) and PK.key which is the private signing key (note: the UEFI spec mandates that all X509 keys be 2048 bit rsa keys). Fill in <days> with how long you want the certificate to be valid for and <my common name> with whatever information you want the common name to be (UEFI doesn’t use this, but it’s customary for every X509 certificate to have at least a common name). We’re still not quite done, because the keys must be in DER form. Conversion is done like this
openssl x509 -in PK.crt -out PK.cer -outform DER
Note that the .cer extension is what tells UEFI that the file contains an x509 key, so you must use it.
Signing UEFI binaries
There are two sets of tools available in Linux for this:
- Jeremy Kerr’s sbtools available from git://kernel.ubuntu.com/jk/sbsigntool
- Peter Jones’ pesign available from git://github.com/vathpela/pesign.git
The opensuse build service UEFI project contains both, but I’ve mostly played with sbsigntools which is what’s described below.
Once you have your .crt and .key files, you can sign efi binaries like this
sbsign –key KEK.key –cert KEK.crt –output HelloWorld-signed.efi HelloWorld.efi
If you’re building this yourself, you must have version 0.3 or later of the sbsigntools because earlier versions wouldn’t correctly sign efi binaries generated by gnu-efi.
The link to Jeremy Kerr’s sbtools i.e git://kernel.ubuntu.com/jk/sbsigntool is incorrect. Do you have an uptodate link?
The URL works for me. It is a git URL, so you have to use git clone to get the source.
A clarification. You state that the PK (The platform key) is “required to be X509”. This is not a UEFI Specification requirement but rather a Microsoft requirement. In fact the UEFI Specification recommends RSA 2048 (see 2.3.1, Errata C, Section 27.5, top of page 1451.)
I’m just going by the code in Tianocore as I look at it. The way it’s coded (doubtless according to the MS specs) is that the PK can *only* be X509. The KEK can contain both X509 and RSA2048
“CRS” is not an ACPI table type — it’s a METHOD for particular devices in the ACPI DSDT/SSDT tables. Please correct your post.
pci=nocrs should not be necessary starting with 13576
Presumably the ‘OVMF bios’ binary would run on the Windows version of Qemu, if I could extract it from the .rpm
I already have qemu running the older (duet) efi-bios
“You must use the CVS version of QEMU to use the BIOS (the version
0.9.0 won’t work).
Replace the default QEMU BIOS (usually in /usr/local/share/qemu) by
the file ‘bios.bin’. “
Pingback: No Boot on UEFI box (Samsung 350V)
Thanks for your highly-useful lca2013 update. Any news on the anticipated final binary signing?
I’ll be posting the signed binary here when it arrives.
I have a problem: I’ve tried to boot windows 8 32 bit with tianocore but it gives me the problem related to ACPI and CRS tables, so it results that the (virtual) Machine is not ACPI-capable. Any suggestions to solve this problem?
I would like to see such solutions in the future:
* You have UEFI + Secure Boot turned on – Linux auto repair system like Windows 8 does.
* You have UEFI + Secure Boot turned off – Linux behave normally, do nothing.
…instead of just passing by something (UEFI + Secure boot) you can just turn off in BIOS 😉
The solution should be automatic and simple to work for all “UEFI/Secure Boot” users, even those non-technical.
You covered creation of PK with openssl but what about the KEK that signed by PK? sounds like a dumb question I know but I want to make sure I have the process clear.
It’s the same process: all keys in the system may be self signed (they don’t have to be, but self signed certificates are just the easiest ones to describe how to create), so you use the PK process but substitute PK<->KEK
openssl req -new -x509 -newkey rsa:2048 -keyout KEK.key -out KEK.crt -days <length> -subj “/CN=<my common name>/”
James, would you be able to provide an updated build of Tianocore/OVMF for openSUSE 13.1? I’d like to attempt legacy-free video card passthrough as per but this requires a (very) recent build of OVMF. I understand it’s a hassle to build hence the question. Thanks!
I looked into this. The first thing I had to do was unbreak all the builds which had collapsed due to various bitrot effects. All the necessary UEFI pieces should now be building … I’m still testing them, however.
By “latest” I assume you mean UDK 2014 which is r15322? Once I complete testing of the current openSUSE 13.1 OVMF, I’ll see if I can do that, but it may take some time given the eccentric and finicky way edk2 builds.
Hi James, your efforts are very much appreciated. I’m quite keen on attempting legacy-free device passthrough as per here. The pre-built binaries linked to on that page for Fedora are what I’d be interested in for openSUSE. It would be good to have the following commit in there: link as I’m using the Q35 chipset model in most VMs.
OK, the updated version of tianocore OVMF (svn version r16499 which includes multiple signatures, dbt support and a few other things) is now live on OBS:
https://build.opensuse.org/package/show/home:jejb1:UEFI/OVMF
Your HashTool.efi can browse EFI media in Text USer Interface.
It seems that many users would be useful Run.efi for browse EFI media and launch EFI applications.
Unable to affect keys in user mode
I downloaded and built the latest version (v1.4.2+2014-05-27); deleted all keys from UEFI; ran LockDown.efi from EFI Shell and reset system.
Booted off EFI USB stick with signed shell (efi\boot\bootx64.efi) successfully. Secure boot is now enabled and in user mode – only signed executables are allow to run.
I am unable to append a new key to the db now I am in user mode; I get a Security Violation error (26).
i.e.
UpdateVars-signed.efi -a db DB2.auth
The DB2 key and authentication file was generated as follows:
openssl req -new -x509 -newkey rsa:2048 -subj “/CN=DB2/” -keyout DB2.key -out DB2.crt -days 3650 -nodes -sha256
cert-to-efi-sig-list -g 11111111-2222-3333-4444-123456789abc DB2.crt DB2.esl
sign-efi-sig-list -a -c KEK.crt -k KEK.key db DB2.esl DB2.auth
I also tried using the KeyTool-signed.efi with same problem.
I can however append the DB2 key when in setup mode and update the variables manually:
UpdateVars.efi db DB.auth
UpdateVars.efi -a db DB2.auth
UpdateVars.efi KEK KEK.auth
UpdateVars.efi PK PK.auth
I have also tried this under Ubuntu 14.04 (signed grubx64.efi) using the following:
sudo efi-updatevar -a -c DB2.crt -k KEK.key db
This time I get a Cannot write to db, wrong filesystem permissions
Also I am unable to switch from user to setup mode using the noPK.auth file either using UpdateVar or KeyTool
e.g.
UpdateVars-signed.efi PK noPK.auth
Do you have any ideas as to why I am having no success?
I have had a response from AMI regarding this issue, does this help …
It looks like the Linux utility is not quite making the signature data per spec. This is listed in section 7.2.1 of the UEFI spec. The following two bolded lines from this section are not compatible:
4. Construct a DER-encoded PKCS
Construct a DER-encoded PKCS #7 version 1.5 SignedData (see [RFC2315]) with the signed content as follows:
a SignedData.version shall be set to 1
b SignedData.digestAlgorithms shall contain the digest algorithm used when preparing the signature. Only a digest algorithm of SHA-256 is accepted.
c SignedData.contentInfo.contentType shall be set to id-data
d SignedData.contentInfo.content shall be absent (the content is provided in the Data parameter to the SetVariable() call)
e SignedData.certificates shall contain, at a minimum, the signer’s DER-encoded X.509 certificate
f SignedData.crls is optional.
g SignedData.signerInfos shall be constructed as:
— SignerInfo.version shall be set to 1
— SignerInfo.issuerAndSerial shall be present and as in the signer’s certificate
— SignerInfo.authenticatedAttributes shall not be present.
…
a.: The SignedData sequence from the utility begins with “SignedData” OID 1 2 840 113549 1 7 2. The spec says the first thing must be SignedData.version.
g.: The utility is including the SignerInfo.authenticatedAttributes field. According to the spec, this should not be present.
This might be due either to a difference in openssl versions or the presence of additional terms in the signing certificate. When I look at what I get for authenticated variable updates, I do see version 1, however, I do see some attributes like s/mime types and signature date.
You can check the signature yourself using asn1parse from openssl (it’s at offset 40 in the bundle)
openssl asn1parse -inform DER -offset 40 -i -in file
The starting data should look like:
0:d=0 hl=4 l=1138 cons: SEQUENCE
4:d=1 hl=2 l= 9 prim: OBJECT :pkcs7-signedData
15:d=1 hl=4 l=1123 cons: cont [ 0 ]
19:d=2 hl=4 l=1119 cons: SEQUENCE
23:d=3 hl=2 l= 1 prim: INTEGER :01
[…]
That integer with value :01 is version 1
It’s possible there’s an extension in your signing certificate that forces the version up (RFC5652 extended RFC2315 and defines versions up to 5 depending on particular signing and signed data characteristics).
The attributes problem should be fixed by version 1.4.3
I am having a similar problem as Dave with trying to get Secure Boot to work. I generate keys using
openssl req -new -x509 -newkey rsa:2048 -subj “/CN=PK/” -keyout PK.key -out PK.crt -days 3650 -nodes -sha256
and then I use
./efitools/cert-to-efi-sig-list -g `uuidgen` PK.crt PK.esl
./efitools/sign-efi-sig-list -k PK.key -c PK.crt KEK KEK.esl KEK.auth
sudo ./efitools/Cefi-updatevar -f PK.auth PK
and I get “Cannot write to PK, wrong filesystem permissions.” If I try to use KeyTool, I get the same error 26 security violation. I am using Ubuntu 14.04 and efitools ede47075ba54791245e3bbf20a7e740eb1d91b33. If I use openssl asn1parse, I see a version 1 with no s/mime or other attributes.
I am definitely sure my system is in setup mode. In case it matters, system is an ASRock Q1900M with BIOS 1.50. Do you have any idea what is wrong?
It’s possibly something in the ASRock UEFI, because I’m getting the same thing on an ASRock H97M Pro4 mobo with UEFI P2.00 and getting the same error.
Apparently the ASRock UEFI doesn’t allow append operations in setup mode, at least the way efi-updatevar performs them.
Pingback: Getting by without passwords: disk encryption (part III) | Random Oracle
My PK private key is in an HSM. I can use OpenSSL to access the key. When I try to replicate
sign-efi-sig-list -t ‘2016-02-25 07:47:47’ -k PK.key -c PK.pem PK PK.esl PK.auth
with
sign-efi-sig-list -t ‘2016-02-25 07:47:47’ -o PK PK.esl PK.forsig
openssl smime -sign -binary -in PK.esl -out PK.signed -signer PK.pem -inkey PK.key -outform DER -md sha256
sign-efi-sig-list -i PK.signed -t ‘2016-02-25 07:47:47’ PK PK.esl PK.auth
I do not get the same results
openssl will add attributes which the usual secure boot signing process strips. Chances are the differences are just these attributes. To see this, you’ll have to use dd to extract the der format pkcs7 signature and then use openssl to convert it to text
Passing in the noattr flag did the trick. Now I can use my HSM’s openssl engine to access the private key.
sign-efi-sig-list -t ‘2016-02-25 00:01:00’ -o PK PK.esl PK.forsig
smime -noattr -sign -binary -in PK.forsig -text -out PK.signed -signer PK.crt -inkey PK.key -outform DER -md sha256
sign-efi-sig-list -i PK.signed -t ‘2016-02-25 00:01:00’ PK PK.esl PK.auth
Pingback: Main Parts of a Linux Machine – programtweak
I am getting some strange behavior trying to manage the secure boot keys from Linux — specifically with the PK/noPK combinations.
I have an AMI based BIOS.
If I install PK.esl into PK (from BIOS), secure boot is enabled, and all the signature checking works as expected (grub, and chainloaded vmlinuz signature checks work).
From Linux, I can remove the PK using the noPK.auth file (good so far). For good measure, I rebooted the system after removing the PK so the new modes get established.
I can now install PK.auth from within Linux, and secure boot gets enabled again.
However, I can no longer remove PK using the noPK.auth file.
If I remove the PK from BIOS, and this time add the PK.auth to the PK database with BIOS, again secure boot gets enabled, but again Linux cannot remove the PK using the noPK.auth file.
With both PK versions (esl/auth) installed, a complete dump of the PK signature [with a version of efi-readvar that uses “X509_print_ex_fp(stdout, X, 0, 0);” for a verbose output] shows to be identical with ESL or AUTH versions of PK installed.
What am I missing in the equation so I can freely install PK.auth and noPK.auth back and forth? Even in KeyTool.efi, I get the same error (security violation error 26) trying to remove the PK with the noPK.auth file.
Any insight is much appreciated.
Looks like I had several issues.
o The efitools published to Ubuntu is pretty old and is missing various issues fixed in the Git repo.
o I had some issues with the “signature” timestamps in the scripts I created for managing the different signatures. For example, the noPK.auth *must* have a later signature timestamp than the PK.auth or it will not work to disable the PK. My timestamps prior to the fix were identical.
Hello,
I need a solution about manage all UEFI secureboot environment and only install my selected (signed by my PK/KEK/DB/ etc … ) windows or Linux version. If it is possible ?
For example I have a custom media include windows 10 and sign bootmgr.efi with my custom PK/KEK/DB and only install this media not other windows .
I have already create my PK KEK and DB.
Thank You,
Aydin KOCAK.
Pingback: VirtualBox Kernel driver not installed – Erawanu Seton
For the record and in case others are stumbling over it. If you get ‘Cannot write to PK, wrong filesystem permissions’ it could be due to the immutable file attribute:
# efi-updatevar -f noPK.auth PK
Cannot write to PK, wrong filesystem permissions
# lsattr /sys/firmware/efi/efivars/PK-*
—-i———– /sys/firmware/efi/efivars/PK-8be4df61-93ca-11d2-aa0d-00e098032b8c
# chattr -i /sys/firmware/efi/efivars/PK-*
# efi-updatevar -f noPK.auth PK
The same might be true if you try to update other variables.
I’m having problems enrolling the platform key with OVMF:
# efi-readvar
Variable PK has no entries
Variable KEK has no entries
Variable db has no entries
Variable dbx has no entries
Variable MokList has no entries
# efi-updatevar -e -f KEK.esl KEK
# efi-updatevar -e -f db.esl db
# efi-updatevar -f PK.auth PK
Cannot write to PK, wrong filesystem permissions
I’ve also tried the UpdateVars EFI application, same result (error 26 or something). I’ve tracked this down and the issue seems to have been introduced with the following OVMF commit from January 2017:
https://github.com/tianocore/edk2/commit/c035e37335ae43229d7e68de74a65f2c01ebc0af
Interestingly, Fedora’s EnrollDefaultKeys EFI application still works, so am I doing something wrong or is this an issue with OVMF or the toolset? Does the signature lists need to be created differently?
It’s probably the fedora addition of an immutable attribute. To reset it you need to do
chattr -i /sys/firmware/efi/efivars/PK-*
And the same for the other variables. I assume the fedora tool is doing this automatically, so I could add the same to the efi-* tools.
Actually, the previous reply was rubbish. It looks like the problem is the check in the authenticode while not wrong is assuming an unwrappered pkcs7 signer. It is legal (and what sign-efi-sig-list does) to leave the initial sequence identifying the pkcs7-signedData type, which the new code now assumes isn’t there. It all previously worked because openssl treats the type as optional.
I can probably fix efitools to strip the initial type sequence when appending a pkcs7 signature.
Hi and thanks for the extremely useful post! I’m trying to use efitools in a QEmu VM (ie. with OVMF), and I’m also stuck by the error:
# efi-updatevar -f PK.auth PK
Cannot write to PK, wrong filesystem permissions
I tried to understand your last message, and to look at the sign-efi-sig-list source code, but I don’t understand much, I’m definitely not big on crypto stuff. Is the error related to openssl usage in the code? Is it really related to https://github.com/tianocore/edk2/commit/c035e37335ae43229d7e68de74a65f2c01ebc0af as @juergh suggests above? Is it a trivial fix?
Thanks
I’ve reported the problem to tianocore. It looks like their original code in the commit is definitely wrong, but the intent might not be. The standard is ambiguous about whether we should have the asn.1 for a full pkcs7 bundle (what openssl generates) or whether we should only have a pkcs7-signedData. If it’s the latter, pretty much all linux tools will need updating. Note that windows is also having similar problems:
https://bugzilla.tianocore.org/show_bug.cgi?id=586
So I’ve reported the issue to the UEFI subteam responsible and asked them to add language to the standard clarifying that either form should be acceptable. If they agree the standard will force tianocore to change.
Hi there,
I have severe problems, writing my own PK to a laptop.
Using either KeyTool.efi or efi-updatevar I can very well upload my own dbx, db and even KEK (but only in *.auth format).
But I cannot upload my PK. Using KeyTool.efi I get error 26 “security violation”.
Using efi-updatevar I get “wrong file permission”, no matter if I try *.auth or *.esl.
Of course, I am in Setup Mode and I did chattr -i /sys/fimrware/efi/efivars/*
Has anyone a hint for me?
Thanks!
The computer vendor support just showed me, they can very well erase and upload custom keys to the same machine with the same BIOS version using Windows PowerShell tool set-SecureBootUEFI. This now makes me wonder, if this is a bug in efitools.
I just discovered this, after trying to upload the PK, the PK has a length of -4 (bytes,chars?):
efi-readvar -v PK
Variable PK, length -4
The fact, the vendor could install custom keys on the same machine makes me wonder if my tool chain is broken.
My keys have worked in a different brand machine, thus the keys should be sane.
One more update.
A Lenovo engineer was able to install custom keys on exactly the same model (E585) using Windows PowerShell tool set-securebootuefi !
This means, the flaw must be in efitools.
Unfortunately the Windows tools seem to require some strange reformatting of keys and syntax voodoo I am not familiar with.
I guess I have to learn using the PowerShell secureboot tools for now….
There’s an ongoing argument in the UEFI security subteam about what the format of an authenticated variable update should be. The standard implies it could either be the entire pkcs7 bundle (as it is for authenticode and signed binaries) or simply the SignedData portion of the pkcs7 bundle. The reference platform, TianoCore, accepted both up until recently when a patch to check the signature types broke the full pkcs7 handling. Platforms that base off the reference have been picking up the change as they update, so it’s possible yours is an affected platform.
Microsoft ran into this bug and updated their tools to emit SignedData, so I can look into doing the same for efitools … I was just hoping to convince tianocore to fix their bug.
Thank you for giving us this information.
In the meantime a Linux user went thru the necessary steps using the Windows tools. At the Lenovo forum there is some hint how to procede, since most Linux users may not be that familiar with the Microsoft secure boot tools:
https://forums.lenovo.com/t5/ThinkPad-11e-Windows-13-E-and/Cannot-install-custom-secure-boot-PK-platform-key/td-p/4318378
Do they blindly follow the reference platform?
Would it be wise to add a switch to efi-tools to chose, if one or the other method fails?
It seems, this especially affects Lenovo / Thinkpad users. I stumbled across some affected users with Thinkpads. And a few messages above I think someone with a Lenovo (ThinkCenter?) machine was affected as well.
Thank you for your efforts.
This is open source, problem identified, problem soon fixed 🙂
I released an updated efitools (1.9.1) which uses SignedData instead of the full PKCS7. I’ve tested it in the new tianocore environment and on my own Dell XPS13. I think this is safe because every platform I’ve seen previously supported both PKCS7 and SignedData, but if there are new platforms that support only SignedData then switching to it should allow efitools to work for everything (including old platforms).
https://git.kernel.org/pub/scm/linux/kernel/git/jejb/efitools.git/snapshot/efitools-1.9.1.tar.gz
Hello,
I am still face the issue with inability to write own PK to my Thinkpad X260.
My environment is the following:
BIOS R02ET73W (1.46 ) 01/08/2020
Kubuntu 20.04 (5.4.0-28-generic)
Latest efitools: http://ftp.ua.debian.org/debian/pool/main/e/efitools/efitools_1.9.2-1_amd64.deb
Log:
==================
root@tiguan:# efi-updatevar -f ./tiguan-pk-signature.auth PK
Failed to update PK: Invalid argument
KeyTool.efi – Error 26 “Security Violation”.
==================
May be someone has overcome this issue on Linux? Because using Win tools as suggested in [1] in order to add PK sounds weird in context of SecureBoot.
[1] https://forums.lenovo.com/t5/ThinkPad-11e-Windows-13-E-and-Edge-series-Laptops/Cannot-install-custom-secure-boot-PK-platform-key/m-p/4318378?page=1#4320041
Well, debugging these issues in a proprietary UEFI implementation is notoriously difficult. However, it seems to me there’s only a couple of possibilities for where the problem lies: either there’s something slightly wrong with the signature for updating the PK … as you know it must be self signed to update even if the system is in setup mode. Or there’s something wrong with the EFI variable update path through linux. Can you try producing PK.auth with a couple of different tools: I presume you made it with the efitools sign-efi-sig-list, but there’s also sbvarsign, part of the sbsigntools package, which your distribution should have, although if not at the right version, the
upstream is here:
https://git.kernel.org/pub/scm/linux/kernel/git/jejb/sbsigntools.git
And finally if you can do it, create the PK.auth with the windows signtool. If none of those work we know it’s a problem with the update path in linux. If any do then sign-efi-sig-list must have a slight issue with the signature it’s producing and I can track it down. Use a throw away PK so you can send me the auth files produced by each tool because I might need to run a comparison.
Unfortunately neither sbvarsign nor Win tools (signtool) are able to generate PK whihs is acceptable by ThinkPad X260. Writing still fails with the ‘Security’ related error.
I have created separate detailied topic on the Lenovo forum, will post link here just to be indexed by Google.
https://forums.lenovo.com/t5/ThinkPad-X-Series-Laptops/Can-t-upload-own-PK-for-SecureBoot-on-ThinkPad-X260/m-p/5025051
Thank you for releasing 1.9.1 so quickly!
I see the new paramter –engine, but unfortunately the man page does not say, what value you can put there….maybe the possible values should be told in the man page?
Looks like I missed it from the sign-efi-sig-list man page: I’ll add it. But if you don’t know what an openssl engine is, the addition isn’t going to help (and if you don’t know, you won’t have any use for the engine parameter because you won’t have a working engine). I need it because my secure boot keys are TPM resident (meaning they can only be accessed via the openssl tpm2 engine) so I mostly did this so I could test out the changes on my real laptop.
If you want to learn about engines, the best resource is openssl itself:
https://github.com/openssl/openssl/blob/master/README.ENGINE
I’m noticing after building the OVMF package from tianocore master and using efitools 1.9.2 in a Ubuntu 18.04 guest, I still get the “wrong filesystem permissions” error when trying to append to the db with efi-updatevar (Secure Boot is enabled in Custom mode with my own keys).
Is this behavior still to be expected or does something else need to be done for this environment?
I have the same problem. Note that efi-updatevar without -a works fine – it’s just appending that fails.
When it fails, also “something” goes wrong and until the efivarfs is remounted, efi-readvar shows the db as being empty with negative length:
# efi-readvar -v db
Variable db, length -4
latest efitools from OBS, tianocore from debian sid 0~20181115.85588389-2
To answer my own question, it looks like appending to EFI variables is broken in a lot of firmwares:
https://github.com/rhboot/shim/pull/129/files
https://github.com/rhboot/shim/issues/55
https://github.com/rhboot/shim/issues/105
So that’s most likely the same problem. A full rewrite works (ie: no -a flag), and multiple esl can be concatenated before signing so there is a workaround.
When you did the full rewrite, were you in setup mode or not?
You probably know about recent Grub2 security issue “BootHole”.
This bug may allow Grub2 to run any unsigned code. Okay. But, doesn´t the UEFI firmware in the end verify the code in order to boot it (or not)? Thus, even if this flaw allows running unsigned code, shouldn´t the UEFI firmware prevent this unsigned code to be used for booting a machine? Is this assumption right? Best regards.
Not really, no. Grub is a shell and the exploit is in the script language. The signature check secure boot performed was on grub itself not on the script it executes. Anyone with access to the script can cause grub to do a lot of unintended things. The secure boot security of grub is supposed to lie in the fact that the scripting language is limited. However, the exploit is a way to trick grub to execute arbitrary code from a buffer overflow in the scripting token length. Since grub is a fully featured link loader there’s no way of stopping the inserted arbitrary code from linking and loading an unsigned kernel.
Not sure where the best place to ask this question is, so please feel free to redirect. Is there a reason efi-readvar would not report the enrolled keys?
Additional details: I am able to enter setup mode write the keys (db/KEK/PK) and verify that they are written with efiread-var. I am able to confirm that SecureBoot is properly using the keys (e.g. fails to boot things unsigned by the db key, but does boot things signed with it). Also able to see the keys with KeyTool. Even the kernel boot process sees the key and the rest of the efivars fs is properly loaded, however efi-readvar reports “no entries” for all secureboot variables.
relevant kernel messages:
[ 0.000000] efi: EFI v2.31 by Lenovo
[ 0.000000] efi: ACPI=0xacdfe000 ACPI 2.0=0xacdfe014 SMBIOS=0xacbfe000 ESRT=0xaa976000
[ 0.000000] Kernel is locked down from EFI secure boot; see https://wiki.debian.org/SecureBoot
[ 0.358456] Registered efivars operations
[ 1.232161] Loaded UEFI:db cert ‘db: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX’ linked to secondary sys keyring
[ 23.465406] EFI Variables Facility v0.08 2004-May-17
I would be happy to provide more details on other things that I have tried if there is an appropriate place?
Thank you in advance for any advice you might be able to provide.
It looks like an issue with the efivarfs. First of all check you have it mounted
mount|grep efivarfs
and if you do strace what a read of PK does:
strace efi-readvar -v PK
It should have a line where it opens the PK variable in the efivarfs filesystem, like
openat(AT_FDCWD, “/sys/firmware/efi/efivars/PK-8be4df61-93ca-11d2-aa0d-00e098032b8c”, O_RDONLY) = 3
Which is likely where the error is.
Thank you for the response, and sorry for the delayed reply (I assumed I would get an email).
“`
$ mount|grep efivarfs
efivarfs on /sys/firmware/efi/efivars type efivarfs (rw,nosuid,nodev,noexec,relatime)
“`
Indeed an strace of efi-readvar shows the attempted open of the PK variable:
“`
openat(AT_FDCWD, “/sys/firmware/efi/efivars/PK-8be4df61-93ca-11d2-aa0d-00e098032b8c”, O_RDONLY) = -1 ENOENT (No such file or directory)
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0x1), …}) = 0
write(1, “Variable PK has no entries\n”, 27Variable PK has no entries
“`
However that specific variable is not being exported by efivarfs (neither are the KEK,db,dbx, or MokList).
For what it’s worth the efivarsfs is exporting other variables like the boot entries and other tools such as efibootmgr are working.
Hello, its really good thread is maintained by Author here.
I am using efitools 1.9.2. trying to enroll secure boot keys. all secure boot variables are cleared, and it’s in setup mode.
I’ve successfully added db and KEK using efi-updatevar but when I am trying to add PK using command efi-updatevar -c pk.pem -k pk.key
I am getting a different error: Failed to get PK: No such file or directory
Here is the output of lsattr /sys/firmware/efi/efivars/{PK,KEK,db,dbx}*
——————– /sys/firmware/efi/efivars/PKDefault-8be4df61-93ca-11d2-aa0d-0
—-i————— /sys/firmware/efi/efivars/KEK-8be4df61-93ca-11d2-aa0d-0
——————– /sys/firmware/efi/efivars/KEKDefault-8be4df61-93ca-11d2-aa0d-0
—-i————— /sys/firmware/efi/efivars/db-d719b2cb-3d3a-4596-a3bc-d
——————– /sys/firmware/efi/efivars/dbDefault-8be4df61-93ca-11d2-a
——————– /sys/firmware/efi/efivars/dbxDefault-8be4df61-93ca-11d2-a
——————– /sys/firmware/efi/efivars/dbxDefault-8be4df61-93ca-11d2-a
I ran PK enrollment command using strace and I got this relevant information:
openat(AT_FDCWD, “/sys/firmware/efi/efivars/PK-8be4df61-93ca-11d2-aa0d-00e098032b8c”, O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, “Failed to get PK: “, 18Failed to get PK: ) = 18
write(2, “No such file or directory\n”, 26No such file or directory
) = 26
exit_group(1) = ?
+++ exited with 1 +++
Any Idea or suggestion on what can be done here and whether its issue of efitools, uefi, or my system?
Hi
We are planning to use UEFI Secureboot in order to verify the GRUB2, and GRUB2 would verify/decrypt the kernel using keys that have been sealed into the TPM. How do we seal keys in TPM? And, how would grub unseal keys from TPM?
On a Thinkpad T460s I get for the PK:
doas strace efi-updatevar -f /home/ti2/Projects/uefi-sb/PK/PK.auth PK
open(“/sys/firmware/efi/efivars/PK-8be4df61-93ca-11d2-aa0d-00e098032b8c”, O_RDWR|O_CREAT|O_TRUNC, 0644) = -1 EPERM (Operation not permitted)
Do you think this could be a bug in Lenovo’s implementation?
Thanks.
I was wondering if efitools was still maintained by you James ? If not, any suggestions where a patch to efitools could be submitted ?
I’ve stumbled on the “efi-readvar length -4” issue recently. I’ve investigated a bit, and found out that efivarfs files are sometimes reported as zero-bytes.
It’s easy to reproduce, just open(2) an efivarfs file with O_TRUNC and close(2) it right away. This won’t change the EFI variable content, but it will set the inode size to 0 bytes. And once that happens, efi-readvar is unable to read the variable content, because its logic is based on the size reported by fstat(2).
In more practical terms, this can happens if you try to update PK/KEK/db and the write fails (e.g. because of an EFI_SECURITY_VIOLATION). That’s how I stumbled on the issue.
Now, is this a bug in the kernel or in efitools ? I’m not 100% sure about what was the intended efivarfs semantics, so it’s a bit hard to tell for me, but I’m feeling it would have been nicer if efivarfs was implemented in such a way that O_TRUNC is “ignored”, or something like that.
But one quick work-around in efitools is to stop using O_TRUNC in the call to open(2) in the set_variable function. Another “fix” is to rework the get_variable logic so it doesn’t rely on the inode reported size.
Thanks
Yes, I still maintain it … although its rate of evolution is extremely slow. There’s a mailing list at
sbsigntools@groups.io
(shared with sbsigntools) which is pretty low volume
Hi, It’s great to see that a very valuable database has been created here.
I’m also having an issue while using efitools 1.9.2 under Debian Bullseye. Trying to create PK.auth following openssl / cert-to-efi-sig-list / sign-efi-sig-list path. And I manage to enroll it using KeyTool.efi into OVMF.
But I need to create detached signature and follow the steps documented at man page (also appending -noattr as discussed here before):
sign-efi-sig-list -t ‘Jul 21 09:39:37 BST 2022’ -o pk PK.esl PK.forsig
openssl smime -sign -noattr -binary -in PK.forsig -out PK.signed -signer PKcrt -inkey PK.key -outform DER -md sha256
sign-efi-sig-list -i PK.signed -t ‘Jul 21 09:39:37 BST 2022’ pk PK.auth
In this way, keytool gives (26) Security Violation while trying to enroll PK.auth.
I’ve had a look for the diff of sig-lists generated from both methods and only found, sign-efi-sig-list uses SignedData as openssl produces PKCS7 wrapped ContentInfo.
Maybe both of them should be accepted by OVMF considering UEFI Specs and previous discussions. I’ve tried also OVMF 2022 (from Debian Bookworm), result is same. I’m wondering if there could be another reason for the issue. But detached signature seems not working eventually.