95 lines
3.5 KiB
Bash
95 lines
3.5 KiB
Bash
|
|
#!/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"
|