diff options
Diffstat (limited to 'sys/boot/tpm.nix')
| -rw-r--r-- | sys/boot/tpm.nix | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/sys/boot/tpm.nix b/sys/boot/tpm.nix new file mode 100644 index 0000000..ecc115b --- /dev/null +++ b/sys/boot/tpm.nix @@ -0,0 +1,128 @@ +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.local.boot.tpm; + + pcrList = concatStringsSep "," (map toString cfg.initrd.pcrs); + + # Crear signing-key con: + # $ openssl genrsa -out ~/vtmp/signing-key.priv 2048 + # $ openssl rsa -in ~/vtmp/signing-key.priv -out ~/vtmp/signing-key.pub -pubout + # Y copiar signing-key.pub a /boot/tpm-boot. Guardar signing-key.priv en lugar seguro. + # + # Crear llave con: + # $ tpm2_loadexternal -G rsa -C owner -u signing-key.pub -c signing-key.ctx -n signing-key.name + # $ tpm2_startauthsession -S session.ctx + # $ tpm2_policyauthorize -S session.ctx -L require-signed.policy -n signing-key.name + # $ tpm2_flushcontext session.ctx + # $ tpm2_createprimary -C owner -g sha256 -G ecc -c prim.ctx + # $ head -c128 /dev/urandom | tpm2_create -C prim.ctx -u key.pub -r key.priv -c key.ctx -L require-signed.policy -i- + # Y mover key.priv/key.pub a /boot/tpm-boot + # + # Usage: tpm2-grant-next-boot < signing-key.priv + # Genera auth.policy y auth.sig + tpm2-grant-next-boot = pkgs.writeShellApplication { + name = "tpm2-grant-next-boot"; + + runtimeInputs = [ + pkgs.jq + pkgs.openssl + pkgs.sbctl + pkgs.tpm2-tools + ]; + + text = '' + if [ -z "''${YES_I_DO_WANT_TO_SIGN_WITH_SECURE_BOOT_DISABLED:=}" ] && [ "$(sbctl status --json | jq .secure_boot)" != "truee" ]; then + echo "$0: bad Secure Boot state, check the output of \`sbctl status\`" >&2 + echo "$0: signing a TPM PCR policy with Secure Boot disabled is dangerous" >&2 + echo "$0: set 'YES_I_DO_WANT_TO_SIGN_WITH_SECURE_BOOT_DISABLED' to skip this check" >&2 + exit 1 + fi + + ctx_dir="$(mktemp -d)" + trap 'rm -rf -- "$ctx_dir"' EXIT + + tpm2_createprimary -Q -C owner -g sha256 -G ecc -c "$ctx_dir/prim.ctx" + + tpm2_startauthsession -Q -S "$ctx_dir/session.ctx" + tpm_resets=$(tpm2_readclock | grep reset_count | sed 's/.*: //') + tpm2_policycountertimer -Q -S "$ctx_dir/session.ctx" resets="$((tpm_resets+1))" + tpm2_policypcr -Q -S "$ctx_dir/session.ctx" -L auth.policy -l sha256:${pcrList} + tpm2_flushcontext -Q "$ctx_dir/session.ctx" + + openssl dgst -sha256 -sign /dev/stdin -out auth.sig auth.policy + ''; + }; +in { + options.local.boot.tpm = { + enable = mkEnableOption "Trusted Platform Module 2.0"; + + driver = mkOption { + type = types.enum ["tis" "crb"]; + }; + + initrd = { + enable = mkEnableOption "TPM2 in initrd"; + + pcrs = mkOption { + type = with types; listOf (ints.between 0 23); + + # From 'systemd-analyze pcrs' + default = [ + 0 # platform-code + 1 # platform-config + 2 # external-code + 3 # external-config + 4 # boot-loader-code + 5 # boot-loader-config + 7 # secure-boot-policy + 9 # kernel-initrd + 11 # kernel-boot + 12 # kernel-config + 13 # sysexts + 14 # shim-policy + ]; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + { + assertion = config.local.boot.efi.enable; + message = "TPM2 requires EFI"; + } + { + assertion = cfg.initrd.enable -> cfg.enable; + message = "TPM2 in initrd requires TPM2"; + } + ]; + + boot.initrd = mkIf cfg.initrd.enable { + extraUtilsCommands = '' + copy_bin_and_libs ${pkgs.tpm2-tools}/bin/.tpm2-wrapped + mv $out/bin/{.tpm2-wrapped,tpm2} + cp {${pkgs.tpm2-tss},$out}/lib/libtss2-tcti-device.so.0 + ''; + + kernelModules = [ + "tpm_${cfg.driver}" + ]; + }; + + environment.systemPackages = optionals cfg.initrd.enable [ + tpm2-grant-next-boot + ]; + + security.tpm2 = { + enable = true; + + pkcs11.enable = true; + tctiEnvironment.enable = true; + }; + }; +} |
