nixpkgs/nixos/modules/security/tpm2.nix
Morgan Jones 423873feaa nixos/tpm2: default pkcs#11 module based on abrmd config
Since there are now variants of tpm2-pkcs11 with and without ABRMD
support (for the kernel resource manager), ensure we pick the correct
default.

Fixes an accidental backwards incompatibility with the module.

(cherry picked from commit 9c1564e395)
2025-05-22 00:37:29 +05:30

190 lines
5.8 KiB
Nix

{
lib,
pkgs,
config,
...
}:
let
cfg = config.security.tpm2;
# This snippet is taken from tpm2-tss/dist/tpm-udev.rules, but modified to allow custom user/groups
# The idea is that the tssUser is allowed to access the TPM and kernel TPM resource manager, while
# the tssGroup is only allowed to access the kernel resource manager
# Therefore, if either of the two are null, the respective part isn't generated
udevRules = tssUser: tssGroup: ''
${lib.optionalString (tssUser != null) ''KERNEL=="tpm[0-9]*", MODE="0660", OWNER="${tssUser}"''}
${
lib.optionalString (tssUser != null || tssGroup != null) ''KERNEL=="tpmrm[0-9]*", MODE="0660"''
+ lib.optionalString (tssUser != null) '', OWNER="${tssUser}"''
+ lib.optionalString (tssGroup != null) '', GROUP="${tssGroup}"''
}
'';
in
{
options.security.tpm2 = {
enable = lib.mkEnableOption "Trusted Platform Module 2 support";
tssUser = lib.mkOption {
description = ''
Name of the tpm device-owner and service user, set if applyUdevRules is
set.
'';
type = lib.types.nullOr lib.types.str;
default = if cfg.abrmd.enable then "tss" else "root";
defaultText = lib.literalExpression ''if config.security.tpm2.abrmd.enable then "tss" else "root"'';
};
tssGroup = lib.mkOption {
description = ''
Group of the tpm kernel resource manager (tpmrm) device-group, set if
applyUdevRules is set.
'';
type = lib.types.nullOr lib.types.str;
default = "tss";
};
applyUdevRules = lib.mkOption {
description = ''
Whether to make the /dev/tpm[0-9] devices accessible by the tssUser, or
the /dev/tpmrm[0-9] by tssGroup respectively
'';
type = lib.types.bool;
default = true;
};
abrmd = {
enable = lib.mkEnableOption ''
Trusted Platform 2 userspace resource manager daemon
'';
package = lib.mkOption {
description = "tpm2-abrmd package to use";
type = lib.types.package;
default = pkgs.tpm2-abrmd;
defaultText = lib.literalExpression "pkgs.tpm2-abrmd";
};
};
pkcs11 = {
enable = lib.mkEnableOption ''
TPM2 PKCS#11 tool and shared library in system path
(`/run/current-system/sw/lib/libtpm2_pkcs11.so`)
'';
package = lib.mkOption {
description = "tpm2-pkcs11 package to use";
type = lib.types.package;
default = if cfg.abrmd.enable then pkgs.tpm2-pkcs11.abrmd else pkgs.tpm2-pkcs11;
defaultText = lib.literalExpression "if config.security.tpm2.abrmd.enable then pkgs.tpm2-pkcs11.abrmd else pkgs.tpm2-pkcs11";
};
};
tctiEnvironment = {
enable = lib.mkOption {
description = ''
Set common TCTI environment variables to the specified value.
The variables are
- `TPM2TOOLS_TCTI`
- `TPM2_PKCS11_TCTI`
'';
type = lib.types.bool;
default = false;
};
interface = lib.mkOption {
description = ''
The name of the TPM command transmission interface (TCTI) library to
use.
'';
type = lib.types.enum [
"tabrmd"
"device"
];
default = "device";
};
deviceConf = lib.mkOption {
description = ''
Configuration part of the device TCTI, e.g. the path to the TPM device.
Applies if interface is set to "device".
The format is specified in the
[
tpm2-tools repository](https://github.com/tpm2-software/tpm2-tools/blob/master/man/common/tcti.md#tcti-options).
'';
type = lib.types.str;
default = "/dev/tpmrm0";
};
tabrmdConf = lib.mkOption {
description = ''
Configuration part of the tabrmd TCTI, like the D-Bus bus name.
Applies if interface is set to "tabrmd".
The format is specified in the
[
tpm2-tools repository](https://github.com/tpm2-software/tpm2-tools/blob/master/man/common/tcti.md#tcti-options).
'';
type = lib.types.str;
default = "bus_name=com.intel.tss2.Tabrmd";
};
};
};
config = lib.mkIf cfg.enable (
lib.mkMerge [
{
# PKCS11 tools and library
environment.systemPackages = lib.mkIf cfg.pkcs11.enable [
(lib.getBin cfg.pkcs11.package)
(lib.getLib cfg.pkcs11.package)
];
services.udev.extraRules = lib.mkIf cfg.applyUdevRules (udevRules cfg.tssUser cfg.tssGroup);
# Create the tss user and group only if the default value is used
users.users.${cfg.tssUser} = lib.mkIf (cfg.tssUser == "tss") {
isSystemUser = true;
group = "tss";
};
users.groups.${cfg.tssGroup} = lib.mkIf (cfg.tssGroup == "tss") { };
environment.variables = lib.mkIf cfg.tctiEnvironment.enable (
lib.attrsets.genAttrs
[
"TPM2TOOLS_TCTI"
"TPM2_PKCS11_TCTI"
]
(
_:
''${cfg.tctiEnvironment.interface}:${
if cfg.tctiEnvironment.interface == "tabrmd" then
cfg.tctiEnvironment.tabrmdConf
else
cfg.tctiEnvironment.deviceConf
}''
)
);
}
(lib.mkIf cfg.abrmd.enable {
systemd.services."tpm2-abrmd" = {
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "dbus";
Restart = "always";
RestartSec = 30;
BusName = "com.intel.tss2.Tabrmd";
ExecStart = "${cfg.abrmd.package}/bin/tpm2-abrmd";
User = "tss";
Group = "tss";
};
};
services.dbus.packages = lib.singleton cfg.abrmd.package;
})
]
);
meta.maintainers = with lib.maintainers; [ lschuermann ];
}