summary refs log tree commit diff
path: root/nixos/modules/system/boot/luksroot.nix
diff options
context:
space:
mode:
authorJan Malakhovski <oxij@oxij.org>2017-09-15 21:47:36 +0000
committerJan Malakhovski <oxij@oxij.org>2018-08-08 02:45:17 +0000
commit12e6907f33b79bb74d2b1502f4d8ff09c5ad56d8 (patch)
tree4556313b83b58ecf024b092f6967cd2f21db5373 /nixos/modules/system/boot/luksroot.nix
parentdc653449c541312a120b2dd25fad118e04828b62 (diff)
downloadnixpkgs-12e6907f33b79bb74d2b1502f4d8ff09c5ad56d8.tar
nixpkgs-12e6907f33b79bb74d2b1502f4d8ff09c5ad56d8.tar.gz
nixpkgs-12e6907f33b79bb74d2b1502f4d8ff09c5ad56d8.tar.bz2
nixpkgs-12e6907f33b79bb74d2b1502f4d8ff09c5ad56d8.tar.lz
nixpkgs-12e6907f33b79bb74d2b1502f4d8ff09c5ad56d8.tar.xz
nixpkgs-12e6907f33b79bb74d2b1502f4d8ff09c5ad56d8.tar.zst
nixpkgs-12e6907f33b79bb74d2b1502f4d8ff09c5ad56d8.zip
nixos: initrd/luks: cleanup and generalize common shell expressions
Also fix Yubikey timeout handling mess.
Diffstat (limited to 'nixos/modules/system/boot/luksroot.nix')
-rw-r--r--nixos/modules/system/boot/luksroot.nix112
1 files changed, 61 insertions, 51 deletions
diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix
index 401c3cc6991..8cdb3981d53 100644
--- a/nixos/modules/system/boot/luksroot.nix
+++ b/nixos/modules/system/boot/luksroot.nix
@@ -5,39 +5,79 @@ with lib;
 let
   luks = config.boot.initrd.luks;
 
-  openCommand = name': { name, device, header, keyFile, keyFileSize, keyFileOffset, allowDiscards, yubikey, fallbackToPassword, ... }: assert name' == name; ''
+  commonFunctions = ''
+    die() {
+      echo "$@" >&2
+      exit 1
+    }
 
-    # Wait for a target (e.g. device, keyFile, header, ...) to appear.
     wait_target() {
         local name="$1"
         local target="$2"
+        local secs="''${3:-10}"
+        local desc="''${4:-$name $target to appear}"
 
         if [ ! -e $target ]; then
-            echo -n "Waiting 10 seconds for $name $target to appear"
+            echo -n "Waiting $secs seconds for $desc..."
             local success=false;
-            for try in $(seq 10); do
+            for try in $(seq $secs); do
                 echo -n "."
                 sleep 1
-                if [ -e $target ]; then success=true break; fi
+                if [ -e $target ]; then
+                    success=true
+                    break
+                fi
             done
-            if [ $success = true ]; then
+            if [ $success == true ]; then
                 echo " - success";
+                return 0
             else
                 echo " - failure";
+                return 1
             fi
         fi
+        return 0
     }
 
+    wait_yubikey() {
+      local secs="''${1:-10}"
+
+      ykinfo -v 1>/dev/null 2>&1
+      if [ $? != 0 ]; then
+          echo -n "Waiting $secs seconds for Yubikey to appear..."
+          local success=false
+          for try in $(seq $secs); do
+              echo -n .
+              sleep 1
+              ykinfo -v 1>/dev/null 2>&1
+              if [ $? == 0 ]; then
+                  success=true
+                  break
+              fi
+          done
+          if [ $success == true ]; then
+              echo " - success";
+              return 0
+          else
+              echo " - failure";
+              return 1
+          fi
+      fi
+      return 0
+    }
+  '';
+
+  openCommand = name': { name, device, header, keyFile, keyFileSize, keyFileOffset, allowDiscards, yubikey, fallbackToPassword, ... }: assert name' == name; ''
     # Wait for luksRoot (and optionally keyFile and/or header) to appear, e.g.
     # if on a USB drive.
-    wait_target "device" ${device}
+    wait_target "device" ${device} || die "${device} is unavailable"
 
-    ${optionalString (keyFile != null) ''
-      wait_target "key file" ${keyFile}
+    ${optionalString (header != null) ''
+      wait_target "header" ${header} || die "${header} is unavailable"
     ''}
 
-    ${optionalString (header != null) ''
-      wait_target "header" ${header}
+    ${optionalString (keyFile != null) ''
+      wait_target "key file" ${keyFile} || die "${keyFile} is unavailable"
     ''}
 
     open_normally() {
@@ -70,7 +110,6 @@ let
     }
 
     open_yubikey() {
-
         # Make all of these local to this function
         # to prevent their values being leaked
         local salt
@@ -95,10 +134,9 @@ let
         response="$(ykchalresp -${toString yubikey.slot} -x $challenge 2>/dev/null)"
 
         for try in $(seq 3); do
-
             ${optionalString yubikey.twoFactor ''
             echo -n "Enter two-factor passphrase: "
-            read -s k_user
+            read -rs k_user
             echo
             ''}
 
@@ -110,7 +148,7 @@ let
 
             echo -n "$k_luks" | hextorb | cryptsetup luksOpen ${device} ${name} ${optionalString allowDiscards "--allow-discards"} --key-file=-
 
-            if [ $? == "0" ]; then
+            if [ $? == 0 ]; then
                 opened=true
                 break
             else
@@ -121,8 +159,7 @@ let
 
         if [ "$opened" == false ]; then
             umount ${yubikey.storage.mountPoint}
-            echo "Maximum authentication errors reached"
-            exit 1
+            die "Maximum authentication errors reached"
         fi
 
         echo -n "Gathering entropy for new salt (please enter random keys to generate entropy if this blocks for long)..."
@@ -157,7 +194,7 @@ let
         echo -n "$new_k_luks" | hextorb > ${yubikey.ramfsMountPoint}/new_key
         echo -n "$k_luks" | hextorb | cryptsetup luksChangeKey ${device} --key-file=- ${yubikey.ramfsMountPoint}/new_key
 
-        if [ $? == "0" ]; then
+        if [ $? == 0 ]; then
             echo -ne "$new_salt\n$new_iterations" > ${yubikey.storage.mountPoint}${yubikey.storage.path}
         else
             echo "Warning: Could not update LUKS key, current challenge persists!"
@@ -170,38 +207,11 @@ let
         umount ${yubikey.storage.mountPoint}
     }
 
-    ${optionalString (yubikey.gracePeriod > 0) ''
-    echo -n "Waiting ${toString yubikey.gracePeriod} seconds as grace..."
-    for i in $(seq ${toString yubikey.gracePeriod}); do
-        sleep 1
-        echo -n .
-    done
-    echo "ok"
-    ''}
-
-    yubikey_missing=true
-    ykinfo -v 1>/dev/null 2>&1
-    if [ $? != "0" ]; then
-        echo -n "waiting 10 seconds for yubikey to appear..."
-        for try in $(seq 10); do
-            sleep 1
-            ykinfo -v 1>/dev/null 2>&1
-            if [ $? == "0" ]; then
-                yubikey_missing=false
-                break
-            fi
-            echo -n .
-        done
-        echo "ok"
+    if wait_yubikey ${toString yubikey.gracePeriod}; then
+        open_yubikey
     else
-        yubikey_missing=false
-    fi
-
-    if [ "$yubikey_missing" == true ]; then
         echo "no yubikey found, falling back to non-yubikey open procedure"
         open_normally
-    else
-        open_yubikey
     fi
     ''}
 
@@ -397,9 +407,9 @@ in
                 };
 
                 gracePeriod = mkOption {
-                  default = 2;
+                  default = 10;
                   type = types.int;
-                  description = "Time in seconds to wait before attempting to find the Yubikey.";
+                  description = "Time in seconds to wait for the Yubikey.";
                 };
 
                 ramfsMountPoint = mkOption {
@@ -520,8 +530,8 @@ in
       ''}
     '';
 
-    boot.initrd.preLVMCommands = concatStrings (mapAttrsToList openCommand preLVM);
-    boot.initrd.postDeviceCommands = concatStrings (mapAttrsToList openCommand postLVM);
+    boot.initrd.preLVMCommands = commonFunctions + concatStrings (mapAttrsToList openCommand preLVM);
+    boot.initrd.postDeviceCommands = commonFunctions + concatStrings (mapAttrsToList openCommand postLVM);
 
     environment.systemPackages = [ pkgs.cryptsetup ];
   };