Talk: Yubikey based Full Disk Encryption (FDE) on NixOS

From NixOS Wiki
Jump to: navigation, search

I've also added a nix expression to set up a shell:

https://github.com/sgillespie/nixos-yubikey-luks

If it's useful I can add it here

With sgillespie's repo, I created a disko config (more install instructions in my repo at https://github.com/David-Kopczynski/nix/tree/ab49a243d25caf5879eee5191d8a3424e299c752/hosts/laptop):

{
  pkgs ? import <nixpkgs> { },
  ...
}:

{
  disko.devices.disk =
    # Default disk setup using EFI partition with LUKS
    {
      "system" = {
        device = "/dev/nvme0n1";
        type = "disk";
        preCreateHook = ''
          mkdir -p /tmp/disko

          ITERATIONS=1000000

          rbtohex() { ( od -An -vtx1 | tr -d ' \n' ) }
          hextorb() { ( tr '[:lower:]' '[:upper:]' | sed -e 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI'| xargs printf ) }

          SALT="$(dd if=/dev/random bs=1 count=16 2>/dev/null | rbtohex)"
          CHALLENGE="$(echo -n "$SALT" | ${with pkgs; openssl}/bin/openssl dgst -binary -sha512 | rbtohex)"
          RESPONSE=$(${with pkgs; yubikey-personalization}/bin/ykchalresp -2 -x "$CHALLENGE" 2>/dev/null)
          LUKS_KEY="$(echo | ${
            pkgs.callPackage "${
              pkgs.fetchFromGitHub {
                owner = "sgillespie";
                repo = "nixos-yubikey-luks";
                rev = "master";
                sha256 = "sha256-qmvBrvSo30kW+meehETdgjvxCmrWrc5cBBGdViJ39gU=";
              }
            }/pbkdf2-sha512" { }
          }/bin/pbkdf2-sha512 $((512 / 8)) $ITERATIONS "$RESPONSE" | rbtohex)"

          echo -n "$LUKS_KEY" | hextorb > /tmp/disko/key-file
          echo -ne "$SALT\n$ITERATIONS" > /tmp/disko/crypt-storage
        '';
        postCreateHook = ''
          rm /tmp/disko/key-file
        '';
        postMountHook = ''
          mkdir -p /mnt/boot/crypt-storage
          cp /tmp/disko/crypt-storage /mnt/boot/crypt-storage/default
        '';
        content = {
          type = "gpt";
          partitions = {
            "ESP" = {
              priority = 1;
              size = "512M";
              type = "EF00";
              content = {
                type = "filesystem";
                format = "vfat";
                mountpoint = "/boot";
                mountOptions = [ "umask=0077" ];
              };
            };
            "crypted" = {
              priority = 2;
              size = "100%";
              content = {
                type = "luks";
                name = "crypted";
                extraOpenArgs = [
                  "--cipher aes-xts-plain64"
                  "--key-size 512"
                  "--hash sha512"
                ];
                settings = {
                  allowDiscards = true;
                  keyFile = "/tmp/disko/key-file";
                };
                content = {
                  type = "lvm_pv";
                  vg = "vg";
                };
              };
            };
          };
        };
      };
    };

  disko.devices.lvm_vg =
    # Simple LVM setup on top of LUKS
    {
      "vg" = {
        type = "lvm_vg";
        lvs = {
          "root" = {
            size = "100%";
            content = {
              type = "filesystem";
              format = "ext4";
              mountpoint = "/";
              mountOptions = [ "defaults" ];
            };
          };
          "swap" = {
            size = "32G";
            content = {
              type = "swap";
              resumeDevice = true;
            };
          };
        };
      };
    };
}

(This generates the LUKS key with the YubiKey plugged in and places the seed + iteration count at the correct location!)

Can I update/improve this page

Hi! I'm fairly new to nix/NixOS and tried this guide to rebuild my Yubikey based decryption which I previously used in Arch. While following the guide, I found some issues and also see some improvements:

  • while the SLOT is definded as env variable, the "2" is hardcoded in the yubikey commands
  • the /dev/partition paths didn't work on my VM using NixOS 23.05, I'd use the "old" paths /dev/mapper/<name> instead
  • I would add a section that tries to close and reopen the luks device with the new credentials to test if the setup was successful
  • I would add a section which adds a password as a Backup decryption method (addresses https://github.com/sgillespie/nixos-yubikey-luks/issues/7)

Can I simply edit the page with those changes or is there some PR/review process for the wiki pages?