diff --git a/pkgs/os-specific/linux/sgx-sdk/default.nix b/pkgs/os-specific/linux/sgx-sdk/default.nix index 130fd12cbb913..cb9d140e4edd1 100644 --- a/pkgs/os-specific/linux/sgx-sdk/default.nix +++ b/pkgs/os-specific/linux/sgx-sdk/default.nix @@ -1,7 +1,6 @@ { lib , stdenv -, fetchpatch -, fetchurl +, fetchzip , fetchFromGitHub , callPackage , autoconf @@ -9,69 +8,86 @@ , binutils , cmake , file +, gdb , git , libtool , nasm -, ncurses , ocaml , ocamlPackages , openssl , perl , python3 , texinfo -, which +, validatePkgConfig , writeShellScript +, writeText }: - +with lib; stdenv.mkDerivation rec { pname = "sgx-sdk"; - version = "2.14"; + version = "2.14.100.2"; + + versionTag = concatStringsSep "." (take 2 (splitVersion version)); src = fetchFromGitHub { owner = "intel"; repo = "linux-sgx"; - rev = "0cea078f17a24fb807e706409972d77f7a958db9"; - sha256 = "1cr2mkk459s270ng0yddgcryi0zc3dfmg9rmdrdh9mhy2mc1kx0g"; + rev = "sgx_${versionTag}"; + hash = "sha256-D/QZWBUe1gRbbjWnV10b7IPoM3utefAsOEKnQuasIrM="; fetchSubmodules = true; }; - patches = [ - (fetchpatch { - name = "replace-bin-cp-with-cp.patch"; - url = "https://github.com/intel/linux-sgx/commit/e0db5291d46d1c124980719d63829d65f89cf2c7.patch"; - sha256 = "0xwlpm1r4rl4anfhjkr6fgz0gcyhr0ng46fv8iw9hfsh891yqb7z"; - }) - (fetchpatch { - name = "sgx_ippcp.h.patch"; - url = "https://github.com/intel/linux-sgx/commit/e5929083f8161a8e7404afc0577936003fbb9d0b.patch"; - sha256 = "12bgs9rxlq82hn5prl9qz2r4mwypink8hzdz4cki4k4cmkw961f5"; - }) - ]; + postUnpack = + let + optlibName = "optimized_libs_${versionTag}.tar.gz"; + optimizedLibs = fetchzip { + url = "https://download.01.org/intel-sgx/sgx-linux/${versionTag}/${optlibName}"; + hash = "sha256-FjNhNV9+KDMvBYdWXZbua6qYOc3Z1/jtcF4j52TSxQY="; + stripRoot = false; + }; + sgxIPPCryptoHeader = "${optimizedLibs}/external/ippcp_internal/inc/sgx_ippcp.h"; + in + '' + # 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) + + # Make sure we use the correct version to build IPP Crypto + grep -q 'optlib_name=${optlibName}' "$src/download_prebuilt.sh" \ + || (echo "Could not find expected optimized libs ${optlibName} in linux-sgx source" >&2 && exit 1) + + # Add missing sgx_ippcp.h: https://github.com/intel/linux-sgx/pull/752 + ln -s ${sgxIPPCryptoHeader} "$sourceRoot/external/ippcp_internal/inc/sgx_ippcp.h" + ''; + postPatch = '' - patchShebangs ./linux/installer/bin/build-installpkg.sh \ - ./linux/installer/common/sdk/createTarball.sh \ - ./linux/installer/common/sdk/install.sh + # https://github.com/intel/linux-sgx/pull/730 + substituteInPlace buildenv.mk --replace '/bin/cp' 'cp' + + patchShebangs linux/installer/bin/build-installpkg.sh \ + linux/installer/common/sdk/createTarball.sh \ + linux/installer/common/sdk/install.sh ''; - dontConfigure = true; + # We need `cmake` as a build input but don't use it to kick off the build phase + dontUseCmakeConfigure = true; # SDK built with stackprotector produces broken enclaves which crash at runtime. # Disable all to be safe, SDK build configures compiler mitigations manually. hardeningDisable = [ "all" ]; nativeBuildInputs = [ + autoconf + automake cmake + file git ocaml ocamlPackages.ocamlbuild perl python3 texinfo - nasm - file - ncurses - autoconf - automake + validatePkgConfig ]; buildInputs = [ @@ -84,75 +100,174 @@ stdenv.mkDerivation rec { # Build external/ippcp_internal first. The Makefile is rewritten to make the # build faster by splitting different versions of ipp-crypto builds and to # avoid patching the Makefile for reproducibility issues. - buildPhase = let - ipp-crypto-no_mitigation = callPackage (import ./ipp-crypto.nix) {}; + preBuild = + let + ipp-crypto-no_mitigation = callPackage ./ipp-crypto.nix { }; - sgx-asm-pp = "python ${src}/build-scripts/sgx-asm-pp.py --assembler=nasm"; + sgx-asm-pp = "python ${src}/build-scripts/sgx-asm-pp.py --assembler=nasm"; - nasm-load = writeShellScript "nasm-load" "${sgx-asm-pp} --MITIGATION-CVE-2020-0551=LOAD $@"; - ipp-crypto-cve_2020_0551_load = callPackage (import ./ipp-crypto.nix) { - extraCmakeFlags = [ "-DCMAKE_ASM_NASM_COMPILER=${nasm-load}" ]; - }; + nasm-load = writeShellScript "nasm-load" "${sgx-asm-pp} --MITIGATION-CVE-2020-0551=LOAD $@"; + ipp-crypto-cve_2020_0551_load = callPackage ./ipp-crypto.nix { + extraCmakeFlags = [ "-DCMAKE_ASM_NASM_COMPILER=${nasm-load}" ]; + }; - nasm-cf = writeShellScript "nasm-cf" "${sgx-asm-pp} --MITIGATION-CVE-2020-0551=CF $@"; - ipp-crypto-cve_2020_0551_cf = callPackage (import ./ipp-crypto.nix) { - extraCmakeFlags = [ "-DCMAKE_ASM_NASM_COMPILER=${nasm-cf}" ]; - }; - in '' - cd external/ippcp_internal + nasm-cf = writeShellScript "nasm-cf" "${sgx-asm-pp} --MITIGATION-CVE-2020-0551=CF $@"; + ipp-crypto-cve_2020_0551_cf = callPackage ./ipp-crypto.nix { + extraCmakeFlags = [ "-DCMAKE_ASM_NASM_COMPILER=${nasm-cf}" ]; + }; + in + '' + header "Setting up IPP crypto build artifacts" - mkdir -p lib/linux/intel64/no_mitigation - cp ${ipp-crypto-no_mitigation}/lib/intel64/libippcp.a lib/linux/intel64/no_mitigation - chmod a+w lib/linux/intel64/no_mitigation/libippcp.a - cp ${ipp-crypto-no_mitigation}/include/* ./inc + pushd 'external/ippcp_internal' - mkdir -p lib/linux/intel64/cve_2020_0551_load - cp ${ipp-crypto-cve_2020_0551_load}/lib/intel64/libippcp.a lib/linux/intel64/cve_2020_0551_load - chmod a+w lib/linux/intel64/cve_2020_0551_load/libippcp.a + install ${ipp-crypto-no_mitigation}/include/* inc/ - mkdir -p lib/linux/intel64/cve_2020_0551_cf - cp ${ipp-crypto-cve_2020_0551_cf}/lib/intel64/libippcp.a lib/linux/intel64/cve_2020_0551_cf - chmod a+w lib/linux/intel64/cve_2020_0551_cf/libippcp.a + install -D -m a+rw ${ipp-crypto-no_mitigation}/lib/intel64/libippcp.a \ + lib/linux/intel64/no_mitigation/libippcp.a + install -D -m a+rw ${ipp-crypto-cve_2020_0551_load}/lib/intel64/libippcp.a \ + lib/linux/intel64/cve_2020_0551_load/libippcp.a + install -D -m a+rw ${ipp-crypto-cve_2020_0551_cf}/lib/intel64/libippcp.a \ + lib/linux/intel64/cve_2020_0551_cf/libippcp.a - rm -f ./inc/ippcp.h - patch ${ipp-crypto-no_mitigation}/include/ippcp.h -i ./inc/ippcp20u3.patch -o ./inc/ippcp.h + rm inc/ippcp.h + patch ${ipp-crypto-no_mitigation}/include/ippcp.h -i inc/ippcp20u3.patch -o inc/ippcp.h - mkdir -p license - cp ${ipp-crypto-no_mitigation.src}/LICENSE ./license + install -D ${ipp-crypto-no_mitigation.src}/LICENSE license/LICENSE - # Build the SDK installation package. - cd ../.. + popd + ''; - # Nix patches make so that $(SHELL) defaults to "sh" instead of "/bin/sh". - # The build uses $(SHELL) as an argument to file -L which requires a path. - make SHELL=$SHELL sdk_install_pkg + buildFlags = [ + "sdk_install_pkg" + ]; - runHook postBuild - ''; + enableParallelBuilding = true; postBuild = '' - patchShebangs ./linux/installer/bin/sgx_linux_x64_sdk_*.bin + patchShebangs linux/installer/bin/sgx_linux_x64_sdk_${version}.bin ''; installPhase = '' - echo -e 'no\n'$out | ./linux/installer/bin/sgx_linux_x64_sdk_*.bin + runHook preInstall + + installDir=$TMPDIR + ./linux/installer/bin/sgx_linux_x64_sdk_${version}.bin -prefix $installDir + installDir=$installDir/sgxsdk + + header "Move files created by installer" + + mkdir -p $out/bin + pushd $out + + mv $installDir/bin/sgx-gdb $out/bin + mkdir $out/bin/x64 + for file in $installDir/bin/x64/*; do + mv $file bin/ + ln -sr bin/$(basename $file) bin/x64/ + done + rmdir $installDir/bin/{x64,} + + # Move `lib64` to `lib` and symlink `lib64` + mv $installDir/lib64 lib + ln -s lib/ lib64 + + mv $installDir/include/ . + + mkdir -p share/ + mv $installDir/{SampleCode,licenses} share/ + + mkdir -p share/bin + mv $installDir/{environment,buildenv.mk} share/bin/ + ln -s share/bin/{environment,buildenv.mk} . + + # pkgconfig should go to lib/ + mv $installDir/pkgconfig lib/ + ln -s lib/pkgconfig/ . + + # Also create the `sdk_libs` for compat. All the files + # link to libraries in `lib64/`, we shouldn't link the entire + # directory, however, as there seems to be some ambiguity between + # SDK and PSW libraries. + mkdir sdk_libs/ + for file in $installDir/sdk_libs/*; do + ln -sr lib/$(basename $file) sdk_libs/ + rm $file + done + rmdir $installDir/sdk_libs + + # No uninstall script required + rm $installDir/uninstall.sh + + # Create an `sgxsdk` symlink which points to `$out` for compat + ln -sr . sgxsdk + + # Make sure we didn't forget any files + rmdir $installDir || (echo "Error: The directory $installDir still contains unhandled files: $(ls -A $installDir)" >&2 && exit 1) + + popd + + runHook postInstall ''; - dontFixup = true; + + preFixup = '' + header "Strip sgxsdk prefix" + for path in "$out/share/bin/environment" "$out/bin/sgx-gdb"; do + substituteInPlace $path --replace "$TMPDIR/sgxsdk" "$out" + done + + header "Fixing pkg-config files" + sed -i "s|prefix=.*|prefix=$out|g" $out/lib/pkgconfig/*.pc + + header "Fixing SGX_SDK default in samples" + substituteInPlace $out/share/SampleCode/LocalAttestation/buildenv.mk \ + --replace '/opt/intel/sgxsdk' "$out" + for file in $out/share/SampleCode/*/Makefile; do + substituteInPlace $file \ + --replace '/opt/intel/sgxsdk' "$out" \ + --replace '$(SGX_SDK)/buildenv.mk' "$out/share/bin/buildenv.mk" + done + + header "Fixing BINUTILS_DIR in buildenv.mk" + substituteInPlace $out/share/bin/buildenv.mk \ + --replace 'BINUTILS_DIR ?= /usr/local/bin' \ + 'BINUTILS_DIR ?= ${BINUTILS_DIR}' + + header "Fixing GDB path in bin/sgx-gdb" + substituteInPlace $out/bin/sgx-gdb --replace '/usr/local/bin/gdb' '${gdb}/bin/gdb' + ''; doInstallCheck = true; - installCheckInputs = [ which ]; + installCheckPhase = '' - source $out/sgxsdk/environment - cd SampleCode/SampleEnclave - make SGX_MODE=SGX_SIM - ./app + runHook preInstallCheck + + # Make sure all symlinks are valid + output=$(find "$out" -type l -exec test ! -e {} \; -print) + if [[ -n "$output" ]]; then + echo "Broken symlinks:" + echo "$output" + exit 1 + fi + + runHook postInstallCheck ''; - meta = with lib; { + setupHook = writeText "setup-hook.sh" '' + sgxsdk() { + export SGX_SDK=@out@ + } + + postHooks+=(sgxsdk) + ''; + + passthru.tests = callPackage ./samples.nix { }; + + meta = { description = "Intel SGX SDK for Linux built with IPP Crypto Library"; homepage = "https://github.com/intel/linux-sgx"; - maintainers = with maintainers; [ sbellem arturcygan ]; + maintainers = with maintainers; [ sbellem arturcygan veehaitch ]; platforms = [ "x86_64-linux" ]; license = with licenses; [ bsd3 ]; }; diff --git a/pkgs/os-specific/linux/sgx-sdk/ipp-crypto.nix b/pkgs/os-specific/linux/sgx-sdk/ipp-crypto.nix index 52cef4f82815b..ac5fd2ad1ccc6 100644 --- a/pkgs/os-specific/linux/sgx-sdk/ipp-crypto.nix +++ b/pkgs/os-specific/linux/sgx-sdk/ipp-crypto.nix @@ -4,7 +4,7 @@ , cmake , python3 , nasm -, extraCmakeFlags ? [] +, extraCmakeFlags ? [ ] }: stdenv.mkDerivation rec { diff --git a/pkgs/os-specific/linux/sgx-sdk/samples.nix b/pkgs/os-specific/linux/sgx-sdk/samples.nix new file mode 100644 index 0000000000000..82dbc24568efd --- /dev/null +++ b/pkgs/os-specific/linux/sgx-sdk/samples.nix @@ -0,0 +1,57 @@ +{ stdenv +, sgx-sdk +, which +}: +let + buildSample = name: stdenv.mkDerivation rec { + inherit name; + + src = sgx-sdk.out; + sourceRoot = "${sgx-sdk.name}/share/SampleCode/${name}"; + + buildInputs = [ + sgx-sdk + ]; + enableParallelBuilding = true; + buildFlags = [ + "SGX_MODE=SIM" + ]; + + installPhase = '' + mkdir $out + install -m 755 app $out/app + install *.so $out/ + ''; + + doInstallCheck = true; + installCheckInputs = [ which ]; + installCheckPhase = '' + pushd $out + ./app + popd + ''; + }; +in +{ + cxx11SGXDemo = buildSample "Cxx11SGXDemo"; + localAttestation = (buildSample "LocalAttestation").overrideAttrs (oldAttrs: { + installPhase = '' + mkdir $out + cp -r bin/. $out/ + ''; + }); + powerTransition = (buildSample "PowerTransition").overrideAttrs (oldAttrs: { + # Requires interaction + doInstallCheck = false; + }); + remoteAttestation = (buildSample "RemoteAttestation").overrideAttrs (oldAttrs: { + dontFixup = true; + installCheckPhase = '' + echo "a" | LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/sample_libcrypto ./app + ''; + }); + sampleEnclave = buildSample "SampleEnclave"; + sampleEnclavePCL = buildSample "SampleEnclavePCL"; + sealUnseal = buildSample "SealUnseal"; + switchless = buildSample "Switchless"; +}