feat: enable secureboot

This commit is contained in:
Marcos Tischer Vallim 2024-09-06 15:43:10 -03:00
parent 87dfd9755f
commit 1e15c105ab
No known key found for this signature in database
GPG Key ID: 25CC9724E702C72F
3 changed files with 276 additions and 140 deletions

View File

@ -37,12 +37,7 @@ sudo apt-get install \
binutils \ binutils \
debootstrap \ debootstrap \
squashfs-tools \ squashfs-tools \
xorriso \ xorriso
grub-pc-bin \
grub-efi-amd64-bin \
mtools \
openssl \
sbsigntool
``` ```
```shell ```shell
@ -211,13 +206,13 @@ From this point we will be configuring the `live system`.
1. Configure keyboard 1. Configure keyboard
<p align="center"> <p align="center">
<img src="images/keyboard-configure-01.png"> <img src="images/keyboard-configure-01.png">
</p> </p>
<p align="center"> <p align="center">
<img src="images/keyboard-configure-02.png"> <img src="images/keyboard-configure-02.png">
</p> </p>
2. Console setup 2. Console setup

View File

@ -99,13 +99,13 @@ function check_config() {
function setup_host() { function setup_host() {
echo "=====> running setup_host ..." echo "=====> running setup_host ..."
sudo apt update sudo apt update
sudo apt install -y binutils debootstrap squashfs-tools xorriso grub-pc-bin grub-efi-amd64-bin mtools dosfstools unzip sudo apt install -y binutils debootstrap squashfs-tools xorriso dosfstools unzip
sudo mkdir -p chroot sudo mkdir -p chroot
} }
function debootstrap() { function debootstrap() {
echo "=====> running debootstrap ... will take a couple of minutes ..." echo "=====> running debootstrap ... will take a couple of minutes ..."
sudo debootstrap --arch=amd64 --variant=minbase $TARGET_UBUNTU_VERSION chroot $TARGET_UBUNTU_MIRROR sudo debootstrap --arch=amd64 --variant=minbase $TARGET_UBUNTU_VERSION chroot $TARGET_UBUNTU_MIRROR
} }
function run_chroot() { function run_chroot() {
@ -136,120 +136,23 @@ function run_chroot() {
function build_iso() { function build_iso() {
echo "=====> running build_iso ..." echo "=====> running build_iso ..."
rm -rf image # move image artifacts
mkdir -p image/{casper,isolinux,install} sudo mv chroot/{image,certificates} .
# copy kernel files
sudo cp chroot/boot/vmlinuz-**-**-generic image/casper/vmlinuz
sudo cp chroot/boot/initrd.img-**-**-generic image/casper/initrd
# memtest86
sudo cp chroot/boot/memtest86+.bin image/install/memtest86+
wget --progress=dot https://www.memtest86.com/downloads/memtest86-usb.zip -O image/install/memtest86-usb.zip
unzip -p image/install/memtest86-usb.zip memtest86-usb.img > image/install/memtest86
rm -f image/install/memtest86-usb.zip
# grub
touch image/ubuntu
cat <<EOF > image/isolinux/grub.cfg
search --set=root --file /ubuntu
insmod all_video
set default="0"
set timeout=30
menuentry "${GRUB_LIVEBOOT_LABEL}" {
linux /casper/vmlinuz boot=casper nopersistent toram quiet splash ---
initrd /casper/initrd
}
menuentry "${GRUB_INSTALL_LABEL}" {
linux /casper/vmlinuz boot=casper only-ubiquity quiet splash ---
initrd /casper/initrd
}
menuentry "Check disc for defects" {
linux /casper/vmlinuz boot=casper integrity-check quiet splash ---
initrd /casper/initrd
}
menuentry "Test memory Memtest86+ (BIOS)" {
linux16 /install/memtest86+
}
menuentry "Test memory Memtest86 (UEFI, long load time)" {
insmod part_gpt
insmod search_fs_uuid
insmod chain
loopback loop /install/memtest86
chainloader (loop,gpt1)/efi/boot/BOOTX64.efi
}
EOF
# generate manifest
sudo chroot chroot dpkg-query -W --showformat='${Package} ${Version}\n' | sudo tee image/casper/filesystem.manifest
sudo cp -v image/casper/filesystem.manifest image/casper/filesystem.manifest-desktop
for pkg in $TARGET_PACKAGE_REMOVE; do
sudo sed -i "/$pkg/d" image/casper/filesystem.manifest-desktop
done
# compress rootfs # compress rootfs
sudo mksquashfs chroot image/casper/filesystem.squashfs \ sudo mksquashfs chroot image/casper/filesystem.squashfs \
-noappend -no-duplicates -no-recovery \ -noappend -no-duplicates -no-recovery \
-wildcards \ -wildcards \
-comp xz -b 1M -Xdict-size 100% \
-e "var/cache/apt/archives/*" \ -e "var/cache/apt/archives/*" \
-e "root/*" \ -e "root/*" \
-e "root/.*" \ -e "root/.*" \
-e "tmp/*" \ -e "tmp/*" \
-e "tmp/.*" \ -e "tmp/.*" \
-e "swapfile" -e "swapfile"
printf $(sudo du -sx --block-size=1 chroot | cut -f1) > image/casper/filesystem.size
# create diskdefines # write the filesystem.size
cat <<EOF > image/README.diskdefines printf $(sudo du -sx --block-size=1 chroot | cut -f1) | sudo tee image/casper/filesystem.size
#define DISKNAME ${GRUB_LIVEBOOT_LABEL}
#define TYPE binary
#define TYPEbinary 1
#define ARCH amd64
#define ARCHamd64 1
#define DISKNUM 1
#define DISKNUM1 1
#define TOTALNUM 0
#define TOTALNUM0 1
EOF
# create iso image
pushd $SCRIPT_DIR/image
grub-mkstandalone \
--format=x86_64-efi \
--output=isolinux/bootx64.efi \
--locales="" \
--fonts="" \
"boot/grub/grub.cfg=isolinux/grub.cfg"
(
cd isolinux && \
dd if=/dev/zero of=efiboot.img bs=1M count=10 && \
sudo mkfs.vfat efiboot.img && \
LC_CTYPE=C mmd -i efiboot.img efi efi/boot && \
LC_CTYPE=C mcopy -i efiboot.img ./bootx64.efi ::efi/boot/
)
grub-mkstandalone \
--format=i386-pc \
--output=isolinux/core.img \
--install-modules="linux16 linux normal iso9660 biosdisk memdisk search tar ls" \
--modules="linux16 linux normal iso9660 biosdisk search" \
--locales="" \
--fonts="" \
"boot/grub/grub.cfg=isolinux/grub.cfg"
cat /usr/lib/grub/i386-pc/cdboot.img isolinux/core.img > isolinux/bios.img
sudo /bin/bash -c "(find . -type f -print0 | xargs -0 md5sum | grep -v -e 'md5sum.txt' -e 'bios.img' -e 'efiboot.img' > md5sum.txt)"
sudo xorriso \ sudo xorriso \
-as mkisofs \ -as mkisofs \
@ -262,7 +165,7 @@ EOF
-boot-info-table \ -boot-info-table \
--eltorito-catalog boot/grub/boot.cat \ --eltorito-catalog boot/grub/boot.cat \
--grub2-boot-info \ --grub2-boot-info \
--grub2-mbr /usr/lib/grub/i386-pc/boot_hybrid.img \ --grub2-mbr ../chroot/usr/lib/grub/i386-pc/boot_hybrid.img \
-eltorito-alt-boot \ -eltorito-alt-boot \
-e EFI/efiboot.img \ -e EFI/efiboot.img \
-no-emul-boot \ -no-emul-boot \

View File

@ -7,7 +7,7 @@ set -u # treat unset variable as error
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
CMD=(setup_host install_pkg finish_up) CMD=(setup_host install_pkg build_image finish_up)
function help() { function help() {
# if $1 is set, use $1 as headline message in help() # if $1 is set, use $1 as headline message in help()
@ -100,23 +100,26 @@ function install_pkg() {
# install live packages # install live packages
apt-get install -y \ apt-get install -y \
sudo \ sudo \
ubuntu-standard \ ubuntu-standard \
casper \ casper \
discover \ discover \
laptop-detect \ laptop-detect \
os-prober \ os-prober \
network-manager \ network-manager \
resolvconf \ resolvconf \
net-tools \ net-tools \
wireless-tools \ wireless-tools \
wpagui \ wpagui \
grub-common \ locales \
grub-gfxpayload-lists \ grub-common \
grub-pc \ grub-gfxpayload-lists \
grub-pc-bin \ grub-pc \
grub2-common \ grub-pc-bin \
locales grub2-common \
grub-efi-amd64-signed \
shim-signed \
binutils
case $TARGET_UBUNTU_VERSION in case $TARGET_UBUNTU_VERSION in
"focal" | "bionic") "focal" | "bionic")
@ -132,11 +135,11 @@ function install_pkg() {
# graphic installer - ubiquity # graphic installer - ubiquity
apt-get install -y \ apt-get install -y \
ubiquity \ ubiquity \
ubiquity-casper \ ubiquity-casper \
ubiquity-frontend-gtk \ ubiquity-frontend-gtk \
ubiquity-slideshow-ubuntu \ ubiquity-slideshow-ubuntu \
ubiquity-ubuntu-artwork ubiquity-ubuntu-artwork
# Call into config function # Call into config function
customize_image customize_image
@ -164,6 +167,241 @@ EOF
apt-get clean -y apt-get clean -y
} }
function build_image() {
echo "=====> running build_image ..."
rm -rf /image
mkdir -p /image/{casper,isolinux,install}
pushd /image
# copy kernel files
cp /boot/vmlinuz-**-**-generic casper/vmlinuz
cp /boot/initrd.img-**-**-generic casper/initrd
# memtest86
cp /boot/memtest86+.bin install/memtest86+
# memtest86++
wget --progress=dot https://www.memtest86.com/downloads/memtest86-usb.zip -O install/memtest86-usb.zip
unzip -p install/memtest86-usb.zip memtest86-usb.img > install/memtest86
rm -f install/memtest86-usb.zip
# grub
touch ubuntu
cat <<EOF > isolinux/grub.cfg
search --set=root --file /ubuntu
insmod all_video
set default="0"
set timeout=30
menuentry "Try Ubuntu FS without installing" {
linux /casper/vmlinuz boot=casper nopersistent toram quiet splash ---
initrd /casper/initrd
}
menuentry "Install Ubuntu FS" {
linux /casper/vmlinuz boot=casper only-ubiquity quiet splash ---
initrd /casper/initrd
}
menuentry "Check disc for defects" {
linux /casper/vmlinuz boot=casper integrity-check quiet splash ---
initrd /casper/initrd
}
menuentry "Test memory Memtest86+ (BIOS)" {
linux16 /install/memtest86+
}
menuentry "Test memory Memtest86 (UEFI, long load time)" {
insmod part_gpt
insmod search_fs_uuid
insmod chain
loopback loop /install/memtest86
chainloader (loop,gpt1)/efi/boot/BOOTX64.efi
}
EOF
# generate manifest
dpkg-query -W --showformat='${Package} ${Version}\n' | sudo tee casper/filesystem.manifest
cp -v casper/filesystem.manifest casper/filesystem.manifest-desktop
for pkg in $TARGET_PACKAGE_REMOVE; do
sudo sed -i "/$pkg/d" casper/filesystem.manifest-desktop
done
# create diskdefines
cat <<EOF > README.diskdefines
#define DISKNAME ${GRUB_LIVEBOOT_LABEL}
#define TYPE binary
#define TYPEbinary 1
#define ARCH amd64
#define ARCHamd64 1
#define DISKNUM 1
#define DISKNUM1 1
#define TOTALNUM 0
#define TOTALNUM0 1
EOF
# create certificates
rm -rf /certificates
mkdir /certificates
pushd /certificates
# create the certificate template
cat <<EOF > config.conf
[ req ]
default_bits = 2048
default_md = sha256
distinguished_name = dn
prompt = no
[ dn ]
C = BR
ST = SP
L = Campinas
O = Scratch, Labs
OU = Labs
CN = \${ENV::CN}
[ root ]
basicConstraints = critical,CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
keyUsage = critical,digitalSignature,keyEncipherment,keyCertSign,cRLSign
[ ca ]
basicConstraints = critical,CA:TRUE,pathlen:0
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
keyUsage = critical,digitalSignature,keyEncipherment,keyCertSign,cRLSign
[ db ]
subjectKeyIdentifier = hash
basicConstraints = critical,CA:FALSE
keyUsage = critical,keyEncipherment,dataEncipherment
authorityKeyIdentifier = keyid,issuer:always
EOF
# create the Root CA certificate
CN="Root, CA" \
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout root.key \
-days 3650 \
-config config.conf \
-extensions root \
-out root.pem
# create the intermediate CA certificate
CN="Ubuntu live from scratch, CA" \
openssl req -newkey rsa:2048 -nodes \
-keyout ca.key \
-config config.conf \
-out ca.pem
# create Database (DB) request certificate
CN="Ubuntu live from scratch, Database" \
openssl req -newkey rsa:2048 -nodes \
-keyout db.key \
-config config.conf \
-out db.pem
# sign the intermediate CA certificate with the Root CA certificate
CN="Ubuntu live from scratch, CA" \
openssl x509 -req \
-extfile config.conf \
-extensions ca \
-in ca.pem \
-CA root.pem \
-CAkey root.key \
-CAcreateserial \
-out ca.pem \
-days 3650 -sha256
# sign Database (DB) certificate using your own CA
CN="Ubuntu live from scratch, Database" \
openssl x509 -req \
-extfile config.conf \
-extensions db \
-in db.pem \
-CA ca.pem \
-CAkey ca.key \
-CAcreateserial \
-out db.pem \
-days 3650 -sha256
# create the intermediate CA certificate chain
cat ca.pem root.pem > ca-chain.pem
# verify the signatures
openssl verify -CAfile ca-chain.pem db.pem
# create DER version of our public key (CA)
openssl x509 -outform DER -in ca.pem -out ca.cer
popd # return to image directory
# create SBAT file
cat <<EOF > isolinux/sbat.csv
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
grub,1,Free Software Foundation,grub,2.04,https://www.gnu.org/software/grub/
EOF
# create a grub UEFI image
grub-mkstandalone \
--format=x86_64-efi \
--output=isolinux/grubx64.efi \
--locales="" \
--fonts="" \
"boot/grub/grub.cfg=isolinux/grub.cfg"
# fix secure boot grub
sed -i 's/SecureBoot/SecureB00t/' isolinux/grubx64.efi
# add .sbat sections
objcopy --set-section-alignment '.sbat=512' --add-section .sbat=isolinux/sbat.csv isolinux/grubx64.efi --adjust-section-vma .sbat+10000000
# UEFI secure boot signing
sbsign --key /certificates/db.key --cert /certificates/db.pem --output isolinux/grubx64.efi isolinux/grubx64.efi
# create a FAT16 UEFI boot disk image containing the EFI bootloader
(
cd isolinux && \
dd if=/dev/zero of=efiboot.img bs=1M count=10 && \
mkfs.vfat -F 16 efiboot.img && \
LC_CTYPE=C mmd -i efiboot.img certificates efi efi/boot && \
LC_CTYPE=C mcopy -i efiboot.img /usr/lib/shim/shimx64.efi.signed.previous ::efi/boot/bootx64.efi && \
LC_CTYPE=C mcopy -i efiboot.img /usr/lib/shim/mmx64.efi ::efi/boot/mmx64.efi && \
LC_CTYPE=C mcopy -i efiboot.img isolinux/grubx64.efi ::efi/boot/grubx64.efi && \
LC_CTYPE=C mcopy -i efiboot.img /certificates/ca.cer ::certificates/
)
# create a grub BIOS image
grub-mkstandalone \
--format=i386-pc \
--output=isolinux/core.img \
--install-modules="linux16 linux normal iso9660 biosdisk memdisk search tar ls" \
--modules="linux16 linux normal iso9660 biosdisk search" \
--locales="" \
--fonts="" \
"boot/grub/grub.cfg=isolinux/grub.cfg"
# combine a bootable Grub cdboot.img
cat /usr/lib/grub/i386-pc/cdboot.img isolinux/core.img > isolinux/bios.img
# generate md5sum.txt
/bin/bash -c "(find . -type f -print0 | xargs -0 md5sum | grep -v -e 'md5sum.txt' -e 'bios.img' -e 'efiboot.img' > md5sum.txt)"
popd # return initial directory
}
function finish_up() { function finish_up() {
echo "=====> finish_up" echo "=====> finish_up"