nixos/tee-supplicant: add tee-supplicant module (and more) (#237613)

Changed files
+384 -4
nixos
doc
manual
release-notes
modules
services
misc
tee-supplicant
tests
pkgs
by-name
op
optee-client
misc
arm-trusted-firmware
optee-os
top-level
+2
nixos/doc/manual/release-notes/rl-2505.section.md
···
- [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).
- [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).
+1
nixos/modules/module-list.nix
···
./services/misc/taskchampion-sync-server.nix
./services/misc/taskserver
./services/misc/tautulli.nix
+
./services/misc/tee-supplicant
./services/misc/tiddlywiki.nix
./services/misc/tp-auto-kbbl.nix
./services/misc/transfer-sh.nix
+95
nixos/modules/services/misc/tee-supplicant/default.nix
···
+
{
+
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" ];
+
};
+
};
+
}
+1
nixos/tests/all-tests.nix
···
openvscode-server = runTest ./openvscode-server.nix;
open-webui = runTest ./open-webui.nix;
openvswitch = runTest ./openvswitch.nix;
+
optee = handleTestOn [ "aarch64-linux" ] ./optee.nix { };
orangefs = runTest ./orangefs.nix;
os-prober = handleTestOn [ "x86_64-linux" ] ./os-prober.nix { };
osquery = handleTestOn [ "x86_64-linux" ] ./osquery.nix { };
+72
nixos/tests/optee.nix
···
+
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")
+
'';
+
}
+
)
+72
pkgs/by-name/op/optee-client/package.nix
···
+
{
+
fetchFromGitHub,
+
isNixOS ? true,
+
lib,
+
libuuid,
+
pkg-config,
+
stdenv,
+
which,
+
}:
+
+
stdenv.mkDerivation (finalAttrs: {
+
pname = "optee-client";
+
version = "4.6.0";
+
+
src = fetchFromGitHub {
+
owner = "OP-TEE";
+
repo = "optee_client";
+
rev = finalAttrs.version;
+
hash = "sha256-hHEIn0WU4XfqwZbOdg9kwSDxDcvK7Tvxtelamfc3IRM=";
+
};
+
+
outputs = [
+
"out"
+
"lib"
+
"dev"
+
];
+
+
strictDeps = true;
+
+
enableParallelBuilding = true;
+
+
nativeBuildInputs = [
+
which
+
pkg-config
+
];
+
buildInputs = [ libuuid ];
+
+
makeFlags =
+
[
+
"CROSS_COMPILE=${stdenv.cc.targetPrefix}"
+
"DESTDIR=$(out)"
+
"SBINDIR=/bin"
+
"INCLUDEDIR=/include"
+
"LIBDIR=/lib"
+
]
+
++
+
# If we are building for NixOS, change default optee config to use paths
+
# that will work well with NixOS.
+
lib.optionals isNixOS [
+
"CFG_TEE_CLIENT_LOAD_PATH=/run/current-system/sw/lib"
+
"CFG_TEE_PLUGIN_LOAD_PATH=/run/current-system/sw/lib/tee-supplicant/plugins"
+
"CFG_TEE_FS_PARENT_PATH=/var/lib/tee"
+
];
+
+
preFixup = ''
+
mkdir -p "$lib" "$dev"
+
mv "$out/lib" "$lib"
+
mv "$out/include" "$dev"
+
'';
+
+
meta = {
+
description = "Normal world client for OPTEE OS";
+
homepage = "https://github.com/OP-TEE/optee_client";
+
changelog = "https://github.com/OP-TEE/optee_client/releases/tag/${finalAttrs.version}";
+
license = lib.licenses.bsd2;
+
maintainers = [ lib.maintainers.jmbaur ];
+
platforms = [
+
"aarch64-linux"
+
"armv7l-linux"
+
];
+
};
+
})
+8 -4
pkgs/misc/arm-trusted-firmware/default.nix
···
}:
let
-
buildArmTrustedFirmware =
+
buildArmTrustedFirmware = lib.makeOverridable (
{
filesToInstall,
installDir ? "$out",
···
depsBuildBuild = [ buildPackages.stdenv.cc ];
-
# For Cortex-M0 firmware in RK3399
-
nativeBuildInputs = [ pkgsCross.arm-embedded.stdenv.cc ];
+
nativeBuildInputs = [
+
pkgsCross.arm-embedded.stdenv.cc # For Cortex-M0 firmware in RK3399
+
openssl # For fiptool
+
];
+
# Make the new toolchain guessing (from 2.11+) happy
# https://github.com/ARM-software/arm-trusted-firmware/blob/4ec2948fe3f65dba2f19e691e702f7de2949179c/make_helpers/toolchains/rk3399-m0.mk#L21-L22
rk3399-m0-oc = "${pkgsCross.arm-embedded.stdenv.cc.targetPrefix}objcopy";
···
// extraMeta;
}
// builtins.removeAttrs args [ "extraMeta" ]
-
);
+
)
+
);
in
{
+127
pkgs/misc/optee-os/default.nix
···
+
{
+
dtc,
+
fetchFromGitHub,
+
lib,
+
pkgsBuildBuild,
+
stdenv,
+
}:
+
+
let
+
defaultVersion = "4.6.0";
+
+
defaultSrc = fetchFromGitHub {
+
owner = "OP-TEE";
+
repo = "optee_os";
+
rev = defaultVersion;
+
hash = "sha256-4z706DNfZE+CAPOa362CNSFhAN1KaNyKcI9C7+MRccs=";
+
};
+
+
buildOptee = lib.makeOverridable (
+
{
+
version ? null,
+
src ? null,
+
platform,
+
extraMakeFlags ? [ ],
+
extraMeta ? { },
+
...
+
}@args:
+
+
let
+
inherit (stdenv.hostPlatform) is32bit is64bit;
+
+
taTarget =
+
{
+
"arm" = "ta_arm32";
+
"arm64" = "ta_arm64";
+
}
+
.${stdenv.hostPlatform.linuxArch};
+
in
+
stdenv.mkDerivation (
+
{
+
pname = "optee-os-${platform}";
+
+
version = if src == null then defaultVersion else version;
+
+
src = if src == null then defaultSrc else src;
+
+
postPatch = ''
+
patchShebangs $(find -type d -name scripts -printf '%p ')
+
'';
+
+
outputs = [
+
"out"
+
"devkit"
+
];
+
+
strictDeps = true;
+
+
enableParallelBuilding = true;
+
+
depsBuildBuild = [ pkgsBuildBuild.stdenv.cc ];
+
+
nativeBuildInputs = [
+
dtc
+
(pkgsBuildBuild.python3.withPackages (
+
p: with p; [
+
pyelftools
+
cryptography
+
]
+
))
+
];
+
+
makeFlags =
+
[
+
"O=out"
+
"PLATFORM=${platform}"
+
"CFG_USER_TA_TARGETS=${taTarget}"
+
]
+
++ (lib.optionals (is32bit) [
+
"CFG_ARM32_core=y"
+
"CROSS_COMPILE32=${stdenv.cc.targetPrefix}"
+
])
+
++ (lib.optionals (is64bit) [
+
"CFG_ARM64_core=y"
+
"CROSS_COMPILE64=${stdenv.cc.targetPrefix}"
+
])
+
++ extraMakeFlags;
+
+
installPhase = ''
+
runHook preInstall
+
+
mkdir -p $out
+
cp out/core/{tee.elf,tee-pageable_v2.bin,tee.bin,tee-header_v2.bin,tee-pager_v2.bin,tee-raw.bin} $out
+
cp -r out/export-${taTarget} $devkit
+
+
runHook postInstall
+
'';
+
+
meta =
+
with lib;
+
{
+
description = "A Trusted Execution Environment for ARM";
+
homepage = "https://github.com/OP-TEE/optee_os";
+
changelog = "https://github.com/OP-TEE/optee_os/blob/${defaultVersion}/CHANGELOG.md";
+
license = licenses.bsd2;
+
maintainers = [ maintainers.jmbaur ];
+
}
+
// extraMeta;
+
}
+
// removeAttrs args [ "extraMeta" ]
+
)
+
);
+
in
+
{
+
inherit buildOptee;
+
+
opteeQemuArm = buildOptee {
+
platform = "vexpress";
+
extraMakeFlags = [ "PLATFORM_FLAVOR=qemu_virt" ];
+
extraMeta.platforms = [ "armv7l-linux" ];
+
};
+
+
opteeQemuAarch64 = buildOptee {
+
platform = "vexpress";
+
extraMakeFlags = [ "PLATFORM_FLAVOR=qemu_armv8a" ];
+
extraMeta.platforms = [ "aarch64-linux" ];
+
};
+
}
+6
pkgs/top-level/all-packages.nix
···
libiberty_static = libiberty.override { staticBuild = true; };
};
+
inherit (callPackage ../misc/optee-os { })
+
buildOptee
+
opteeQemuArm
+
opteeQemuAarch64
+
;
+
patchelf = callPackage ../development/tools/misc/patchelf { };
patchelfUnstable = lowPrio (callPackage ../development/tools/misc/patchelf/unstable.nix { });