veilor-os/scripts/gen-mok-key.sh

95 lines
3.5 KiB
Bash
Raw Permalink Normal View History

#!/usr/bin/env bash
# gen-mok-key.sh — Generate a Machine Owner Key (MOK) pair for Secure Boot
#
# Purpose:
# Produces an RSA-4096 key pair used to sign EFI binaries (BOOTX64.EFI,
# shim, grub) and out-of-tree kernel modules so they pass UEFI Secure Boot
# verification once the public cert is enrolled in the firmware.
#
# Output (gitignored):
# build/keys/MOK.priv — PEM private key (sbsign / sign-file input)
# build/keys/MOK.der — DER public certificate (mokutil enrollment input)
# build/keys/MOK.pem — PEM public certificate (sbsign --cert input)
#
# Idempotent: if MOK.priv already exists, exits 0 without regenerating.
# Re-running with existing keys is safe — won't clobber a key already used
# to sign released ISOs.
#
# ─── User enrollment workflow (post-install) ─────────────────────────────
# 1. Copy build/keys/MOK.der to the installed system (USB / scp / etc.)
# 2. On the booted veilor-os system, as root:
# mokutil --import /path/to/MOK.der
# Set a one-time password when prompted.
# 3. Reboot. The shim's MokManager will appear on next boot — choose
# "Enroll MOK", confirm with the password from step 2, then continue
# boot. The cert is now in the kernel's .platform keyring.
# 4. Verify enrollment:
# mokutil --list-enrolled | grep -A2 'veilor'
#
# ─── Uploading to GitHub Actions secrets ─────────────────────────────────
# After running this script, populate the CI signing secrets with:
# gh secret set MOK_PRIVATE_KEY < build/keys/MOK.priv
# gh secret set MOK_CERT < build/keys/MOK.der
#
# Keep build/keys/ off-disk-backup-medium-of-record offline. Anyone with
# MOK.priv can sign code that boots on enrolled machines.
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
KEY_DIR="$REPO_ROOT/build/keys"
PRIV_KEY="$KEY_DIR/MOK.priv"
DER_CERT="$KEY_DIR/MOK.der"
PEM_CERT="$KEY_DIR/MOK.pem"
# Subject for the X.509 cert. Tweak CN if you fork the project.
SUBJ="/CN=veilor-os Machine Owner Key/O=veilor-org/OU=secure-boot/"
# Cert validity — 10 years. Long enough that we don't churn re-enrollment;
# short enough that a leaked key has a hard expiry.
DAYS=3650
if [[ -f "$PRIV_KEY" ]]; then
echo "[INFO] $PRIV_KEY already exists — skipping (idempotent)."
echo "[INFO] To regenerate, delete $KEY_DIR/ first."
exit 0
fi
mkdir -p "$KEY_DIR"
chmod 700 "$KEY_DIR"
echo "[*] Generating RSA-4096 MOK keypair → $KEY_DIR/"
# Single openssl invocation produces PEM private key + DER public cert.
# -nodes = no passphrase on the key (CI must use it non-interactively).
# Protect the resulting MOK.priv with filesystem perms only.
openssl req \
-new \
-x509 \
-newkey rsa:4096 \
-nodes \
-sha256 \
-days "$DAYS" \
-subj "$SUBJ" \
-keyout "$PRIV_KEY" \
-outform DER \
-out "$DER_CERT"
# Also emit a PEM-encoded copy of the cert — sbsign accepts PEM more
# reliably than DER in some distros' build of the tool.
openssl x509 -inform DER -in "$DER_CERT" -outform PEM -out "$PEM_CERT"
chmod 600 "$PRIV_KEY"
chmod 644 "$DER_CERT" "$PEM_CERT"
echo "[OK] MOK keypair written:"
echo " private : $PRIV_KEY (mode 600)"
echo " cert DER: $DER_CERT (enroll via mokutil --import)"
echo " cert PEM: $PEM_CERT (sbsign --cert input)"
echo ""
echo "[next] Upload to CI:"
echo " gh secret set MOK_PRIVATE_KEY < $PRIV_KEY"
echo " gh secret set MOK_CERT < $DER_CERT"