diff options
Diffstat (limited to 'sys/boot/detached-luks.nix')
| -rw-r--r-- | sys/boot/detached-luks.nix | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/sys/boot/detached-luks.nix b/sys/boot/detached-luks.nix new file mode 100644 index 0000000..78ae35c --- /dev/null +++ b/sys/boot/detached-luks.nix @@ -0,0 +1,117 @@ +{ + 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 + touch ${escapeShellArg hardwareKeyPath} + + unseal_tpm_key() { + tpm2 createprimary -Q -C owner -g sha256 -G ecc -c /tpm/prim.ctx || return + + tpm2 loadexternal -Q -C owner -G rsa -u ${tpmPath}/signing-key.pub -c /tpm/signing-key.ctx -n /tpm/signing-key.name || return + tpm2 verifysignature -Q -c /tpm/signing-key.ctx -g sha256 -m ${tpmPath}/auth.policy -s ${tpmPath}/auth.sig -t /tpm/verified.ticket -f rsassa || return + + tpm2 startauthsession -Q -S /tpm/session.ctx --policy-session || return + + tpm_resets=`tpm2 readclock | grep reset_count | sed 's/.*: //g'` + tpm2 policycountertimer -Q -S /tpm/session.ctx resets="$tpm_resets" || return + tpm2 policypcr -Q -S /tpm/session.ctx -l sha256:${pcrList} || return + tpm2 policyauthorize -Q -S /tpm/session.ctx -i ${tpmPath}/auth.policy -n /tpm/signing-key.name -t /tpm/verified.ticket || return + + tpm2 load -Q -C /tpm/prim.ctx -u ${tpmPath}/key.pub -r ${tpmPath}/key.priv -c /tpm/key.ctx || return + tpm2 unseal -Q -c /tpm/key.ctx -p session:/tpm/session.ctx -o ${escapeShellArg hardwareKeyPath} || return + + tpm2 flushcontext /tpm/session.ctx + } + + unseal_tpm_key + ''; + + 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; + }; + }; +} |
