UEFI Secure Boot

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:

  1. Jeremy Kerr’s sbtools available from git://kernel.ubuntu.com/jk/sbsigntool
  2. 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.

65 thoughts on “UEFI Secure Boot

  1. Finnbarr P. Murphy

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

    Reply
    1. jejb Post author

      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

      Reply
  2. Seth

    “CRS” is not an ACPI table type — it’s a METHOD for particular devices in the ACPI DSDT/SSDT tables. Please correct your post.

    Reply
  3. xsoliman3

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

    Reply
  4. Pingback: No Boot on UEFI box (Samsung 350V)

  5. Tony

    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?

    Reply
  6. Darek

    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.

    Reply
  7. giggler

    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.

    Reply
    1. jejb Post author

      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>/”

      Reply
    1. jejb Post author

      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.

      Reply
      1. Maarten

        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.

        Reply
  8. 0ffer

    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.

    Reply
  9. Dave

    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?

    Reply
    1. Dave

      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.

      Reply
      1. jejb Post author

        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

        Reply
  10. Robert

    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?

    Reply
    1. Tatterdemalian

      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.

      Reply
  11. Pingback: Getting by without passwords: disk encryption (part III) | Random Oracle

  12. Trevor

    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

    Reply
    1. jejb Post author

      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

      Reply
      1. Trevor

        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

        Reply
  13. Pingback: Main Parts of a Linux Machine – programtweak

  14. Michael Allen

    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.

    Reply
    1. Michael Allen

      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.

      Reply
  15. Aydin KOCAK

    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.

    Reply
  16. Pingback: VirtualBox Kernel driver not installed – Erawanu Seton

  17. juergh

    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.

    Reply
  18. juergh

    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?

    Reply
    1. jejb Post author

      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.

      Reply
      1. jejb Post author

        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.

        Reply
        1. Arnaud

          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

          Reply
          1. jejb Post author

            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.

  19. Dunno

    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!

    Reply
    1. Dunno

      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.

      Reply
    2. Dunno

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

      Reply
      1. jejb Post author

        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.

        Reply
        1. Dunno

          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 🙂

          Reply
          1. jejb Post author

            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

    3. Vitalii

      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

      Reply
      1. jejb Post author

        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.

        Reply
  20. Dunno

    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?

    Reply
    1. jejb Post author

      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

      Reply
  21. gopack2014

    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?

    Reply
    1. Luca Boccassi

      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

      Reply
  22. M.G.

    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.

    Reply
    1. jejb Post author

      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.

      Reply
  23. Roy

    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.

    Reply
    1. jejb Post author

      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.

      Reply
      1. Roy

        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.

        Reply
  24. Parth

    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?

    Reply
  25. Ram

    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?

    Reply
  26. ti2

    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.

    Reply
  27. Etienne

    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

    Reply
  28. CC

    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.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.