TPM Enrollment
Version: 1.0
Date: 2025-11-03
Module: keystone.tpmEnrollment
Overview
This guide explains how to configure TPM-based automatic disk unlock for your Keystone installation. TPM (Trusted Platform Module) enrollment allows your system to unlock encrypted disks automatically during boot without manual password entry, while maintaining secure recovery credentials for emergency scenarios.
Quick Start
After a fresh Keystone installation, you'll see a security warning on first login:
��������������������������������������������������������������
TPM ENROLLMENT NOT CONFIGURED
��������������������������������������������������������������Choose one of these commands to get started:
# Recommended: Generate recovery key
$ sudo keystone-enroll-recovery
# Alternative: Set custom password
$ sudo keystone-enroll-passwordBoth commands will:
- Configure your chosen recovery credential
- Enroll TPM for automatic unlock
- Remove the default "keystone" password
- Enable automatic boot unlock
Prerequisites
Before enrolling TPM, verify these requirements:
1. Secure Boot Must Be Enabled
$ sudo bootctl status | grep "Secure Boot"
Secure Boot: enabled (user)If output shows disabled or setup, complete Secure Boot enrollment first:
$ sudo sbctl status2. TPM 2.0 Must Be Available
$ ls /dev/tpm*
/dev/tpm0 /dev/tpmrm0For VMs: Enable TPM 2.0 emulation in your hypervisor For bare metal: Enable TPM in BIOS/UEFI settings
3. Credstore Volume Must Exist
$ ls /dev/zvol/rpool/credstore
/dev/zvol/rpool/credstoreThis is automatically created during Keystone installation with keystone.disko.enable = true.
Enrollment Methods
Method 1: Recovery Key (Recommended)
Recovery keys provide maximum security with minimal memorization burden.
Run:
$ sudo keystone-enroll-recoveryYou will receive a recovery key like:
fda7-w4n8-km9p-3jc2-vx5h-7qte-2nuw-8rbgCRITICAL: Save this key immediately in:
- Password manager (with offline backup)
- Printed paper in physical safe
- NOT on the encrypted disk
- NOT only in digital form on same hardware
Advantages:
- Maximum entropy (256-bit cryptographic key)
- No memorization required (write it down)
- Copy/paste friendly during recovery
Disadvantages:
- Must be stored externally (requires secure storage infrastructure)
- Easy to lose if not properly backed up
Method 2: Custom Password
Custom passwords are familiar and don't require external storage.
Run:
$ sudo keystone-enroll-passwordRequirements:
- Minimum 12 characters
- Maximum 64 characters
- Cannot be "keystone" (default password)
- No complexity requirements (but longer is better)
Password Examples:
GOOD: "coffee-morning-laptop-window" (28 characters)
GOOD: "MyBlueServer2024Today" (20 characters)
GOOD: "xK9mP2vL4nQ8wR7tY3nB" (20 characters)
BAD: "Password1!" (11 characters - too short)
BAD: "keystone" (prohibited - publicly known)Advantages:
- Familiar password workflow
- No external storage needed
- Can be committed to memory
Disadvantages:
- Must be remembered (may not use for months/years)
- Lower entropy than recovery key
- Risk of forgetting during emergency recovery
What Happens During Enrollment
Both enrollment methods follow this workflow:
-
Prerequisite Validation
- Verify Secure Boot enabled in User Mode
- Verify TPM 2.0 device available
- Verify credstore volume exists
-
Credential Setup
- Recovery key: Generate cryptographically secure key
- Custom password: Prompt and validate password (12-64 chars)
- Add credential to LUKS keyslot
-
TPM Enrollment
- Configure TPM unlock using PCRs 1,7 (configurable)
- Store sealed unlock key in LUKS header
- PCR 1: Firmware configuration
- PCR 7: Secure Boot certificates
-
Security Cleanup
- Verify TPM enrollment succeeded
- Remove default "keystone" password
- Create enrollment marker file
-
Completion
- Display confirmation message
- Suppress future login banners
After enrollment, the system will unlock automatically during normal boots.
Recovery Scenarios
When Will I Need My Recovery Credential?
You will need your recovery key or custom password in these situations:
Hardware Changes
- Motherboard replacement: New TPM chip has different keys
- TPM hardware failure: Manufacturing defects (rare)
- RAM/CPU changes: May affect firmware PCR measurements (depends on firmware)
Firmware Changes
- Secure Boot key modifications: If you re-enroll Secure Boot keys, PCR 7 changes
- Secure Boot disabled: System refuses automatic unlock (security feature working correctly)
- BIOS/UEFI downgrade or reflash: Firmware state changes affect PCRs
Software Changes (with PCRs 1,7)
- Normal NixOS updates: No re-enrollment needed (signed by same Secure Boot keys)
- Kernel updates: No re-enrollment needed
- Bootloader updates: No re-enrollment needed
- BIOS settings changes: May require re-enrollment if PCR 1 affected
Disaster Scenarios
- Lost TPM unlock: TPM chip becomes permanently locked (dictionary attack)
- PCR policy corruption: Extremely rare firmware bugs
Re-Enrolling TPM After Changes
If you intentionally changed firmware or Secure Boot configuration:
# 1. Boot with recovery key/custom password (system will prompt)
# 2. Verify Secure Boot is enabled
$ sudo bootctl status | grep "Secure Boot: enabled"
# 3. Remove old TPM keyslot (bound to old PCR values)
$ sudo systemd-cryptenroll --wipe-slot=tpm2 /dev/zvol/rpool/credstore
# 4. Enroll new TPM keyslot with updated PCR values
$ sudo keystone-enroll-tpm
# 5. Reboot to verify automatic unlock
$ sudo rebootAfter reboot, the system should unlock automatically with the new PCR measurements.
Testing Your Recovery Credential
IMPORTANT: Test your recovery key/password BEFORE you need it:
Test Recovery Key
# 1. Temporarily disable TPM unlock
$ sudo systemd-cryptenroll --wipe-slot=tpm2 /dev/zvol/rpool/credstore
# 2. Reboot - system will prompt for password
$ sudo reboot
# Boot prompt will appear:
# Please enter passphrase for disk credstore: _
# 3. Enter your recovery key at the prompt
# 4. After successful login, re-enable TPM
$ sudo keystone-enroll-tpm
# 5. Reboot to verify automatic unlock works again
$ sudo rebootTest Custom Password
Same procedure as recovery key testing above - enter your custom password at the boot prompt.
Advanced Configuration
Customizing PCR List
By default, TPM enrollment uses PCRs 1 and 7. You can customize this in your NixOS configuration:
# configuration.nix
{
keystone.tpmEnrollment = {
enable = true;
# Custom PCR list - choose based on your security vs update trade-off
tpmPCRs = [ 7 ]; # Secure Boot only (most update-resilient)
# tpmPCRs = [ 1 7 ]; # Default: Firmware config + Secure Boot
# tpmPCRs = [ 0 1 7 ]; # More restrictive: Firmware code + config + Secure Boot
};
}PCR Selection Guide:
| PCR List | Security | Update Resilience | When to Use |
|---|---|---|---|
[7] | Good | Excellent | Frequent firmware updates, prioritize convenience |
[1 7] | Better | Good | Default balanced approach (recommended) |
[0 1 7] | Best | Poor | Maximum security, rare firmware updates |
[7 11] | Excellent | Poor | Requires signed PCR policies (future feature) |
Trade-offs:
- More PCRs = More security (harder to bypass) but more re-enrollment needed
- Fewer PCRs = Less re-enrollment but easier to bypass with identical measurements
Custom Credstore Device
If you modified the disko configuration to use a different credstore path:
{
keystone.tpmEnrollment = {
enable = true;
credstoreDevice = "/dev/mapper/my-custom-credstore";
};
}Troubleshooting
Problem: Banner Still Appears After Enrollment
Symptoms: Login banner shows "TPM ENROLLMENT NOT CONFIGURED" even after running enrollment
Diagnosis:
# Check if TPM keyslot exists
$ sudo cryptsetup luksDump /dev/zvol/rpool/credstore | grep systemd-tpm2
# Check marker file
$ cat /var/lib/keystone/tpm-enrollment-completeSolutions:
- If TPM keyslot exists but no marker file: Logout/login (self-healing will create marker)
- If no TPM keyslot: Re-run enrollment command
- If enrollment failed silently: Check error logs and re-run
Problem: System Prompts for Password on Every Boot
Symptoms: After enrollment, system still asks for password at boot
Diagnosis:
# Check boot logs for TPM unlock attempts
$ sudo journalctl -b | grep -i "credstore\|tpm"
# Expected: "Failed to activate with TPM2" (indicates PCR mismatch)Common Causes:
-
Secure Boot disabled: PCR 7 value changed
- Fix: Re-enable Secure Boot in BIOS, reboot
-
Firmware updated: PCR values changed
- Fix: Re-enroll TPM (see "Re-Enrolling TPM" section)
-
TPM enrollment failed silently: No TPM keyslot created
- Fix: Re-run enrollment command, check for errors
-
Wrong PCR configuration: PCRs configured don't match boot state
- Fix: Adjust tpmPCRs in configuration, re-enroll
Problem: "No TPM2 Device Found" Error
For Virtual Machines:
libvirt/virt-manager:
# Check if TPM is enabled in VM XML
$ virsh dumpxml your-vm-name | grep -A 3 "<tpm"
# If missing, add TPM device:
$ virsh edit your-vm-name
# Add this in <devices> section:
# <tpm model='tpm-crb'>
# <backend type='emulator' version='2.0'/>
# </tpm>QEMU directly:
# Add TPM emulation to QEMU command:
qemu-system-x86_64 \
-tpmdev emulator,id=tpm0,chardev=chrtpm \
-chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
-device tpm-crb,tpmdev=tpm0 \
...bin/virtual-machine script:
The Keystone bin/virtual-machine script automatically includes TPM 2.0 emulation.
For Bare Metal:
- Reboot into BIOS/UEFI firmware settings
- Look for "Security" or "Advanced" section
- Enable "TPM Device" or "TPM 2.0"
- Save and reboot
- Verify:
ls /dev/tpm*
Problem: "Secure Boot Not Enabled" Error
Check current status:
$ sudo bootctl status
Secure Boot: disabled (setup)
Setup Mode: setupIf in Setup Mode:
- Secure Boot keys not yet enrolled
- Run Keystone Secure Boot enrollment (done during installation)
- Reboot to activate User Mode
If Secure Boot disabled in BIOS:
- Reboot into BIOS/UEFI settings
- Enable "Secure Boot"
- Save and reboot
- Verify:
sudo bootctl status
Security Considerations
Why Remove Default Password?
The default "keystone" password is:
- Publicly documented in Keystone documentation
- Known to attackers who research the project
- Zero security - anyone can unlock your disk
Enrollment scripts remove this password after adding your secure credential.
Why TPM + Recovery Credential?
TPM Automatic Unlock:
- Provides convenience (no password entry during normal boots)
- Binds unlock to specific boot state (Secure Boot + firmware config)
- Prevents unauthorized boot configurations from accessing disk
Recovery Credential (recovery key or custom password):
- Required for disaster recovery (TPM hardware failure)
- Needed when PCR values change (firmware updates)
- Ensures you never lose access to your data
Both together provide defense-in-depth:
- Normal operation: Seamless automatic unlock
- Hardware failure: Recovery credential works
- Firmware changes: Re-enroll TPM with same recovery credential
PCR Selection Security
Default PCRs 1,7 Provide:
- Protection against Secure Boot bypass
- Protection against firmware tampering
- Protection against unauthorized boot configurations
Default PCRs 1,7 Do NOT Protect Against:
- Booting different OS signed with same Secure Boot keys
- Rollback attacks to older signed kernels
- Attacks that modify only non-measured boot components
For enhanced security, consider:
- PCR 7+11 with signed policies (future feature)
- Additional physical security measures
- Regular firmware and software updates
Configuration Reference
Module Options
# configuration.nix
{
keystone.tpmEnrollment = {
# Enable the TPM enrollment module
enable = true;
# PCR list for TPM binding (default: [1 7])
tpmPCRs = [ 1 7 ];
# Credstore device path (default matches disko module)
credstoreDevice = "/dev/zvol/rpool/credstore";
};
}Available Commands
After enabling the module, these commands become available:
| Command | Purpose |
|---|---|
keystone-enroll-recovery | Generate recovery key + enroll TPM |
keystone-enroll-password | Set custom password + enroll TPM |
keystone-enroll-tpm | Enroll TPM only (advanced users) |
File Locations
| File | Purpose |
|---|---|
/var/lib/keystone/tpm-enrollment-complete | Enrollment status marker |
/dev/zvol/rpool/credstore | LUKS-encrypted credstore volume |
/etc/profile.d/tpm-enrollment-warning.sh | Login banner script |
Frequently Asked Questions
Q: Can I enroll both recovery key AND custom password?
Yes! LUKS supports up to 32 keyslots. You can run:
$ sudo keystone-enroll-recovery
# Save recovery key
$ sudo systemd-cryptenroll --password /dev/zvol/rpool/credstore
# Enter custom passwordBoth credentials will work for recovery scenarios.
Q: How do I change my custom password?
# Add new password (will prompt for current password)
$ sudo systemd-cryptenroll --password /dev/zvol/rpool/credstore
# Remove old password (optional - you can keep both)
$ sudo systemd-cryptenroll --wipe-slot=1 /dev/zvol/rpool/credstoreQ: How do I view current LUKS keyslots?
$ sudo systemd-cryptenroll /dev/zvol/rpool/credstore
SLOT TYPE
1 recovery
2 tpm2
# Or detailed view:
$ sudo cryptsetup luksDump /dev/zvol/rpool/credstoreQ: Can I disable TPM automatic unlock?
# Remove TPM keyslot
$ sudo systemd-cryptenroll --wipe-slot=tpm2 /dev/zvol/rpool/credstore
# System will now prompt for password on every bootQ: What if I lose my recovery key?
Prevention: Save recovery key in multiple secure locations immediately
If lost before TPM failure: Generate new recovery key while system is accessible:
$ sudo systemd-cryptenroll --recovery-key /dev/zvol/rpool/credstore
# Save new key immediatelyIf lost after TPM failure: DATA IS UNRECOVERABLE - no way to unlock disk
Q: Can I use the same recovery key on multiple systems?
No - each system generates a unique recovery key during enrollment. This is a security feature - if one system's key is compromised, other systems remain secure.
Q: How do I check which PCRs are currently enrolled?
$ sudo cryptsetup luksDump /dev/zvol/rpool/credstore | grep -A 4 systemd-tpm2
0: systemd-tpm2
tpm2-hash-pcrs: 1+7
tpm2-pcr-bank: sha256
tpm2-pin: falseQ: Can I add a PIN to TPM unlock?
Currently not supported by the enrollment scripts, but can be done manually:
$ sudo systemd-cryptenroll --wipe-slot=tpm2 /dev/zvol/rpool/credstore
$ sudo systemd-cryptenroll \
--tpm2-device=auto \
--tpm2-pcrs=1,7 \
--tpm2-with-pin=yes \
/dev/zvol/rpool/credstoreThis will prompt for a PIN during boot before TPM unlock.
Best Practices
1. Test Recovery Immediately
Don't wait for an emergency - test your recovery credential right after enrollment:
# Disable TPM temporarily
$ sudo systemd-cryptenroll --wipe-slot=tpm2 /dev/zvol/rpool/credstore
$ sudo reboot
# Use recovery credential at boot prompt
# Re-enroll TPM after successful login
$ sudo keystone-enroll-tpm2. Store Recovery Key Offline
DO:
- Print recovery key on paper, store in physical safe
- Save in password manager with offline backup
- Keep copy in safety deposit box (for critical systems)
DON'T:
- Store only on the encrypted disk (defeats the purpose)
- Store only on same physical machine
- Store in unencrypted cloud storage
- Email recovery key to yourself
3. Document Your PCR Configuration
If you customize tpmPCRs, document the choice:
{
keystone.tpmEnrollment = {
enable = true;
# Using PCR 7 only for maximum update resilience
# Acceptable for home server with physical security
tpmPCRs = [ 7 ];
};
}4. Regular Testing Schedule
Test recovery quarterly:
- Q1: Test recovery key/password works
- Q2: Verify automatic unlock still working
- Q3: Test PCR re-enrollment procedure
- Q4: Review and rotate credentials if needed
Migration and Compatibility
Upgrading from Manual TPM Enrollment
If you manually enrolled TPM before this module existed:
The module will self-heal:
- Login banner script detects existing TPM keyslot
- Automatically creates marker file
- Banner stops appearing on subsequent logins
No action required - existing enrollment continues working.
Disabling the Module
To disable TPM enrollment features:
{
keystone.tpmEnrollment.enable = false;
}This will:
- Remove enrollment commands from PATH
- Remove login banner
- NOT affect existing TPM enrollment (LUKS configuration persists)
To fully remove TPM unlock:
$ sudo systemd-cryptenroll --wipe-slot=tpm2 /dev/zvol/rpool/credstoreTechnical Details
LUKS Keyslot Layout
After enrollment, typical keyslot configuration:
| Slot | Type | Credential |
|---|---|---|
| 0 | (removed) | Default "keystone" password (removed) |
| 1 | password/recovery | Your recovery key or custom password |
| 2 | tpm2 | TPM-sealed automatic unlock |
TPM Token Structure
The TPM token stored in LUKS header contains:
- PCR Policy: Which PCRs must match (e.g., 1,7)
- PCR Bank: Hash algorithm (sha256)
- Sealed Blob: Encrypted unlock key (only unseals when PCRs match)
- Public Key: TPM's public endorsement key
Boot Process with TPM
1. UEFI firmware loads bootloader (lanzaboote)
2. TPM measures boot state into PCRs
3. systemd initrd starts
4. systemd-cryptsetup attempts unlock:
a. Try TPM unlock (if PCRs match policy)
b. If TPM fails, prompt for password/recovery key
5. Credstore unlocks, ZFS key loaded
6. System continues bootingSupport and Troubleshooting
Debug Commands
# Check TPM device
$ ls -la /dev/tpm*
# Check TPM capabilities
$ sudo tpm2_getcap properties-variable
# Check PCR values
$ sudo tpm2_pcrread
# Check Secure Boot status
$ sudo bootctl status
# Check LUKS keyslots
$ sudo cryptsetup luksDump /dev/zvol/rpool/credstore
# Check enrollment marker
$ cat /var/lib/keystone/tpm-enrollment-complete
# Check boot logs
$ sudo journalctl -b | grep -i "credstore\|tpm"Get Help
If you encounter issues:
- Check Prerequisites: Verify Secure Boot and TPM available
- Review Error Messages: Enrollment scripts provide detailed guidance
- Consult Boot Logs:
journalctl -b | grep tpm - Test Recovery: Ensure recovery credential works before relying on TPM
References
- systemd-cryptenroll man page
- ArchWiki: systemd-cryptenroll
- ArchWiki: Trusted Platform Module
- Linux TPM PCR Registry
- Keystone Secure Boot Guide:
docs/secure-boot.md - Keystone Disko Module:
modules/disko-single-disk-root/
Version: 1.0 Last Updated: 2025-11-03 Maintainer: Keystone Project