1 { config, options, pkgs, lib, ... }:
4 cfg = config.services.aesmd;
5 opt = options.services.aesmd;
7 sgx-psw = pkgs.sgx-psw.override { inherit (cfg) debug; };
9 configFile = with cfg.settings; pkgs.writeText "aesmd.conf" (
10 concatStringsSep "\n" (
11 optional (whitelistUrl != null) "whitelist url = ${whitelistUrl}" ++
12 optional (proxy != null) "aesm proxy = ${proxy}" ++
13 optional (proxyType != null) "proxy type = ${proxyType}" ++
14 optional (defaultQuotingType != null) "default quoting type = ${defaultQuotingType}" ++
15 # Newline at end of file
21 options.services.aesmd = {
22 enable = mkEnableOption "Intel's Architectural Enclave Service Manager (AESM) for Intel SGX";
26 description = "Whether to build the PSW package in debug mode.";
28 environment = mkOption {
29 type = with types; attrsOf str;
31 description = "Additional environment variables to pass to the AESM service.";
32 # Example environment variable for `sgx-azure-dcap-client` provider library
34 AZDCAP_COLLATERAL_VERSION = "v2";
35 AZDCAP_DEBUG_LOG_LEVEL = "INFO";
38 quoteProviderLibrary = mkOption {
39 type = with types; nullOr path;
41 example = literalExpression "pkgs.sgx-azure-dcap-client";
42 description = "Custom quote provider library to use.";
45 description = "AESM configuration";
47 type = types.submodule {
48 options.whitelistUrl = mkOption {
49 type = with types; nullOr str;
51 example = "http://whitelist.trustedservices.intel.com/SGX/LCWL/Linux/sgx_white_list_cert.bin";
52 description = "URL to retrieve authorized Intel SGX enclave signers.";
54 options.proxy = mkOption {
55 type = with types; nullOr str;
57 example = "http://proxy_url:1234";
58 description = "HTTP network proxy.";
60 options.proxyType = mkOption {
61 type = with types; nullOr (enum [ "default" "direct" "manual" ]);
62 default = if (cfg.settings.proxy != null) then "manual" else null;
63 defaultText = literalExpression ''
64 if (config.${opt.settings}.proxy != null) then "manual" else null
68 Type of proxy to use. The `default` uses the system's default proxy.
69 If `direct` is given, uses no proxy.
70 A value of `manual` uses the proxy from
71 {option}`services.aesmd.settings.proxy`.
74 options.defaultQuotingType = mkOption {
75 type = with types; nullOr (enum [ "ecdsa_256" "epid_linkable" "epid_unlinkable" ]);
77 example = "ecdsa_256";
78 description = "Attestation quote type.";
84 config = mkIf cfg.enable {
86 assertion = !(config.boot.specialFileSystems."/dev".options ? "noexec");
87 message = "SGX requires exec permission for /dev";
90 hardware.cpu.intel.sgx.provision.enable = true;
92 # Make sure the AESM service can find the SGX devices until
93 # https://github.com/intel/linux-sgx/issues/772 is resolved
94 # and updated in nixpkgs.
95 hardware.cpu.intel.sgx.enableDcapCompat = mkForce true;
97 systemd.services.aesmd =
99 storeAesmFolder = "${sgx-psw}/aesm";
100 # Hardcoded path AESM_DATA_FOLDER in psw/ae/aesm_service/source/oal/linux/aesm_util.cpp
101 aesmDataFolder = "/var/opt/aesmd/data";
104 description = "Intel Architectural Enclave Service Manager";
105 wantedBy = [ "multi-user.target" ];
114 NAME = "aesm_service";
115 AESM_PATH = storeAesmFolder;
116 LD_LIBRARY_PATH = makeLibraryPath [ cfg.quoteProviderLibrary ];
117 } // cfg.environment;
119 # Make sure any of the SGX application enclave devices is available
120 unitConfig.AssertPathExists = [
121 # legacy out-of-tree driver
129 serviceConfig = rec {
130 ExecStartPre = pkgs.writeShellScript "copy-aesmd-data-files.sh" ''
132 whiteListFile="${aesmDataFolder}/white_list_cert_to_be_verify.bin"
133 if [[ ! -f "$whiteListFile" ]]; then
134 ${pkgs.coreutils}/bin/install -m 644 -D \
135 "${storeAesmFolder}/data/white_list_cert_to_be_verify.bin" \
139 ExecStart = "${sgx-psw}/bin/aesm_service --no-daemon";
140 ExecReload = ''${pkgs.coreutils}/bin/kill -SIGHUP "$MAINPID"'';
142 Restart = "on-failure";
147 SupplementaryGroups = [
148 config.hardware.cpu.intel.sgx.provision.group
153 WorkingDirectory = storeAesmFolder;
154 StateDirectory = "aesmd";
155 StateDirectoryMode = "0700";
156 RuntimeDirectory = "aesmd";
157 RuntimeDirectoryMode = "0750";
161 # chroot into the runtime directory
162 RootDirectory = "%t/aesmd";
163 BindReadOnlyPaths = [
165 # Hardcoded path AESM_CONFIG_FILE in psw/ae/aesm_service/source/utils/aesm_config.cpp
166 "${configFile}:/etc/aesmd.conf"
169 # Hardcoded path CONFIG_SOCKET_PATH in psw/ae/aesm_service/source/core/ipc/SocketConfig.h
170 "%t/aesmd:/var/run/aesmd"
171 "%S/aesmd:/var/opt/aesmd"
174 # PrivateDevices=true will mount /dev noexec which breaks AESM
175 PrivateDevices = false;
176 DevicePolicy = "closed";
178 # legacy out-of-tree driver
183 "/dev/sgx_enclave rw"
184 "/dev/sgx_provision rw"
187 # Requires Internet access for attestation
188 PrivateNetwork = false;
190 RestrictAddressFamilies = [
191 # Allocates the socket /var/run/aesmd/aesm.socket
193 # Uses the HTTP protocol to initialize some services
199 MemoryDenyWriteExecute = false;
201 # needs the ipc syscall in order to run
222 SystemCallArchitectures = "native";
223 SystemCallErrorNumber = "EPERM";
225 CapabilityBoundingSet = "";
226 KeyringMode = "private";
227 LockPersonality = true;
228 NoNewPrivileges = true;
229 NotifyAccess = "none";
230 PrivateMounts = true;
235 ProtectControlGroups = true;
237 ProtectHostname = true;
238 ProtectKernelLogs = true;
239 ProtectKernelModules = true;
240 ProtectKernelTunables = true;
241 ProtectProc = "invisible";
242 ProtectSystem = "strict";
244 RestrictNamespaces = true;
245 RestrictRealtime = true;
246 RestrictSUIDSGID = true;