diff --git a/nixos/modules/services/security/aesmd.nix b/nixos/modules/services/security/aesmd.nix index 864d408c0220a..4caeab4dea417 100644 --- a/nixos/modules/services/security/aesmd.nix +++ b/nixos/modules/services/security/aesmd.nix @@ -1,10 +1,12 @@ { config, options, pkgs, lib, ... }: -with lib; let + inherit (lib) concatStringsSep literalExpression makeLibraryPath mkEnableOption + mkForce mkIf mkOption mkPackageOption mkRemovedOptionModule optional types; + cfg = config.services.aesmd; opt = options.services.aesmd; - sgx-psw = pkgs.sgx-psw.override { inherit (cfg) debug; }; + sgx-psw = cfg.package; configFile = with cfg.settings; pkgs.writeText "aesmd.conf" ( concatStringsSep "\n" ( @@ -18,13 +20,17 @@ let ); in { + imports = [ + (mkRemovedOptionModule [ "debug" ] '' + Enable debug mode by overriding the aesmd package directly: + + services.aesmd.package = pkgs.sgx-psw.override { debug = true; }; + '') + ]; + options.services.aesmd = { enable = mkEnableOption "Intel's Architectural Enclave Service Manager (AESM) for Intel SGX"; - debug = mkOption { - type = types.bool; - default = false; - description = "Whether to build the PSW package in debug mode."; - }; + package = mkPackageOption pkgs "sgx-psw" { }; environment = mkOption { type = with types; attrsOf str; default = { }; @@ -126,7 +132,7 @@ in "|/dev/sgx_enclave" ]; - serviceConfig = rec { + serviceConfig = { ExecStartPre = pkgs.writeShellScript "copy-aesmd-data-files.sh" '' set -euo pipefail whiteListFile="${aesmDataFolder}/white_list_cert_to_be_verify.bin" diff --git a/pkgs/os-specific/linux/sgx/psw/cppmicroservices-no-mtime.patch b/pkgs/os-specific/linux/sgx/psw/cppmicroservices-no-mtime.patch new file mode 100644 index 0000000000000..019f58927152a --- /dev/null +++ b/pkgs/os-specific/linux/sgx/psw/cppmicroservices-no-mtime.patch @@ -0,0 +1,26 @@ +diff --git a/external/CppMicroServices/framework/src/bundle/BundleResourceContainer.cpp b/external/CppMicroServices/framework/src/bundle/BundleResourceContainer.cpp +index aee499e9..13fa89d4 100644 +--- a/external/CppMicroServices/framework/src/bundle/BundleResourceContainer.cpp ++++ b/external/CppMicroServices/framework/src/bundle/BundleResourceContainer.cpp +@@ -105,7 +105,7 @@ bool BundleResourceContainer::GetStat(int index, + const_cast(&m_ZipArchive), index) + ? true + : false; +- stat.modifiedTime = zipStat.m_time; ++ stat.modifiedTime = 0; + stat.crc32 = zipStat.m_crc32; + // This will limit the size info from uint64 to uint32 on 32-bit + // architectures. We don't care because we assume resources > 2GB +diff --git a/external/CppMicroServices/third_party/miniz.c b/external/CppMicroServices/third_party/miniz.c +index 6b0ebd7a..fa2aebca 100644 +--- a/external/CppMicroServices/third_party/miniz.c ++++ b/external/CppMicroServices/third_party/miniz.c +@@ -170,7 +170,7 @@ + // If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or + // get/set file times, and the C run-time funcs that get/set times won't be called. + // The current downside is the times written to your archives will be from 1979. +-//#define MINIZ_NO_TIME ++#define MINIZ_NO_TIME + + // Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's. + //#define MINIZ_NO_ARCHIVE_APIS diff --git a/pkgs/os-specific/linux/sgx/psw/default.nix b/pkgs/os-specific/linux/sgx/psw/default.nix index 829b0c6525ecc..6a73775dbf83f 100644 --- a/pkgs/os-specific/linux/sgx/psw/default.nix +++ b/pkgs/os-specific/linux/sgx/psw/default.nix @@ -1,22 +1,37 @@ { stdenv , lib , fetchurl +, fetchFromGitHub , cmake , coreutils , curl , file +, git , makeWrapper , nixosTests , protobuf , python3 -, sgx-sdk +, ocaml +, ocamlPackages , which , debug ? false }: stdenv.mkDerivation rec { - inherit (sgx-sdk) patches src version versionTag; pname = "sgx-psw"; + # Version as given in se_version.h + version = "2.25.100.3"; + # Version as used in the Git tag + versionTag = "2.25"; + src = fetchFromGitHub { + owner = "intel"; + repo = "linux-sgx"; + rev = "sgx_${versionTag}"; + hash = "sha256-RR+vFTd9ZM6XUn3KgQeUM+xoj1Ava4zQzFYA/nfXyaw="; + fetchSubmodules = true; + }; + + # Extract Intel-provided, pre-built enclaves and libs. postUnpack = let # Fetch the pre-built, Intel-signed Architectural Enclaves (AE). They help @@ -24,34 +39,104 @@ stdenv.mkDerivation rec { # attestation quotes, and do platform certification. ae.prebuilt = fetchurl { url = "https://download.01.org/intel-sgx/sgx-linux/${versionTag}/prebuilt_ae_${versionTag}.tar.gz"; - hash = "sha256-IGV9VEwY/cQBV4Vz2sps4JgRweWRl/l08ocb9P4SH8Q="; + hash = "sha256-Hlh96rYOyml2y50d8ASKz6U97Fl0hbGYECeZiG9nMSQ="; + }; + + # Pre-built ipp-crypto with mitigations. + optlib.prebuilt = fetchurl { + url = "https://download.01.org/intel-sgx/sgx-linux/${versionTag}/optimized_libs_${versionTag}.tar.gz"; + hash = "sha256-7mDTaLtpOQLHQ6Fv+FWJ2k/veJZPXIcuj7kOdRtRqhg="; }; - # Also include the Data Center Attestation Primitives (DCAP) platform - # enclaves. + + # Fetch the Data Center Attestation Primitives (DCAP) platform enclaves + # and pre-built sgxssl. dcap = rec { - version = "1.21"; + version = "1.22"; filename = "prebuilt_dcap_${version}.tar.gz"; prebuilt = fetchurl { url = "https://download.01.org/intel-sgx/sgx-dcap/${version}/linux/${filename}"; - hash = "sha256-/PPD2MyNxoCwzNljIFcpkFvItXbyvymsJ7+Uf4IyZuk="; + hash = "sha256-RTpJQ6epoAN8YQXSJUjJQ5mPaQIiQpStTWFsnspjjDQ="; }; }; in - sgx-sdk.postUnpack + '' + '' + # Make sure this is the right version of linux-sgx + grep -q '"${version}"' "$src/common/inc/internal/se_version.h" \ + || (echo "Could not find expected version ${version} in linux-sgx source" >&2 && exit 1) + + tar -xzvf ${ae.prebuilt} -C $sourceRoot/ + tar -xzvf ${optlib.prebuilt} -C $sourceRoot/ + # Make sure we use the correct version of prebuilt DCAP grep -q 'ae_file_name=${dcap.filename}' "$src/external/dcap_source/QuoteGeneration/download_prebuilt.sh" \ || (echo "Could not find expected prebuilt DCAP ${dcap.filename} in linux-sgx source" >&2 && exit 1) - tar -zxf ${ae.prebuilt} -C $sourceRoot/ - tar -zxf ${dcap.prebuilt} -C $sourceRoot/external/dcap_source/QuoteGeneration/ + tar -xzvf ${dcap.prebuilt} -C $sourceRoot/external/dcap_source ./prebuilt/ + tar -xzvf ${dcap.prebuilt} -C $sourceRoot/external/dcap_source/QuoteGeneration ./psw/ + ''; + + patches = [ + # There's a `make preparation` step that downloads some prebuilt binaries + # and applies some patches to the in-repo git submodules. This patch removes + # the parts that download things, since we can't do that inside the sandbox. + ./disable-downloads.patch + + # This patch disables mtime in bundled zip file for reproducible builds. + # + # Context: The `aesm_service` binary depends on a vendored library called + # `CppMicroServices`. At build time, this lib creates and then bundles + # service resources into a zip file and then embeds this zip into the + # binary. Without changes, the `aesm_service` will be different after every + # build because the embedded zip file contents have different modified times. + ./cppmicroservices-no-mtime.patch + ]; + + postPatch = + let + # The base directories we want to copy headers from. The exact headers are + # parsed from + bomDirsToCopyFrom = builtins.concatStringsSep "|" [ + "common/" + "external/dcap_source/" + "external/ippcp_internal/" + "external/sgx-emm/" + "psw/" + "sdk/tlibcxx/" + ]; + in + '' + patchShebangs \ + external/sgx-emm/create_symlink.sh \ + linux/installer/bin/build-installpkg.sh \ + linux/installer/common/psw/createTarball.sh \ + linux/installer/common/psw/install.sh + + # Run sgx-sdk preparation step + make preparation + + # Build a fake SGX_SDK directory. Normally sgx-psw depends on first building + # all of sgx-sdk, however we can actually build them independently by just + # copying a few header files and building `sgx_edger8r` separately. + mkdir .sgxsdk + export SGX_SDK="$(readlink -f .sgxsdk)" + + # Parse the BOM for the headers we need, then copy them into SGX_SDK + # Each line in the BOM.txt looks like: + # /...\t/package/...\t.... + # TODO(phlip9): hardlink? + sed -n -r 's:^/(${bomDirsToCopyFrom})(\S+)\s/package/(\S+)\s.*$:\1\2\n.sgxsdk/\3:p' \ + < linux/installer/common/sdk/BOMs/sdk_base.txt \ + | xargs --max-args=2 install -v -D ''; nativeBuildInputs = [ cmake file + git makeWrapper + ocaml + ocamlPackages.ocamlbuild python3 - sgx-sdk which ]; @@ -60,27 +145,24 @@ stdenv.mkDerivation rec { protobuf ]; - hardeningDisable = [ - # causes redefinition of _FORTIFY_SOURCE - "fortify3" - ] ++ lib.optionals debug [ - "fortify" - ]; + dontUseCmakeConfigure = true; - postPatch = '' - patchShebangs \ - linux/installer/bin/build-installpkg.sh \ - linux/installer/common/psw/createTarball.sh \ - linux/installer/common/psw/install.sh - ''; + preBuild = '' + # Build `sgx_edger8r`, the enclave .edl -> .h file codegen tool. + # Then place it in `$SGX_SDK/bin` and `$SGX_SDK/bin/x64`. + make -C sdk/edger8r/linux + mkdir -p $SGX_SDK/bin/x64 + sgx_edger8r_bin="$(readlink -f build/linux/sgx_edger8r)" + ln -s $sgx_edger8r_bin $SGX_SDK/bin/ + ln -s $sgx_edger8r_bin $SGX_SDK/bin/x64/ - dontUseCmakeConfigure = true; + # Add this so we can link against libsgx_urts. + build_dir="$(readlink -f build/linux)" + ln -s $build_dir $SGX_SDK/lib + ln -s $build_dir $SGX_SDK/lib64 + ''; - buildFlags = [ - "psw_install_pkg" - ] ++ lib.optionals debug [ - "DEBUG=1" - ]; + buildFlags = [ "psw_install_pkg" ] ++ lib.optionals debug [ "DEBUG=1" ]; installFlags = [ "-C linux/installer/common/psw/output" diff --git a/pkgs/os-specific/linux/sgx/psw/disable-downloads.patch b/pkgs/os-specific/linux/sgx/psw/disable-downloads.patch new file mode 100644 index 0000000000000..fff31cb67ebee --- /dev/null +++ b/pkgs/os-specific/linux/sgx/psw/disable-downloads.patch @@ -0,0 +1,32 @@ +diff --git a/Makefile b/Makefile +index 19bc05a..6b1acd4 100644 +--- a/Makefile ++++ b/Makefile +@@ -50,13 +50,13 @@ tips: + preparation: + # As SDK build needs to clone and patch openmp, we cannot support the mode that download the source from github as zip. + # Only enable the download from git +- git submodule update --init --recursive ++ # git submodule update --init --recursive + cd external/dcap_source/external/jwt-cpp && git apply ../0001-Add-a-macro-to-disable-time-support-in-jwt-for-SGX.patch >/dev/null 2>&1 || \ + git apply ../0001-Add-a-macro-to-disable-time-support-in-jwt-for-SGX.patch -R --check +- ./external/dcap_source/QuoteVerification/prepare_sgxssl.sh nobuild ++ # ./external/dcap_source/QuoteVerification/prepare_sgxssl.sh nobuild + cd external/openmp/openmp_code && git apply ../0001-Enable-OpenMP-in-SGX.patch >/dev/null 2>&1 || git apply ../0001-Enable-OpenMP-in-SGX.patch --check -R + cd external/protobuf/protobuf_code && git apply ../sgx_protobuf.patch >/dev/null 2>&1 || git apply ../sgx_protobuf.patch --check -R +- cd external/protobuf/protobuf_code && git submodule update --init --recursive && cd third_party/abseil-cpp && git apply ../../../sgx_abseil.patch>/dev/null 2>&1 || git apply ../../../sgx_abseil.patch --check -R ++ cd external/protobuf/protobuf_code && cd third_party/abseil-cpp && git apply ../../../sgx_abseil.patch>/dev/null 2>&1 || git apply ../../../sgx_abseil.patch --check -R + ./external/sgx-emm/create_symlink.sh + cd external/mbedtls/mbedtls_code && git apply ../sgx_mbedtls.patch >/dev/null 2>&1 || git apply ../sgx_mbedtls.patch --check -R + cd external/cbor && cp -r libcbor sgx_libcbor +@@ -64,8 +64,8 @@ preparation: + cd external/cbor/sgx_libcbor && git apply ../sgx_cbor.patch >/dev/null 2>&1 || git apply ../sgx_cbor.patch --check -R + cd external/ippcp_internal/ipp-crypto && git apply ../0001-IPP-crypto-for-SGX.patch > /dev/null 2>&1 || git apply ../0001-IPP-crypto-for-SGX.patch --check -R + cd external/ippcp_internal/ipp-crypto && mkdir -p build +- ./download_prebuilt.sh +- ./external/dcap_source/QuoteGeneration/download_prebuilt.sh ++ # ./download_prebuilt.sh ++ # ./external/dcap_source/QuoteGeneration/download_prebuilt.sh + + psw: + $(MAKE) -C psw/ USE_OPT_LIBS=$(USE_OPT_LIBS)