summaryrefslogtreecommitdiff
path: root/sys/boot/tpm.nix
blob: 4093e47c40ad06b761a606973f02ba783e77d711 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
{ 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.openssl pkgs.tpm2-tools ];

    text = ''
      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);
        default = [ 0 2 7 8 11 ];
      };
    };
  };

  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;
    };
  };
}