{ config, lib, pkgs, ... }: with lib; let cfg = config.local.boot.detachedLuks; bootFs = config.fileSystems."/boot"; tpmInitrd = config.local.boot.tpm.initrd.enable; pcrList = concatStringsSep "," (map toString config.local.boot.tpm.initrd.pcrs); in { options.local.boot.detachedLuks = { enable = mkEnableOption "detached LUKS header in initrd"; headerFromBoot = mkOption { type = types.str; }; tpmStorageFromBoot = mkOption { type = types.str; default = "tpm-boot"; }; crypt = mkOption { type = types.str; }; target = mkOption { type = types.str; }; }; config = mkIf cfg.enable { boot.initrd = let headerPath = "/initrd-boot/${cfg.headerFromBoot}"; headerPathEscaped = escapeShellArg headerPath; tpmPath = escapeShellArg "/initrd-boot/${cfg.tpmStorageFromBoot}"; hardwareKeyPath = "/tpm/unsealed.luks-key"; in { preDeviceCommands = '' mkdir -p `dirname ${headerPathEscaped}` touch ${headerPathEscaped} ''; postDeviceCommands = mkIf (!config.boot.initrd.systemd.enable) '' # Set the system time from the hardware clock to work around a # bug in qemu-kvm > 1.5.2 (where the VM clock is initialised # to the *boot time* of the host). hwclock -s ''; #FIXME: Demasiado vulgar preLVMCommands = optionalString (config.local.boot.efi.enable && config.local.boot.efi.removable) '' sleep 2 ''; luks.devices.${cfg.target} = { device = cfg.crypt; header = headerPath; preLVM = false; keyFile = mkIf tpmInitrd hardwareKeyPath; fallbackToPassword = tpmInitrd; preOpenCommands = '' mount -o ro -t ${bootFs.fsType} ${bootFs.device} /initrd-boot '' + optionalString tpmInitrd '' mkdir /tpm tpm2 createprimary -Q -C owner -g sha256 -G ecc -c /tpm/prim.ctx tpm2 loadexternal -Q -C owner -G rsa -u ${tpmPath}/signing-key.pub -c /tpm/signing-key.ctx -n /tpm/signing-key.name tpm2 verifysignature -Q -c /tpm/signing-key.ctx -g sha256 -m ${tpmPath}/auth.policy -s ${tpmPath}/auth.sig -t /tpm/verified.ticket -f rsassa tpm2 startauthsession -Q -S /tpm/session.ctx --policy-session tpm_resets=`tpm2 readclock | grep reset_count | sed 's/.*: //g'` tpm2 policycountertimer -Q -S /tpm/session.ctx resets="$tpm_resets" tpm2 policypcr -Q -S /tpm/session.ctx -l sha256:${pcrList} tpm2 policyauthorize -Q -S /tpm/session.ctx -i ${tpmPath}/auth.policy -n /tpm/signing-key.name -t /tpm/verified.ticket tpm2 load -Q -C /tpm/prim.ctx -u ${tpmPath}/key.pub -r ${tpmPath}/key.priv -c /tpm/key.ctx tpm2 unseal -Q -c /tpm/key.ctx -p session:/tpm/session.ctx -o /tpm/unsealed.luks-key echo "Unsealed!" cat /tpm/unsealed.luks-key echo "Unsealed! END" tpm2 flushcontext /tpm/session.ctx ''; postOpenCommands = mkBefore ('' umount /initrd-boot '' + optionalString tpmInitrd '' rm -r /tpm ''); }; }; local.boot = { stack = { btrfsToplevelMultidrive.toplevel.device = "/dev/mapper/${cfg.target}"; luksExt4FscryptImpermanence = { inherit (cfg) target; }; }; tpm.initrd.enable = mkDefault config.local.boot.tpm.enable; }; }; }