sbctl

package module
v0.0.0-...-0ef7b8f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 22, 2024 License: MIT Imports: 32 Imported by: 1

README

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.16
  • 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!
# 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

Documentation

Index

Constants

View Source
const (
	// from /usr/include/linux/fs.h
	FS_SECRM_FL        = 0x00000001 /* Secure deletion */
	FS_UNRM_FL         = 0x00000002 /* Undelete */
	FS_COMPR_FL        = 0x00000004 /* Compress file */
	FS_SYNC_FL         = 0x00000008 /* Synchronous updates */
	FS_IMMUTABLE_FL    = 0x00000010 /* Immutable file */
	FS_APPEND_FL       = 0x00000020 /* writes to file may only append */
	FS_NODUMP_FL       = 0x00000040 /* do not dump file */
	FS_NOATIME_FL      = 0x00000080 /* do not update atime */
	FS_DIRTY_FL        = 0x00000100
	FS_COMPRBLK_FL     = 0x00000200 /* One or more compressed clusters */
	FS_NOCOMP_FL       = 0x00000400 /* Don't compress */
	FS_ECOMPR_FL       = 0x00000800 /* Compression error */
	FS_BTREE_FL        = 0x00001000 /* btree format dir */
	FS_INDEX_FL        = 0x00001000 /* hash-indexed directory */
	FS_IMAGIC_FL       = 0x00002000 /* AFS directory */
	FS_JOURNAL_DATA_FL = 0x00004000 /* Reserved for ext3 */
	FS_NOTAIL_FL       = 0x00008000 /* file tail should not be merged */
	FS_DIRSYNC_FL      = 0x00010000 /* dirsync behaviour (directories only) */
	FS_TOPDIR_FL       = 0x00020000 /* Top of directory hierarchies*/
	FS_EXTENT_FL       = 0x00080000 /* Extents */
	FS_DIRECTIO_FL     = 0x00100000 /* Use direct i/o */
	FS_NOCOW_FL        = 0x00800000 /* Do not cow file */
	FS_PROJINHERIT_FL  = 0x20000000 /* Create with parents projid */
	FS_RESERVED_FL     = 0x80000000 /* reserved for ext2 lib */
)

Variables

View Source
var (
	DatabasePath = "/usr/share/secureboot/"
	KeysPath     = filepath.Join(DatabasePath, "keys")
	PKKey        = filepath.Join(KeysPath, "PK", "PK.key")
	PKCert       = filepath.Join(KeysPath, "PK", "PK.pem")
	KEKKey       = filepath.Join(KeysPath, "KEK", "KEK.key")
	KEKCert      = filepath.Join(KeysPath, "KEK", "KEK.pem")
	DBKey        = filepath.Join(KeysPath, "db", "db.key")
	DBCert       = filepath.Join(KeysPath, "db", "db.pem")
	DBPath       = filepath.Join(DatabasePath, "files.db")

	GUIDPath = filepath.Join(DatabasePath, "GUID")
)
View Source
var (
	ErrOprom      = errors.New("uefi has oprom")
	ErrNoEventlog = errors.New("no eventlog found")
)
View Source
var BundleDBPath = filepath.Join(DatabasePath, "bundles.db")
View Source
var EfivarFSFiles = []string{
	"/sys/firmware/efi/efivars/PK-8be4df61-93ca-11d2-aa0d-00e098032b8c",
	"/sys/firmware/efi/efivars/KEK-8be4df61-93ca-11d2-aa0d-00e098032b8c",
	"/sys/firmware/efi/efivars/db-d719b2cb-3d3a-4596-a3bc-dad00e67656f",
}
View Source
var ErrAlreadySigned = errors.New("already signed file")
View Source
var ErrImmutable = errors.New("file is immutable")
View Source
var ErrNoESP = errors.New("failed to find EFI system partition")
View Source
var ErrNotImmutable = errors.New("file is not immutable")
View Source
var Immutable = false
View Source
var RSAKeySize = 4096
View Source
var SecureBootKeys = []struct {
	Key         string
	Description string
}{
	{
		Key:         "PK",
		Description: "Platform Key",
	},
	{
		Key:         "KEK",
		Description: "Key Exchange Key",
	},
	{
		Key:         "db",
		Description: "Database Key",
	},
}

Map up our default keys in a struct

Functions

func AddChecked

func AddChecked(path string)

func BundleIter

func BundleIter(fn func(s *Bundle) error) error

func CanVerifyFiles

func CanVerifyFiles() error

Check if we can access the db certificate to verify files

func CheckEventlogOprom

func CheckEventlogOprom(eventlog string) error

func CheckIfKeysInitialized

func CheckIfKeysInitialized(output string) bool

Check if we have already intialized keys in the given output directory

func CheckImmutable

func CheckImmutable() error

Check if any files in efivarfs has the immutable bit set

func CheckMSDos

func CheckMSDos(r io.Reader) (bool, error)

func CheckSbctlInstallation

func CheckSbctlInstallation(path string) bool

Checks if sbctl is setup on this computer

func ChecksumFile

func ChecksumFile(file string) (string, error)

func CombineFiles

func CombineFiles(microcode, initramfs string) (afero.File, error)

func CopyDirectory

func CopyDirectory(src, dst string) error

CopyDirectory moves files and creates directories

func CopyFile

func CopyFile(src, dst string) error

func CreateBundle

func CreateBundle(bundle Bundle) error

func CreateDirectory

func CreateDirectory(path string) error

func CreateGUID

func CreateGUID(output string) ([]byte, error)

func CreateKey

func CreateKey(name string) ([]byte, []byte, error)

func CreateUUID

func CreateUUID() []byte

func DetectTPMEventlog

func DetectTPMEventlog(sb *signature.SignatureDatabase) bool

func Enroll

func Enroll(sigdb *signature.SignatureDatabase, signerKey, signerPem []byte, efivar string) error

func EnrollCustom

func EnrollCustom(customBytes []byte, efivar string) error

func GenerateBundle

func GenerateBundle(bundle *Bundle) (bool, error)

func GetAttr

func GetAttr(f *os.File) (int32, error)

GetAttr retrieves the attributes of a file on a linux filesystem

func GetESP

func GetESP() (string, error)

Slightly more advanced check

func GetEfistub

func GetEfistub() (string, error)

func GetEnrolledVendorCerts

func GetEnrolledVendorCerts() []string

func GetEventlogChecksums

func GetEventlogChecksums(eventlog string) (*signature.SignatureDatabase, error)

func GetEventlogEvents

func GetEventlogEvents(eventlog string) ([]attest.Event, error)

func GetGUID

func GetGUID() (uuid.UUID, error)

func InChecked

func InChecked(path string) bool

func InitializeSecureBootKeys

func InitializeSecureBootKeys(output string) error

Initialize the secure boot keys needed to setup secure boot. It creates the following keys:

  • Platform Key (PK)
  • Key Exchange Key (KEK)
  • db (database)
  • dbx (forbidden database)

func IsImmutable

func IsImmutable(file string) error

Check if a given file has the immutable bit set

func ReadOrCreateFile

func ReadOrCreateFile(filePath string) ([]byte, error)

func SaveKey

func SaveKey(k []byte, file string) error

func SetAttr

func SetAttr(f *os.File, attr int32) error

SetAttr sets the attributes of a file on a linux filesystem to the given value

func Sign

func Sign(file, output string, enroll bool) error

func SignDatabase

func SignDatabase(sigdb *signature.SignatureDatabase, signerKey, signerPem []byte, efivar string) ([]byte, error)

func SignFile

func SignFile(key, cert, file, output, checksum string) error

func SigningEntryIter

func SigningEntryIter(fn func(s *SigningEntry) error) error

func VerifyFile

func VerifyFile(cert, file string) (bool, error)

func WriteBundleDatabase

func WriteBundleDatabase(dbpath string, bundles Bundles) error

func WriteFileDatabase

func WriteFileDatabase(dbpath string, files SigningEntries) error

Types

type Bundle

type Bundle struct {
	Output         string `json:"output"`
	IntelMicrocode string `json:"intel_microcode"`
	AMDMicrocode   string `json:"amd_microcode"`
	KernelImage    string `json:"kernel_image"`
	Initramfs      string `json:"initramfs"`
	Cmdline        string `json:"cmdline"`
	Splash         string `json:"splash"`
	OSRelease      string `json:"os_release"`
	EFIStub        string `json:"efi_stub"`
	ESP            string `json:"esp"`
}

func NewBundle

func NewBundle() (bundle *Bundle, err error)

type Bundles

type Bundles map[string]*Bundle

func ReadBundleDatabase

func ReadBundleDatabase(dbpath string) (Bundles, error)

type LsblkEntry

type LsblkEntry struct {
	Parttype   string `json:"parttype"`
	Mountpoint string `json:"mountpoint"`
	Pttype     string `json:"pttype"`
	Fstype     string `json:"fstype"`
}

type LsblkRoot

type LsblkRoot struct {
	Blockdevices []LsblkEntry `json:"blockdevices"`
}

type SigningEntries

type SigningEntries map[string]*SigningEntry

func ReadFileDatabase

func ReadFileDatabase(dbpath string) (SigningEntries, error)

type SigningEntry

type SigningEntry struct {
	File       string `json:"file"`
	OutputFile string `json:"output_file"`
	Checksum   string `json:"checksum"`
}

Directories

Path Synopsis
cmd
tests

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL