Risiko Kedaluwarsa Sertifikat Secure Boot

UEFI Secure Boot mengandalkan rantai kepercayaan (chain of trust) berbasis sertifikat X.509 yang disimpan dalam database NVRAM (PK, KEK, DB) serta shim MOK (Machine Owner Key). Ketika sertifikat penandatangan (baik sertifikat CA internal, kunci vendor, maupun MOK) kedaluwarsa, firmware UEFI menolak mengeksekusi bootloader atau kernel binary (vmlinuz). Pada level OS, kernel dengan konfigurasi CONFIG_MODULE_SIG_FORCE=y atau mode UEFI Lockdown akan langsung memblokir pemuatan modul kernel (.ko) yang memiliki signature kedaluwarsa atau tidak valid.

Insiden kedaluwarsa sertifikat root dan CA publik (seperti transisi sertifikat UEFI CA 2025/2026) menunjukkan bahwa rotasi sertifikat tidak bisa ditangani secara ad-hoc. Kegagalan audit di pipeline packaging menyebabkan binary OS yang dirilis memicu bootloop massal pada mesin target tanpa fallback otomatis.

Audit Otomatis Masa Berlaku Sertifikat X.509

Sebelum memicu proses kompilasi kernel atau packaging image (ISO/raw image), pipeline CI harus menjalankan pemeriksaan masa aktif sertifikat penandatangan secara deterministik. Skrip audit berikut menggunakan openssl x509 dengan argumen -checkend untuk mendeteksi apakah sertifikat akan kedaluwarsa dalam rentang waktu toleransi (ambang batas default 30 hari atau 2.592.000 detik).

#!/usr/bin/env bash
set -euo pipefail

CERT_PATH="${1:-}"
THRESHOLD_DAYS="${2:-30}"
THRESHOLD_SECONDS=$(( THRESHOLD_DAYS * 86400 ))

if [[ -z "$CERT_PATH" || ! -f "$CERT_PATH" ]]; then
    echo "Error: File sertifikat tidak ditemukan: $CERT_PATH" >&2
    exit 2
fi

# Ekstrak informasi masa berlaku sertifikat (support format PEM dan DER)
if openssl x509 -in "$CERT_PATH" -inform DER -noout >/dev/null 2>&1; then
    CERT_FORMAT="DER"
else
    CERT_FORMAT="PEM"
fi

EXPIRY_DATE=$(openssl x509 -in "$CERT_PATH" -inform "$CERT_FORMAT" -noout -enddate | cut -d= -f2)
SUBJECT=$(openssl x509 -in "$CERT_PATH" -inform "$CERT_FORMAT" -noout -subject | sed 's/subject=//')

echo "Audit Sertifikat: $SUBJECT"
echo "Tanggal Kedaluwarsa: $EXPIRY_DATE"

# Fail-fast check
if ! openssl x509 -in "$CERT_PATH" -inform "$CERT_FORMAT" -noout -checkend "$THRESHOLD_SECONDS"; then
    echo "CRITICAL: Sertifikat akan kedaluwarsa dalam kurang dari $THRESHOLD_DAYS hari!" >&2
    exit 1
fi

echo "PASS: Sertifikat valid untuk minimal $THRESHOLD_DAYS hari ke depan."

Implementasi Dual-Signing pada Binary EFI

Selama periode migrasi kunci lama ke kunci baru, binary EFI (bootloader dan kernel) harus ditandatangani oleh dua sertifikat sekaligus agar image OS dapat di-boot pada mesin yang belum memperbarui DB/MOK tanpa merusak kompatibilitas mesin yang sudah menerapkan trust database baru. Format PE/COFF Authenticode memungkinkan banyak signature disematkan secara berantai.

Gunakan utilitas sbsign dari paket sbsigntool. Tanda tangan kedua disematkan langsung ke binary yang telah ditandatangani sebelumnya tanpa menghapus signature pertama.

# 1. Sign pertama menggunakan kunci lama
sbsign --key keys/old_secureboot.key \
       --cert keys/old_secureboot.crt \
       --output vmlinuz-signed-v1.efi \
       arch/x86/boot/bzImage

# 2. Sign kedua (dual-signing) menggunakan kunci baru pada output binary pertama
sbsign --key keys/new_secureboot.key \
       --cert keys/new_secureboot.crt \
       --output vmlinuz-dual-signed.efi \
       vmlinuz-signed-v1.efi
Catatan Modul Kernel (.ko): Modul kernel Linux menggunakan struktur signature PKCS#7 yang disematkan pada byte terakhir file (appended signature via scripts/sign-file). Berbeda dengan PE/COFF, parser bawaan kernel standar (kernel/module/signing.c) hanya mengevaluasi satu signature di akhir binary. Untuk modul kernel, transisi sertifikat dilakukan dengan mendaftarkan kunci baru dan kunci lama sekaligus ke keyring kernel (.secondary_trusted_keys atau MOK) sebelum modul yang ditandatangani kunci baru didistribusikan.

Verifikasi Signature Headless pada CI Runner

Pipeline CI harus memverifikasi integritas signature yang telah disematkan secara independen sebelum binary di-package ke disk image.

1. Verifikasi Binary EFI

Gunakan sbverify untuk menguji apakah binary valid terhadap sertifikat target:

# Verifikasi validitas tanda tangan terhadap sertifikat kunci baru
sbverify --cert keys/new_secureboot.crt vmlinuz-dual-signed.efi

# Verifikasi bahwa signature pertama (kunci lama) tetap utuh
sbverify --cert keys/old_secureboot.crt vmlinuz-dual-signed.efi

Jika output mengembalikan Signature verification OK, binary siap digunakan.

2. Verifikasi Modul Kernel (.ko)

Gunakan utilitas modinfo untuk membaca metadata signature yang tersemat pada modul:

# Periksa signer dan key identifier pada modul kernel
modinfo -F signer drivers/net/custom_driver.ko
modinfo -F sig_key drivers/net/custom_driver.ko
modinfo -F sig_hashalgo drivers/net/custom_driver.ko

Bila signer tidak cocok dengan sertifikat aktif di CI atau hash algorithm yang digunakan tidak aman (misal SHA1 alih-alih SHA256/SHA512), gagalkan proses build.

Konfigurasi Fail-Fast Pipeline CI

Berikut adalah contoh konfigurasi pipeline GitHub Actions yang memadukan audit expiry sertifikat, dual-signing binary EFI kernel, signing modul kernel, serta verifikasi headless:

name: Kernel Signing and Certificate Expiry Audit

on:
  push:
    branches: [ main, release/* ]
  pull_request:
    branches: [ main ]

jobs:
  audit-and-sign:
    runs-on: ubuntu-24.04
    steps:
      - name: Checkout Source Code
        uses: actions/checkout@v4

      - name: Install Signing Tooling
        run: |
          sudo apt-get update
          sudo apt-get install -y sbsigntool openssl kmod linux-headers-generic

      - name: Decrypt Private Keys and Load Certs
        env:
          SIGNING_SECRET: ${{ secrets.SECURE_BOOT_SIGNING_PASSPHRASE }}
        run: |
          mkdir -p keys
          # Contoh dekripsi kredensial dari secrets vault
          echo "${{ secrets.SB_ACTIVE_CERT }}" | base64 -d > keys/active.crt
          echo "${{ secrets.SB_ACTIVE_KEY }}" | base64 -d > keys/active.key
          echo "${{ secrets.SB_ROTATION_CERT }}" | base64 -d > keys/rotation.crt
          echo "${{ secrets.SB_ROTATION_KEY }}" | base64 -d > keys/rotation.key
          chmod 600 keys/*.key

      - name: Fail-Fast: Audit Certificate Expiry
        run: |
          chmod +x ./scripts/audit-cert-expiry.sh
          # Audit toleransi 45 hari untuk sertifikat aktif
          ./scripts/audit-cert-expiry.sh keys/active.crt 45
          # Audit toleransi 180 hari untuk sertifikat rotasi berikutnya
          ./scripts/audit-cert-expiry.sh keys/rotation.crt 180

      - name: Build and Dual-Sign Kernel EFI Binary
        run: |
          # Asumsi bzImage hasil build berada pada build/bzImage
          # 1. Tanda tangan dengan active key
          sbsign --key keys/active.key \
                 --cert keys/active.crt \
                 --output build/bzImage.signed.tmp \
                 build/bzImage

          # 2. Tanda tangan dengan rotation key
          sbsign --key keys/rotation.key \
                 --cert keys/rotation.crt \
                 --output build/bzImage.efi \
                 build/bzImage.signed.tmp
          rm -f build/bzImage.signed.tmp

      - name: Sign Out-Of-Tree Kernel Modules
        run: |
          # Sign modul menggunakan active key via sign-file Linux
          SIGN_FILE="/usr/lib/linux-kbuild-$(uname -r | cut -d- -f1)/scripts/sign-file"
          if [[ ! -f "$SIGN_FILE" ]]; then
            SIGN_FILE="$(find /usr/src/ -name sign-file -type f -perm /111 | head -n 1)"
          fi

          find build/modules/ -name "*.ko" -exec \
            "$SIGN_FILE" sha256 keys/active.key keys/active.crt {} \;

      - name: Headless Verification Step
        run: |
          echo "Validating EFI signatures..."
          sbverify --cert keys/active.crt build/bzImage.efi
          sbverify --cert keys/rotation.crt build/bzImage.efi

          echo "Validating kernel modules..."
          for mod in $(find build/modules/ -name "*.ko"); do
            SIGNER=$(modinfo -F signer "$mod")
            if [[ -z "$SIGNER" ]]; then
              echo "ERROR: Modul $mod tidak memiliki signature valid!" >&2
              exit 1
            fi
          done
          echo "All verification checks passed."

      - name: Cleanup Sensitive Keys
        if: always()
        run: |
          rm -rf keys/*.key

Mitigasi Bootloop dan Manajemen Rotasi MOK

Untuk memastikan image OS hasil build aman digunakan di infrastruktur produksi, terapkan langkah mitigasi berikut:

  • Otomasi Rotasi Key: Jadwalkan pipeline periodik mingguan (cron trigger) yang hanya menjalankan stage audit sertifikat. Jika sertifikat mencapai ambang batas 60 hari sebelum kedaluwarsa, CI harus mengirimkan alert otomatis ke PagerDuty/Slack agar tim infrastruktur memicu workflow pembaharuan MOK.
  • Validasi Fallback EFI: Pastikan binary shimx64.efi yang digunakan di image memiliki database sertifikat vendor yang sesuai. Jika shim ditandatangani oleh Microsoft Third Party UEFI CA lama, binary shim harus diperbarui ke versi yang ditandatangani CA baru sebelum masa kedaluwarsa CA publik tiba.
  • Validasi Revokasi (SBAT): Selain masa berlaku sertifikat, pastikan nilai generation SBAT (Secure Boot Advanced Targeting) pada binary GRUB dan kernel tidak memicu penolakan oleh NVRAM DBX mesin target. Lakukan pengecekan metadata SBAT menggunakan objdump -s -j .sbat <binary.efi> di dalam CI.