summaryrefslogtreecommitdiff
path: root/sys/boot/detached-luks.nix
diff options
context:
space:
mode:
Diffstat (limited to 'sys/boot/detached-luks.nix')
-rw-r--r--sys/boot/detached-luks.nix117
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;
+ };
+ };
+}