Skip to content

Commit

Permalink
Secure Boot support for x64 - shim and mokmanager
Browse files Browse the repository at this point in the history
- Add and use Microsoft-signed shim from Ubuntu with MOK manager and
  fallback loader

- Migrate Batocera's syslinux EFI loaders to /boot/EFI/batocera/ with
  CSV for creation of EFI boot entry via fallback loader

- Self-sign the x64 syslinux EFI loader (with .sbat section required
  by new shim)

- Install self-signed syslinux EFI loader as "grubx86.efi" to be found
  by the shim infrastucture (no it's not actually grub)

- Install the self-signing public certificate, for end-user
  installation via MOK manager

- Script to generate self-signed EFI for cert regeneration (if needed)
  or for adaptation to other EFI binaries

- Install mokutil for command-line management of Machine Owner Keys
  and shim/mok behavior
  • Loading branch information
n2qz committed Oct 20, 2023
1 parent 8856274 commit 54181f1
Show file tree
Hide file tree
Showing 19 changed files with 170 additions and 13 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ make.log
package/batocera/emulationstation/batocera-emulationstation/keys.txt
.directory
*.po~
batocera-mok.key
2 changes: 2 additions & 0 deletions Config.in
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ menu "System"

menu "Boot"
source "$BR2_EXTERNAL_BATOCERA_PATH/package/batocera/boot/batocera-initramfs/Config.in"
source "$BR2_EXTERNAL_BATOCERA_PATH/package/batocera/boot/batocera-shim-signed-efi-x64/Config.in"
source "$BR2_EXTERNAL_BATOCERA_PATH/package/batocera/boot/batocera-syslinux-efi/Config.in"
source "$BR2_EXTERNAL_BATOCERA_PATH/package/batocera/boot/uboot-odroid-xu4/Config.in"
source "$BR2_EXTERNAL_BATOCERA_PATH/package/batocera/boot/uboot-odroid-goa/Config.in"
Expand Down Expand Up @@ -489,6 +490,7 @@ menu "Utils"
source "$BR2_EXTERNAL_BATOCERA_PATH/package/batocera/utils/vdpauinfo/Config.in"
source "$BR2_EXTERNAL_BATOCERA_PATH/package/batocera/utils/ledspicer/Config.in"
source "$BR2_EXTERNAL_BATOCERA_PATH/package/batocera/utils/innoextract/Config.in"
source "$BR2_EXTERNAL_BATOCERA_PATH/package/batocera/utils/mokutil/Config.in"
endmenu

menu "Cases"
Expand Down
1 change: 1 addition & 0 deletions board/batocera/x86/boot/bootia32.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
shimia32.efi,Batocera,,Batocera.linux READY TO RETRO
1 change: 1 addition & 0 deletions board/batocera/x86/boot/bootx64.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
shimx64.efi,Batocera,,Batocera.linux READY TO RETRO
41 changes: 34 additions & 7 deletions board/batocera/x86/create-boot-script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ BATOCERA_BINARIES_DIR=$6

mkdir -p "${BATOCERA_BINARIES_DIR}/boot/boot/syslinux" || exit 1
mkdir -p "${BATOCERA_BINARIES_DIR}/boot/EFI/BOOT" || exit 1
mkdir -p "${BATOCERA_BINARIES_DIR}/boot/EFI/batocera" || exit 1

# Batocera kernel, initrd, and root
cp "${BINARIES_DIR}/bzImage" "${BATOCERA_BINARIES_DIR}/boot/boot/linux" || exit 1
cp "${BINARIES_DIR}/initrd.gz" "${BATOCERA_BINARIES_DIR}/boot/boot/" || exit 1
cp "${BINARIES_DIR}/rootfs.squashfs" "${BATOCERA_BINARIES_DIR}/boot/boot/batocera.update" || exit 1
Expand All @@ -26,13 +28,38 @@ cp "${BOARD_DIR}/boot/syslinux.cfg" "${BATOCERA_BINARIES_DIR}/boot/boot/sy
cp "${BINARIES_DIR}/syslinux/menu.c32" "${BATOCERA_BINARIES_DIR}/boot/boot/syslinux/" || exit 1
cp "${BINARIES_DIR}/syslinux/libutil.c32" "${BATOCERA_BINARIES_DIR}/boot/boot/syslinux/" || exit 1

# What's this used by? My guess is that it's unused.
cp "${BOARD_DIR}/boot/syslinux.cfg" "${BATOCERA_BINARIES_DIR}/boot/EFI/" || exit 1
cp "${BOARD_DIR}/boot/syslinux.cfg" "${BATOCERA_BINARIES_DIR}/boot/EFI/BOOT/" || exit 1
cp "${BINARIES_DIR}/syslinux/efi64/menu.c32" "${BATOCERA_BINARIES_DIR}/boot/EFI/BOOT/" || exit 1
cp "${BINARIES_DIR}/syslinux/efi64/libutil.c32" "${BATOCERA_BINARIES_DIR}/boot/EFI/BOOT/" || exit 1
cp "${BINARIES_DIR}/syslinux/ldlinux.e32" "${BATOCERA_BINARIES_DIR}/boot/EFI/BOOT/" || exit 1
cp "${BINARIES_DIR}/syslinux/ldlinux.e64" "${BATOCERA_BINARIES_DIR}/boot/EFI/BOOT/" || exit 1
cp "${BINARIES_DIR}/syslinux/bootx64.efi" "${BATOCERA_BINARIES_DIR}/boot/EFI/BOOT/" || exit 1
cp "${BINARIES_DIR}/syslinux/bootia32.efi" "${BATOCERA_BINARIES_DIR}/boot/EFI/BOOT/" || exit 1

# Syslinux EFI loader with Batocera boot configuration
# https://github.com/rhboot/shim/blob/a1170bb00a116783cc6623b403e785d86b2f97d7/README.fallback
# https://www.rodsbooks.com/efi-bootloaders/fallback.html
cp "${BOARD_DIR}/boot/syslinux.cfg" "${BATOCERA_BINARIES_DIR}/boot/EFI/batocera/" || exit 1
cp "${BINARIES_DIR}/syslinux/efi64/menu.c32" "${BATOCERA_BINARIES_DIR}/boot/EFI/batocera/" || exit 1
cp "${BINARIES_DIR}/syslinux/efi64/libutil.c32" "${BATOCERA_BINARIES_DIR}/boot/EFI/batocera/" || exit 1
cp "${BINARIES_DIR}/syslinux/ldlinux.e32" "${BATOCERA_BINARIES_DIR}/boot/EFI/batocera/" || exit 1
cp "${BINARIES_DIR}/syslinux/ldlinux.e64" "${BATOCERA_BINARIES_DIR}/boot/EFI/batocera/" || exit 1
cp "${BINARIES_DIR}/syslinux/bootx64.efi" "${BATOCERA_BINARIES_DIR}/boot/EFI/batocera/grubx64.efi" || exit 1
cp "${BINARIES_DIR}/syslinux/batocera-mok.cer" "${BATOCERA_BINARIES_DIR}/boot/EFI/batocera/" || exit 1
cp "${BINARIES_DIR}/shim-signed/shimx64.efi" "${BATOCERA_BINARIES_DIR}/boot/EFI/batocera/" || exit 1
cp "${BINARIES_DIR}/shim-signed/shimx64.efi" "${BATOCERA_BINARIES_DIR}/boot/EFI/batocera/bootx64.efi" || exit 1
cp "${BINARIES_DIR}/shim-signed/mmx64.efi" "${BATOCERA_BINARIES_DIR}/boot/EFI/batocera/" || exit 1

# EFI boot manager entries to be created by fbx86.efi if missing
( printf '\xFF\xFE' ; iconv -t UCS-2 < "${BOARD_DIR}/boot/bootx64.csv" ) > "${BATOCERA_BINARIES_DIR}/boot/EFI/batocera/BOOTX64.CSV" || exit 1

# Fallback boot loader with secure boot shim and Machine Owner Key (MOK) Manager
cp "${BINARIES_DIR}/shim-signed/shimx64.efi" "${BATOCERA_BINARIES_DIR}/boot/EFI/BOOT/BOOTX64.EFI" || exit 1
cp "${BINARIES_DIR}/shim-signed/mmx64.efi" "${BATOCERA_BINARIES_DIR}/boot/EFI/BOOT/" || exit 1
cp "${BINARIES_DIR}/shim-signed/fbx64.efi" "${BATOCERA_BINARIES_DIR}/boot/EFI/BOOT/" || exit 1

# Another copy of the MOK cert with a hard-to-miss name at the top level, for ease-of-use
cp "${BINARIES_DIR}/syslinux/batocera-mok.cer" "${BATOCERA_BINARIES_DIR}/boot/ENROLL_THIS_KEY_IN_MOKMANAGER_batocera.cer" || exit 1

# Keep old 32-bit EFI loader untouched for now
# Many reports indicate it's not working, but we have nothing better for the moment
cp "${BINARIES_DIR}/syslinux/bootia32.efi" "${BATOCERA_BINARIES_DIR}/boot/EFI/BOOT/" || exit 1
# For when we have a fbia32.efi:
#( printf '\xFF\xFE' ; iconv -t UCS-2 < "${BOARD_DIR}/boot/bootia32.csv" ) > "${BATOCERA_BINARIES_DIR}/boot/EFI/batocera/BOOTIA32.CSV" || exit 1

exit 0
1 change: 1 addition & 0 deletions configs/batocera-x86_64.board
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ BR2_TARGET_SYSLINUX_MBR=y
BR2_TARGET_SYSLINUX_C32="menu.c32 libutil.c32"
BR2_PACKAGE_SDL_X11=y
BR2_PACKAGE_EFIBOOTMGR=y
BR2_PACKAGE_BATOCERA_SHIM_SIGNED_EFI_X64=y

BR2_PACKAGE_BATOCERA_SPLASH_MPV=y
30 changes: 30 additions & 0 deletions package/batocera/boot/batocera-shim-signed-efi-x64/COPYRIGHT
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Copyright 2012 Red Hat, Inc <[email protected]>

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the
distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.

Significant portions of this code are derived from Tianocore
(http://tianocore.sf.net) and are Copyright 2009-2012 Intel
Corporation.
6 changes: 6 additions & 0 deletions package/batocera/boot/batocera-shim-signed-efi-x64/Config.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
config BR2_PACKAGE_BATOCERA_SHIM_SIGNED_EFI_X64
bool "batocera-shim-signed-efi-x64"
help
Signed EFI shim binaries

https://launchpad.net/ubuntu/+source/shim-signed
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Locally computed:
sha256 b2d84b300e68ac2139afee3f9a609857ef80f12eed9218087ced4b31ecb7fd76 shim-signed_1.56+15.7-0ubuntu1_amd64.deb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
################################################################################
#
# batocera-shim-signed-efi-x64
#
################################################################################

BATOCERA_SHIM_SIGNED_EFI_X64_VERSION = 1.56+15.7-0ubuntu1
BATOCERA_SHIM_SIGNED_EFI_X64_SITE = https://launchpad.net/ubuntu/+archive/primary/+files
BATOCERA_SHIM_SIGNED_EFI_X64_SOURCE = shim-signed_$(BATOCERA_SHIM_SIGNED_EFI_X64_VERSION)_amd64.deb

define BATOCERA_SHIM_SIGNED_EFI_X64_EXTRACT_CMDS
mkdir -p $(@D)/shim-signed
dpkg-deb -R $(BATOCERA_SHIM_SIGNED_EFI_X64_DL_DIR)/$(BATOCERA_SHIM_SIGNED_EFI_X64_SOURCE) $(@D)/shim-signed
endef

define BATOCERA_SHIM_SIGNED_EFI_X64_BUILD_CMDS
endef

define BATOCERA_SHIM_SIGNED_EFI_X64_INSTALL_TARGET_CMDS
mkdir -p $(BINARIES_DIR)/shim-signed

cp $(@D)/shim-signed/usr/lib/shim/fbx64.efi $(BINARIES_DIR)/shim-signed/
cp $(@D)/shim-signed/usr/lib/shim/shimx64.efi.signed.latest $(BINARIES_DIR)/shim-signed/shimx64.efi
cp $(@D)/shim-signed/usr/lib/shim/mmx64.efi $(BINARIES_DIR)/shim-signed/
endef

$(eval $(generic-package))
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ endef

define BATOCERA_SYSLINUX_EFI_INSTALL_TARGET_CMDS
mkdir -p $(BINARIES_DIR)/syslinux/efi64
cp $(@D)/bootx64.efi $(BINARIES_DIR)/syslinux/
cp $(@D)/ldlinux.e64 $(BINARIES_DIR)/syslinux/
cp $(@D)/bootia32.efi $(BINARIES_DIR)/syslinux/
cp $(@D)/ldlinux.e32 $(BINARIES_DIR)/syslinux/
cp $(@D)/menu.c32 $(BINARIES_DIR)/syslinux/efi64
cp $(@D)/libutil.c32 $(BINARIES_DIR)/syslinux/efi64
cp $(@D)/bootx64.selfsigned.efi $(BINARIES_DIR)/syslinux/bootx64.efi
cp $(@D)/batocera-mok.cer $(BINARIES_DIR)/syslinux/
cp $(@D)/ldlinux.e64 $(BINARIES_DIR)/syslinux/
cp $(@D)/bootia32.efi $(BINARIES_DIR)/syslinux/
cp $(@D)/ldlinux.e32 $(BINARIES_DIR)/syslinux/
cp $(@D)/menu.c32 $(BINARIES_DIR)/syslinux/efi64
cp $(@D)/libutil.c32 $(BINARIES_DIR)/syslinux/efi64
endef

$(eval $(generic-package))
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDHTCCAgWgAwIBAgIUW06pOSneG9Fug5BfnVoAI3r8yugwDQYJKoZIhvcNAQEL
BQAwHTEbMBkGA1UEAwwSQmF0b2NlcmEubGludXggTU9LMCAXDTIzMTAyMDEzNTM1
OFoYDzIwNTMxMDEyMTM1MzU4WjAdMRswGQYDVQQDDBJCYXRvY2VyYS5saW51eCBN
T0swggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCfiMMTgJU6ZxK0HuQ/
AMeHm/s21i5yJZ/8GU9kLsJTUlznMelbmoOBtFF5ZIUk35eNfGQdWv9ZWE736bI0
mFITukju3aDSDyPmZvTAxRr6ejL4DKtmMi3rIpXoCzGLAm3F53vnmnjZPom0mLq4
FNSIbLeJwNma2GSZy3itadi3FBjIn7oTA3E6J0d10L20V8feOIFuX7mo+Mn9yfJm
1lRwJ+mD3qs+zBVWKod5XCDL7FpT3u5GuTlmTOpGjRfb46FZdQXbK8ejaPG6h4wm
LBLfBqCmNO4660JDs9uqbraQj7O9lM8WHrh+TDKD7NlrJ4VllztniDaDlL4TN8cM
cZk5AgMBAAGjUzBRMB0GA1UdDgQWBBQMIZZYWn98dvaSm0zZKjiw5PRDvjAfBgNV
HSMEGDAWgBQMIZZYWn98dvaSm0zZKjiw5PRDvjAPBgNVHRMBAf8EBTADAQH/MA0G
CSqGSIb3DQEBCwUAA4IBAQAf+8WxGJqV+5sjfRfiPVisOreIEhM0zlAwwonTy1aQ
tbVnS5w6//9c5alhdoUpamU8C/cDmqWjAVK/nW562jvWmn4FdnJ1g3y+W7GOrDss
tdXz4SXkscCXnJLgrLZxKW+T4dY0ytlhECNckVF+0D4VKQs14LVmssVoEWj5Q/HJ
UvUxxzjMIUv7hmg3cjhUvK9jQAXgnFQK0EFCSI+hPHSpk75+NjQX0kWKG1i26jrk
BG7nx/b9ufY9lgGQGCLi9f3RSja0JJtMmdHuCwTqHOzewLnf/lTXqzQjO0C8mdQC
THmc5RTQc0447LJGRC2YZb7/mqpIwdxFK33IKTsKL5/O
-----END CERTIFICATE-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
batocera,1,Batocera.linux,batocera,39,https://batocera.org/
Binary file not shown.
17 changes: 17 additions & 0 deletions package/batocera/boot/batocera-syslinux-efi/binaries/selfsign.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#! /bin/bash

# https://www.rodsbooks.com/efi-bootloaders/secureboot.html#signing

# Generate a signing certificate, and use it to self-sign the x64
# bootloader. This allows the end-user to import the certificate into
# the MOK store via mmx64.efi to bootstrap the Secure Boot flow.

# This is not run as part of the buildroot pipeline; it is included to
# document the process in case additional or updated self-signed EFI
# binaries are needed in the future.

openssl req -new -x509 -newkey rsa:2048 -keyout batocera-mok.key -out batocera-mok.crt -nodes -days 10950 -subj "/CN=Batocera.linux MOK/"
openssl x509 -in batocera-mok.crt -out batocera-mok.cer -outform DER
cp bootx64.efi /tmp/bootx64.sbat.efi
objcopy --set-section-alignment '.sbat=512' --add-section .sbat=batocera.csv --adjust-section-vma .sbat+10000000 /tmp/bootx64.sbat.efi
sbsign --key batocera-mok.key --cert batocera-mok.crt --output bootx64.selfsigned.efi /tmp/bootx64.sbat.efi
1 change: 1 addition & 0 deletions package/batocera/core/batocera-system/Config.in
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ config BR2_PACKAGE_BATOCERA_SYSTEM
select BR2_PACKAGE_SYNCTHING # sync files across multiple batoceras
select BR2_PACKAGE_RCLONE if BR2_PACKAGE_BATOCERA_TARGET_X86_64_ANY # sync files in the cloud (require x86_64)
select BR2_PACKAGE_BTOP # htop alternative
select BR2_PACKAGE_MOKUTIL if BR2_PACKAGE_BATOCERA_TARGET_X86_64_ANY # mokutil machine owner key utility

# Controllers
select BR2_PACKAGE_XONE if !BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_4_4 # xbox receiver (require linux >= 4.15)
Expand Down
6 changes: 6 additions & 0 deletions package/batocera/utils/mokutil/Config.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
config BR2_PACKAGE_MOKUTIL
bool "mokutil"
help
The utility to manipulate machines owner keys which managed in shim

https://github.com/lcp/mokutil
13 changes: 13 additions & 0 deletions package/batocera/utils/mokutil/mokutil.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
################################################################################
#
# mokutil
#
################################################################################

MOKUTIL_VERSION = 0.6.0
MOKUTIL_SITE = $(call github,lcp,mokutil,$(MOKUTIL_VERSION))
MOKUTIL_LICENSE = GPLv3
MOKUTIL_DEPENDENCIES = openssl efivar keyutils
MOKUTIL_AUTORECONF = YES

$(eval $(autotools-package))

0 comments on commit 54181f1

Please sign in to comment.