Giter Site home page Giter Site logo

sbctl's Introduction

sbctl - Secure Boot Manager

Build Status

sbctl intends to be a user-friendly secure boot key manager capable of setting up secure boot, offer key management capabilities, and keep track of files that needs to be signed in the boot chain.

It is written top-to-bottom in Golang using go-uefi for the API layer and doesn't rely on existing secure boot tooling. It also tries to sport some integration testing towards tianocore utilizing vmtest.

Features

  • User-friendly
  • Manages secure boot keys
  • Live enrollment of keys
  • Signing database to help keep track of files to sign
  • Verify ESP of files missing signatures
  • EFI stub generation
  • JSON output

Roadmap to 1.0

  • Key rotation
  • TPM support
  • Hardware token support
  • Configuration Files
  • Automatic boot chain signing using the Boot Loader Interface

Dependencies

  • util-linux (using lsblk)
  • binutils (using objcopy)
  • Go >= 1.20
  • asciidoc (only for building)

Installation

To fetch, build and install sbctl from the Github source:

$ go install github.com/foxboron/sbctl/cmd/sbctl@latest
$ $(go env GOPATH)/bin/sbctl

To install through git:

$ git clone https://github.com/foxboron/sbctl.git
$ cd sbctl
$ make
$ ./sbctl

Available packages

For Arch Linux:

# pacman -S sbctl

For Alpine Linux:

# apk add sbctl

For Gentoo Linux:

# emerge --ask app-crypt/sbctl

For openSUSE:

# zypper install sbctl

For Fedora Linux (unofficial package):

# dnf copr enable chenxiaolong/sbctl
# dnf install sbctl

You can find a updated list of sbctl packages on Repology.

In addition, sbctl is also available for Ubuntu (unofficial). Follow the Expert Download links to find installation instructions according to your operating system.

Support and development channel

Development discussions and support happens in #sbctl on the libera.chat IRC network.

Usage

$ sbctl
Secure Boot Key Manager

Usage:
  sbctl [command]

Available Commands:
  bundle           Bundle the needed files for an EFI stub image
  create-keys      Create a set of secure boot signing keys
  enroll-keys      Enroll the current keys to EFI
  generate-bundles Generate all EFI stub bundles
  help             Help about any command
  list-bundles     List stored bundles
  list-files       List enrolled files
  remove-bundle    Remove bundle from database
  remove-file      Remove file from database
  sign             Sign a file with secure boot keys
  sign-all         Sign all enrolled files with secure boot keys
  status           Show current boot status
  verify           Find and check if files in the ESP are signed or not

Flags:
  -h, --help   help for sbctl
      --json   Output as json

Use "sbctl [command] --help" for more information about a command.

Key creation and enrollment

See example enrollment for a workflow with screenshots of real firmware setup menus.

# sbctl status
Installed:	✘ Sbctl is not installed
Setup Mode:	✘ Enabled
Secure Boot:	✘ Disabled

# sbctl create-keys
Created Owner UUID a9fbbdb7-a05f-48d5-b63a-08c5df45ee70
Creating secure boot keys...✔
Secure boot keys created!

# sbctl enroll-keys
Enrolling keys to EFI variables...✔
Enrolled keys to the EFI variables!

# sbctl status
Installed:	✔ Sbctl is installed
Owner GUID:	a9fbbdb7-a05f-48d5-b63a-08c5df45ee70
Setup Mode:	✔ Disabled
Secure Boot:	✘ Disabled

// Reboot and enable secure boot in the bios!
# sbctl status
Installed:	✔ Sbctl is installed
Owner GUID:	a9fbbdb7-a05f-48d5-b63a-08c5df45ee70
Setup Mode:	✔ Disabled
Secure Boot:	✔ Enabled

Signatures

# sbctl verify
Verifying file database and EFI images in /efi...
✘ /boot/vmlinuz-linux is not signed
✘ /efi/EFI/BOOT/BOOTX64.EFI is not signed
✘ /efi/EFI/BOOT/KeyTool-signed.efi is not signed
✘ /efi/EFI/Linux/linux-linux.efi is not signed
✘ /efi/EFI/arch/fwupdx64.efi is not signed
✘ /efi/EFI/systemd/systemd-bootx64.efi is not signed

# sbctl sign -s /efi/EFI/BOOT/BOOTX64.EFI
✔ Signed /efi/EFI/BOOT/BOOTX64.EFI...

# sbctl sign -s /efi/EFI/arch/fwupdx64.efi
✔ Signed /efi/EFI/arch/fwupdx64.efi...

# sbctl sign -s /efi/EFI/systemd/systemd-bootx64.efi
✔ Signed /efi/EFI/systemd/systemd-bootx64.efi...

# sbctl sign -s /usr/lib/fwupd/efi/fwupdx64.efi -o /usr/lib/fwupd/efi/fwupdx64.efi.signed
✔ Signed /usr/lib/fwupd/efi/fwupdx64.efi...

# sbctl verify
Verifying file database and EFI images in /efi...
✔ /usr/lib/fwupd/efi/fwupdx64.efi.signed is signed
✔ /efi/EFI/BOOT/BOOTX64.EFI is signed
✔ /efi/EFI/arch/fwupdx64.efi is signed
✔ /efi/EFI/systemd/systemd-bootx64.efi is signed
✘ /boot/vmlinuz-linux is not signed
✘ /efi/EFI/BOOT/KeyTool-signed.efi is not signed
✘ /efi/EFI/Linux/linux-linux.efi is not signed

# sbctl list-files
/boot/vmlinuz-linux
Signed:		✘ Not Signed

/efi/EFI/BOOT/KeyTool-signed.efi
Signed:		✘ Not Signed

/efi/EFI/Linux/linux-linux.efi
Signed:		✘ Not Signed

/efi/EFI/arch/fwupdx64.efi
Signed:		✔ Signed

/efi/EFI/BOOT/BOOTX64.EFI
Signed:		✔ Signed

/usr/lib/fwupd/efi/fwupdx64.efi
Signed:		✔ Signed
Output File:	/usr/lib/fwupd/efi/fwupdx64.efi.signed

/efi/EFI/systemd/systemd-bootx64.efi
Signed:		✔ Signed

Generate Unified Kernel Images (UKI)

Note: It is generally recommended to use the initramfs generator for this. mkinitcpio and dracut support this through their respective --uki and --uefi flags, or the ukify tool from systemd.

This feature is considered a second class citizen in sbctl.

# sbctl bundle -s -i /boot/intel-ucode.img \
      -l /usr/share/systemd/bootctl/splash-arch.bmp \
      -k /boot/vmlinuz-linux \
      -f /boot/initramfs-linux.img \
      /efi/EFI/Linux/linux-linux.efi
Wrote EFI bundle /efi/EFI/Linux/linux-linux.efi

# sbctl list-bundles
Enrolled bundles:

/efi/EFI/Linux/linux-linux.efi
	Signed:		✔ Signed
	ESP Location:	/efi
	Output:		└─/EFI/Linux/linux-linux.efi
	EFI Stub Image:	  └─/usr/lib/systemd/boot/efi/linuxx64.efi.stub
	Splash Image:	    ├─/usr/share/systemd/bootctl/splash-arch.bmp
	Cmdline:	    ├─/etc/kernel/cmdline
	OS Release:	    ├─/usr/lib/os-release
	Kernel Image:	    ├─/boot/vmlinuz-linux
	Initramfs Image:    └─/boot/initramfs-linux.img
	Intel Microcode:      └─/boot/intel-ucode.img


# sbctl generate-bundles
Generating EFI bundles....
Wrote EFI bundle /efi/EFI/Linux/linux-linux.efi

sbctl's People

Contributors

arctize avatar cornelicorn avatar cosmastech avatar dawidpotocki avatar depate avatar dkwo avatar env25 avatar ericonr avatar evilbit avatar foxboron avatar freegnu avatar hboetes avatar igo95862 avatar jimmykarily avatar joseph-digiovanni avatar medhefgo avatar mithicspirit avatar ml- avatar modelmat avatar pheiduck avatar pschichtel avatar punoko avatar robertkwiatkowski avatar sebinnyshkim avatar silkeh avatar svenschwermer avatar swsnr avatar tblancher avatar tyilo avatar whynothugo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sbctl's Issues

Remove-file doesn't error out when removing file that doesn't exist.

Commands like the ones below don't print any error messages. Since we are only saving files with the absolute path, a non absolute path for remove-file should either be an error, or it should get the absolute path before trying to remove the file. If the absolute path doesn't exist we shoud get an error, IMO.

We could omit feedback for the successful case.

$ sbctl remove-file file
$ sbctl remove-file /non/existent/file

Inconsistent error when enrolling keys

# sbctl status
==> WARNING: Setup Mode: Enabled
==> WARNING: Secure Boot: Disabled
# sbctl enroll-keys
==> Syncing /usr/share/secureboot/keys to EFI variables...
Invalid key /usr/share/secureboot/keys/PK/PK.pem
 - unknown cert type
Invalid key /usr/share/secureboot/keys/PK/PK.der
 - unknown cert type
Invalid key /usr/share/secureboot/keys/PK/PK.der.esl
 - unknown cert type
Invalid key /usr/share/secureboot/keys/PK/PK.key
 - unknown cert type
Invalid key /usr/share/secureboot/keys/KEK/KEK.key
 - unknown cert type
Invalid key /usr/share/secureboot/keys/KEK/KEK.der
 - unknown cert type
Invalid key /usr/share/secureboot/keys/KEK/KEK.der.esl
 - unknown cert type
Invalid key /usr/share/secureboot/keys/KEK/KEK.pem
 - unknown cert type
Invalid key /usr/share/secureboot/keys/db/db.der
 - unknown cert type
Invalid key /usr/share/secureboot/keys/db/db.der.esl
 - unknown cert type
Invalid key /usr/share/secureboot/keys/db/db.pem
 - unknown cert type
Invalid key /usr/share/secureboot/keys/db/db.key
 - unknown cert type
Filesystem keystore:
  /usr/share/secureboot/keys/db/db.der [1276 bytes]
  /usr/share/secureboot/keys/db/db.der.esl [1320 bytes]
  /usr/share/secureboot/keys/db/db.pem [1785 bytes]
  /usr/share/secureboot/keys/db/db.key [3272 bytes]
  /usr/share/secureboot/keys/db/db.auth [3433 bytes]
  /usr/share/secureboot/keys/KEK/KEK.auth [3425 bytes]
  /usr/share/secureboot/keys/KEK/KEK.key [3272 bytes]
  /usr/share/secureboot/keys/KEK/KEK.der [1292 bytes]
  /usr/share/secureboot/keys/KEK/KEK.der.esl [1336 bytes]
  /usr/share/secureboot/keys/KEK/KEK.pem [1805 bytes]
  /usr/share/secureboot/keys/PK/PK.auth [3409 bytes]
  /usr/share/secureboot/keys/PK/PK.pem [1785 bytes]
  /usr/share/secureboot/keys/PK/PK.der [1276 bytes]
  /usr/share/secureboot/keys/PK/PK.der.esl [1320 bytes]
  /usr/share/secureboot/keys/PK/PK.key [3272 bytes]
firmware keys:
  PK:
  KEK:
    /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Corporation KEK CA 2011
    /C=US/ST=Texas/L=Round Rock/O=Dell Inc./CN=Dell Inc. Key Exchange Key
  db:
    /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Windows Production PCA 2011
    /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Corporation UEFI CA 2011
    /C=US/ST=Texas/L=Round Rock/O=Dell Inc./CN=Dell Inc. UEFI DB
  dbx:
    45c7c8ae750acfbb48fc37527d6412dd644daed8913ccd8a24c94d856967df8e
    64575bd912789a2e14ad56f6341f52af6bf80cf94400785975e9f04e2d64d745
    939aeef4f5fa51e23340c3f2e49048ce8872526afdf752c3a7f3a3f2bc9f6049
    3b0287533e0cc3d0ec1aa823cbf0a941aad8721579d1c499802dd1c3a636b8a9
    c83cb13922ad99f560744675dd37cc94dcad5a1fcba6472fee341171d939e884
    77dd190fa30d88ff5e3b011a0ae61e6209780c130b535ecb87e6f0888a0b6b2f
    55b99b0de53dbcfe485aa9c737cf3fb616ef3d91fab599aa7cab19eda763b5ba
    ca171d614a8d7e121c93948cd0fe55d39981f9d11aa96e03450a415227c2c65b
    fecfb232d12e994b6d485d2c7167728aa5525984ad5ca61e7516221f079a1436
    fe63a84f782cc9d3fcf2ccf9fc11fbd03760878758d26285ed12669bdc6e6d01
    fddd6e3d29ea84c7743dad4a1bdbc700b5fec1b391f932409086acc71dd6dbd8
    e92c22eb3b5642d65c1ec2caf247d2594738eebb7fb3841a44956f59e2b0d1fa
    d8cbeb9735f5672b367e4f96cdc74969615d17074ae96c724d42ce0216f8f3fa
    ce3bfabe59d67ce8ac8dfd4a16f7c43ef9c224513fbc655957d735fa29f540ce
    cb6b858b40d3a098765815b592c1514a49604fafd60819da88d7a76e9778fef7
    c90f336617b8e7f983975413c997f10b73eb267fd8a10cb9e3bdbfc667abdb8b
    c617c1a8b1ee2a811c28b5a81b4c83d7c98b5b0c27281d610207ebe692c2967f
    c409bdac4775add8db92aa22b5b718fb8c94a1462c1fe9a416b95d8a3388c2fc
    bc87a668e81966489cb508ee805183c19e6acd24cf17799ca062d2e384da0ea7
    b97a0889059c035ff1d54b6db53b11b9766668d9f955247c028b2837d7a04cd9
    b8f078d983a24ac433216393883514cd932c33af18e7dd70884c8235f4275736
    b54f1ee636631fad68058d3b0937031ac1b90ccb17062a391cca68afdbe40d55
    afe2030afb7d2cda13f9fa333a02e34f6751afec11b010dbcd441fdf4c4002b3
    aeebae3151271273ed95aa2e671139ed31a98567303a332298f83709a9d55aa1
    ad6826e1946d26d3eaf3685c88d97d85de3b4dcb3d0ee2ae81c70560d13c5720
    a7f32f508d4eb0fead9a087ef94ed1ba0aec5de6f7ef6ff0a62b93bedf5d458d
    a6b5151f3655d3a2af0d472759796be4a4200e5495a7d869754c4848857408a7
    9e4a69173161682e55fde8fef560eb88ec1ffedcaf04001f66c0caf707b2b734
    9998d363c491be16bd74ba10b94d9291001611736fdca643a36664bc0f315a42
    8d8ea289cfe70a1c07ab7365cb28ee51edd33cf2506de888fbadd60ebf80481c
    8bf434b49e00ccf71502a2cd900865cb01ec3b3da03c35be505fdf7bd563f521
    8ad64859f195b5f58dafaa940b6a6167acd67a886e8f469364177221c55945b9
    895a9785f617ca1d7ed44fc1a1470b71f3f1223862d9ff9dcc3ae2df92163daf
    82db3bceb4f60843ce9d97c3d187cd9b5941cd3de8100e586f2bda5637575f67
    81a8b965bb84d3876b9429a95481cc955318cfaa1412d808c8a33bfd33fff0e4
    7827af99362cfaf0717dade4b1bfe0438ad171c15addc248b75bf8caa44bb2c5
    72e0bd1867cf5d9d56ab158adf3bddbc82bf32a8d8aa1d8c5e2f6df29428d6d8
    726b3eb654046a30f3f83d9b96ce03f670e9a806d1708a0371e62dc49d2c23c1
    71f2906fd222497e54a34662ab2497fcc81020770ff51368e9e3d9bfcbfd6375
    6f1428ff71c9db0ed5af1f2e7bbfcbab647cc265ddf5b293cdb626f50a3a785e
    6c8854478dd559e29351b826c06cb8bfef2bCan't create key file /sys/firmware/efi/efivars/db-d719b2cb-3d3a-4596-a3bc-dad00e67656f: Operation not permitted
Error syncing keystore file /usr/share/secureboot/keys/db/db.auth
Can't create key file /sys/firmware/efi/efivars/KEK-8be4df61-93ca-11d2-aa0d-00e098032b8c: Operation not permitted
Error syncing keystore file /usr/share/secureboot/keys/KEK/KEK.auth
94ad3538358772d193f82ed1ca11
    6b1d138078e4418aa68deb7bb35e066092cf479eeb8ce4cd12e7d072ccb42f66
    5ae949ea8855eb93e439dbc65bda2e42852c2fdf6789fa146736e3c3410f2b5c
    518831fe7382b514d03e15c621228b8ab65479bd0cbfa3c5c1d0f48d9c306135
    47cc086127e2069a86e03a6bef2cd410f8c55a6d6bdb362168c31b2ce32a5adf
    4397daca839e7f63077cb50c92df43bc2d2fb2a8f59f26fc7a0e4bd4d9751692
    3fce9b9fdf3ef09d5452b0f95ee481c2b7f06d743a737971558e70136ace3e73
    3841d221368d1583d75c0a02e62160394d6c4e0a6760b6f607b90362bc855b02
    3608edbaf5ad0f41a414a1777abf2faf5e670334675ec3995e6935829e0caad2
    306628fa5477305728ba4a467de7d0387a54f569d3769fce5e75ec89d28d1593
    2e70916786a6f773511fa7181fab0f1d70b557c6322ea923b2a8d3b92b51af7d
    2c73d93325ba6dcbe589d4a4c63c5b935559ef92fbf050ed50c4e2085206f17d
    2bbf2ca7b8f1d91f27ee52b6fb2a5dd049b85a2b9b529c5d6662068104b055f8
    2b99cf26422e92fe365fbf4bc30d27086c9ee14b7a6fff44fb2f6b9001699939
    18333429ff0562ed9f97033e1148dceee52dbe2e496d5410b5cfd6c864d2d10f
    174e3a0b5b43c6a607bbd3404f05341e3dcf396267ce94f8b50e2e23a9da920c
    106faceacfecfd4e303b74f480a08098e2d0802b936f8ec774ce21f31686689c
    0dc9f3fb99962148c3ca833632758d3ed4fc8d0b0007b95b31e6528f2acd5bfc
    0d0dbeca6f29eca06f331a7d72e4884b12097fb348983a2a14a0d73f4f10140f
    0c189339762df336ab3dd006a463df715a39cfb0f492465c600e6c6bd7bd898c
    0bbb4392daac7ab89b30a4ac657531b97bfaab04f90b0dafe5f9b6eb90a06374
    09df5f4e511208ec78b96d12d08125fdb603868de39f6f72927852599b659c26
    07e6c6a858646fb1efc67903fe28b116011f2367fe92e6be2b36999eff39d09e
    075eea060589548ba060b2feed10da3c20c7fe9b17cd026b94e8a683b8115238
    90fbe70e69d633408d3e170c6832dbb2d209e0272527dfb63d49d29572a6f44c
    29c6eb52b43c3aa18b2cd8ed6ea8607cef3cfae1bafe1165755cf2e614844a44
    d063ec28f67eba53f1642dbf7dff33c6a32add869f6013fe162e2c32f1cbe56d
    d626157e1d6a718bc124ab8da27cbb65072ca03a7b6b257dbdcbbd60f65ef3d1
    5391c3a2fb112102a6aa1edc25ae77e19f5d6f09cd09eeb2509922bfcd5992ea
    58fb941aef95a25943b3fb5f2510a0df3fe44c58c95e0ab80487297568ab9771
    c3a99a460da464a057c3586d83cef5f4ae08b7103979ed8932742df0ed530c66
    e6ca68e94146629af03f69c2f86e6bef62f930b37c6fbcc878b78df98c0334e5
    1aec84b84b6c65a51220a9be7181965230210d62d6d33c48999c6b295a2b0a06
    363384d14d1f2e0b7815626484c459ad57a318ef4396266048d058c5a19bbf76
    c5d9d8a186e2c82d09afaa2a6f7f2e73870d3e64f72c4e08ef67796a840f0fbd
    f52f83a3fa9cfbd6920f722824dbe4034534d25b8507246b3b957dac6e1bce7a
    80b4d96931bf0d02fd91a61e19d14f1da452e66db2408ca8604d411f92659f0a
    /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Windows PCA 2010
filesystem keys:
  PK:
    /C=Platform Key/CN=Platform Key
     from /usr/share/secureboot/keys/PK/PK.auth
  KEK:
    /C=Key Exchange Key/CN=Key Exchange Key
     from /usr/share/secureboot/keys/KEK/KEK.auth
  db:
    /C=Database Key/CN=Database Key
     from /usr/share/secureboot/keys/db/db.auth
  dbx:
New keys in filesystem:
 /usr/share/secureboot/keys/db/db.auth
 /usr/share/secureboot/keys/KEK/KEK.auth
 /usr/share/secureboot/keys/PK/PK.auth
Inserting key update /usr/share/secureboot/keys/db/db.auth into db
Inserting key update /usr/share/secureboot/keys/KEK/KEK.auth into KEK

==> ERROR: Couldn't sync keys

I've looked at #19, which had a simliar issue.

I tried deleting all keys from the firmware interface (and obviously rebooting into Arch). Nothing changed.

I tried running ran chattr -i :

# chattr -i /sys/firmware/efi/efivars/KEK-8be4df61-93ca-11d2-aa0d-00e098032b8c
# chattr -i /sys/firmware/efi/efivars/db-d719b2cb-3d3a-4596-a3bc-dad00e67656f
# sbctl status
==> WARNING: Setup Mode: Enabled
==> WARNING: Secure Boot: Disabled
# sbctl enroll-keys
==> ERROR: File is immutable: /sys/firmware/efi/efivars/KEK-8be4df61-93ca-11d2-aa0d-00e098032b8c
==> ERROR: File is immutable: /sys/firmware/efi/efivars/db-d719b2cb-3d3a-4596-a3bc-dad00e67656f
==> ERROR: You need to chattr -i files in efivarfs

I'll admit that the firmware UI is extremely confusing though, and it's never 100% clear if I'm deleting the keys properly or not. This is a XPS 13 9370.

Setup Mode still shows: Enabled after sbctl enroll-keys

After creating the keys and running sbctl enroll-keys, sbctl status still shows:

==> WARNING: Setup Mode: Enabled
==> WARNING: Secure Boot: Disabled

I rebooted, cleared firmware keys and run enroll-keys, with same status as above!

(not sure if this normal, but I noticed it's different result from Usage section in README)

Your help is appreciated.

Show the current Secure Boot related EFI variables

It would very useful to be able to show the current value of all the Secure Boot EFI variables, and export/import them as .pem/.hex files.

Currently I'm using efi-readvar as:

apt-get install -y efitools
efi-readvar

Which outputs something alike:

Variable PK, length 862
PK: List 0, type X509
    Signature 0, size 834, owner 26dc4851-195f-4ae1-9a19-fbf883bbb35e
        Subject:
            CN=DO NOT TRUST - AMI Test PK
        Issuer:
            CN=DO NOT TRUST - AMI Test PK
Variable KEK, length 1560
KEK: List 0, type X509
    Signature 0, size 1532, owner 77fa9abd-0359-4d32-bd60-28f4e78f784b
        Subject:
            C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Corporation KEK CA 2011
        Issuer:
            C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Corporation Third Party Marketplace Root
Variable db, length 3143
db: List 0, type X509
    Signature 0, size 1572, owner 77fa9abd-0359-4d32-bd60-28f4e78f784b
        Subject:
            C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Corporation UEFI CA 2011
        Issuer:
            C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Corporation Third Party Marketplace Root
db: List 1, type X509
    Signature 0, size 1515, owner 77fa9abd-0359-4d32-bd60-28f4e78f784b
        Subject:
            C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Windows Production PCA 2011
        Issuer:
            C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Root Certificate Authority 2010
Variable dbx, length 3724
dbx: List 0, type SHA256
    Signature 0, size 48, owner 77fa9abd-0359-4d32-bd60-28f4e78f784b
        Hash:80b4d96931bf0d02fd91a61e19d14f1da452e66db2408ca8604d411f92659f0a
    ... OMITED FOR BREVITY ...
Variable MokList has no entries

It can also save them to files and convert to known file formats:

efi-readvar -v PK -o PK.esl   # Platform Key (PK).
efi-readvar -v KEK -o KEK.esl # Key Exchange Key (KEK).
efi-readvar -v db -o db.esl   # Signature Database (DB); aka Allow list database.
efi-readvar -v dbx -o dbx.esl # Forbidden Signature Database (DBX); ala Deny list database.

# convert them to an openssl compatible .der or .hash files.
sig-list-to-certs PK.esl PK
sig-list-to-certs KEK.esl KEK
sig-list-to-certs db.esl db
sig-list-to-certs dbx.esl dbx

# show them.
find . -type f -name '*.der' -print | sort | xargs -I% bash -c 'echo;set -x;openssl x509 -noout -text -inform der -in %'
find . -type f -name '*.hash' -print | sort | xargs -I% bash -c 'echo;set -x;xxd -c 72 -p %'

What do you think?

Sign the fwupmgr bootloader

Hey there! I know the verify command checks files that are in the ESP partition, but there are other pieces of software that need to be signed and aren't in the ESP. The example I have is the fwupdmgr bootloader, which lives in /usr/libexec/fwupd/efi/fwupdx64.efi (on Void, I don't remember where it was on Arch). The issue is that, when trying to check for updates, fwupdmgr fails in the system firmware part on a secure boot protected device, because it can't find the signed version of the bootloader.

$ fwupdmgr get-devices
[...]
├─System Firmware:
│     Device ID:           xxxx
│     Current version:     xxxx
│     Minimum Version:     xxxx
│     Vendor:              Dell Inc. (DMI:Dell Inc.)
│     Update Error:        missing signed bootloader for secure boot: /usr/libexec/fwupd/efi/fwupdx64.efi.signed cannot be found
│     GUID:                xxxx
│     Device Flags:        • Internal device
│                          • Requires AC power
│                          • Needs a reboot after installation
│                          • Cryptographic hash verification is available
[...]

The part about it failing is probably a bug on their part, which I opened an issue about (fwupd/fwupd#2219), but I don't think it makes sense for them to implement some way of signing the bootloader. Do you think this is something that could be included in sbctl? If yes, what would the mechanism for it be? Some system wide configuration file / configuration directory, or hard coded behavior?

Thanks!

Implement sbctl.conf

There are a few lines which should probably be refactored into config.go. Mainly the files in keys.go.

I think we should leave room to specify which protocol one want, files vs yubikey and so on. Along with desired RSA key sizes.

Can probably use yaml or toml for the file itself. Not super keen on having json.

Error when compiling using clang

I'm not sure if I'm missing anything go-specific here. I've seen people compiling go projects with clang since forever, so I'm not really sure if I'm missing some go-specific environment variable here.

Compile flags:

export CC=clang
export CXX=clang++
export LD=/usr/bin/ld.lld
export AR="llvm-ar"
export NM="llvm-nm"
export RANLIB="llvm-ranlib"

# qmake stuff
export QMAKE_CC=clang
export QMAKE_CXX=clang++
export QMAKE_LINK=/usr/bin/ld.lld
export QMAKESPEC=linux-clang

CARCH="x86_64"
CHOST="x86_64-pc-linux-gnu"

# -Wno-error=range-loop-construct is for MultiMC, else it fails to build
CFLAGS="-march=znver1 -mtune=znver1 -flto=thin -O2 -pipe -fno-plt -Wno-error=range-loop-construct -Wno-long-long -Wno-cast-align"
CXXFLAGS+="${CFLAGS}"
LDFLAGS="-fuse-ld=lld -Wl,-O1,--sort-common,--as-needed,-z,relro,--thinlto-cache-dir=/home/kodehawa/.local/share/makepkg/cache/clang"
#-- Make Flags: change this for DistCC/SMP systems
MAKEFLAGS="-j12"

#-- Debugging flags
DEBUG_CFLAGS="-g"
DEBUG_CXXFLAGS="-g"

# Rust flags
RUSTFLAGS="-C opt-level=2 -C target-cpu=native"

Error message:

go build ./cmd/sbctl
# net
cannot parse gcc output $WORK/b070//_cgo_.o as ELF, Mach-O, PE, XCOFF object
make: *** [Makefile:22: sbctl] Error 2
make: *** Waiting for unfinished jobs....

Thanks you ❤️

sbtl requires root to run: couldn't sync keys:

Hey, Thanks for creating this project.

➜  sbctl-0.6 sudo ./sbctl enroll-keys
[sudo] password for garvit-joshi: 
‼ File is immutable: /sys/firmware/efi/efivars/PK-8be4df61-93ca-11d2-aa0d-00e098032b8c
‼ File is immutable: /sys/firmware/efi/efivars/KEK-8be4df61-93ca-11d2-aa0d-00e098032b8c
‼ File is immutable: /sys/firmware/efi/efivars/db-d719b2cb-3d3a-4596-a3bc-dad00e67656f
You need to chattr -i files in efivarfs

➜  sbctl-0.6 sudo chattr -i /sys/firmware/efi/efivars/PK-8be4df61-93ca-11d2-aa0d-00e098032b8c

➜  sbctl-0.6 sudo chattr -i /sys/firmware/efi/efivars/KEK-8be4df61-93ca-11d2-aa0d-00e098032b8c

➜  sbctl-0.6 sudo chattr -i /sys/firmware/efi/efivars/db-d719b2cb-3d3a-4596-a3bc-dad00e67656f

➜  sbctl-0.6 sudo ./sbctl enroll-keys                                                         
Enrolling keys to EFI variables...✘ 
sbtl requires root to run: couldn't sync keys: couldn't write efi variable: write /sys/firmware/efi/efivars/db-d719b2cb-3d3a-4596-a3bc-dad00e67656f: permission denied

Can you please help me with this...
I am using manjaro - Kernel 5.13.5

Make a 1.0 release without go-uefi?

My original plan was to hack on go-uefi and ensure we could port all the functionality from sbsigntools. But I'm'slow and we are soon at 1 year since the release of both tools.

I'm wondering if we should much rather try get the basic configuration stuff into sbctl and do a 1.0 release.

New CLI output format

Some mockups for sbctl interface that fits better with existing *ctl tooling.

Inspiration:
* boltctl
* fwupdmgr
* bootctl

✔ (Green)       Positive/Succsess
✘ (Red)         Negative/Error
‼ (Yellow)      Warning
⁇ (Yellow(?))   Unknwon/Exception/Somethingweird

Errors/Exceptions

λ bin » sbctl list-bundles
⁇ It might be necessary to run this tool as root:
⁇ open /usr/share/secureboot/bundles.db: permission denied
(Bold red?)

Status

$ sbctl status
✔ Secure Boot: Disabled
✔ Setup Mode:  User

Curent boot entry
✔ Signed / ✘ Not Signed (!)
    Title:		Arch Linux (systemd-linux.efi)
    Id:			systemd-linux.efi
    Source:		/efi/EFI/Linux/systemd-linux.efi
    Linux:		EFI/Linux/systemd-linux.efi
    Options:	rw quiet acpi_osi= acpi_backlight=thinkpad_screen nowatchdog bgrt_disable lockdown=confidentiality

json = {
    "Secure Boot": true,
    "Setup Mode": "user"
}

Verify

$ sbctl verify
Verifying file database and EFI images in /efi...
✔ signed /boot/vmlinuz-linux
✔ signed /efi/EFI/BOOT/BOOTX64.EFI 
✔ signed /efi/EFI/Linux/linux-linux.efi
✔ signed /efi/EFI/Linux/systemd-linux.efi 
✔ signed /efi/EFI/arch/fwupdx64.efi 
✔ signed /efi/EFI/systemd/systemd-bootx64.efi 
✔ signed /usr/lib/fwupd/efi/fwupdx64.efi.signed 
✘ could not sign /efi/EFI/Linux/linux-linux-mitigations.efi

[
    {
        "file": "/boot/vmlinuz-linux"
        "is_signed": True,
    }
]

List Files

$ sbctl list-files
Enrolled files:

/efi/EFI/arch/fwupdx64.efi
    Signed:		✔ Signed / ✘ Not Signed (!)

/efi/EFI/systemd/systemd-bootx64.efi
    Signed:		✔ Signed / ✘ Not Signed (!)

/usr/lib/fwupd/efi/fwupdx64.efi
    Output:		/usr/lib/fwupd/efi/fwupdx64.efi.signed
    Signed:		✔ Signed / ✘ Not Signed (!)

/boot/vmlinuz-linux
    Signed:		✔ Signed / ✘ Not Signed (!)

/efi/EFI/BOOT/BOOTX64.EFI
    Signed:		✔ Signed / ✘ Not Signed (!)

/efi/EFI/Linux/linux-linux.efi
    Signed:		✔ Signed / ✘ Not Signed (!)

/efi/EFI/Linux/systemd-linux.efi
    Signed:		✔ Signed / ✘ Not Signed (!)

List Bundles

$ sudo sbctl list-bundles
Enrolled bundles:

/efi/EFI/Linux/linux-linux.efi
    ESP Location:       /efi
    Output:             └─/EFI/Linux/linux-linux.efi
    EFI Stub Image:       └─/usr/lib/systemd/boot/efi/linuxx64.efi.stub
    Splash Image:           ├─/usr/share/systemd/bootctl/splash-arch.bmp
    Cmdline:                ├─/etc/kernel/cmdline
    OS Release:             ├─/usr/lib/os-release
    Kernel Image:           ├─/boot/vmlinuz-linux
    Initramfs Image:        └─/boot/initramfs-linux.img
    Intel Microcode:          └─/boot/intel-ucode.img
    Signed:             ✔ Signed / ✘ Not Signed (!)

Using /proc/cmdline may include unnecessary initrd

The contents of /proc/cmdline at some boot might include the microcode and initramfs supplied as arguments to initrd. This is not required any more when creating a bundle because both of those are dealt-with separately.

So should any initrd components be trimmed before inclusion?

Failure in build for cmd/sbctl/main.go

Using makechrootpkg on a clean chroot with latest sbctl-git package files. Not sure if related to #43 ....

==> Starting build()...
go: downloading github.com/spf13/cobra v1.0.0
go: downloading github.com/foxboron/go-uefi v0.0.0-20210105211851-5faf8e43ee9b
go: downloading github.com/google/uuid v1.1.1
go: downloading golang.org/x/sys v0.0.0-20201109165425-215b40eba54c
go: downloading github.com/spf13/pflag v1.0.3
a2x --no-xmllint --asciidoc-opts="-f docs/asciidoc.conf" -d manpage -f manpage -D docs docs/sbctl.8.txt
go build ./cmd/sbctl
# github.com/foxboron/sbctl/cmd/sbctl
cmd/sbctl/main.go:224:8: no new variables on left side of :=
make: *** [Makefile:24: sbctl] Error 2
==> ERROR: A failure occurred in build().
    Aborting...

Support for hardware tokens / HSMs (OpenPGP, PKCS#11, etc.)

A configurable key storage backend (plain files, OpenPGP smartcard, PKCS#11 token/HSM, etc.) would greatly benefit the underlying security model of sbctl and would enable integration into larger PKI infrastructures.

Relying on open standards would enable advanced scenarios, like signing with a remote HSM conditional on prior remote attestation of current system state using a local TPM (i.e. DRTM-based TCB attestation).

Replace `log.Fatal` with `log.Panic`?

log.Fatal:

2021/05/04 15:10:55 exit status 1
exit status 1

VS

log.Panic:

2021/05/04 15:09:17 exit status 1
panic: exit status 1

goroutine 1 [running]:
log.Panic(0xc0000b3dc8, 0x1, 0x1)
	/usr/lib/go/src/log/log.go:354 +0xae
github.com/foxboron/sbctl.GetESP(0x656580, 0xc000066840)
	/home/user/Projects/sbctl/sbctl.go:26 +0x176
main.bundleCmd(0x7e1d00)
	/home/user/Projects/sbctl/cmd/sbctl/main.go:235 +0x249
main.main()
	/home/user/Projects/sbctl/cmd/sbctl/main.go:338 +0x1fc
exit status 2

I think having trackbacks is very nice for debugging and bug reports.

UX Issues

General issue for any UX issues people experience with sbctl.

Add option to add Microsoft/vendor certs to the signature database

Unfortunately, I found out that some(?) firmwares try to validate option ROMs with the custom keys the user imported, which will not succeed and might even result in a semi-bricked motherboard when no iGPU/APU is present. Adding Microsofts or the vendors certs to the signature database seems to be the only way to use secure boot with such a setup.

See also:

Neither .der nor .auth keys generated

I ran sbctl create-keys, which succeeded without errors, but neither .der nor .auth files were generated:

archlinux% ls /usr/share/secureboot/keys/*
/usr/share/secureboot/keys/db:
db.key  db.pem

/usr/share/secureboot/keys/KEK:
KEK.key  KEK.pem

/usr/share/secureboot/keys/PK:
PK.key  PK.pem

Is this normal?
I need them because I have an issue similar to #67, and I'd like to try to enroll them in my UEFI (it doesn't accept .pem files).

`GetESP` returns an empty string

I'm using systemd's Discoverable Partitions Specification.

That is, my efi partition is not in my fstab:

$ cat /etc/fstab
# Static information about the filesystems.
# See fstab(5) for details.

# See https://github.com/systemd/systemd/issues/20019
UUID=e68d67d9-c05c-45c3-93f9-fc499f3e2e64	none      	swap      	defaults	0 0

It is auto-mounted by systemd based on its partition type:

$ mount | grep efi
efivarfs on /sys/firmware/efi/efivars type efivarfs (rw,nosuid,nodev,noexec,relatime)
systemd-1 on /efi type autofs (rw,relatime,fd=51,pgrp=1,timeout=120,minproto=5,maxproto=5,direct,pipe_ino=13874)
/dev/nvme0n1p1 on /efi type vfat (rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro)

However, the partition is auto-mounted when it's accessed, so before reading it or accessing it, it's not mounted, and therefore, won't show up in lsblk:

$ lsblk --json --output PARTTYPE,MOUNTPOINT,PTTYPE,FSTYPE
{
   "blockdevices": [
      {
         "parttype": null,
         "mountpoint": "/",
         "pttype": null,
         "fstype": "ext4"
      },{
         "parttype": null,
         "mountpoint": "[SWAP]",
         "pttype": null,
         "fstype": "swap"
      },{
         "parttype": null,
         "mountpoint": null,
         "pttype": "gpt",
         "fstype": null
      },{
         "parttype": "c12a7328-f81f-11d2-ba4b-00a0c93ec93b",
         "mountpoint": null,
         "pttype": "gpt",
         "fstype": "vfat"
      },{
         "parttype": "4f68bce3-e8cd-4db1-96e7-fbcaf984b709",
         "mountpoint": null,
         "pttype": "gpt",
         "fstype": "crypto_LUKS"
      },{
         "parttype": "0657fd6d-a4ab-43c4-84e5-0933c84b4f4f",
         "mountpoint": null,
         "pttype": "gpt",
         "fstype": "crypto_LUKS"
      }
   ]
}

This results in GetESP returning an empty string.

It also seems that systemd will unmount the partition if it's not accessed for two minutes (this is the default TimeoutIdleSec=120):

$ mount | grep efi
efivarfs on /sys/firmware/efi/efivars type efivarfs (rw,nosuid,nodev,noexec,relatime)
systemd-1 on /efi type autofs (rw,relatime,fd=51,pgrp=1,timeout=120,minproto=5,maxproto=5,direct,pipe_ino=13874)

This uses the systemd.automount(5) machinery.

Possible solution 1

Use /efi as a final fallback.

This is currently an empty string, which is never correct anyway.

This isn't a perfect solution, but I can't see obvious scenarios where it would fail. It definitely won't break any scenarios which currently work.

Possible solution 2

Try to read /efi, and other known locations, to trigger the automount, and then use lsblk.

Return an error if no candidate location seems to be the ESP.

This is hacky, but far safer.


None of these two solutions should negatively impact non-systemd setups.

`list-bundles` gives an error if a bundle is absent in the file system

I understand that the bundle command creates a bundle description in /usr/share/secureboot/bundles.db and creates the bundle (file). I suppose that ${NAME} in sbctl bundle ${NAME} is the path to the bundle; this is not clear from the man page.

Executing

sbctl bundle --amducode /boot/amd* --save /boot/efi/boot/bootx64.efi
rm /boot/efi/boot/bootx64.efi
sbctl list-bundles

gives

Wrote EFI bundle /boot/efi/boot/bootx64.efi
open /boot/efi/boot/bootx64.efi: no such file or directory

The program doesn't show the bundle description for /boot/efi/boot/bootx64.efi despite that it exists in /usr/share/secureboot/bundles.db. Not showing it as a normal entry is confusing. Also sbctl list-bundles shows no bundle descriptions at all (if there are more than one) if at least one bundle is absent in the file system. For a mysterious reason, I see bundle descriptions for bundles that are present in the file system when I redirect the program output to a file.

I believe that user deleting a bundle is a realistic scenario.

P. S. I guess that the default paths that start with /efi should be fixed on the man page. It seems that in my case, /boot is the default:

Enrolled bundles:

/boot/efi/boot/bootx64.efi
	Signed:		✔ Signed
	ESP Location:	/boot
	Output:		└─/efi/boot/bootx64.efi
	EFI Stub Image:	  └─/usr/lib/systemd/boot/efi/linuxx64.efi.stub
	Cmdline:	    ├─/etc/kernel/cmdline
	OS Release:	    ├─/usr/lib/os-release
	Kernel Image:	    ├─/boot/vmlinuz-linux
	Initramfs Image:    └─/boot/initramfs-linux.img
	AMD Microcode:        └─/boot/amd-ucode.img

Best way to deal with versioned kernels

So, unlike Arch, Void has versioned kernels, which look like linux-5.4.53_1.efi, for example, in the case of a UEFI bundle generated by dracut. This means two things in the current version: each new kernel version will have to be added to the database manually, and old kernel versions that are removed at some point will lead to complaints from sbctl, though not outright failures. I've thought of a few solutions:

For the new kernel part:

  • have a distribution level hook that adds the kernels to the list for you, nothing needs to be done in sbctl
  • have an option to sign all files in the ESP, potentially unsafe

For the old kernel part:

  • have a command line flag to automatically remove files that don't exist any more from the database

I hadn't realized this is an issue because I use a custom initramfs, so it's versioned a bit differently, and gets bumped less often.

Feature request: MOK & Shim support

On some machines enabling UEFI secure boot setup mode is a no-can-do due to company policies or horrible UEFI UIs.
Support for using a Microsoft CA signed Shim with a MOK key would enable using secure boot on these machines.

ERROR: Couldn't sync keys

 ~ sudo sbctl enroll-keys
==> Syncing /usr/share/secureboot/keys to EFI variables...
Invalid key /usr/share/secureboot/keys/PK/PK.der.esl
 - unknown cert type
Invalid key /usr/share/secureboot/keys/PK/PK.pem
 - unknown cert type
Invalid key /usr/share/secureboot/keys/PK/PK.der
 - unknown cert type
Invalid key /usr/share/secureboot/keys/PK/PK.key
 - unknown cert type
Invalid key /usr/share/secureboot/keys/KEK/KEK.der.esl
 - unknown cert type
Invalid key /usr/share/secureboot/keys/KEK/KEK.pem
 - unknown cert type
Invalid key /usr/share/secureboot/keys/KEK/KEK.der
 - unknown cert type
Invalid key /usr/share/secureboot/keys/KEK/KEK.key
 - unknown cert type
Invalid key /usr/share/secureboot/keys/db/db.der.esl
 - unknown cert type
Invalid key /usr/share/secureboot/keys/db/db.pem
 - unknown cert type
Invalid key /usr/share/secureboot/keys/db/db.der
 - unknown cert type
Invalid key /usr/share/secureboot/keys/db/db.key
 - unknown cert type
Filesystem keystore:
  /usr/share/secureboot/keys/db/db.auth [3285 bytes]
  /usr/share/secureboot/keys/db/db.der.esl [1263 bytes]
  /usr/share/secureboot/keys/db/db.pem [1708 bytes]
  /usr/share/secureboot/keys/db/db.der [1219 bytes]
  /usr/share/secureboot/keys/db/db.key [3272 bytes]
  /usr/share/secureboot/keys/KEK/KEK.auth [3281 bytes]
  /usr/share/secureboot/keys/KEK/KEK.der.esl [1271 bytes]
  /usr/share/secureboot/keys/KEK/KEK.pem [1716 bytes]
  /usr/share/secureboot/keys/KEK/KEK.der [1227 bytes]
  /usr/share/secureboot/keys/KEK/KEK.key [3272 bytes]
  /usr/share/secureboot/keys/PK/PK.auth [3273 bytes]
  /usr/share/secureboot/keys/PK/PK.der.esl [1263 bytes]
  /usr/share/secureboot/keys/PK/PK.pem [1708 bytes]
  /usr/share/secureboot/keys/PK/PK.der [1219 bytes]
  /usr/share/secureboot/keys/PK/PK.key [3272 bytes]
firmware keys:
  PK:
  KEK:
    /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Corporation KEK CA 2011
    /C=JP/ST=Kanagawa/L=Yokohama/O=Lenovo Ltd./CN=Lenovo Ltd. KEK CA 2012
  db:
    /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Windows Production PCA 2011
    /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Corporation UEFI CA 2011
    /C=US/ST=North Carolina/O=Lenovo/CN=Lenovo UEFI CA 2014
    /C=JP/ST=Kanagawa/L=Yokohama/O=Lenovo Ltd./CN=ThinkPad Product CA 2012
  dbx:
    10d45fcba396aef3153ee8f6ecae58afe8476a280a2026fc71f6217dcf49ba2f
    <...>
    895a9785f617ca1d7ed44fc1a1470b71f3f1223862d9ff9dcc3ae2df92163daf
    82db3bceb4f60843ce9d97c3d187cd9b594Can't create key file /sys/firmware/efi/efivars/db-d719b2cb-3d3a-4596-a3bc-dad00e67656f: Operation not permitted
Error syncing keystore file /usr/share/secureboot/keys/db/db.auth
Can't create key file /sys/firmware/efi/efivars/KEK-8be4df61-93ca-11d2-aa0d-00e098032b8c: Operation not permitted
Error syncing keystore file /usr/share/secureboot/keys/KEK/KEK.auth
1cd3de8100e586f2bda5637575f67
    81a8b965bb84d3876b9429a95481cc955318cfaa1412d808c8a33bfd33fff0e4
    <...>
    80b4d96931bf0d02fd91a61e19d14f1da452e66db2408ca8604d411f92659f0a
filesystem keys:
  PK:
    /C=Platform Key
     from /usr/share/secureboot/keys/PK/PK.auth
  KEK:
    /C=Key Exchange Key
     from /usr/share/secureboot/keys/KEK/KEK.auth
  db:
    /C=Database Key
     from /usr/share/secureboot/keys/db/db.auth
  dbx:
New keys in filesystem:
 /usr/share/secureboot/keys/db/db.auth
 /usr/share/secureboot/keys/KEK/KEK.auth
 /usr/share/secureboot/keys/PK/PK.auth
Inserting key update /usr/share/secureboot/keys/db/db.auth into db
Inserting key update /usr/share/secureboot/keys/KEK/KEK.auth into KEK

==> ERROR: Couldn't sync keys

Better error messages when keys are already present with `enroll-keys`

Currently when enrolling-keys we dont check if there is no keys on the system. We just blindly sbkeysync and assume it's fine.

We should preferably do a check on the PK, KEK and db files in efivars and abort early with a better error message. Maybe explain to one needs to clear out any existing keys.

Add a --force option?

Support linux keyring for kernel module signing

Heftig is probably adding support for loading UEFI keys into the Linux keyring when secure boot is enabled. This allows us to use the db key for kernel module signing which is handy if you are using lockdown=confidentialy and dkms modules needs to be signed by a trusted key.

https://bbs.archlinux.org/viewtopic.php?pid=1861193#p1861193

I think sbctl should have some support to sign kernel modules by path, or by name. And also verify that the keyring has the UEFI certificate loaded.

Improve GetESP()

GetESP() in sbctl.go assumes that there is only one partition with the ESP type AND that it is mounted. Both assumptions can fail when:

  • you have multiple disks, each can have its own ESP (and UEFI can boot from any from its boot menu)
  • by default systemd sets an automount for the ESP, so it's not even mounted by default - the lsblk -o "PARTTYPE,MOUNTPOINT" will print the UUID without any mount points.

This affects for ex. the verify command and probably others too.

the approach in systemd (bootctl) is to try[1] "/efi", "/boot" and "/boot/efi", and can be overridden with a SYSTEMD_ESP_PATH env var. And then it tries to also access[2] that path before deciding it's really an ESP.

[1] https://github.com/systemd/systemd/blob/c335b7c3f8164677316936c7a22e6fca85be28af/src/shared/bootspec.c#L1154
[2] https://github.com/systemd/systemd/blob/c335b7c3f8164677316936c7a22e6fca85be28af/src/shared/bootspec.c#L1080

sbctl could re-implement this same approach or somehow re-use the output of bootctl.

Shouln't `/etc` be a place to store configuration instead of `/usr`

/usr is the second major section of the filesystem. /usr is shareable, read-only data. That means that /usr should be shareable between various FHS-compliant hosts and must not be written to. Any information that is host-specific or varies with time is stored elsewhere.

From Linux Filesystem Hierarchy Standard

/usr might be useful if you have machines with same secure boot keys but I think for a host specific configuration /etc should be used.

Shell completions are corrupted.

Screenshot from 2021-05-05 10-09-33

All of shell completions have this binary string at the end.

In less it looks like this:

ESC(BESC[m

Probably an issue with upstream library?

Please add `binutils` package as dependency for arch linux packaging

First of all many thanks for your effort on this project. It is pretty cool :D

I tried it out yesterday on a freshly installed arch linux system and I think I discovered a missing dependency of sbctl.
Because of using objcopy in bundles.go we will have funny behaviour while generating combined EFISTUB file with binutils missing on arch systems.

root@test ~# sbctl list-bundles
==> Bundle: /boot/efi/EFI/Linux/arch-linux.efi
  -> Intel Microcode: /boot/intel-ucode.img
  -> Kernel Image: /boot/vmlinuz-linux
  -> Initramfs Image: /boot/initramfs-linux.img
  -> Cmdline: /boot/cmdline-linux
  -> OS Release: /usr/lib/os-release
  -> EFI Stub Image: /usr/lib/systemd/boot/efi/linuxx64.efi.stub
  -> ESP Location: /boot/efi
  -> Splash Image: /usr/share/systemd/bootctl/splash-arch.bmp
  -> Output: /boot/efi/EFI/Linux/arch-linux.efi
root@test ~# sbctl generate-bundles
==> Generating EFI bundles....
==> Wrote EFI bundle /boot/efi/EFI/Linux/arch-linux.efi

But /boot/efi/EFI/Linux/remains empty. As this fails silently without any errors it will take some time to track down the missing package...

Logging infrastructure

Having taken a look at the code for logging, I have a few ideas for it:

  • Introduce a dependency on github.com/mattn/go-isatty for tty detection. So you get colored output in the terminal and non-colored output when piping into something. We could also have a bit more logic to add a ``--color=always|never|auto` command line flag. I've tested the isatty bit already.

  • I'm going to take a look at how other projects do it for logging, but for now I am considering having a single logger with the formatting logic inside it, which you can pick using enums. Given that this is an administrative tool, having output for syslog is something I think it would make sense to add too.

  • Logging levels: the standard output is fine for daily usage, but having a debug option would surely help for those wanting to diagnose potential issues.

Follow recommended project layout

According to https://github.com/golang-standards/project-layout, commands should go in cmd/<command-name>/, and all supporting files in either pkg/ or internal/, depending on if you wish to export them to other Go projects. That would allow the sbctl command to be installed with go install ./..., which is considerably easier.

I would be interested in making these changes if you agree to them, just need to know where you'd prefer the supporting files to be (pkg or internal).

Exit codes

Stolen from makepkg(8). But this could maybe work as an outline?

ERRORS
       On exit, makepkg will return one of the following error codes.

       0
           Normal exit condition.

       1
           Not run with root.

       2
           Error in configuration file.

       3
           User specified an invalid option.

       4
           Error in the flags.

       5
           Failed to sign file.

       6
           Failed to create bundle.

       10
           Missing signing keys.

UEFI verification sometimes fail

After a kernel/systemd-boot upgrade and a reboot, UEFI might say verification failed.
I always have to grab my rescue livecd and reinstall kernel.
No errors.
Contents of /usr/share/libalpm/hooks/99-sbctl.hook:

[Trigger]
Type = Path
Operation = Install
Operation = Upgrade
Operation = Remove
Target = boot/*
Target = efi/*
Target = usr/lib/modules/*/vmlinuz

[Action]
Description = Signing EFI binaries...
When = PostTransaction
Exec = /usr/bin/sbctl sign-all -g

sbctl-git r74.gdfa6fb1-1
Linux archlinux 5.11.11-hardened1-1-hardened #1 SMP PREEMPT Sat, 03 Apr 2021 20:20:28 +0000 x86_64 GNU/Linux

Bundles not signed after kernel update

Prior to update

root@soji ~# sbctl list-bundles
==> Bundle: /efi/EFI/Linux/linux-arch-zen.efi
  -> Intel Microcode: /boot/intel-ucode.img
  -> Kernel Image: /boot/vmlinuz-linux-zen
  -> Initramfs Image: /boot/initramfs-linux-zen.img
  -> Cmdline: /proc/cmdline
  -> OS Release: /usr/lib/os-release
  -> EFI Stub Image: /usr/lib/systemd/boot/efi/linuxx64.efi.stub
  -> ESP Location: /efi
  -> Splash Image: /usr/share/systemd/bootctl/splash-arch.bmp
  -> Output: /efi/EFI/Linux/linux-arch-zen.efi
==> Bundle: /efi/EFI/Linux/linux-linux.efi
  -> Intel Microcode: /boot/intel-ucode.img
  -> Kernel Image: /boot/vmlinuz-linux
  -> Initramfs Image: /boot/initramfs-linux.img
  -> Cmdline: /proc/cmdline
  -> OS Release: /usr/lib/os-release
  -> EFI Stub Image: /usr/lib/systemd/boot/efi/linuxx64.efi.stub
  -> ESP Location: /efi
  -> Splash Image: /usr/share/systemd/bootctl/splash-arch.bmp
  -> Output: /efi/EFI/Linux/linux-linux.efi

root@soji ~# sbctl verify
==> Verifying file database and EFI images in /efi...
  -> /efi/EFI/BOOT/BOOTX64.EFI is signed
  -> /efi/EFI/systemd/systemd-bootx64.efi is signed
  -> /usr/lib/fwupd/efi/fwupdx64.efi.signed is signed
  -> /efi/EFI/Linux/linux-arch-zen.efi is signed
  -> /efi/EFI/Linux/linux-linux.efi is signed
  -> /efi/vmlinuz-linux-lts is signed

Trigger pacman hook

root@soji ~# pacman -S linux   
warning: linux-5.7.12.arch1-1 is up to date -- reinstalling
resolving dependencies...            
looking for conflicting packages...
                                                                       
Package (1)  Old Version     New Version     Net Change
                                                                       
core/linux   5.7.12.arch1-1  5.7.12.arch1-1    0,00 MiB
                                                                       
Total Installed Size:  75,85 MiB  
Net Upgrade Size:       0,00 MiB                                      
                                                                       
:: Proceed with installation? [Y/n]                                                                                                           
(1/1) checking keys in keyring                                                                                                                                             [----------------------------------------------------------------------------------------------------------] 100%
(1/1) checking package integrity                                                                                                                                           [----------------------------------------------------------------------------------------------------------] 100%
(1/1) loading package files                                                                                                                                                [----------------------------------------------------------------------------------------------------------] 100%
(1/1) checking for file conflicts                                                                                                                                          [----------------------------------------------------------------------------------------------------------] 100%
(1/1) checking available disk space                                                                                                                                        [----------------------------------------------------------------------------------------------------------] 100%
:: Running pre-transaction hooks...
(1/2) Performing snapper pre snapshots for the following configurations...
==> root: 881                                             
(2/2) Saving Linux kernel modules...                     
:: Processing package changes...     
(1/1) reinstalling linux                                                                                                                                                   [----------------------------------------------------------------------------------------------------------] 100%
:: Running post-transaction hooks...
(1/7) Restoring Linux kernel modules...
++ uname -r                                                                                                                                   
+ KVER=5.7.12-zen1-1-zen       
+ test -e /usr/lib/modules/backup/5.7.12-zen1-1-zen
+ rsync -AHXal --ignore-existing /usr/lib/modules/backup/5.7.12-zen1-1-zen /usr/lib/modules/
+ rm -rf /usr/lib/modules/backup                      
(2/7) Arming ConditionNeedsUpdate...               
(3/7) Updating module dependencies...                 
(4/7) Updating linux initcpios...               
==> Building image from preset: /etc/mkinitcpio.d/linux.preset: 'default'
  -> -k /boot/vmlinuz-linux -c /etc/mkinitcpio.conf -g /boot/initramfs-linux.img
==> Starting build: 5.7.12-arch1-1                                                                                                            
  -> Running build hook: [base]
  -> Running build hook: [systemd]
  -> Running build hook: [autodetect]
  -> Running build hook: [keyboard]
  -> Running build hook: [modconf]
  -> Running build hook: [block]
  -> Running build hook: [sd-encrypt]
  -> Running build hook: [filesystems]
  -> Running build hook: [fsck]
==> Generating module dependencies
==> Creating gzip-compressed initcpio image: /boot/initramfs-linux.img
==> Image generation successful
==> Building image from preset: /etc/mkinitcpio.d/linux.preset: 'fallback'
  -> -k /boot/vmlinuz-linux -c /etc/mkinitcpio.conf -g /boot/initramfs-linux-fallback.img -S autodetect
==> Starting build: 5.7.12-arch1-1
  -> Running build hook: [base]
  -> Running build hook: [systemd]
  -> Running build hook: [keyboard]
  -> Running build hook: [modconf]
  -> Running build hook: [block]
==> WARNING: Possibly missing firmware for module: aic94xx
==> WARNING: Possibly missing firmware for module: wd719x
  -> Running build hook: [sd-encrypt]
  -> Running build hook: [filesystems]
  -> Running build hook: [fsck]
==> Generating module dependencies
==> Creating gzip-compressed initcpio image: /boot/initramfs-linux-fallback.img
==> Image generation successful
(5/7) Signing EFI binaries...
==> Generating EFI bundles....
==> Wrote EFI bundle /efi/EFI/Linux/linux-arch-zen.efi
==> Wrote EFI bundle /efi/EFI/Linux/linux-linux.efi
==> /usr/lib/fwupd/efi/fwupdx64.efi has been signed...
==> /efi/EFI/BOOT/BOOTX64.EFI has been signed...
==> /efi/EFI/systemd/systemd-bootx64.efi has been signed...
(6/7) Updating pkgfile database
(7/7) Performing snapper post snapshots for the following configurations...
==> root: 882

root@soji ~# sbctl verify
==> Verifying file database and EFI images in /efi...
  -> /efi/EFI/BOOT/BOOTX64.EFI is signed
  -> /efi/EFI/systemd/systemd-bootx64.efi is signed
  -> /usr/lib/fwupd/efi/fwupdx64.efi.signed is signed
  -> WARNING: /efi/EFI/Linux/linux-arch-zen.efi is not signed
  -> WARNING: /efi/EFI/Linux/linux-linux.efi is not signed
  -> /efi/vmlinuz-linux-lts is signed

I would expect the bundles to be signed as well or am i missing something?

Thanks for your great work!

Enrolling / exporting / importing signatures.

In this section of the README, we could link to some article / wiki page / something for instructions on how to put the device in Setup Mode, or just explain it ourselves. According to https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-secure-boot-key-creation-and-management-guidance , it should require only resetting all current Secure Boot configuration on the device.

$ sbctl status
==> WARNING: Setup Mode: Enabled
==> WARNING: Secure Boot: Disabled

$ sbctl create-keys
==> Creating secure boot keys...
  -> Using UUID d6e9af79-c6b5-4b43-b893-dbb7e6570142...
==> Signing /usr/share/secureboot/keys/PK/PK.der.esl with /usr/share/secureboot/keys/PK/PK.key...
==> Signing /usr/share/secureboot/keys/KEK/KEK.der.esl with /usr/share/secureboot/keys/PK/PK.key...
==> Signing /usr/share/secureboot/keys/db/db.der.esl with /usr/share/secureboot/keys/KEK/KEK.key...

$ sbctl enroll-keys
==> Syncing /usr/share/secureboot/keys to EFI variables...
==> Synced keys!

However, in my case, since I was already in the UEFI menu, I imported the keys manually, from the .auth files. Perhaps it could make sense to have a command to export keys (and then, only the necessary .auth/.esr./.cel files) into a folder for use with either the device's UEFI firmware or KeyTool.

Finally, what do you think of moving keys across devices? Should it be a supported thing, or should users just manually copy the /usr/share/secureboot folder?

Signing history and revocation

With the recent boothole stuff I think it would be neat to track the signatures done so we can revoke them retroactively.

We should probably also sport a revocation API where we can import siglists, and pass files that should be added to the dbx list.

Parts of this would be fairly simple to implement with goefi, so I should probably work a bit more on that.

# sbctl signature-history
Num     Binary                  Date Time               Checksum
1       /efi/vmlinuz-linux      20200804T190000         abcdef12345deadbeef
2       /efi/grub.efi           20200804T190000         abcdef12345deadbeef
# sbctl signature-history revoke 2 // or take a range: 1 2

Revoke API

# sbctl revoke /efi/vmlinuz-linux
# sbctl revoke --siglist ./banned-hashes.bin
# sbctl checksum /efi/vmlinuz-linux | sbctl revoke --checksum -
# sbcrl revoke-list
// List the revoked EFI binaries

sbctl verify warns about unsigned binaries on permission error

sbctl complains that binaries aren't signed when in fact it just doesn't have access rights, i.e.

$ sbctl verify
==> Verifying file database and EFI images in /efi...
  -> WARNING: /efi/EFI/BOOT/BOOTX64.EFI is not signed
  -> WARNING: /efi/EFI/systemd/systemd-bootx64.efi is not signed
  -> /usr/lib/fwupd/efi/fwupdx64.efi.signed is signed
2021/04/03 09:57:38 open /efi: permission denied

In fact binaries are signed properly:

$  sudo sbctl verify
==> Verifying file database and EFI images in /efi...
  -> /efi/EFI/BOOT/BOOTX64.EFI is signed
  -> /efi/EFI/systemd/systemd-bootx64.efi is signed
  -> /usr/lib/fwupd/efi/fwupdx64.efi.signed is signed
  -> /efi/EFI/Linux/linux-5.10.27-1-lts-816184afa8524f2ca42a23ee0624abfb-rolling.efi is signed
  -> /efi/EFI/Linux/linux-5.11.11-arch1-1-816184afa8524f2ca42a23ee0624abfb-rolling.efi is signed
  -> WARNING: /efi/KeyTool.efi is not signed

I found the first message a bit scary; initially I thought I had done something wrong, when in fact I just had to call sbctl verify as root.

Perhaps the permission error could be made to stand out more?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.