nixos/tee-supplicant: add tee-supplicant module
The tee-supplicant is a program that interacts with OP-TEE OS and allows loading trusted applications at runtime (among other things). There is an `optee` test included that uses the pkcs11 trusted application (in upstream OP-TEE OS), loads it during system startup via tee-supplicant, and uses `pkcs11-tool` to list available token slots.
This commit is contained in:
parent
516e9fae60
commit
b8937303ce
@ -222,6 +222,8 @@ Alongside many enhancements to NixOS modules and general system improvements, th
|
|||||||
|
|
||||||
- [Limine](https://github.com/limine-bootloader/limine) a modern, advanced, portable, multiprotocol bootloader and boot manager. Available as [boot.loader.limine](#opt-boot.loader.limine.enable).
|
- [Limine](https://github.com/limine-bootloader/limine) a modern, advanced, portable, multiprotocol bootloader and boot manager. Available as [boot.loader.limine](#opt-boot.loader.limine.enable).
|
||||||
|
|
||||||
|
- [tee-supplicant](https://github.com/OP-TEE/optee_client), a userspace supplicant for OP-TEE OS. Available as [services.tee-supplicant](#opt-services.tee-supplicant.enable).
|
||||||
|
|
||||||
- [Orthanc](https://orthanc.uclouvain.be/) a lightweight, RESTful DICOM server for healthcare and medical research. Available as [services.orthanc](#opt-services.orthanc.enable).
|
- [Orthanc](https://orthanc.uclouvain.be/) a lightweight, RESTful DICOM server for healthcare and medical research. Available as [services.orthanc](#opt-services.orthanc.enable).
|
||||||
|
|
||||||
- [Docling Serve](https://github.com/docling-project/docling-serve) running [Docling](https://github.com/docling-project/docling) as an API service. Available as [services.docling-serve](#opt-services.docling-serve.enable).
|
- [Docling Serve](https://github.com/docling-project/docling-serve) running [Docling](https://github.com/docling-project/docling) as an API service. Available as [services.docling-serve](#opt-services.docling-serve.enable).
|
||||||
|
@ -930,6 +930,7 @@
|
|||||||
./services/misc/taskchampion-sync-server.nix
|
./services/misc/taskchampion-sync-server.nix
|
||||||
./services/misc/taskserver
|
./services/misc/taskserver
|
||||||
./services/misc/tautulli.nix
|
./services/misc/tautulli.nix
|
||||||
|
./services/misc/tee-supplicant
|
||||||
./services/misc/tiddlywiki.nix
|
./services/misc/tiddlywiki.nix
|
||||||
./services/misc/tp-auto-kbbl.nix
|
./services/misc/tp-auto-kbbl.nix
|
||||||
./services/misc/transfer-sh.nix
|
./services/misc/transfer-sh.nix
|
||||||
|
95
nixos/modules/services/misc/tee-supplicant/default.nix
Normal file
95
nixos/modules/services/misc/tee-supplicant/default.nix
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib)
|
||||||
|
getExe'
|
||||||
|
mkEnableOption
|
||||||
|
mkIf
|
||||||
|
mkOption
|
||||||
|
mkPackageOption
|
||||||
|
types
|
||||||
|
;
|
||||||
|
|
||||||
|
cfg = config.services.tee-supplicant;
|
||||||
|
|
||||||
|
taDir = "optee_armtz";
|
||||||
|
|
||||||
|
trustedApplications = pkgs.linkFarm "runtime-trusted-applications" (
|
||||||
|
map (
|
||||||
|
ta:
|
||||||
|
let
|
||||||
|
# This is safe since we are using it as the path value, so the context
|
||||||
|
# will still ensure that this nix store path exists on the running
|
||||||
|
# system.
|
||||||
|
taFile = builtins.baseNameOf (builtins.unsafeDiscardStringContext ta);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = "lib/${taDir}/${taFile}";
|
||||||
|
path = ta;
|
||||||
|
}
|
||||||
|
) cfg.trustedApplications
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.services.tee-supplicant = {
|
||||||
|
enable = mkEnableOption "OP-TEE userspace supplicant";
|
||||||
|
|
||||||
|
package = mkPackageOption pkgs "optee-client" { };
|
||||||
|
|
||||||
|
trustedApplications = mkOption {
|
||||||
|
type = types.listOf types.path;
|
||||||
|
default = [ ];
|
||||||
|
description = ''
|
||||||
|
A list of full paths to trusted applications that will be loaded at
|
||||||
|
runtime by tee-supplicant.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
pluginPath = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = "/run/current-system/sw/lib/tee-supplicant/plugins";
|
||||||
|
description = ''
|
||||||
|
The directory where plugins will be loaded from on startup.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
reeFsParentPath = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = "/var/lib/tee";
|
||||||
|
description = ''
|
||||||
|
The directory where the secure filesystem will be stored in the rich
|
||||||
|
execution environment (REE FS).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
environment = mkIf (cfg.trustedApplications != [ ]) {
|
||||||
|
systemPackages = [ trustedApplications ];
|
||||||
|
pathsToLink = [ "/lib/${taDir}" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.tee-supplicant = {
|
||||||
|
description = "Userspace supplicant for OPTEE-OS";
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = toString [
|
||||||
|
(getExe' cfg.package "tee-supplicant")
|
||||||
|
"--ta-dir ${taDir}"
|
||||||
|
"--fs-parent-path ${cfg.reeFsParentPath}"
|
||||||
|
"--plugin-path ${cfg.pluginPath}"
|
||||||
|
];
|
||||||
|
Restart = "always";
|
||||||
|
};
|
||||||
|
|
||||||
|
after = [ "modprobe@optee.service" ];
|
||||||
|
wants = [ "modprobe@optee.service" ];
|
||||||
|
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@ -1064,6 +1064,7 @@ in
|
|||||||
openvscode-server = runTest ./openvscode-server.nix;
|
openvscode-server = runTest ./openvscode-server.nix;
|
||||||
open-webui = runTest ./open-webui.nix;
|
open-webui = runTest ./open-webui.nix;
|
||||||
openvswitch = runTest ./openvswitch.nix;
|
openvswitch = runTest ./openvswitch.nix;
|
||||||
|
optee = handleTestOn [ "aarch64-linux" ] ./optee.nix { };
|
||||||
orangefs = runTest ./orangefs.nix;
|
orangefs = runTest ./orangefs.nix;
|
||||||
os-prober = handleTestOn [ "x86_64-linux" ] ./os-prober.nix { };
|
os-prober = handleTestOn [ "x86_64-linux" ] ./os-prober.nix { };
|
||||||
osquery = handleTestOn [ "x86_64-linux" ] ./osquery.nix { };
|
osquery = handleTestOn [ "x86_64-linux" ] ./osquery.nix { };
|
||||||
|
72
nixos/tests/optee.nix
Normal file
72
nixos/tests/optee.nix
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import ./make-test-python.nix (
|
||||||
|
{ pkgs, lib, ... }:
|
||||||
|
{
|
||||||
|
name = "optee";
|
||||||
|
|
||||||
|
meta = with pkgs.lib.maintainers; {
|
||||||
|
maintainers = [ jmbaur ];
|
||||||
|
};
|
||||||
|
|
||||||
|
nodes.machine =
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
let
|
||||||
|
inherit (pkgs) armTrustedFirmwareQemu opteeQemuAarch64 ubootQemuAarch64;
|
||||||
|
|
||||||
|
# Default environment for qemu-arm64 uboot does not work well with
|
||||||
|
# large nixos kernel/initrds.
|
||||||
|
uboot = ubootQemuAarch64.overrideAttrs (old: {
|
||||||
|
postPatch =
|
||||||
|
(old.postPatch or "")
|
||||||
|
+ ''
|
||||||
|
substituteInPlace board/emulation/qemu-arm/qemu-arm.env \
|
||||||
|
--replace-fail "ramdisk_addr_r=0x44000000" "ramdisk_addr_r=0x46000000"
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
|
||||||
|
bios = armTrustedFirmwareQemu.override {
|
||||||
|
extraMakeFlags = [
|
||||||
|
"SPD=opteed"
|
||||||
|
"BL32=${opteeQemuAarch64}/tee-header_v2.bin"
|
||||||
|
"BL32_EXTRA1=${opteeQemuAarch64}/tee-pager_v2.bin"
|
||||||
|
"BL32_EXTRA2=${opteeQemuAarch64}/tee-pageable_v2.bin"
|
||||||
|
"BL33=${uboot}/u-boot.bin"
|
||||||
|
"all"
|
||||||
|
"fip"
|
||||||
|
];
|
||||||
|
filesToInstall = [
|
||||||
|
"build/qemu/release/bl1.bin"
|
||||||
|
"build/qemu/release/fip.bin"
|
||||||
|
];
|
||||||
|
postInstall = ''
|
||||||
|
dd if=$out/bl1.bin of=$out/bios.bin bs=4096 conv=notrunc
|
||||||
|
dd if=$out/fip.bin of=$out/bios.bin seek=64 bs=4096 conv=notrunc
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
virtualisation = {
|
||||||
|
inherit bios;
|
||||||
|
cores = 2;
|
||||||
|
qemu.options = [
|
||||||
|
"-machine virt,secure=on,accel=tcg,gic-version=2"
|
||||||
|
"-cpu cortex-a57"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# VM boots up via qfw
|
||||||
|
boot.loader.grub.enable = false;
|
||||||
|
|
||||||
|
services.tee-supplicant = {
|
||||||
|
enable = true;
|
||||||
|
# pkcs11 trusted application
|
||||||
|
trustedApplications = [ "${opteeQemuAarch64.devkit}/ta/fd02c9da-306c-48c7-a49c-bbd827ae86ee.ta" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
testScript = ''
|
||||||
|
machine.wait_for_unit("tee-supplicant.service")
|
||||||
|
out = machine.succeed("${pkgs.opensc}/bin/pkcs11-tool --module ${lib.getLib pkgs.optee-client}/lib/libckteec.so --list-token-slots")
|
||||||
|
if out.find("OP-TEE PKCS11 TA") < 0:
|
||||||
|
raise Exception("optee pkcs11 token not found")
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user