about summary refs log tree commit diff
path: root/nixos/modules/system/boot/luksroot.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/system/boot/luksroot.nix')
-rw-r--r--nixos/modules/system/boot/luksroot.nix79
1 files changed, 77 insertions, 2 deletions
diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix
index 0bb8396a44fc..31f1e22cda32 100644
--- a/nixos/modules/system/boot/luksroot.nix
+++ b/nixos/modules/system/boot/luksroot.nix
@@ -4,6 +4,7 @@ with lib;
 
 let
   luks = config.boot.initrd.luks;
+  kernelPackages = config.boot.kernelPackages;
 
   commonFunctions = ''
     die() {
@@ -139,7 +140,7 @@ let
     umount /crypt-ramfs 2>/dev/null
   '';
 
-  openCommand = name': { name, device, header, keyFile, keyFileSize, keyFileOffset, allowDiscards, yubikey, gpgCard, fallbackToPassword, ... }: assert name' == name;
+  openCommand = name': { name, device, header, keyFile, keyFileSize, keyFileOffset, allowDiscards, yubikey, gpgCard, fido2, fallbackToPassword, ... }: assert name' == name;
   let
     csopen   = "cryptsetup luksOpen ${device} ${name} ${optionalString allowDiscards "--allow-discards"} ${optionalString (header != null) "--header=${header}"}";
     cschange = "cryptsetup luksChangeKey ${device} ${optionalString (header != null) "--header=${header}"}";
@@ -387,7 +388,31 @@ let
     }
     ''}
 
-    ${if (luks.yubikeySupport && (yubikey != null)) || (luks.gpgSupport && (gpgCard != null)) then ''
+    ${optionalString (luks.fido2Support && (fido2.credential != null)) ''
+
+    open_with_hardware() {
+      local passsphrase
+
+        ${if fido2.passwordLess then ''
+          export passphrase=""
+        '' else ''
+          read -rsp "FIDO2 salt for ${device}: " passphrase
+          echo
+        ''}
+        ${optionalString (lib.versionOlder kernelPackages.kernel.version "5.4") ''
+          echo "On systems with Linux Kernel < 5.4, it might take a while to initialize the CRNG, you might want to use linuxPackages_latest."
+          echo "Please move your mouse to create needed randomness."
+        ''}
+          echo "Waiting for your FIDO2 device..."
+          fido2luks -i open ${device} ${name} ${fido2.credential} --await-dev ${toString fido2.gracePeriod} --salt string:$passphrase
+        if [ $? -ne 0 ]; then
+          echo "No FIDO2 key found, falling back to normal open procedure"
+          open_normally
+        fi
+    }
+    ''}
+
+    ${if (luks.yubikeySupport && (yubikey != null)) || (luks.gpgSupport && (gpgCard != null)) || (luks.fido2Support && (fido2.credential != null)) then ''
     open_with_hardware
     '' else ''
     open_normally
@@ -608,6 +633,31 @@ in
             });
           };
 
+          fido2 = {
+            credential = mkOption {
+              default = null;
+              example = "f1d00200d8dc783f7fb1e10ace8da27f8312d72692abfca2f7e4960a73f48e82e1f7571f6ebfcee9fb434f9886ccc8fcc52a6614d8d2";
+              type = types.str;
+              description = "The FIDO2 credential ID.";
+            };
+
+            gracePeriod = mkOption {
+              default = 10;
+              type = types.int;
+              description = "Time in seconds to wait for the FIDO2 key.";
+            };
+
+            passwordLess = mkOption {
+              default = false;
+              type = types.bool;
+              description = ''
+                Defines whatever to use an empty string as a default salt.
+
+                Enable only when your device is PIN protected, such as <link xlink:href="https://trezor.io/">Trezor</link>.
+              '';
+            };
+          };
+
           yubikey = mkOption {
             default = null;
             description = ''
@@ -706,6 +756,15 @@ in
             and a Yubikey to work with this feature.
           '';
     };
+
+    boot.initrd.luks.fido2Support = mkOption {
+      default = false;
+      type = types.bool;
+      description = ''
+        Enables support for authenticating with FIDO2 devices.
+      '';
+    };
+
   };
 
   config = mkIf (luks.devices != {} || luks.forceLuksSupportInInitrd) {
@@ -714,6 +773,14 @@ in
       [ { assertion = !(luks.gpgSupport && luks.yubikeySupport);
           message = "Yubikey and GPG Card may not be used at the same time.";
         }
+
+        { assertion = !(luks.gpgSupport && luks.fido2Support);
+          message = "FIDO2 and GPG Card may not be used at the same time.";
+        }
+
+        { assertion = !(luks.fido2Support && luks.yubikeySupport);
+          message = "FIDO2 and Yubikey may not be used at the same time.";
+        }
       ];
 
     # actually, sbp2 driver is the one enabling the DMA attack, but this needs to be tested
@@ -753,6 +820,11 @@ in
         chmod +x $out/bin/openssl-wrap
       ''}
 
+      ${optionalString luks.fido2Support ''
+        copy_bin_and_libs ${pkgs.fido2luks}/bin/fido2luks
+      ''}
+
+
       ${optionalString luks.gpgSupport ''
         copy_bin_and_libs ${pkgs.gnupg}/bin/gpg
         copy_bin_and_libs ${pkgs.gnupg}/bin/gpg-agent
@@ -783,6 +855,9 @@ in
         $out/bin/gpg-agent --version
         $out/bin/scdaemon --version
       ''}
+      ${optionalString luks.fido2Support ''
+        $out/bin/fido2luks --version
+      ''}
     '';
 
     boot.initrd.preFailCommands = postCommands;