Privacy Tools Guide

Secure Boot prevents unauthorized code from running at startup, but simply having Secure Boot enabled does not tell you whether your boot chain has been compromised. Measured Boot and TPM attestation give you cryptographic proof that each stage — firmware, bootloader, kernel — is exactly what you expect.

Understanding the Boot Chain

UEFI Firmware
    └─ Bootloader (GRUB / systemd-boot)
            └─ Linux Kernel + initrd
                    └─ init / systemd
                            └─ Userspace

Each stage can be measured and its hash recorded in the TPM’s PCRs (Platform Configuration Registers). A change to any stage produces a different PCR value.

Step 1: Check Secure Boot Status

mokutil --sb-state
# SecureBoot enabled

bootctl status 2>/dev/null | grep "Secure Boot"
# Secure Boot: enabled (user)

# Check which keys are enrolled
mokutil --list-enrolled | grep Subject

Step 2: Check TPM Status

ls /dev/tpm*
# /dev/tpm0  /dev/tpmrm0

cat /sys/class/tpm/tpm0/tpm_version_major
# 2

sudo apt install tpm2-tools
tpm2_getcap properties-fixed | grep -A2 TPM_PT_FIRMWARE

Step 3: Read Current PCR Values

# Read all PCR values
tpm2_pcrread

# Common PCR assignments (SHA-256):
# PCR 0: UEFI firmware code
# PCR 4: Bootloader
# PCR 7: Secure Boot state and certificates
# PCR 11: systemd-boot entries

tpm2_pcrread sha256:0,4,7,11

Step 4: Record a Known-Good Baseline

After a fresh trusted installation:

tpm2_pcrread sha256:0,1,2,3,4,5,6,7 > /root/pcr-baseline-$(date +%Y%m%d).txt

# Store offline. On subsequent boots, compare:
tpm2_pcrread sha256:0,1,2,3,4,5,6,7 > /tmp/pcr-current.txt
diff /root/pcr-baseline-*.txt /tmp/pcr-current.txt

Any difference indicates a change to the measured component.

Step 5: Check Bootloader Signatures

# GRUB
sudo apt install sbsigntool
sbverify --list /boot/efi/EFI/ubuntu/grubx64.efi

# systemd-boot
bootctl status

# Verify kernel signature
pesign --show-signature --in /boot/vmlinuz-$(uname -r)

Step 6: Kernel Module Signature Verification

# Check module signing enforcement
grep -r "CONFIG_MODULE_SIG" /boot/config-$(uname -r) 2>/dev/null | \
  grep -E "FORCE|REQUIRE"

# List modules without valid signatures
for mod in $(lsmod | awk 'NR>1 {print $1}'); do
    sig=$(modinfo $mod 2>/dev/null | grep "sig_key")
    if [ -z "$sig" ]; then
        echo "UNSIGNED: $mod"
    fi
done

Step 7: TPM-Based Disk Encryption

Bind LUKS disk encryption to TPM PCR values — the disk only auto-unlocks if the boot chain matches:

# Enroll TPM bound to PCRs 0, 4, 7
sudo systemd-cryptenroll \
  --tpm2-device=auto \
  --tpm2-pcrs=0+4+7 \
  /dev/sda3

If any measured component changes (GRUB update, firmware update), the PCR values change and the TPM refuses to release the key. Re-enroll after deliberate updates:

sudo systemd-cryptenroll --wipe-slot=tpm2 /dev/sda3
sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+4+7 /dev/sda3

Step 8: Remote Attestation

Remote attestation lets a server verify that a client’s boot chain is trustworthy before granting access:

# Generate an attestation quote
tpm2_createprimary -C e -g sha256 -G ecc -c primary.ctx
tpm2_createak -C primary.ctx -c ak.ctx -u ak.pub -n ak.name
tpm2_quote \
  --key-context ak.ctx \
  --pcr-list sha256:0,4,7 \
  --message nonce.bin \
  --signature quote.sig \
  --pcrs quote.pcrs

The attestation quote can be sent to a remote server that verifies PCR values match the expected baseline before issuing a VPN certificate or access token.

Automated Boot Chain Verification Script

Monitor your boot chain continuously:

#!/bin/bash
# boot-verify.sh — automated PCR monitoring

BASELINE="/root/pcr-baseline.txt"
CURRENT="/tmp/pcr-current.txt"
ALERT_EMAIL="admin@example.com"

# Read current PCR values
tpm2_pcrread sha256:0,1,2,3,4,5,6,7 > "$CURRENT"

# Compare to baseline
if ! diff "$BASELINE" "$CURRENT" > /dev/null; then
    echo "WARNING: Boot chain modified!" | mail -s "TPM PCR Mismatch Alert" "$ALERT_EMAIL"
    echo "Baseline:" && cat "$BASELINE"
    echo "Current:" && cat "$CURRENT"
    diff "$BASELINE" "$CURRENT"
    exit 1
fi

echo "Boot chain verified OK at $(date)"
exit 0

Run this at startup via cron:

# /etc/cron.d/boot-verify
@reboot root /root/boot-verify.sh

UEFI Firmware Validation

Beyond kernel signing, verify the firmware itself has not been modified:

# Check firmware updates applied
fwupdmgr get-devices
fwupdmgr get-history

# If using Dell, HP, or Lenovo firmware:
# Download the BIOS file and verify its signature
# Most OEMs publish GPG keys for BIOS firmware

# Example: Dell
gpg --recv-key 0x1234ABCD  # Dell's key
gpg --verify BIOS_update.sig BIOS_update.bin

Firmware is rarely compromised but is the hardest component to validate post-deployment. This verification works only if you establish a trusted baseline immediately after OS installation.

TPM Limitations and Assumptions

TPM Measured Boot does NOT protect against:

  1. Supply chain attacks: Compromised firmware at manufacturing
  2. Evil maid attacks: Physical replacement of boot components
  3. Rootkits loaded after boot: Only the boot chain is measured, not runtime code
  4. Insider threats: Someone with root access can re-measure and create new baselines

TPM IS effective against:

  1. Software-based BIOS/firmware rootkits
  2. Unauthorized bootloader modifications
  3. Kernel tampering
  4. Detecting when your system was compromised (post-incident)

It’s an audit tool, not a complete security solution. Use alongside:

Bootloader Hardening Beyond Secureboot

GRUB Password Protection

# Generate a password hash
grub-mkpasswd-pbkdf2

# Edit /etc/grub.d/40_custom and add:
set superusers="root"
password_pbkdf2 root grub.pbkdf2.sha512.10000.HASH_HERE

# Rebuild GRUB config
sudo grub-mkconfig -o /boot/grub/grub.cfg

Now GRUB menu is password protected — cannot boot into single-user mode without the password.

Immutable Boot Directory (systemd-protect-system)

On systemd systems, mark the boot directory immutable:

sudo chattr +i /boot
sudo chattr +i /boot/vmlinuz-*

An attacker cannot modify the kernel even with root access (requires special CAP_LINUX_IMMUTABLE capability).

Validating Your Own System Configuration

Create a boot chain report:

#!/bin/bash
# system-security-report.sh

echo "=== SECURE BOOT CONFIGURATION ==="
mokutil --sb-state
bootctl status

echo -e "\n=== TPM STATUS ==="
ls /dev/tpm* 2>/dev/null && echo "TPM present" || echo "TPM NOT present"
tpm2_getcap properties-fixed 2>/dev/null | grep TPM_PT_FIRMWARE

echo -e "\n=== PCR VALUES (SHA256) ==="
tpm2_pcrread sha256:0,4,7,11

echo -e "\n=== BOOTLOADER SIGNING ==="
sbverify --list /boot/efi/EFI/*/grubx64.efi 2>/dev/null

echo -e "\n=== KERNEL MODULE SIGNING ==="
grep -r "CONFIG_MODULE_SIG" /boot/config-$(uname -r) 2>/dev/null

echo -e "\n=== DISK ENCRYPTION STATUS ==="
cryptsetup luksDump /dev/sda3 2>/dev/null | grep "TPM"

echo -e "\n=== AUDIT LOG CONFIG ==="
auditctl -l | head -5

Run regularly:

chmod +x system-security-report.sh
./system-security-report.sh > security-baseline-$(date +%Y%m%d).txt