Compare commits

...

10 commits

Author SHA1 Message Date
Tobias Strobel b9a74a70d7 Build own initrd inspired by mkiso-initrd 2023-12-21 00:14:35 +01:00
Tobias Strobel 7edd716eb8 Separate repart.d Definitions per Image 2023-12-20 21:57:39 +01:00
Tobias Strobel ce5ff24e8c Miscellaneous improvements 2023-12-20 21:56:44 +01:00
Tobias Strobel 58c1fb804a Use RSA 2048 for Secure Boot 2023-12-20 21:53:18 +01:00
Tobias Strobel 45d2d697f6 Define own "base" packages 2023-12-20 18:37:18 +01:00
Tobias Strobel 83220841c8 Rearrange Seed and SourceDateEpoch 2023-12-20 18:36:04 +01:00
Tobias Strobel 66c47bf84a Separate repart.d definitions per image 2023-12-20 18:33:39 +01:00
Tobias Strobel fbfc89bfdf Separate keys for verity and secure boot 2023-12-20 16:40:22 +01:00
Tobias Strobel 70169efc27 Inline NoExtract options in pacman.conf 2023-12-20 15:23:58 +01:00
Tobias Strobel 983bebd0d3 Add NoExtract directives for pacman 2023-12-19 20:09:20 +01:00
42 changed files with 465 additions and 44 deletions

6
.gitignore vendored
View file

@ -1,9 +1,11 @@
!mkosi.builddir/.gitkeep
mkosi.builddir/*
!mkosi.cache/.gitkeep
mkosi.cache/*
!mkosi.output/.gitkeep
mkosi.output/*
!mkosi.builddir/.gitkeep
mkosi.builddir/*
!mkosi.tools/.gitkeep
mkosi.tools/*
# Build version of the image
*.version

View file

@ -1,15 +1,23 @@
[Distribution]
Distribution=arch
Architecture=x86-64
CacheOnly=true
[Config]
Images=server
[Output]
# For Reproducible Builds
Seed=834dd70f55be43cc9934b20fc0b7f7be
[Validation]
SecureBoot=true
SecureBootKey=signing-keys/rafeOS_mok.key
SecureBootCertificate=signing-keys/rafeOS_mok.crt
# Use RSA 2048 keys for wide UEFI compatibility
SecureBootKey=signing-keys/rafeOS_secureboot.key
SecureBootCertificate=signing-keys/rafeOS_secureboot.crt
SignExpectedPcr=true
VerityKey=signing-keys/rafeOS_mok.key
VerityCertificate=signing-keys/rafeOS_mok.crt
# Use modern EC keys
VerityKey=signing-keys/rafeOS_verity.key
VerityCertificate=signing-keys/rafeOS_verity.crt
Checksum=true
[Host]

View file

@ -3,16 +3,40 @@ Format=directory
[Content]
Bootable=no
SourceDateEpoch=0
MakeInitrd=no
CleanPackageMetadata=no
Packages=
# Minimal package set to define a basic Arch Linux installation
base
# Modular initramfs image creation utility
mkinitcpio
# Based on "base" group, without pacman, mkinitcpio and archlinux-keyring
bash
bzip2
coreutils
file
filesystem
findutils
gawk
gcc-libs
gettext
glibc
grep
gzip
iproute2
iputils
licenses
pciutils
procps-ng
psmisc
sed
shadow
tar
util-linux
xz
# system and service manager
systemd
# systemd: show QR codes
# sysvinit compat for systemd
systemd-sysvcompat
# systemd: show QR codes (systemd-bsod)
qrencode
# systemd: unlocking LUKS2 volumes with FIDO2 token
libfido2
@ -50,4 +74,4 @@ Packages=
# Programmable completion for the bash shell
bash-completion
# Fork of Vim aiming to improve user experience, plugins, and GUIs
neovim
neovim

View file

@ -1 +1,5 @@
enable apparmor.service
# Load all AppArmor profiles on startup
enable apparmor.service
# Displays boot-time emergency log message in full screen.
enable systemd-bsod.service

View file

@ -0,0 +1,12 @@
# vim:set ft=sh
HOOKS=(
systemd
keyboard
modconf
kms
block
sd-vconsole
sd-encrypt
filesystems
fsck
)

View file

@ -0,0 +1,8 @@
# mkinitcpio preset file for the '%PKGBASE%' package
ALL_kver="/boot/vmlinuz-%PKGBASE%"
ALL_microcode=(/boot/*-ucode.img)
PRESETS=('default')
default_image="/boot/initramfs-%PKGBASE%.img"

View file

@ -0,0 +1 @@
KEYMAP=de

View file

@ -0,0 +1,88 @@
# Inspired by https://github.com/systemd/mkosi/tree/main/mkosi/resources/mkosi-initrd
[Output]
Format=cpio
[Content]
Bootable=no
SourceDateEpoch=0
MakeInitrd=yes
CleanPackageMetadata=yes
Packages=
systemd
util-linux
# for emergency logins
bash
# Make "systemctl" nicer to use
less
# Various libraries that are dlopen'ed by systemd
libfido2
tpm2-tss
p11-kit
# Filesystem toolt
erofs-utils
btrfs-progs
e2fsprogs
# For compressed keymap unpacking by loadkeys
gzip
# Configure locale explicitly so that all other locale data is stripped on distros whose package manager supports it.
Locale=C.UTF-8
WithDocs=no
# Make sure various core modules are always included in the initrd.
KernelModulesInclude=
btrfs
dm-crypt
dm-integrity
dm-verity
erofs
ext4
loop
overlay
vfat
RemoveFiles=
# we don't need this after the binary catalogs have been built
/usr/lib/systemd/catalog
/etc/udev/hwdb.d
/usr/lib/udev/hwdb.d
# this is not needed by anything updated in the last 20 years
/etc/services
# Including kernel images in the initrd is generally not useful.
# This also stops mkosi from extracting the kernel image out of the image as a separate output.
/usr/lib/modules/*/vmlinuz*
/usr/lib/modules/*/System.map
# Arch Linux doesn't split their gcc-libs package so we manually remove
# unneeded stuff here to make sure it doesn't end up in the initrd.
/usr/lib/libgfortran.so*
/usr/lib/libgo.so*
/usr/lib/libgomp.so*
/usr/lib/libgphobos.so*
/usr/lib/libobjc.so*
/usr/lib/libasan.so*
/usr/lib/libtsan.so*
/usr/lib/liblsan.so*
/usr/lib/libubsan.so*
/usr/lib/libstdc++.so*
/usr/lib/libgdruntime.so*
# Remove all files that are only required for development.
/usr/lib/*.a
/usr/include/*
/usr/share/i18n/*
/usr/share/hwdata/*
/usr/share/iana-etc/*
/usr/share/doc/*
/usr/share/man/*
/usr/share/locale/*
/usr/share/info/*
/usr/share/gtk-doc/*
[Validation]
SecureBoot=false
SignExpectedPcr=false
Checksum=false

View file

@ -0,0 +1,2 @@
# Make sure that services are disabled by default.
disable *

View file

@ -0,0 +1,2 @@
[Service]
ImportCredential=cryptsetup.*

View file

@ -0,0 +1,7 @@
# Copied from https://github.com/dracutdevs/dracut/blob/059/modules.d/90dm/11-dm.rules
SUBSYSTEM!="block", GOTO="dm_end"
KERNEL!="dm-[0-9]*", GOTO="dm_end"
ACTION!="add|change", GOTO="dm_end"
OPTIONS+="db_persist"
LABEL="dm_end"

View file

@ -1,4 +1,5 @@
[Config]
Dependencies=initrd
Dependencies=base
[Output]
@ -8,14 +9,14 @@ ManifestFormat=json,changelog
ImageId=rafeOS
SectorSize=4096
CompressOutput=xz
# For Reproducible Builds
Seed=834dd70f55be43cc9934b20fc0b7f7be
[Content]
Bootable=yes
SourceDateEpoch=0
Autologin=yes
BaseTrees=../../mkosi.output/base/
Initrds=../../mkosi.output/initrd
CleanPackageMetadata=yes
Packages=
# Control and monitor S.M.A.R.T. enabled ATA and SCSI Hard Drives
smartmontools
@ -29,7 +30,13 @@ KernelCommandLine=
rd.shell=0
# prevents access to a shell if the root is corrupt
rd.emergency=reboot
# prevents untrusted code from running (the default behavior will just print an error to dmesg)
systemd.verity_root_options=panic-on-corruption
# reboots system 30 seconds after a kernel panic
panic=30
# enable apparmor
lsm=landlock,lockdown,yama,integrity,apparmor,bpf audit=1 audit_backlog_limit=256
# enable apparmor (enables kernel lockdown mode, requires signed kernel modules)
lsm=landlock,lockdown,yama,integrity,apparmor,bpf audit=1 audit_backlog_limit=256
# enable automatic unlock of rootfs via TPM2 security chip
rd.luks.options=tpm2-device=auto
# enable unlock of rootfs via FIDO2 security token
rd.luks.options=fido2-device=auto

View file

@ -0,0 +1,18 @@
[Partition]
Type=root
Format=btrfs
FactoryReset=true
Label=%M-root
Encrypt=key-file
MakeDirectories=/etc
MakeDirectories=/var
MakeDirectories=/var/log
MakeDirectories=/var/tmp
MakeDirectories=/srv
MakeDirectories=/home
Subvolumes=/etc
Subvolumes=/var
Subvolumes=/var/log
Subvolumes=/var/tmp
Subvolumes=/srv
Subvolumes=/home

View file

@ -0,0 +1,6 @@
[Partition]
Type=esp
SizeMinBytes=1G
SizeMaxBytes=1G
Format=vfat
CopyFiles=/efi:/

View file

@ -1,5 +1,6 @@
[Config]
Dependencies=base
Dependencies=initrd
[Output]
Format=disk
@ -8,14 +9,14 @@ ManifestFormat=json,changelog
ImageId=rafeOS
SectorSize=4096
CompressOutput=xz
# For Reproducible Builds
Seed=834dd70f55be43cc9934b20fc0b7f7be
[Content]
Bootable=yes
SourceDateEpoch=0
Autologin=yes
BaseTrees=../../mkosi.output/base/
Initrds=../../mkosi.output/rafeOS-initrd
CleanPackageMetadata=yes
Packages=
# A utility for reading man pages
man-db

View file

@ -0,0 +1,5 @@
[Partition]
Type=esp
CopyBlocks=auto
SizeMinBytes=1G
SizeMaxBytes=1G

View file

@ -0,0 +1,5 @@
[Partition]
Type=usr
CopyBlocks=auto
SizeMinBytes=3G
SizeMaxBytes=3G

View file

@ -0,0 +1,5 @@
[Partition]
Type=usr-verity
CopyBlocks=auto
SizeMinBytes=256M
SizeMaxBytes=256M

View file

@ -0,0 +1,5 @@
[Partition]
Type=usr-verity-sig
CopyBlocks=auto
SizeMinBytes=16K
SizeMaxBytes=16K

View file

@ -0,0 +1,5 @@
[Partition]
Type=usr
Label=_empty
SizeMinBytes=3G
SizeMaxBytes=3G

View file

@ -0,0 +1,5 @@
[Partition]
Type=usr-verity
Label=_empty
SizeMinBytes=256M
SizeMaxBytes=256M

View file

@ -0,0 +1,5 @@
[Partition]
Type=usr-verity-sig
Label=_empty
SizeMinBytes=16K
SizeMaxBytes=16K

View file

@ -0,0 +1,6 @@
[Partition]
Type=esp
SizeMinBytes=1G
SizeMaxBytes=1G
Format=vfat
CopyFiles=/efi:/

View file

@ -0,0 +1,10 @@
[Partition]
Type=usr
Label=%M-%W_%A
SizeMinBytes=5G
SizeMaxBytes=5G
Minimize=best
Verity=data
VerityMatchKey=usr
Format=erofs
CopyFiles=/usr:/

View file

@ -0,0 +1,10 @@
[Partition]
Type=usr-verity
Label=%M-%W_%A
SizeMinBytes=256M
SizeMaxBytes=256M
Minimize=best
Verity=hash
VerityMatchKey=usr
VerityDataBlockSizeBytes=4096
VerityHashBlockSizeBytes=4096

View file

@ -0,0 +1,5 @@
[Partition]
Type=usr-verity-sig
Label=%M-%W_%A
Verity=signature
VerityMatchKey=usr

View file

@ -1,8 +0,0 @@
[Partition]
Type=esp
SizeMinBytes=1G
SizeMaxBytes=1G
Format=vfat
CopyFiles=/efi:/
ExcludeFilesTarget=/efi/EFI/systemd/systemd-bootia32.efi
ExcludeFilesTarget=/efi/EFI/BOOT/BOOTIA32.EFI

View file

@ -0,0 +1,142 @@
#
# /etc/pacman.conf
#
# See the pacman.conf(5) manpage for option and repository directives
#
# GENERAL OPTIONS
#
[options]
# The following paths are commented out with their default values listed.
# If you wish to use different paths, uncomment and update the paths.
#RootDir = /
#DBPath = /var/lib/pacman/
#CacheDir = /var/cache/pacman/pkg/
#LogFile = /var/log/pacman.log
#GPGDir = /etc/pacman.d/gnupg/
#HookDir = /etc/pacman.d/hooks/
HoldPkg = pacman glibc
#XferCommand = /usr/bin/curl -L -C - -f -o %o %u
#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u
#CleanMethod = KeepInstalled
Architecture = auto
# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
#IgnorePkg =
#IgnoreGroup =
#NoUpgrade =
#NoExtract =
# Prevent the installation of all but English, German and general locales
NoExtract = usr/share/locale/*
NoExtract = !usr/share/locale/en*
NoExtract = !usr/share/locale/de
NoExtract = !usr/share/locale/locale.*
NoExtract = usr/share/i18n/locales/*
NoExtract = !usr/share/i18n/locales/en_??
NoExtract = !usr/share/i18n/locales/de_??
NoExtract = !usr/share/i18n/locales/i18n*
NoExtract = !usr/share/i18n/locales/iso*
NoExtract = !usr/share/i18n/locales/trans*
NoExtract = !usr/share/i18n/locales/C
NoExtract = !usr/share/i18n/locales/POSIX
# Prevent the installation of all but English and German man pages
NoExtract = usr/share/man/*
NoExtract = !usr/share/man/man*
NoExtract = !usr/share/man/de
# Prevent the installation of all but English and German help content
NoExtract = usr/share/help/*
NoExtract = !usr/share/help/en_??
NoExtract = !usr/share/help/de
# Prevent the installation of all the HTML documentation in GTK applications
NoExtract = usr/share/gtk-doc/html/*
# Prevent the installation of all but English and German content in Qt applications
NoExtract = usr/share/*/translations/*.qm
NoExtract = usr/share/*/nls/*.qm
NoExtract = usr/share/qt/phrasebooks/*.qph
NoExtract = usr/share/qt/translations/*.pak
NoExtract = !*/en-US.pak
NoExtract = !*/de.pak
# Prevent the installation of all but English and German content in Electron applications
NoExtract = usr/share/*/locales/*.pak
NoExtract = opt/*/locales/*.pak
NoExtract = usr/lib/*/locales/*.pak
NoExtract = !*/en-US.pak
NoExtract = !*/de.pak
# Prevent the installation of English files in LibreOffice
NoExtract = usr/lib/libreoffice/help/en-US/*
# Misc options
#UseSyslog
#Color
#NoProgressBar
CheckSpace
#VerbosePkgLists
ParallelDownloads = 5
# By default, pacman accepts packages signed by keys that its local keyring
# trusts (see pacman-key and its man page), as well as unsigned packages.
SigLevel = Required DatabaseOptional
LocalFileSigLevel = Optional
#RemoteFileSigLevel = Required
# NOTE: You must run `pacman-key --init` before first using pacman; the local
# keyring can then be populated with the keys of all official Arch Linux
# packagers with `pacman-key --populate archlinux`.
#
# REPOSITORIES
# - can be defined here or included from another file
# - pacman will search repositories in the order defined here
# - local/custom mirrors can be added here or in separate files
# - repositories listed first will take precedence when packages
# have identical names, regardless of version number
# - URLs will have $repo replaced by the name of the current repo
# - URLs will have $arch replaced by the name of the architecture
#
# Repository entries are of the format:
# [repo-name]
# Server = ServerName
# Include = IncludePath
#
# The header [repo-name] is crucial - it must be present and
# uncommented to enable the repo.
#
# The testing repositories are disabled by default. To enable, uncomment the
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.
#[core-testing]
#Include = /etc/pacman.d/mirrorlist
[core]
Include = /etc/pacman.d/mirrorlist
#[extra-testing]
#Include = /etc/pacman.d/mirrorlist
[extra]
Include = /etc/pacman.d/mirrorlist
# If you want to run 32 bit applications on your x86_64 system,
# enable the multilib repositories as required here.
#[multilib-testing]
#Include = /etc/pacman.d/mirrorlist
#[multilib]
#Include = /etc/pacman.d/mirrorlist
# An example of a custom package repository. See the pacman manpage for
# tips on creating your own repositories.
#[custom]
#SigLevel = Optional TrustAll
#Server = file:///home/custompkgs

View file

@ -4,6 +4,8 @@
# P-384 curve (prime384v1) for key generation.
#
# UEFI Specification: https://uefi.org/specs/UEFI/2.10/32_Secure_Boot_and_Driver_Signing.html#firmware-os-crypto-algorithm-exchange
#
# Tip: View certificate content with "openssl x509 -noout -text -in *secureboot.crt"
set -eu
@ -13,10 +15,11 @@ generate_key_pair() {
# Parameters
FILENAME_PREFIX="$1"
SUBJECT="$2"
KEY_ALG="$3"
# Check if parameters are provided
if [ -z "$FILENAME_PREFIX" ] || [ -z "$SUBJECT" ]; then
echo "Usage: generate_key_pair <filename_prefix> <subject>"
if [ -z "$FILENAME_PREFIX" ] || [ -z "$SUBJECT" ] || [ -z "$KEY_ALG" ]; then
echo "Usage: generate_key_pair <filename_prefix> <subject> <rsa|ec>"
exit 2
fi
@ -41,38 +44,66 @@ generate_key_pair() {
chmod 0400 "$PRIVATE_KEY_FILE" "$CERTIFICATE_FILE"
else
# Neither private key nor certificate exists, generate both
openssl req -newkey ec \
-pkeyopt ec_paramgen_curve:P-384 -pkeyopt ec_param_enc:named_curve \
-noenc -keyout "$PRIVATE_KEY_FILE" \
-new -x509 -sha256 \
-days "$CERT_VALIDITY_DAYS" \
-subj "$SUBJECT" \
-out "$CERTIFICATE_FILE"
case "$KEY_ALG" in
"rsa")
# Legacy RSA 2048, i.e. for wide compatibility UEFI Secure Boot keys
openssl req -newkey rsa:2048 \
-noenc -keyout "$PRIVATE_KEY_FILE" \
-new -x509 -sha256 \
-days "$CERT_VALIDITY_DAYS" \
-subj "$SUBJECT" \
-out "$CERTIFICATE_FILE"
;;
"ec")
# Modern P-348 EC Key
openssl req -newkey ec \
-pkeyopt ec_paramgen_curve:P-384 -pkeyopt ec_param_enc:named_curve \
-noenc -keyout "$PRIVATE_KEY_FILE" \
-new -x509 -sha256 \
-days "$CERT_VALIDITY_DAYS" \
-subj "$SUBJECT" \
-out "$CERTIFICATE_FILE"
;;
*)
echo "Error: Invalid value for <secureboot|verity|all>."
exit 1
;;
esac
echo "$FILENAME_PREFIX: Private key and certificate generated with filenames: $PRIVATE_KEY_FILE, $CERTIFICATE_FILE."
# Set permissions for the new files
chmod 0400 "$PRIVATE_KEY_FILE" "$CERTIFICATE_FILE"
# Protect files from modifications
chattr +i "$PRIVATE_KEY_FILE" "$CERTIFICATE_FILE"
fi
}
generate_mok_keys() {
generate_key_pair "mok" "/CN=$IMAGE_ID MOK"
generate_secureboot_keys() {
generate_key_pair "secureboot" "/CN=$IMAGE_ID UEFI CA $(date +%Y)" "rsa"
}
generate_verity_keys() {
generate_key_pair "verity" "/CN=$IMAGE_ID Verity CA $(date +%Y)" "ec"
}
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <mok|all>"
echo "Usage: $0 <secureboot|verity|all>"
exit 1
fi
case "$1" in
"mok")
generate_mok_keys
"secureboot")
generate_secureboot_keys
;;
"verity")
generate_verity_keys
;;
"all")
generate_mok_keys
generate_secureboot_keys
generate_verity_keys
;;
*)
echo "Error: Invalid value for <mok|all>."
echo "Error: Invalid value for <secureboot|verity|all>."
exit 1
;;
esac