summary refs log tree commit diff
path: root/nixos/modules/system/boot/luksroot.nix
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2013-10-10 13:28:20 +0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2013-10-10 13:28:20 +0200
commit5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010 (patch)
treea6c0f605be6de3f372ae69905b331f9f75452da7 /nixos/modules/system/boot/luksroot.nix
parent6070bc016bd2fd945b04347e25cfd3738622d2ac (diff)
downloadnixpkgs-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar
nixpkgs-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar.gz
nixpkgs-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar.bz2
nixpkgs-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar.lz
nixpkgs-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar.xz
nixpkgs-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar.zst
nixpkgs-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.zip
Move all of NixOS to nixos/ in preparation of the repository merge
Diffstat (limited to 'nixos/modules/system/boot/luksroot.nix')
-rw-r--r--nixos/modules/system/boot/luksroot.nix176
1 files changed, 176 insertions, 0 deletions
diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix
new file mode 100644
index 00000000000..29f5eb4fd77
--- /dev/null
+++ b/nixos/modules/system/boot/luksroot.nix
@@ -0,0 +1,176 @@
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+  luks = config.boot.initrd.luks;
+
+  openCommand = { name, device, keyFile, keyFileSize, allowDiscards, ... }: ''
+    # Wait for luksRoot to appear, e.g. if on a usb drive.
+    # XXX: copied and adapted from stage-1-init.sh - should be
+    # available as a function.
+    if ! test -e ${device}; then
+        echo -n "waiting 10 seconds for device ${device} to appear..."
+        for try in $(seq 10); do
+            sleep 1
+            if test -e ${device}; then break; fi
+            echo -n .
+        done
+        echo "ok"
+    fi
+
+    ${optionalString (keyFile != null) ''
+    if ! test -e ${keyFile}; then
+        echo -n "waiting 10 seconds for key file ${keyFile} to appear..."
+        for try in $(seq 10); do
+            sleep 1
+            if test -e ${keyFile}; then break; fi
+            echo -n .
+        done
+        echo "ok"
+    fi
+    ''}
+
+    # open luksRoot and scan for logical volumes
+    cryptsetup luksOpen ${device} ${name} ${optionalString allowDiscards "--allow-discards"} \
+      ${optionalString (keyFile != null) "--key-file=${keyFile} ${optionalString (keyFileSize != null) "--keyfile-size=${toString keyFileSize}"}"}
+  '';
+
+  isPreLVM = f: f.preLVM;
+  preLVM = filter isPreLVM luks.devices;
+  postLVM = filter (f: !(isPreLVM f)) luks.devices;
+
+in
+{
+
+  options = {
+    boot.initrd.luks.enable = mkOption {
+      default = false;
+      description = "Obsolete.";
+    };
+
+    boot.initrd.luks.mitigateDMAAttacks = mkOption {
+      default = true;
+      description = ''
+        Unless enabled, encryption keys can be easily recovered by an attacker with physical
+        access to any machine with PCMCIA, ExpressCard, ThunderBolt or FireWire port.
+        More information: http://en.wikipedia.org/wiki/DMA_attack
+
+        This option blacklists FireWire drivers, but doesn't remove them. You can manually
+        load the drivers if you need to use a FireWire device, but don't forget to unload them!
+      '';
+    };
+
+    boot.initrd.luks.cryptoModules = mkOption {
+      default =
+        [ "aes" "aes_generic" "blowfish" "twofish"
+          "serpent" "cbc" "xts" "lrw" "sha1" "sha256" "sha512"
+          (if pkgs.stdenv.system == "x86_64-linux" then "aes_x86_64" else "aes_i586")
+        ];
+      description = ''
+        A list of cryptographic kernel modules needed to decrypt the root device(s).
+        The default includes all common modules.
+      '';
+    };
+
+    boot.initrd.luks.devices = mkOption {
+      default = [ ];
+      example = [ { name = "luksroot"; device = "/dev/sda3"; preLVM = true; } ];
+      description = ''
+        The list of devices that should be decrypted using LUKS before trying to mount the
+        root partition. This works for both LVM-over-LUKS and LUKS-over-LVM setups.
+
+        The devices are decrypted to the device mapper names defined.
+
+        Make sure that initrd has the crypto modules needed for decryption.
+      '';
+
+      type = types.listOf types.optionSet;
+
+      options = {
+
+        name = mkOption {
+          example = "luksroot";
+          type = types.string;
+          description = "Named to be used for the generated device in /dev/mapper.";
+        };
+
+        device = mkOption {
+          example = "/dev/sda2";
+          type = types.string;
+          description = "Path of the underlying block device.";
+        };
+
+        keyFile = mkOption {
+          default = null;
+          example = "/dev/sdb1";
+          type = types.nullOr types.string;
+          description = ''
+            The name of the file (can be a raw device or a partition) that
+            should be used as the decryption key for the encrypted device. If
+            not specified, you will be prompted for a passphrase instead.
+          '';
+        };
+
+        keyFileSize = mkOption {
+          default = null;
+          example = 4096;
+          type = types.nullOr types.int;
+          description = ''
+            The size of the key file. Use this if only the beginning of the
+            key file should be used as a key (often the case if a raw device
+            or partition is used as key file). If not specified, the whole
+            <literal>keyFile</literal> will be used decryption, instead of just
+            the first <literal>keyFileSize</literal> bytes.
+          '';
+        };
+
+        preLVM = mkOption {
+          default = true;
+          type = types.bool;
+          description = "Whether the luksOpen will be attempted before LVM scan or after it.";
+        };
+
+        allowDiscards = mkOption {
+          default = false;
+          type = types.bool;
+          description = ''
+            Whether to allow TRIM requests to the underlying device. This option
+            has security implications, please read the LUKS documentation before
+            activating in.
+          '';
+        };
+
+      };
+    };
+  };
+
+  config = mkIf (luks.devices != []) {
+
+    # actually, sbp2 driver is the one enabling the DMA attack, but this needs to be tested
+    boot.blacklistedKernelModules = optionals luks.mitigateDMAAttacks
+      ["firewire_ohci" "firewire_core" "firewire_sbp2"];
+
+    # Some modules that may be needed for mounting anything ciphered
+    boot.initrd.availableKernelModules = [ "dm_mod" "dm_crypt" "cryptd" ] ++ luks.cryptoModules;
+
+    # copy the cryptsetup binary and it's dependencies
+    boot.initrd.extraUtilsCommands = ''
+      cp -pdv ${pkgs.cryptsetup}/sbin/cryptsetup $out/bin
+      # XXX: do we have a function that does this?
+      for lib in $(ldd $out/bin/cryptsetup |grep '=>' |grep /nix/store/ |cut -d' ' -f3); do
+        cp -pdvn $lib $out/lib
+        cp -pvn $(readlink -f $lib) $out/lib
+      done
+    '';
+
+    boot.initrd.extraUtilsCommandsTest = ''
+      $out/bin/cryptsetup --version
+    '';
+
+    boot.initrd.preLVMCommands = concatMapStrings openCommand preLVM;
+    boot.initrd.postDeviceCommands = concatMapStrings openCommand postLVM;
+
+    environment.systemPackages = [ pkgs.cryptsetup ];
+  };
+}