Full Disk Encryption: Difference between revisions

Golbinex (talk | contribs)
mNo edit summary
 
(14 intermediate revisions by 9 users not shown)
Line 1: Line 1:
There are a few options for full disk encryption. The easiest way is to use the graphical installer and choose „encrypt“ while doing the installation.
There are a few options for full disk encryption. The easiest way is to use the graphical installer and choose "encrypt" while doing the installation.


= Enter password on Boot (LVM on LUKS) =
= LVM on LUKS =


In this example, everything except for the <code>/boot</code> partition is encrypted.
In this example, everything except for the <code>/boot</code> partition is encrypted.
Line 22: Line 22:
     └─vg-root 254:2    0 225.3G  0 lvm  /
     └─vg-root 254:2    0 225.3G  0 lvm  /
</syntaxhighlight>
</syntaxhighlight>
== Enter password on Boot ==


The initrd needs to be configured to unlock the encrypted <code>/dev/sda2</code> partition during stage 1 of the boot process.
The initrd needs to be configured to unlock the encrypted <code>/dev/sda2</code> partition during stage 1 of the boot process.
Line 27: Line 29:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
    boot = {
boot = {
      loader = {
  loader = {
        efi.canTouchEfiVariables = true;
    efi.canTouchEfiVariables = true;
        grub = {
    grub = {
          enable = true;
      enable = true;
          device = "nodev";
      device = "nodev";
          efiSupport = true;
      efiSupport = true;
        };
      };
      initrd.luks.devices.cryptroot.device = "/dev/disk/by-uuid/UUID-OF-SDA2";
     };
     };
  };
  initrd.luks.devices.cryptroot.device = "/dev/disk/by-uuid/UUID-OF-SDA2";
};
</syntaxhighlight>
</syntaxhighlight>


With <code lang="nix">initrd.luks.devices.cryptroot.device = "/dev/disk/by-uuid/UUID-OF-SDA2";</code>, the initrd knows it must unlock <code>/dev/sda2</code> before activating LVM and proceeding with the boot process.
With <code lang="nix">initrd.luks.devices.cryptroot.device = "/dev/disk/by-uuid/UUID-OF-SDA2";</code>, the initrd knows it must unlock <code>/dev/sda2</code> before activating LVM and proceeding with the boot process.


= Unattended Boot via USB =
== Unattended Boot via USB ==


Sometimes it is necessary to boot a system without needing an keyboard and monitor. You will create a secret key, add it to a key slot and put it onto an USB stick.
Sometimes it is necessary to boot a system without needing a keyboard and monitor. You will create a secret key, add it to a key slot and put it onto a USB stick.


<syntaxhighlight lang="bash">
<syntaxhighlight lang=console>
dd if=/dev/random of=hdd.key bs=4096 count=1
# dd if=/dev/random of=hdd.key bs=4096 count=1
cryptsetup luksAddKey /dev/sda1 ./hdd.key
# cryptsetup luksAddKey /dev/sda1 ./hdd.key
</syntaxhighlight>You can enable fallback to password (in case the USB stick is lost or corrupted) by setting the <code>boot.initrd.luks.devices.<name>.fallbackToPassword</code> option to <code>true</code>. By default, this option is <code>false</code> so you will have to perform a manual recovery if the USB stick becomes unavailable (which you may prefer, depending on your use case).
</syntaxhighlight>You can enable fallback to password (in case the USB stick is lost or corrupted) by setting the <code>boot.initrd.luks.devices.<name>.fallbackToPassword</code> option to <code>true</code>. By default, this option is <code>false</code> so you will have to perform a manual recovery if the USB stick becomes unavailable (which you may prefer, depending on your use case).


== Option 1: Write key onto the start of the stick ==
=== Option 1: Write key onto the start of the stick ===


This will make the usb-stick unusable for any other operations than being used for decryption. Write the key onto the stick:
This will make the USB stick unusable for any other operations than being used for decryption. Write the key onto the stick:


<syntaxhighlight lang="bash">
<syntaxhighlight lang=console>
dd if=hdd.key of=/dev/sdb
# dd if=hdd.key of=/dev/sdb
</syntaxhighlight>
</syntaxhighlight>


Line 80: Line 82:
}</syntaxhighlight>
}</syntaxhighlight>


== Option 2: Copy Key as file onto a vfat usb stick ==
=== Option 2: Copy Key as file onto a vfat USB stick ===


If you want to use your stick for other stuff or it already has other keys on it you can use the following method by Tzanko Matev. Add this to your <code>configuration.nix</code>:
If you want to use your stick for other stuff or it already has other keys on it you can use the following method by Tzanko Matev. Add this to your <code>configuration.nix</code>:
Line 98: Line 100:
   boot.initrd.postDeviceCommands = pkgs.lib.mkBefore ''
   boot.initrd.postDeviceCommands = pkgs.lib.mkBefore ''
     mkdir -m 0755 -p /key
     mkdir -m 0755 -p /key
     sleep 2 # To make sure the usb key has been loaded
     sleep 2 # To make sure the USB key has been loaded
     mount -n -t vfat -o ro `findfs UUID=${PRIMARYUSBID}` /key || mount -n -t vfat -o ro `findfs UUID=${BACKUPUSBID}` /key
     mount -n -t vfat -o ro `findfs UUID=${PRIMARYUSBID}` /key || mount -n -t vfat -o ro `findfs UUID=${BACKUPUSBID}` /key
   '';
   '';
Line 109: Line 111:
</syntaxhighlight>
</syntaxhighlight>


= Unattended Boot via keyfile =
== Unattended Boot via keyfile ==


A simpler but insecure option for unattended boots is to copy the keyfile into the initrd itself.
A simpler but insecure option for unattended boots is to copy the keyfile into the initrd itself.
Line 116: Line 118:


First move the key to a safe location.
First move the key to a safe location.
<syntaxhighlight lang="bash">
<syntaxhighlight lang=console>
mkdir /var/lib/secrets
# mkdir /var/lib/secrets
chown root:root /var/lib/secrets
# chown root:root /var/lib/secrets
chmod 700 /var/lib/secrets
# chmod 700 /var/lib/secrets
mv -v hdd.key /var/lib/secrets/
# mv -v hdd.key /var/lib/secrets/
chmod 600 /var/lib/secrets/hdd.key
# chmod 600 /var/lib/secrets/hdd.key
</syntaxhighlight>
</syntaxhighlight>


Line 136: Line 138:
   boot.initrd.secrets = { "/${keyFile}" = /var/lib/secrets/${keyFile}; };
   boot.initrd.secrets = { "/${keyFile}" = /var/lib/secrets/${keyFile}; };
}
}
</syntaxhighlight>
== Store key on FIDO2 device or TPM ==
Unattended boot can also happen with a FIDO2 device (e.g. Yubikey) or TPM. This cannot be performed in a fully declarative way because every such security device is unique; some manual running of <code>systemd-cryptenroll</code> is required.
For FIDO2, directly read the [https://github.com/NixOS/nixpkgs/blob/7be68f763d94cdb4c809b7980647828e3274a511/nixos/doc/manual/configuration/luks-file-systems.section.md chapter in the official manual].
=== TPM2 ===
To store a key on the TPM2 module to unlock the device unattended, first find the UUID values of the encrypted LUKS devices. One way to do this is by running the <code>lsblk</code> command and seeing an output similar to:
<pre>
NAME                                          MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINTS
nvme0n1                                      259:0    0  1.8T  0 disk 
├─nvme0n1p1                                  259:1    0    1G  0 part  /boot
├─nvme0n1p2                                  259:2    0  1.8T  0 part 
│ └─luks-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 254:1    0  1.8T  0 crypt /nix/store
│                                                                      /
└─nvme0n1p3                                  259:3    0    8G  0 part 
  └─luks-yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy 254:0    0  7.9G  0 crypt [SWAP]
</pre>
You are looking for devices in the format of <code>luks-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</code> where <code>xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</code> is replaced with an actual UUID. There may be multiple of these drives, in which case complete the following step on each device individually if unlocking via TPM2 is desired for all (in this example there are two devices due to the encrypted swap).
Run the following command but replace <code>YOUR-UUID</code> with the UUID you found in the previous step '''without the <code>luks-</code> at the start''':
<syntaxhighlight lang=console>
# systemd-cryptenroll --wipe-slot=tpm2 --tpm2-device=auto /dev/disk/by-uuid/YOUR-UUID
</syntaxhighlight>
Now the device should unlock without prompting you for the password. After this is working, you should add certain restrictions to your saved key using Platform Configuration Registers (PCR). All options for these can be found at the [https://uapi-group.org/specifications/specs/linux_tpm_pcr_registry/ Linux TPM PCR Registry]. If using the default <code>systemd-boot</code> without [[Secure Boot]], then a standard set of options to use is <code>4+9+12</code>. This can be applied by running the above command again with <code>--tpm2-pcrs=4+9+12</code>. If your system uses secure boot with [[Limine]] you may want to use <code>--tpm2-pcrs=4+7+8+9</code> instead.
Because the TPM is attached to your computer, it provides no protection against a stolen computer when used on its own (it usually allows for setting a password, but that is it). It can only protect against a stolen drive.
= Encrypted /boot =
[https://libreboot.org/ Libreboot] supports decrypting boot partition with built-in GRUB.
Example layout of unified LUKS-encrypted btrfs partition:
* boot subvolume mounted at /boot
* home subvolume mounted at /home
* nix subvolume mounted at /nix
* swap subvolume mounted at /swap
NixOS-generated grub.cfg may cause problems when loaded with Libreboot GRUB, so using extlinux configuration file is recommended instead.<syntaxhighlight lang="nix">
boot.loader.grub.enable = false;
boot.loader.generic-extlinux-compatible.enable = true;
</syntaxhighlight>Partition can be decrypted and booted with following GRUB commands:<syntaxhighlight lang="console">
# cryptomount -a
# try_bootcfg crypto0 # assuming configuration file is located at /boot/extlinux/extlinux.conf
</syntaxhighlight>
</syntaxhighlight>


Line 153: Line 203:
Boot the NixOS installer and partition things according to your taste. What we are then going to do is prepare sda4 with a luks encryption layer:
Boot the NixOS installer and partition things according to your taste. What we are then going to do is prepare sda4 with a luks encryption layer:


<syntaxhighlight lang="bash">
<syntaxhighlight lang=console>
# format the partition with the luks structure
# # format the partition with the luks structure
cryptsetup luksFormat /dev/sda4
# cryptsetup luksFormat /dev/sda4
# open the encrypted partition and map it to /dev/mapper/cryptroot
# # open the encrypted partition and map it to /dev/mapper/cryptroot
cryptsetup luksOpen /dev/sda4 cryptroot
# cryptsetup luksOpen /dev/sda4 cryptroot
# format as usual
# # format as usual
mkfs.ext4 -L nixos /dev/mapper/cryptroot
# mkfs.ext4 -L nixos /dev/mapper/cryptroot
# mount
# # mount
mount /dev/disk/by-label/nixos /mnt
# mount /dev/disk/by-label/nixos /mnt
mkdir /mnt/boot
# mkdir /mnt/boot
mount /dev/sda1 /mnt/boot
# mount /dev/sda1 /mnt/boot
</syntaxhighlight>
</syntaxhighlight>


Now keep installing as usual, nixos-generate-config should detect the right partitioning. You should have something like this in your /etc/nixos/hardware-configuration.nix:
Now keep installing as usual, nixos-generate-config should detect the right partitioning. You should have something like this in your /etc/nixos/hardware-configuration.nix:


<syntaxhighlight lang="nix">
{{file|configuration.nix|nix|3=
{ # cut
{ # cut
   fileSystems."/" =
   fileSystems."/" =
Line 184: Line 234:
   swapDevices = [ ];
   swapDevices = [ ];
}
}
</syntaxhighlight>
}}


To create a swap add the following in your /etc/nixos/configuration.nix:
To create a swap add the following in your /etc/nixos/configuration.nix:
<syntaxhighlight lang="nix">
{{file|configuration.nix|nix|3=
{
{
   swapDevices = [{device = "/swapfile"; size = 10000;}];
   swapDevices = [{device = "/swapfile"; size = 10000;}];
}
}
</syntaxhighlight>
}}


== Perf test ==
== Perf test ==


<syntaxhighlight lang="bash">
<syntaxhighlight lang=console>
# compare
$ # compare
nix-shell -p hdparm --run "hdparm -Tt /dev/mapper/cryptroot"
$ nix-shell -p hdparm --run "hdparm -Tt /dev/mapper/cryptroot"
# with
$ # with
nix-shell -p hdparm --run "hdparm -Tt /dev/sda1"
$ nix-shell -p hdparm --run "hdparm -Tt /dev/sda1"
</syntaxhighlight>
</syntaxhighlight>


Line 218: Line 268:


Encrypt the drive and create the filesystem on it (LVM is used in this example):
Encrypt the drive and create the filesystem on it (LVM is used in this example):
<syntaxhighlight lang="bash">
<syntaxhighlight lang=console>
cryptsetup luksFormat --label CRYPTSTORAGE /dev/sdb
# cryptsetup luksFormat --label CRYPTSTORAGE /dev/sdb
cryptsetup open /dev/sdb cryptstorage
# cryptsetup open /dev/sdb cryptstorage
pvcreate /dev/mapper/cryptstorage
# pvcreate /dev/mapper/cryptstorage
vgcreate vg-storage /dev/mapper/cryptstorage
# vgcreate vg-storage /dev/mapper/cryptstorage
lvcreate -l 100%FREE -n storage vg-storage
# lvcreate -l 100%FREE -n storage vg-storage
mkfs.ext4 -L STORAGE /dev/vg-storage/storage
# mkfs.ext4 -L STORAGE /dev/vg-storage/storage
</syntaxhighlight>
</syntaxhighlight>


Line 248: Line 298:


First, create a keyfile for your secondary drive, store it safely and add it as a LUKS key:
First, create a keyfile for your secondary drive, store it safely and add it as a LUKS key:
<syntaxhighlight lang="bash">
<syntaxhighlight lang=console>
dd bs=512 count=4 if=/dev/random of=/root/mykeyfile.key iflag=fullblock
# dd bs=512 count=4 if=/dev/random of=/root/mykeyfile.key iflag=fullblock
chmod 400 /root/mykeyfile.key
# chmod 400 /root/mykeyfile.key
cryptsetup luksAddKey /dev/sdb /root/mykeyfile.key
# cryptsetup luksAddKey /dev/sdb /root/mykeyfile.key
</syntaxhighlight>
</syntaxhighlight>


Line 257: Line 307:
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
{
{
  environment.etc.crypttab.text = ''
  environment.etc.crypttab.text = ''
     cryptstorage UUID=UUID-OF-SDB /root/mykeyfile.key
     cryptstorage UUID=UUID-OF-SDB /root/mykeyfile.key
   ''
   '';
}
}
</syntaxhighlight>
</syntaxhighlight>
Line 276: Line 326:
* [[Remote disk unlocking|Using Tor and SSH to unlock your LUKS Disk over the internet]].
* [[Remote disk unlocking|Using Tor and SSH to unlock your LUKS Disk over the internet]].
* [[Bcachefs]], filesystem which supports native encryption
* [[Bcachefs]], filesystem which supports native encryption
 
* [https://discourse.nixos.org/t/full-disk-encryption-tpm2/29454/2 Automatically unlock encrypted disks using TPM2]


[[Category:Desktop]]
[[Category:Desktop]]
[[Category:Server]]
[[Category:Server]]