]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
mkosi-obs: add support for UEFI SecureBoot self enrollment 3550/head
authorLuca Boccassi <luca.boccassi@gmail.com>
Tue, 25 Feb 2025 00:12:36 +0000 (00:12 +0000)
committerLuca Boccassi <luca.boccassi@gmail.com>
Tue, 25 Feb 2025 00:12:42 +0000 (00:12 +0000)
Create authvars and store them in the ESP with the project cert
used as PK/KEK/db

mkosi/resources/mkosi-obs/mkosi.build
mkosi/resources/mkosi-obs/mkosi.postoutput

index 358d205cb52e877f18976155f2fc04f224274992..dc5ed891775a46c7b181f879068515fbe81983d5 100755 (executable)
@@ -33,6 +33,7 @@ mkdir nss-db
 nss_db="$PWD/nss-db"
 certutil -N -d sql:"$nss_db" --empty-password
 certutil -A -d sql:"$nss_db" -n cert -t CT,CT,CT -i /usr/src/packages/SOURCES/_projectcert.crt
+openssl x509 -inform PEM -in /usr/src/packages/SOURCES/_projectcert.crt -outform DER -out _projectcert.cer
 
 cp -r /usr/src/packages/SOURCES/"$IMAGE_ID"* "$OUTPUTDIR"
 rm -f "$OUTPUTDIR/hashes.cpio.rsasign*" "$OUTPUTDIR"/*.sha*
@@ -225,4 +226,49 @@ while read -r SIG; do
 done < <(find hashes/roothashes -type f -name '*.sig')
 rm -rf hashes/roothashes
 
+# Sixth step: prepare EFI authvars for self-enrollment
+# as implemented by https://github.com/openSUSE/pesign-obs-integration/blob/master/pesign-repackage.spec.in#L162
+while read -r SIG; do
+    test -x /usr/lib/rpm/pesign/kernel-sign-file || break
+    f="${SIG%.sig}"
+    /usr/lib/rpm/pesign/kernel-sign-file -N -P -d -C _projectcert.cer -i pkcs7 -s "$SIG" sha256 _projectcert.cer "$f"
+    fbase="${f##*/}"
+    fbase="${fbase%.auth}"
+    fbase="${fbase%%-*}"
+    perl -0777 -npe 's/\A(?:[\040-\176]\0)+.{18}\0\0.{14}\0\0//s' < "$f" > "$f.orig"
+    sign-efi-sig-list -t "${SOURCE_DATE_EPOCH:-$(date +%s)}" -i "$f.p7sd" "$fbase" "$f.orig" "$f.tmp"
+    mv "$f.tmp" "$f"
+    rm -f "$f.p7s" "$f.p7sd" "$f.orig"
+done < <(find hashes/authvars -type f -name '*.auth.sig')
+declare -a AUTHVARS
+mapfile -t AUTHVARS < <(find hashes/authvars -type f -name "*.auth")
+if (( ${#AUTHVARS[@]} > 0 )); then
+    for ddi in "$OUTPUTDIR"/*.raw*; do
+        test -f "$ddi" || continue
+        if [[ $ddi == *.zst ]]; then
+            unzstd "${ddi}"
+            recompress=1
+        fi
+        offset="$(systemd-repart --json=short "${ddi%.zst}" | jq -r '.[] | select(.type == "esp") | .offset')"
+        if [ -z "$offset" ] || [ "$offset" = "null" ]; then
+            if [[ $ddi == *.zst ]]; then
+                rm -f "${ddi%.zst}"
+            fi
+            continue
+        fi
+
+        mmd -D s -i "${ddi%.zst}@@${offset}" ::loader ::loader/keys ::loader/keys/auto || true
+        for authvar in "${AUTHVARS[@]}"; do
+            test -f "$authvar" || continue
+            mcopy -o -i "${ddi%.zst}@@${offset}" "$authvar" "::loader/keys/auto/$(basename "$authvar")"
+        done
+
+        if ((recompress)); then
+            zstd --force "${ddi%.zst}"
+            rm -f "${ddi%.zst}"
+        fi
+    done
+fi
+rm -rf hashes/authvars
+
 rm -rf hashes "$nss_db"
index 19569aa5342bc3278e7a51324b15c9450351f3f8..4d80d0cd5c6ce3f2e291579e34da3cff2c61a73c 100755 (executable)
@@ -93,6 +93,22 @@ for ddi in "${DDIS[@]}"; do
     rm -rf EFI
 done
 
+# If there is at least one DDI then there might be an ESP, so prepare the authvars for self-enrollment
+if ((${#DDIS[@]} > 0)); then
+    mkdir -p hashes/authvars
+    pushd hashes/authvars 2>/dev/null
+    # Same as the GUID used by bootctl
+    guid=a5c059a1-94e4-4aa7-87b5-ab155c2bf072
+    cert-to-efi-sig-list -g "$guid" /usr/src/packages/SOURCES/_projectcert.crt db.esl
+    cp db.esl KEK.esl
+    cp db.esl PK.esl
+    env
+    for i in *.esl; do
+        sign-efi-sig-list -o -g "$guid" -t "${SOURCE_DATE_EPOCH:-$(date +%s)}" "${i%.esl}" "$i" "${i%.esl}.auth"
+    done
+    popd 2>/dev/null
+fi
+
 # Pack everything into a CPIO archive and place it where OBS expects it
 pushd hashes
 find . -type f | cpio -H newc -o >"$OUTPUTDIR/hashes.cpio.rsasign"