From 8a223177093da64a5d071b36127d12b04c0d3397 Mon Sep 17 00:00:00 2001 From: "Li, Xun" Date: Tue, 24 Oct 2023 11:05:23 +0800 Subject: [PATCH] Linux 2.22 Open Source Gold Release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upgraded to OpenSSL 3.0.10. Added interoperable RA-TLS support which follows CCC design. Enhanced Protect File System performance and added additional dependency `libsgx_pthread.a`. Added the Constant Time instruction Decoder (CTD) into the default AEX-Notify mitigation handler in order to prevent the introduction of any additional subtle sidechannel leakages within the default handler. Added Mistletoe 3 mitigations to the IPP Cryptography Library to the AES-ECB, AESGCM, and AES-CMAC algorithms. These have been incorporated transparently into the `sgx_tcrypto` library. Resigned all IntelĀ® SGX Architecture Enclaves. Upgraded Intel SGX Quote Verification Enclave to integrate OpenSSL/SgxSSL 3.0.10. Added Attestation Library support for Intel(R) TDX Migration TD. Added Rust wrapper for low-level Quote Generation APIs. Enabled `SE_TRACE` log in release binary. Updated Rust QVL wrapper to use native Rust structure for quote verification collateral. Added a limitation in the DCAP QVL to only allow the user to set the QvE load policy once. Fixed bugs. Signed-off-by: Li, Xun --- .gitmodules | 3 + Makefile | 5 +- README.md | 89 +-- .../Enclave/TrustedLibrary/Libcxx.cpp | 4 +- .../App/UntrustedEnclaveMessageExchange.cpp | 2 +- .../LocalAttestation/AppResponder/CPTask.cpp | 1 + .../EnclaveMessageExchange.cpp | 2 +- .../SampleAEXNotify/Enclave/Enclave.cpp | 2 - SampleCode/SampleAttestedTLS/Makefile | 3 +- .../client/enc/openssl_client.cpp | 15 +- .../SampleAttestedTLS/client/host/host.cpp | 10 +- .../common/openssl_utility.cpp | 6 +- .../SampleAttestedTLS/common/utility.cpp | 74 +-- .../common/verify_callback.cpp | 8 +- .../non_enc_client/client.cpp | 10 +- .../SampleAttestedTLS/prepare_sgxssl.sh | 16 +- .../server/enc/openssl_server.cpp | 119 ++-- .../SampleAttestedTLS/server/host/host.cpp | 61 +- .../SampleAttestedTLS/server_tdx/Makefile | 27 +- .../server_tdx/openssl_server.cpp | 114 ++-- .../SampleAttestedTLS/server_tdx/server.cpp | 53 +- SampleCode/SampleAttestedTLS/sgxenv.mk | 22 +- SampleCode/SampleEnclave/README.txt | 10 +- common/inc/internal/metadata.h | 2 +- common/inc/internal/se_cpu_feature_defs_ext.h | 5 +- common/inc/internal/se_trace.h | 27 +- common/inc/internal/se_version.h | 24 +- common/inc/sgx_ecp_types.h | 3 +- common/inc/sgx_error.h | 1 + common/inc/sgx_key.h | 2 +- common/inc/sgx_tprotected_fs.edl | 16 +- common/inc/sgx_tprotected_fs.h | 19 + common/inc/sgx_tseal.h | 2 +- common/src/crypto_cmac_128.cpp | 64 +- common/src/se_trace.c | 13 + docker/build/tdx-qgs.dockerfile | 14 +- download_prebuilt.sh | 8 +- external/cbor/Makefile | 128 ++++ external/cbor/libcbor | 1 + external/cbor/raw_cbor.patch | 26 + external/cbor/sgx_cbor.patch | 85 +++ external/dcap_source | 2 +- external/sgx-emm/Makefile | 2 +- external/sgx-emm/emm_src | 2 +- external/sgxssl/prepare_sgxssl.sh | 10 +- linux/installer/bin/install-sgx-sdk.bin.tmpl | 3 +- .../sgx-aesm-service-1.0/debian/control | 4 +- .../libsgx-aesm-ecdsa-plugin.spec | 2 +- .../libsgx-aesm-pce-plugin.spec | 2 +- .../build_and_launch_docker.sh | 6 +- psw/ae/aesm_service/source/CMakeLists.txt | 3 +- .../CMakeLists.txt | 8 +- .../aesm_http_msg.cpp | 160 ++++- .../aesm_network.h | 1 + .../linux_network_service_bundle.cpp | 3 +- .../source/common/ssl_compat_wrapper.h | 13 - .../source/core/AESMLogicWrapper.cpp | 5 - .../aesm_service/source/qcnl/CMakeLists.txt | 18 +- .../qcnl/pck_cert_selection/CMakeLists.txt | 133 ++++ .../aesm_service/source/utils/CMakeLists.txt | 12 +- .../source/utils/crypto_cmac128.cpp | 62 +- .../aesm_service/source/utils/crypto_ecc.cpp | 205 +++--- .../aesm_service/source/utils/crypto_rsa.cpp | 65 +- .../source/utils/ssl_compat_wrapper.cpp | 102 --- psw/ae/data/prebuilt/README.md | 8 +- psw/ae/data/prebuilt/le_prod_css.bin | Bin 1808 -> 1808 bytes psw/ae/pce/config.xml | 2 +- psw/ae/pve/config.xml | 2 +- psw/ae/pve/helper.cpp | 8 +- psw/ae/qe/config.xml | 2 +- psw/enclave_common/sgx_enclave_common.cpp | 2 +- psw/enclave_common/sgx_enclave_common.lds | 2 + psw/uae_service/linux/libsgx_epid.lds | 2 + psw/uae_service/linux/libsgx_launch.lds | 2 + psw/uae_service/linux/libsgx_quote_ex.lds | 2 + psw/uae_service/linux/uae_service.lds | 2 + psw/urts/cpu_features_ext.cpp | 2 +- psw/urts/enclave.cpp | 3 +- psw/urts/enclave_creator_hw_com.cpp | 22 +- psw/urts/linux/urts.cpp | 2 +- psw/urts/linux/urts.lds | 2 + psw/urts/linux/urts_internal.lds | 2 + psw/urts/parser/elfparser.cpp | 2 - psw/urts/parser/update_global_data.hxx | 2 - psw/urts/urts_com.h | 4 +- sdk/ec_dh_lib/ec_dh.cpp | 3 +- sdk/edger8r/linux/CodeGen.ml | 6 +- sdk/edger8r/linux/Makefile | 9 - sdk/edger8r/linux/Util.ml | 2 +- .../sgx_tprotected_fs/file_flush.cpp | 445 +++++++------ .../sgx_tprotected_fs/file_init.cpp | 84 +-- .../sgx_tprotected_fs/file_other.cpp | 14 +- .../sgx_tprotected_fs/file_read_write.cpp | 24 +- .../sgx_tprotected_fs/lru_cache.cpp | 3 + .../sgx_tprotected_fs/protected_fs_file.h | 57 +- .../sgx_tprotected_fs/protected_fs_nodes.h | 13 - .../sgx_tprotected_fs/sgx_tprotected_fs.cpp | 11 + .../sgx_uprotected_fs/sgx_uprotected_fs.cpp | 285 ++++----- sdk/sign_tool/SignTool/Makefile | 22 +- sdk/sign_tool/SignTool/manage_metadata.cpp | 23 +- sdk/sign_tool/SignTool/manage_metadata.h | 1 + sdk/sign_tool/SignTool/parse_key_file.cpp | 92 ++- sdk/sign_tool/SignTool/parse_key_file.h | 7 +- sdk/sign_tool/SignTool/sign_tool.cpp | 117 ++-- sdk/simulation/tinst/deriv.cpp | 8 +- sdk/simulation/tinst/deriv.h | 4 +- sdk/simulation/tinst/t_instructions.cpp | 6 +- sdk/simulation/trtssim/linux/Makefile | 13 +- sdk/simulation/uae_service_sim/linux/Makefile | 12 +- .../uae_service_sim/linux/libsgx_epid.lds | 2 + .../uae_service_sim/linux/libsgx_quote_ex.lds | 2 + .../linux/libsgx_uae_service.lds | 2 + sdk/simulation/uinst/u_instructions.cpp | 16 +- .../urtssim/enclave_creator_sim.cpp | 17 - sdk/simulation/urtssim/linux/Makefile | 8 +- .../sgx_tswitchless/sgx_ocall_switchless.c | 10 + sdk/tlibcrypto/ipp/sgx_aes_gcm.cpp | 20 +- sdk/tlibcrypto/ipp/sgx_cmac128.cpp | 17 +- sdk/tlibcrypto/sgx_common_init_ipp.cpp | 23 +- sdk/tlibcrypto/sgxssl/sgx_cmac128.cpp | 115 ++-- sdk/tlibcrypto/sgxssl/sgx_ecc256.cpp | 492 +++++++++------ sdk/tlibcrypto/sgxssl/sgx_ecc256_ecdsa.cpp | 215 +++---- sdk/tlibcrypto/sgxssl/sgx_hmac.cpp | 73 ++- sdk/tlibcrypto/sgxssl/sgx_rsa3072.cpp | 144 +---- sdk/tlibcrypto/sgxssl/sgx_rsa_encryption.cpp | 239 +++---- sdk/trts/trts_aex.cpp | 33 +- sdk/trts/trts_ecall.cpp | 6 + sdk/trts/trts_veh.cpp | 68 +- sdk/ttls/Makefile | 36 +- sdk/ttls/cert_generator.cpp | 45 +- sdk/ttls/cert_header.h | 47 +- sdk/ttls/cert_verifier.cpp | 586 ++++++++++++++++-- sdk/ttls/ttls.cpp | 440 +++++++++---- sdk/utls/Makefile | 22 +- sdk/utls/utls.cpp | 135 ++-- 135 files changed, 3752 insertions(+), 2316 deletions(-) create mode 100644 external/cbor/Makefile create mode 160000 external/cbor/libcbor create mode 100644 external/cbor/raw_cbor.patch create mode 100644 external/cbor/sgx_cbor.patch create mode 100644 psw/ae/aesm_service/source/qcnl/pck_cert_selection/CMakeLists.txt diff --git a/.gitmodules b/.gitmodules index d980c15ab..d0632e255 100644 --- a/.gitmodules +++ b/.gitmodules @@ -23,3 +23,6 @@ [submodule "external/mbedtls/mbedtls_code"] path = external/mbedtls/mbedtls_code url = https://github.com/Mbed-TLS/mbedtls.git +[submodule "external/cbor/libcbor"] + path = external/cbor/libcbor + url = https://github.com/PJK/libcbor.git diff --git a/Makefile b/Makefile index 9367fdb71..0a08dd728 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,10 @@ preparation: 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 ./external/sgx-emm/create_symlink.sh - @# download prebuilt binaries + 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 + cd external/cbor/libcbor && git apply ../raw_cbor.patch >/dev/null 2>&1 || git apply ../raw_cbor.patch --check -R + cd external/cbor/sgx_libcbor && git apply ../sgx_cbor.patch >/dev/null 2>&1 || git apply ../sgx_cbor.patch --check -R ./download_prebuilt.sh ./external/dcap_source/QuoteGeneration/download_prebuilt.sh diff --git a/README.md b/README.md index 4a4cde36c..3a008255c 100644 --- a/README.md +++ b/README.md @@ -36,13 +36,13 @@ Introduction ------------ Intel(R) Software Guard Extensions (Intel(R) SGX) is an Intel technology for application developers seeking to protect select code and data from disclosure or modification. -The Linux\* Intel(R) SGX software stack is comprised of the Intel(R) SGX driver, the Intel(R) SGX SDK, and the Intel(R) SGX Platform Software (PSW). The Intel(R) SGX SDK and Intel(R) SGX PSW are hosted in the [linux-sgx](https://github.com/01org/linux-sgx) project. +The Linux\* Intel(R) SGX software stack is comprised of the Intel(R) SGX driver, the Intel(R) SGX SDK, and the Intel(R) SGX Platform Software (PSW). The Intel(R) SGX SDK and Intel(R) SGX PSW are hosted in the [linux-sgx](https://github.com/intel/linux-sgx) project. The [SGXDataCenterAttestationPrimitives](https://github.com/intel/SGXDataCenterAttestationPrimitives/) project maintains an out-of-tree driver for the Linux\* Intel(R) SGX software stack, which will be used until the driver upstreaming process is complete. It is used on the platforms with *Flexible Launch Control* and *Intel(R) AES New Instructions* support and could support both Elliptic Curve Digital Signature algorithm (ECDSA) based attestation and Enhanced Privacy Identification (EPID) based attestation. **Note**: Ice Lake Xeon-SP (and the future Xeon-SP platforms) doesn't support EPID attestation. -The [linux-sgx-driver](https://github.com/01org/linux-sgx-driver) project hosts the other out-of-tree driver for the Linux\* Intel(R) SGX software stack, which will be used until the driver upstreaming process is complete. It is used to support Enhanced Privacy Identification (EPID) based attestation on the platforms without *Flexible Launch Control*. +The [linux-sgx-driver](https://github.com/intel/linux-sgx-driver) project hosts the other out-of-tree driver for the Linux\* Intel(R) SGX software stack, which will be used until the driver upstreaming process is complete. It is used to support Enhanced Privacy Identification (EPID) based attestation on the platforms without *Flexible Launch Control*. The [intel-device-plugins-for-kubernetes](https://github.com/intel/intel-device-plugins-for-kubernetes) project enables users to run container applications running Intel(R) SGX enclaves in Kubernetes clusters. It also gives instructions how to set up ECDSA based attestation in a cluster. @@ -63,8 +63,8 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for details. Documentation ------------- -- [Intel(R) SGX for Linux\* OS](https://01.org/intel-softwareguard-extensions) project home page on [01.org](https://01.org) -- [Intel(R) SGX Programming Reference](https://software.intel.com/sites/default/files/managed/7c/f1/332831-sdm-vol-3d.pdf) +- [Intel(R) SGX for Linux\* OS](https://www.intel.com/content/www/us/en/developer/tools/software-guard-extensions/linux-overview.html) project home page on [Intel Developer Zone](https://www.intel.com/content/www/us/en/developer/overview.html) +- [Intel(R) SGX Programming Reference](https://www.intel.com/content/dam/develop/external/us/en/documents/329298-002-629101.pdf) Quick Start with Docker and Docker Compose ----------------------------------------- @@ -82,26 +82,24 @@ $ cd linux/installer/docker && ./build_compose_run.sh Build and Install the Intel(R) SGX Driver ----------------------------------------- Follow the [README.md](https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/master/driver/linux/README.md) in the [SGXDataCenterAttestationPrimitives](https://github.com/intel/SGXDataCenterAttestationPrimitives/) project to build and install the Intel(R) SGX driver. -**NOTE**: The above Intel(R) SGX driver requires *Flexible Launch Control* and *Intel(R) AES New Instructions* support. If your platform doesn't meet the requirement, please follow the instructions in the [linux-sgx-driver](https://github.com/01org/linux-sgx-driver) project to build and install this version of Intel(R) SGX driver. +**NOTE**: The above Intel(R) SGX driver requires *Flexible Launch Control* and *Intel(R) AES New Instructions* support. If your platform doesn't meet the requirement, please follow the instructions in the [linux-sgx-driver](https://github.com/intel/linux-sgx-driver) project to build and install this version of Intel(R) SGX driver. Build the Intel(R) SGX SDK and Intel(R) SGX PSW Package ------------------------------------------------------- ### Prerequisites: - Ensure that you have one of the following required operating systems: - * Ubuntu\* 18.04 LTS Desktop 64bits - * Ubuntu\* 18.04 LTS Server 64bits * Ubuntu\* 20.04 LTS Desktop 64bits * Ubuntu\* 20.04 LTS Server 64bits * Ubuntu\* 22.04 LTS Server 64bits - * Red Hat Enterprise Linux Server release 8.6 64bits - * CentOS Stream 8 64bits + * Red Hat Enterprise Linux Server release 9.2 64bits + * CentOS Stream 9 64bits * CentOS 8.3 64bits * SUSE Linux Enterprise Server 15.4 64bits * Anolis OS 8.6 64bits * Debian 10 64bits - Use the following command(s) to install the required tools to build the Intel(R) SGX SDK: - * On Ubuntu 18.04 and Debian 10: + * On Debian 10: ``` $ sudo apt-get install build-essential ocaml ocamlbuild automake autoconf libtool wget python3 libssl-dev git cmake perl $ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 1 @@ -110,13 +108,17 @@ Build the Intel(R) SGX SDK and Intel(R) SGX PSW Package ``` $ sudo apt-get install build-essential ocaml ocamlbuild automake autoconf libtool wget python-is-python3 libssl-dev git cmake perl ``` - * On Red Hat Enterprise Linux 8.6: + * On Red Hat Enterprise Linux 9.2: ``` $ sudo yum groupinstall 'Development Tools' $ sudo yum install ocaml ocaml-ocamlbuild wget python3 openssl-devel git cmake perl - $ sudo alternatives --set python /usr/bin/python3 ``` - * On CentOS Stream 8 and CentOS 8.3: + * On CentOS Stream 9: + ``` + $ sudo dnf group install 'Development Tools' + $ sudo dnf install ocaml ocaml-ocamlbuild redhat-rpm-config openssl-devel wget rpm-build git cmake perl python3 + ``` + * On CentOS 8.3: ``` $ sudo dnf group install 'Development Tools' $ sudo dnf --enablerepo=powertools install ocaml ocaml-ocamlbuild redhat-rpm-config openssl-devel wget rpm-build git cmake perl python3 @@ -145,11 +147,15 @@ Build the Intel(R) SGX SDK and Intel(R) SGX PSW Package ``` $ sudo apt-get install libssl-dev libcurl4-openssl-dev protobuf-compiler libprotobuf-dev debhelper cmake reprepro unzip pkgconf libboost-dev libboost-system-dev libboost-thread-dev lsb-release libsystemd0 ``` - * On Red Hat Enterprise Linux 8.6: + * On Red Hat Enterprise Linux 9.2: ``` $ sudo yum install openssl-devel libcurl-devel protobuf-devel cmake rpm-build createrepo yum-utils pkgconf boost-devel protobuf-lite-devel systemd-libs ``` - * On CentOS Stream 8 and CentOS 8.3: + * On CentOS Stream 9: + ``` + $ sudo dnf install openssl-devel libcurl-devel protobuf-devel cmake rpm-build createrepo yum-utils pkgconf boost-devel protobuf-lite-devel systemd-libs + ``` + * On CentOS 8.3: ``` $ sudo dnf --enablerepo=powertools install openssl-devel libcurl-devel protobuf-devel cmake rpm-build createrepo yum-utils pkgconf boost-devel protobuf-lite-devel systemd-libs ``` @@ -249,7 +255,7 @@ You can find the tools and libraries generated in the `build/linux` directory. $ make ``` - To build the Intel(R) SGX PSW installer, enter the following command: - * On Ubuntu 18.04, Ubuntu 20.04, Ubuntu 22.04 and Debian 10: + * On Ubuntu 20.04, Ubuntu 22.04 and Debian 10: ``` $ make deb_psw_pkg ``` @@ -262,7 +268,7 @@ You can find the tools and libraries generated in the `build/linux` directory. ``` $ make deb_psw_pkg DEBUG=1 ``` - * On Red Hat Enterprise Linux 8.6, CentOS Stream 8, CentOS 8.3, Anolis OS 8.6 and SUSE Linux Enterprise Server 15.4: + * On Red Hat Enterprise Linux 9.2, CentOS Stream 9, CentOS 8.3, Anolis OS 8.6 and SUSE Linux Enterprise Server 15.4: ``` $ make rpm_psw_pkg ``` @@ -282,10 +288,6 @@ You can find the tools and libraries generated in the `build/linux` directory. **Note**: The above command builds the local package repository. If you want to use it, you need to add it to the system repository configuration. The local package repository is not signed, you need to trust it for the purpose of development. - To add the local Debian package repository to the system repository configuration, append the following line to /etc/apt/sources.list. You need to replace PATH_TO_LOCAL_REPO with the proper path on your system: - * On Ubuntu 18.04: - ``` - deb [trusted=yes arch=amd64] file:/PATH_TO_LOCAL_REPO bionic main - ``` * On Ubuntu 20.04: ``` deb [trusted=yes arch=amd64] file:/PATH_TO_LOCAL_REPO focal main @@ -312,7 +314,7 @@ You can find the tools and libraries generated in the `build/linux` directory. **Note**: The above command builds the local package repository. If you want to use it, you need to add it to the system repository configuration. Since the local package repository is not signed with GPG, you should ignore the gpgcheck when installing the packages. - To add the local RPM package repository to the system repository configuration, you can use the following command. You need to replace PATH_TO_LOCAL_REPO with the proper path on your system: - * On Red Hat Enterprise Linux 8.6, CentOS Stream 8, CentOS 8.3, Anolis OS 8.6: + * On Red Hat Enterprise Linux 9.2, CentOS Stream 9, CentOS 8.3, Anolis OS 8.6: ``` $ sudo yum-config-manager --add-repo file://PATH_TO_LOCAL_REPO ``` @@ -321,11 +323,11 @@ You can find the tools and libraries generated in the `build/linux` directory. $ sudo zypper addrepo PATH_TO_LOCAL_REPO LOCAL_REPO_ALIAS ``` - To ignore the gpgcheck when you install the package, enter the following command: - * On Red Hat Enterprise Linux 8.6, CentOS Stream 8, CentOS 8.3, Anolis OS 8.6: + * On Red Hat Enterprise Linux 9.2, CentOS Stream 9, CentOS 8.3, Anolis OS 8.6: ``` $ sudo yum --nogpgcheck install ``` - * On SUSE Linux Enterprise Server 15.5: + * On SUSE Linux Enterprise Server 15.4: ``` $ sudo zypper --no-gpg-checks install ``` @@ -334,28 +336,31 @@ Install the Intel(R) SGX SDK ------------------------ ### Prerequisites - Ensure that you have one of the following operating systems: - * Ubuntu\* 18.04 LTS Desktop 64bits - * Ubuntu\* 18.04 LTS Server 64bits * Ubuntu\* 20.04 LTS Desktop 64bits * Ubuntu\* 20.04 LTS Server 64bits * Ubuntu\* 22.04 LTS Server 64bits - * Red Hat Enterprise Linux Server release 8.6 64bits - * CentOS Stream 8 64bits + * Red Hat Enterprise Linux Server release 9.2 64bits + * CentOS Stream 9 64bits * CentOS 8.3 64bits * SUSE Linux Enterprise Server 15.4 64bits * Anolis OS 8.6 64bits * Debian 10 64bits - Use the following command to install the required tool to use Intel(R) SGX SDK: - * On Ubuntu 18.04 and Debian 10: + * On Debian 10: ``` $ sudo apt-get install build-essential python3 - $ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 1 + $ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 ``` * On Ubuntu 20.04 and Ubuntu 22.04: ``` $ sudo apt-get install build-essential python-is-python3 ``` - * On Red Hat Enterprise Linux 8.6, CentOS Stream 8, CentOS 8.3 and Anolis OS 8.6: + * On Red Hat Enterprise Linux 9.2 and CentOS Stream 9: + ``` + $ sudo yum groupinstall 'Development Tools' + $ sudo yum install python3 + ``` + * On CentOS 8.3 and Anolis OS 8.6: ``` $ sudo yum groupinstall 'Development Tools' $ sudo yum install python3 @@ -421,13 +426,11 @@ Install the Intel(R) SGX PSW ---------------------------- ### Prerequisites - Ensure that you have one of the following operating systems: - * Ubuntu\* 18.04 LTS Desktop 64bits - * Ubuntu\* 18.04 LTS Server 64bits * Ubuntu\* 20.04 LTS Desktop 64bits * Ubuntu\* 20.04 LTS Server 64bits * Ubuntu\* 22.04 LTS Server 64bits - * Red Hat Enterprise Linux Server release 8.6 64bits - * CentOS Stream 8 64bits + * Red Hat Enterprise Linux Server release 9.2 64bits + * CentOS Stream 9 64bits * CentOS 8.3 64bits * SUSE Linux Enterprise Server 15.4 64bits * Anolis OS 8.6 64bits @@ -437,15 +440,19 @@ Install the Intel(R) SGX PSW - Configure the system with the **Intel SGX hardware enabled** option and install Intel(R) SGX driver in advance. See the earlier topic, *Build and Install the Intel(R) SGX Driver*, for information on how to install the Intel(R) SGX driver. - Install the library using the following command: - * On Ubuntu 18.04, Ubuntu 20.04, Ubuntu 22.04 and Debian 10: + * On Ubuntu 20.04, Ubuntu 22.04 and Debian 10: ``` $ sudo apt-get install libssl-dev libcurl4-openssl-dev libprotobuf-dev ``` - * On Red Hat Enterprise Linux 8.6: + * On Red Hat Enterprise Linux 9.2: ``` $ sudo yum install openssl-devel libcurl-devel protobuf-devel ``` - * On CentOS Stream 8 and CentOS 8.3: + * On CentOS Stream 9: + ``` + $ sudo dnf install libcurl-devel protobuf-devel + ``` + * On CentOS 8.3: ``` $ sudo dnf --enablerepo=powertools install libcurl-devel protobuf-devel ``` @@ -463,7 +470,7 @@ The SGX PSW provides 3 services: launch, EPID-based attestation, and algorithm a #### Using the local repo(recommended) -| |Ubuntu 18.04, Ubuntu 20.04, Ubuntu 22.04 and Debian 10|Red Hat Enterprise Linux 8.6, CentOS Stream 8 and CentOS 8.3| SUSE Linux Enterprise Server 15| +| |Ubuntu 20.04, Ubuntu 22.04 and Debian 10|Red Hat Enterprise Linux 9.2, CentOS Stream 9, CentOS 8.3 and Anolis OS 8.6| SUSE Linux Enterprise Server 15| | ------------ | ------------ | ------------ | ------------ | |launch service |apt-get install libsgx-launch libsgx-urts|yum install libsgx-launch libsgx-urts|zypper install libsgx-launch libsgx-urts| |EPID-based attestation service|apt-get install libsgx-epid libsgx-urts|yum install libsgx-epid libsgx-urts|zypper install libsgx-epid libsgx-urts| @@ -484,11 +491,11 @@ apt-get dist-upgrade -o Dpkg::Options::="--force-overwrite" ``` #### Configure the installation Some packages are configured with recommended dependency on other packages that are not required for certain usage. For instance, the background daemon is not required for container usage. It will be installed by default, but you can drop it by using the additional option during the installation. -* On Ubuntu 18.04, Ubuntu 20.04, Ubuntu 22.04 and Debian 10: +* On Ubuntu 20.04, Ubuntu 22.04 and Debian 10: ``` --no-install-recommends ``` -* On Red Hat Enterprise Linux 8.6, CentOS Stream 8, CentOS 8.3 and Anolis OS 8.6: +* On Red Hat Enterprise Linux 9.2, CentOS Stream 9, CentOS 8.3 and Anolis OS 8.6: ``` --setopt=install_weak_deps=False ``` diff --git a/SampleCode/Cxx17SGXDemo/Enclave/TrustedLibrary/Libcxx.cpp b/SampleCode/Cxx17SGXDemo/Enclave/TrustedLibrary/Libcxx.cpp index 547d3d006..e95fca170 100644 --- a/SampleCode/Cxx17SGXDemo/Enclave/TrustedLibrary/Libcxx.cpp +++ b/SampleCode/Cxx17SGXDemo/Enclave/TrustedLibrary/Libcxx.cpp @@ -846,7 +846,7 @@ void ecall_cxx17_gcd_lcm() { void print_map(std::string_view comment, const auto& data) { - printf("%s", comment); + printf("%s", comment.data()); for (auto [k, v] : data) printf(" %d(%c)", k, v); printf("\n"); @@ -967,7 +967,7 @@ void ecall_cxx17_string_view() { for (int y{}, p{}; y != 3; ++y, p = ((p + 1) % 4)) { for (int x{}; x != 16; ++x) - printf("%s", unicode[p]); + printf("%s", unicode[p].data()); printf("\n"); } } diff --git a/SampleCode/LocalAttestation/App/UntrustedEnclaveMessageExchange.cpp b/SampleCode/LocalAttestation/App/UntrustedEnclaveMessageExchange.cpp index 603804aa6..a732d04fd 100644 --- a/SampleCode/LocalAttestation/App/UntrustedEnclaveMessageExchange.cpp +++ b/SampleCode/LocalAttestation/App/UntrustedEnclaveMessageExchange.cpp @@ -108,7 +108,7 @@ ATTESTATION_STATUS send_request_ocall(uint32_t session_id, secure_message_t* req ATTESTATION_STATUS end_session_ocall(uint32_t session_id) { sgx_status_t ret; - uint32_t retcode; + uint32_t retcode = (uint32_t) INVALID_SESSION; ret = end_session(responder_enclave_id, &retcode, session_id); if (ret != SGX_SUCCESS || retcode != SGX_SUCCESS) diff --git a/SampleCode/LocalAttestation/AppResponder/CPTask.cpp b/SampleCode/LocalAttestation/AppResponder/CPTask.cpp index 7da098fdf..863f060c1 100644 --- a/SampleCode/LocalAttestation/AppResponder/CPTask.cpp +++ b/SampleCode/LocalAttestation/AppResponder/CPTask.cpp @@ -258,6 +258,7 @@ int process_close_req(int clientfd, SESSION_CLOSE_REQ * close_req) return -1; // send back response + memset(&close_ack, 0, sizeof(FIFO_MSG)); close_ack.header.type = FIFO_DH_CLOSE_RESP; close_ack.header.size = 0; diff --git a/SampleCode/LocalAttestation/EnclaveInitiator/EnclaveMessageExchange.cpp b/SampleCode/LocalAttestation/EnclaveInitiator/EnclaveMessageExchange.cpp index b4245fa1b..fb125b191 100644 --- a/SampleCode/LocalAttestation/EnclaveInitiator/EnclaveMessageExchange.cpp +++ b/SampleCode/LocalAttestation/EnclaveInitiator/EnclaveMessageExchange.cpp @@ -317,7 +317,7 @@ ATTESTATION_STATUS send_request_receive_response(dh_session_t *session_info, ATTESTATION_STATUS close_session(dh_session_t *session_info) { sgx_status_t status; - uint32_t retstatus; + uint32_t retstatus = (uint32_t) ATTESTATION_SE_ERROR; if(!session_info) { diff --git a/SampleCode/SampleAEXNotify/Enclave/Enclave.cpp b/SampleCode/SampleAEXNotify/Enclave/Enclave.cpp index 30ab6f0e3..ae6e741e6 100644 --- a/SampleCode/SampleAEXNotify/Enclave/Enclave.cpp +++ b/SampleCode/SampleAEXNotify/Enclave/Enclave.cpp @@ -90,12 +90,10 @@ void count_powers_of_two_with_aex(uint64_t low, uint64_t high, uint32_t* count, sgx_aex_mitigation_node_t node; sgx_register_aex_handler(&node, my_aex_notify_handler, (const void*)args); - sgx_set_ssa_aexnotify(1); const uint32_t local_count = count_powers_of_two(low,high); *count = local_count; - sgx_set_ssa_aexnotify(0); sgx_unregister_aex_handler(my_aex_notify_handler); *aex_count = g_aex_count; diff --git a/SampleCode/SampleAttestedTLS/Makefile b/SampleCode/SampleAttestedTLS/Makefile index b354653d2..5b633f3e5 100644 --- a/SampleCode/SampleAttestedTLS/Makefile +++ b/SampleCode/SampleAttestedTLS/Makefile @@ -51,8 +51,9 @@ build: $(SGXSSL_HEADER_CHECK) $(MAKE) -C client $(MAKE) -C non_enc_client -tdx: $(SGXSSL_HEADER_CHECK) +tdx: $(MAKE) -C server_tdx + $(MAKE) -C non_enc_client clean: $(MAKE) -C server clean diff --git a/SampleCode/SampleAttestedTLS/client/enc/openssl_client.cpp b/SampleCode/SampleAttestedTLS/client/enc/openssl_client.cpp index 36b57bc99..ff0f00f37 100644 --- a/SampleCode/SampleAttestedTLS/client/enc/openssl_client.cpp +++ b/SampleCode/SampleAttestedTLS/client/enc/openssl_client.cpp @@ -83,7 +83,8 @@ int communicate_with_server(SSL* ssl) if (error == SSL_ERROR_WANT_WRITE) continue; t_print(TLS_CLIENT "Failed! SSL_write returned %d\n", error); - ret = bytes_written; + if (bytes_written == 0) ret = -1; + else ret = bytes_written; goto done; } @@ -103,12 +104,16 @@ int communicate_with_server(SSL* ssl) continue; t_print(TLS_CLIENT "Failed! SSL_read returned error=%d\n", error); - ret = bytes_read; + if (bytes_read == 0) ret = -1; + else ret = bytes_read; break; } t_print(TLS_CLIENT " %d bytes read\n", bytes_read); // check to to see if received payload is expected + // Note that if you just want to use client here but server from other + // applications, you need to ignore this check, SERVER_PAYLOAD_SIZE + // need to be adjusted. if ((bytes_read != SERVER_PAYLOAD_SIZE) || (memcmp(SERVER_PAYLOAD, buf, bytes_read) != 0)) { @@ -136,7 +141,7 @@ int communicate_with_server(SSL* ssl) int create_socket(char* server_name, char* server_port) { int sockfd = -1; - struct sockaddr_in dest_sock; + struct sockaddr_in dest_sock; int res = -1; sockfd = socket(AF_INET, SOCK_STREAM, 0); @@ -204,14 +209,14 @@ int launch_tls_client(char* server_name, char* server_port) // specify the verify_callback for custom verification SSL_CTX_set_verify(ssl_client_ctx, SSL_VERIFY_PEER, &verify_callback); - t_print(TLS_CLIENT "load cert and key\n"); + t_print(TLS_CLIENT "load cert and key\n"); if (load_tls_certificates_and_keys(ssl_client_ctx, cert, pkey) != 0) { t_print(TLS_CLIENT " unable to load certificate and private key on the client\n"); goto done; } - + if ((ssl_session = SSL_new(ssl_client_ctx)) == nullptr) { t_print(TLS_CLIENT diff --git a/SampleCode/SampleAttestedTLS/client/host/host.cpp b/SampleCode/SampleAttestedTLS/client/host/host.cpp index b8efbb76a..bbdee806f 100644 --- a/SampleCode/SampleAttestedTLS/client/host/host.cpp +++ b/SampleCode/SampleAttestedTLS/client/host/host.cpp @@ -139,15 +139,15 @@ void print_error_message(sgx_status_t ret) } if (idx == ttl) - printf("Error code is 0x%X. Please refer to the \"Intel SGX SDK Developer Reference\" for more details.\n", ret); + printf("Error code is 0x%X. Please refer to the \"Intel SGX SDK Developer Reference\" for more details.\n", ret); } sgx_status_t initialize_enclave(const char *enclave_path) { - sgx_status_t ret = SGX_ERROR_UNEXPECTED; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; - // the 1st parameter should be CLIENT_ENCLAVE_FILENAME - ret = sgx_create_enclave(enclave_path, SGX_DEBUG_FLAG, NULL, NULL, &client_global_eid, NULL); + // the 1st parameter should be CLIENT_ENCLAVE_FILENAME + ret = sgx_create_enclave(enclave_path, SGX_DEBUG_FLAG, NULL, NULL, &client_global_eid, NULL); printf("Client Enc: Enclave library %s\n", enclave_path); if (ret != SGX_SUCCESS) @@ -160,7 +160,7 @@ sgx_status_t initialize_enclave(const char *enclave_path) void terminate_enclave() { - sgx_destroy_enclave(client_global_eid); + sgx_destroy_enclave(client_global_eid); printf("Host: Enclave successfully terminated.\n"); } diff --git a/SampleCode/SampleAttestedTLS/common/openssl_utility.cpp b/SampleCode/SampleAttestedTLS/common/openssl_utility.cpp index 9370eeb75..8a1ab2c00 100644 --- a/SampleCode/SampleAttestedTLS/common/openssl_utility.cpp +++ b/SampleCode/SampleAttestedTLS/common/openssl_utility.cpp @@ -38,7 +38,7 @@ sgx_status_t generate_certificate_and_pkey(X509*& certificate, EVP_PKEY*& pkey) size_t public_key_buffer_size = 0; const unsigned char* certificate_buffer_ptr = nullptr; BIO* mem = nullptr; - int key_type = RSA_TYPE; + int key_type = EC_TYPE; if (key_type) { PRINT(" generating keys by EC P-384\n"); @@ -60,8 +60,8 @@ sgx_status_t generate_certificate_and_pkey(X509*& certificate, EVP_PKEY*& pkey) PRINT("public_key_buf_size:[%ld]\n", public_key_buffer_size); PRINT("%s\n", public_key_buffer); - PRINT("private_key_buf_size:[%ld]\n", private_key_buffer_size); - PRINT("%s\n", private_key_buffer); + PRINT("private_key_buf_size:[%ld]\n", private_key_buffer_size); + PRINT("%s\n", private_key_buffer); qresult = tee_get_certificate_with_evidence( certificate_subject_name, private_key_buffer, diff --git a/SampleCode/SampleAttestedTLS/common/utility.cpp b/SampleCode/SampleAttestedTLS/common/utility.cpp index 688160e7e..eb8839e9a 100644 --- a/SampleCode/SampleAttestedTLS/common/utility.cpp +++ b/SampleCode/SampleAttestedTLS/common/utility.cpp @@ -46,55 +46,45 @@ int get_pkey_by_rsa(EVP_PKEY *pk) { int res = -1; - RSA* rsa = nullptr; - BIGNUM* e = nullptr; + EVP_PKEY_CTX *ctx = NULL; - - e = BN_new(); - if (!e) { - PRINT("BN_new failed\n"); - goto done; - } - - res = BN_set_word(e, (BN_ULONG)RSA_F4); - if (!res) { - PRINT("BN_set_word failed (%d)\n", res); - goto done; + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + if (ctx == NULL) + return res; + res = EVP_PKEY_keygen_init(ctx); + if (res <= 0) + { + PRINT("keygen_init failed (%d)\n", res); + goto done; } - rsa = RSA_new(); - if (!rsa) { - PRINT("RSA_new failed\n"); - res = -1; - goto done; + res = EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, RSA_3072_PRIVATE_KEY_SIZE); + if (res <= 0) + { + PRINT("set_rsa_kengen_bits failed (%d)\n", res); + goto done; } - res = RSA_generate_key_ex( - rsa, - RSA_3072_PRIVATE_KEY_SIZE, /* number of bits for the key value */ - e, /* exponent - RSA_F4 is defined as 0x10001L */ - nullptr /* callback argument - not needed in this case */ - ); - - if (!res) + /* Generate key */ + res = EVP_PKEY_keygen(ctx, &pk); + if (res <= 0) { - PRINT("RSA_generate_key failed (%d)\n", res); - goto done; + PRINT("keygen failed (%d)\n", res); + goto done; } - // Assign RSA key to EVP_PKEY structure - EVP_PKEY_assign_RSA(pk, rsa); - done: - if (e) - BN_clear_free(e); + if (ctx) + EVP_PKEY_CTX_free(ctx); + return res; + } int get_pkey_by_ec(EVP_PKEY *pk) { - int res = -1; - EVP_PKEY_CTX *ctx; + int res = -1; + EVP_PKEY_CTX *ctx; ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); if (ctx == NULL) @@ -122,8 +112,8 @@ int get_pkey_by_ec(EVP_PKEY *pk) } done: - if (ctx) - EVP_PKEY_CTX_free(ctx); + if (ctx) + EVP_PKEY_CTX_free(ctx); return res; } @@ -133,7 +123,7 @@ int get_pkey_by_ec(EVP_PKEY *pk) // hardare independant sgx_status_t generate_key_pair( int type, - uint8_t** public_key, + uint8_t** public_key, size_t* public_key_size, uint8_t** private_key, size_t* private_key_size) @@ -171,8 +161,8 @@ sgx_status_t generate_key_pair( if (res <= 0) { PRINT("get_pkey failed (%d)\n", res); - result = SGX_ERROR_UNEXPECTED; - goto done; + result = SGX_ERROR_UNEXPECTED; + goto done; } // Allocate memory @@ -200,7 +190,7 @@ sgx_status_t generate_key_pair( if (!bio) { PRINT("BIO_new for local_public_key failed\n"); - goto done; + goto done; } res = PEM_write_bio_PUBKEY(bio, pkey); @@ -259,7 +249,7 @@ sgx_status_t generate_key_pair( if (pkey) EVP_PKEY_free(pkey); // When this is called, rsa is also freed if (result != SGX_SUCCESS) - { + { if (local_public_key) free(local_public_key); if (local_private_key) diff --git a/SampleCode/SampleAttestedTLS/common/verify_callback.cpp b/SampleCode/SampleAttestedTLS/common/verify_callback.cpp index 90e636ae1..db1230d42 100644 --- a/SampleCode/SampleAttestedTLS/common/verify_callback.cpp +++ b/SampleCode/SampleAttestedTLS/common/verify_callback.cpp @@ -110,11 +110,11 @@ int verify_callback(int preverify_ok, X509_STORE_CTX* ctx) der_len); PRINT(" verifying certificate start \n"); - //inside enclave, the current_time is acquired by ocall, this is just an example - // current_time by ocall is untrusted, user please be aware of it. - GETCURRTIME(¤t_time); + //inside enclave, the current_time is acquired by ocall, this is just an example + // current_time by ocall is untrusted, user please be aware of it. + GETCURRTIME(¤t_time); - // verify tls certificate + // verify tls certificate result = VERIFY_CALLBACK( der, der_len, current_time, &qv_result, &sup_data, (uint32_t *)&sup_data_len); diff --git a/SampleCode/SampleAttestedTLS/non_enc_client/client.cpp b/SampleCode/SampleAttestedTLS/non_enc_client/client.cpp index c74436465..336010300 100644 --- a/SampleCode/SampleAttestedTLS/non_enc_client/client.cpp +++ b/SampleCode/SampleAttestedTLS/non_enc_client/client.cpp @@ -100,7 +100,8 @@ int communicate_with_server(SSL* ssl) if (error == SSL_ERROR_WANT_WRITE) continue; printf(TLS_CLIENT "Failed! SSL_write returned %d\n", error); - ret = bytes_written; + if (bytes_written == 0) ret = -1; + else ret = bytes_written; goto done; } @@ -120,13 +121,17 @@ int communicate_with_server(SSL* ssl) continue; printf(TLS_CLIENT "Failed! SSL_read returned error=%d\n", error); - ret = bytes_read; + if (bytes_read == 0) ret = -1; + else ret = bytes_read; goto done; } printf(TLS_CLIENT " %d bytes read\n", bytes_read); // check to to see if received payload is expected + // Note that if you want to use client here but server from other + // applications, you need to ignore this check for SERVER_PAYLOAD_SIZE + // which need to be adjusted for an actual value if ((bytes_read != SERVER_PAYLOAD_SIZE) || (memcmp(SERVER_PAYLOAD, buf, bytes_read) != 0)) { @@ -241,7 +246,6 @@ int main(int argc, char** argv) // initialize openssl library and register algorithms OpenSSL_add_all_algorithms(); - ERR_load_BIO_strings(); ERR_load_crypto_strings(); SSL_load_error_strings(); diff --git a/SampleCode/SampleAttestedTLS/prepare_sgxssl.sh b/SampleCode/SampleAttestedTLS/prepare_sgxssl.sh index 62929e783..37f3e43d5 100755 --- a/SampleCode/SampleAttestedTLS/prepare_sgxssl.sh +++ b/SampleCode/SampleAttestedTLS/prepare_sgxssl.sh @@ -35,17 +35,23 @@ project_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" echo "project_dir is $project_dir" sgxssl_dir=$project_dir/sgxssl openssl_out_dir=$sgxssl_dir/openssl_source -openssl_ver_name=openssl-1.1.1t +openssl_ver_name=openssl-3.0.10 intel_sgx_ssl_url=https://github.com/intel/intel-sgx-ssl -support_tls_branch=support_tls +support_tls_branch=support_tls_openssl3 build_script=$sgxssl_dir/Linux/build_openssl.sh server_url_path=https://www.openssl.org/source full_openssl_url=$server_url_path/$openssl_ver_name.tar.gz -full_openssl_url_old=$server_url_path/old/1.1.1/$openssl_ver_name.tar.gz +full_openssl_url_old=$server_url_path/old/3.0.10/$openssl_ver_name.tar.gz FileExists() { pushd $sgxssl_dir/Linux/ - make clean sgxssl_no_mitigation + if [ $SGX_DEBUG == 0 ] ; then + echo "build release mode openssl" + make clean sgxssl_no_mitigation + else + echo "build debug mode openssl" + make clean sgxssl_no_mitigation DEBUG=1 + fi echo "build sgxssl completed" popd } @@ -56,7 +62,7 @@ if [ $debug == true ] ; then read -n 1 -p "download souce code only, because we need to build ourselves" fi -openssl_chksum=8dee9b24bdb1dcbf0c3d1e9b02fb8f6bf22165e807f45adeb7c9677536859d3b +openssl_chksum=1761d4f5b13a1028b9b6f3d4b8e17feb0cedc9370f6afe61d7193d2cdce83323 rm -f check_sum_openssl.txt if [ ! -f $build_script ]; then git clone $intel_sgx_ssl_url -b $support_tls_branch $sgxssl_dir || exit 1 diff --git a/SampleCode/SampleAttestedTLS/server/enc/openssl_server.cpp b/SampleCode/SampleAttestedTLS/server/enc/openssl_server.cpp index a81130dc9..418143bd6 100644 --- a/SampleCode/SampleAttestedTLS/server/enc/openssl_server.cpp +++ b/SampleCode/SampleAttestedTLS/server/enc/openssl_server.cpp @@ -36,7 +36,7 @@ extern "C" { int set_up_tls_server(char* server_port, bool keep_server_up); - sgx_status_t ocall_close(int *ret, int fd); + sgx_status_t ocall_close(int *ret, int fd); }; int verify_callback(int preverify_ok, X509_STORE_CTX* ctx); @@ -92,75 +92,72 @@ int handle_communication_until_done( bool keep_server_up) { int ret = -1; - int test_error = 1; -waiting_for_connection_request: - - struct sockaddr_in addr; - uint len = sizeof(addr); - - // reset ssl_session and client_socket_fd to prepare for the new TLS - // connection - if (client_socket_fd > 0) - { - ocall_close(&ret, client_socket_fd); - if (ret != 0) { - t_print(TLS_SERVER "OCALL: error closing client socket before starting a new TLS session.\n"); - goto exit; + int test_error = 1; + + do { + struct sockaddr_in addr; + uint len = sizeof(addr); + + // reset ssl_session and client_socket_fd to prepare for the new TLS + // connection + if (client_socket_fd > 0) + { + ocall_close(&ret, client_socket_fd); + if (ret != 0) { + t_print(TLS_SERVER "OCALL: error closing client socket before starting a new TLS session.\n"); + break; + } } - } - SSL_free(ssl_session); - t_print(TLS_SERVER " waiting for client connection\n"); + SSL_free(ssl_session); + t_print(TLS_SERVER " waiting for client connection\n"); - client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&addr, &len); + client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&addr, &len); - if (client_socket_fd < 0) - { - t_print(TLS_SERVER "Unable to accept the client request\n"); - goto exit; - } - - // create a new SSL structure for a connection - if ((ssl_session = SSL_new(ssl_server_ctx)) == nullptr) - { - t_print(TLS_SERVER - "Unable to create a new SSL connection state object\n"); - goto exit; - } + if (client_socket_fd < 0) + { + t_print(TLS_SERVER "Unable to accept the client request\n"); + break; + } - SSL_set_fd(ssl_session, client_socket_fd); + // create a new SSL structure for a connection + if ((ssl_session = SSL_new(ssl_server_ctx)) == nullptr) + { + t_print(TLS_SERVER + "Unable to create a new SSL connection state object\n"); + break; + } - // wait for a TLS/SSL client to initiate a TLS/SSL handshake + SSL_set_fd(ssl_session, client_socket_fd); - t_print(TLS_SERVER "initiating a passive connect SSL_accept\n"); - test_error = SSL_accept(ssl_session); - if (test_error <= 0) - { - t_print(TLS_SERVER " SSL handshake failed, error(%d)(%d)\n", - test_error, SSL_get_error(ssl_session, test_error)); - goto exit; - } + // wait for a TLS/SSL client to initiate a TLS/SSL handshake - t_print(TLS_SERVER "<---- Read from client:\n"); - if (read_from_session_peer( - ssl_session, CLIENT_PAYLOAD, CLIENT_PAYLOAD_SIZE) != 0) - { - t_print(TLS_SERVER " Read from client failed\n"); - goto exit; - } + t_print(TLS_SERVER "initiating a passive connect SSL_accept\n"); + test_error = SSL_accept(ssl_session); + if (test_error <= 0) + { + t_print(TLS_SERVER " SSL handshake failed, error(%d)(%d)\n", + test_error, SSL_get_error(ssl_session, test_error)); + break; + } - t_print(TLS_SERVER "<---- Write to client:\n"); - if (write_to_session_peer( - ssl_session, SERVER_PAYLOAD, strlen(SERVER_PAYLOAD)) != 0) - { - t_print(TLS_SERVER " Write to client failed\n"); - goto exit; - } + t_print(TLS_SERVER "<---- Read from client:\n"); + if (read_from_session_peer( + ssl_session, CLIENT_PAYLOAD, CLIENT_PAYLOAD_SIZE) != 0) + { + t_print(TLS_SERVER " Read from client failed\n"); + break; + } - if (keep_server_up) - goto waiting_for_connection_request; + t_print(TLS_SERVER "<---- Write to client:\n"); + if (write_to_session_peer( + ssl_session, SERVER_PAYLOAD, strlen(SERVER_PAYLOAD)) != 0) + { + t_print(TLS_SERVER " Write to client failed\n"); + break; + } + ret = 0; + } while (keep_server_up); - ret = 0; -exit: return ret; } @@ -196,7 +193,7 @@ int set_up_tls_server(char* server_port, bool keep_server_up) " unable to load certificate and private key on the server\n "); goto exit; } - + server_port_number = (unsigned int)atoi(server_port); // convert to char* to int if (create_listener_socket(server_port_number, server_socket_fd) != 0) { diff --git a/SampleCode/SampleAttestedTLS/server/host/host.cpp b/SampleCode/SampleAttestedTLS/server/host/host.cpp index 5e21af2b6..05616b8bb 100644 --- a/SampleCode/SampleAttestedTLS/server/host/host.cpp +++ b/SampleCode/SampleAttestedTLS/server/host/host.cpp @@ -141,11 +141,11 @@ sgx_status_t initialize_enclave(const char *enclave_path) { sgx_status_t ret = SGX_ERROR_UNEXPECTED; - // the 1st parameter should be SERVER_ENCLAVE_FILENAME - ret = sgx_create_enclave(enclave_path, SGX_DEBUG_FLAG, NULL, NULL, - &server_global_eid, NULL); + // the 1st parameter should be SERVER_ENCLAVE_FILENAME + ret = sgx_create_enclave(enclave_path, SGX_DEBUG_FLAG, NULL, NULL, + &server_global_eid, NULL); - printf("Server Enc: Enclave library %s\n", enclave_path); + printf("Server Enc: Enclave library %s\n", enclave_path); if (ret != SGX_SUCCESS) { @@ -169,21 +169,23 @@ int main(int argc, const char* argv[]) int keep_server_up = 0; // should be bool type, 0 false, 1 true /* Check argument count */ - if (argc != 3) + if (argc == 4) { - if (argc == 4) + if (strcmp(argv[3], LOOP_OPTION) != 0) { - if (strcmp(argv[3], LOOP_OPTION) != 0) - { - goto print_usage; - } - else - { - keep_server_up = 1; - goto read_port; - } + printf( + "Usage: %s TLS_SERVER_ENCLAVE_PATH -port: [%s]\n", + argv[0], + LOOP_OPTION); + return 1; } - print_usage: + else + { + keep_server_up = 1; + } + } + else if (argc != 3) + { printf( "Usage: %s TLS_SERVER_ENCLAVE_PATH -port: [%s]\n", argv[0], @@ -191,21 +193,22 @@ int main(int argc, const char* argv[]) return 1; } -read_port: // read port parameter + char* option = (char*)"-port:"; + size_t param_len = 0; + param_len = strlen(option); + if (strncmp(argv[2], option, param_len) == 0) { - char* option = (char*)"-port:"; - size_t param_len = 0; - param_len = strlen(option); - if (strncmp(argv[2], option, param_len) == 0) - { - server_port = (char*)(argv[2] + param_len); - } - else - { - fprintf(stderr, "Unknown option %s\n", argv[2]); - goto print_usage; - } + server_port = (char*)(argv[2] + param_len); + } + else + { + fprintf(stderr, "Unknown option %s\n", argv[2]); + printf( + "Usage: %s TLS_SERVER_ENCLAVE_PATH -port: [%s]\n", + argv[0], + LOOP_OPTION); + return 1; } printf("server port = %s\n", server_port); diff --git a/SampleCode/SampleAttestedTLS/server_tdx/Makefile b/SampleCode/SampleAttestedTLS/server_tdx/Makefile index 314ce2310..774047c62 100644 --- a/SampleCode/SampleAttestedTLS/server_tdx/Makefile +++ b/SampleCode/SampleAttestedTLS/server_tdx/Makefile @@ -31,11 +31,30 @@ include ../sgxenv.mk -all: server +Server_Include_Path := -I. -I$(SGX_SDK)/include -I/usr/include/openssl +Server_Cpp_Flags := -DCLIENT_USE_QVL $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(Server_Include_Path) -server: - $(CXX) -c -DTDX_ENV -DCLIENT_USE_QVL $(App_Cpp_Flags) server.cpp openssl_server.cpp ../common/verify_callback.cpp ../common/utility.cpp ../common/openssl_utility.cpp ../common/err_msg.cpp - $(CXX) -o tls_server server.o openssl_server.o verify_callback.o utility.o openssl_utility.o err_msg.o $(App_Link_Flags) -lssl -ltdx_tls -lsgx_dcap_quoteverify -ltdx_attest +ifeq ($(SGX_DEBUG), 1) + Server_Cpp_Flags += -DDEBUG -UNDEBUG -UEDEBUG +else ifeq ($(SGX_PRERELEASE), 1) + Server_Cpp_Flags += -DNDEBUG -DEDEBUG -UDEBUG +else + Server_Cpp_Flags += -DNDEBUG -UEDEBUG -UDEBUG +endif + +Server_Cpp_Flags += -std=c++11 + +Server_Link_Flags := $(SGX_COMMON_CFLAGS) -L. -lssl \ + -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lsgx_utls \ + -lsgx_dcap_ql -lsgx_dcap_quoteverify -lcrypto + +.PHONY: all build clean #run + +all: build + +build: + $(CXX) -c -DTDX_ENV -DCLIENT_USE_QVL $(Server_Cpp_Flags) server.cpp openssl_server.cpp ../common/verify_callback.cpp ../common/utility.cpp ../common/openssl_utility.cpp ../common/err_msg.cpp + $(CXX) -o tls_server server.o openssl_server.o verify_callback.o utility.o openssl_utility.o err_msg.o $(Server_Link_Flags) -lssl -ltdx_tls -lsgx_dcap_quoteverify -ltdx_attest clean: rm -f tls_server *.o diff --git a/SampleCode/SampleAttestedTLS/server_tdx/openssl_server.cpp b/SampleCode/SampleAttestedTLS/server_tdx/openssl_server.cpp index 6a3ca15e1..d831ea596 100644 --- a/SampleCode/SampleAttestedTLS/server_tdx/openssl_server.cpp +++ b/SampleCode/SampleAttestedTLS/server_tdx/openssl_server.cpp @@ -88,75 +88,73 @@ int handle_communication_until_done( bool keep_server_up) { int ret = -1; - int test_error = 1; -waiting_for_connection_request: - - struct sockaddr_in addr; - uint len = sizeof(addr); - - // reset ssl_session and client_socket_fd to prepare for the new TLS - // connection - if (client_socket_fd > 0) - { - ret = close(client_socket_fd); - if (ret != 0) { - PRINT(TLS_SERVER "error closing client socket before starting a new TLS session.\n"); - goto exit; + int test_error = 1; + + do { + struct sockaddr_in addr; + uint len = sizeof(addr); + + // reset ssl_session and client_socket_fd to prepare for the new TLS + // connection + if (client_socket_fd > 0) + { + ret = close(client_socket_fd); + if (ret != 0) { + PRINT(TLS_SERVER "error closing client socket before starting a new TLS session.\n"); + break; + } } - } - SSL_free(ssl_session); - PRINT(TLS_SERVER " waiting for client connection\n"); + SSL_free(ssl_session); + PRINT(TLS_SERVER " waiting for client connection\n"); - client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&addr, &len); + client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&addr, &len); - if (client_socket_fd < 0) - { - PRINT(TLS_SERVER "Unable to accept the client request\n"); - goto exit; - } + if (client_socket_fd < 0) + { + PRINT(TLS_SERVER "Unable to accept the client request\n"); + break; + } - // create a new SSL structure for a connection - if ((ssl_session = SSL_new(ssl_server_ctx)) == nullptr) - { - PRINT(TLS_SERVER - "Unable to create a new SSL connection state object\n"); - goto exit; - } + // create a new SSL structure for a connection + if ((ssl_session = SSL_new(ssl_server_ctx)) == nullptr) + { + PRINT(TLS_SERVER + "Unable to create a new SSL connection state object\n"); + break; + } - SSL_set_fd(ssl_session, client_socket_fd); + SSL_set_fd(ssl_session, client_socket_fd); - // wait for a TLS/SSL client to initiate a TLS/SSL handshake + // wait for a TLS/SSL client to initiate a TLS/SSL handshake - PRINT(TLS_SERVER "initiating a passive connect SSL_accept\n"); - test_error = SSL_accept(ssl_session); - if (test_error <= 0) - { - PRINT(TLS_SERVER " SSL handshake failed, error(%d)(%d)\n", - test_error, SSL_get_error(ssl_session, test_error)); - goto exit; - } + PRINT(TLS_SERVER "initiating a passive connect SSL_accept\n"); + test_error = SSL_accept(ssl_session); + if (test_error <= 0) + { + PRINT(TLS_SERVER " SSL handshake failed, error(%d)(%d)\n", + test_error, SSL_get_error(ssl_session, test_error)); + break; + } - PRINT(TLS_SERVER "<---- Read from client:\n"); - if (read_from_session_peer( - ssl_session, CLIENT_PAYLOAD, CLIENT_PAYLOAD_SIZE) != 0) - { - PRINT(TLS_SERVER " Read from client failed\n"); - goto exit; - } + PRINT(TLS_SERVER "<---- Read from client:\n"); + if (read_from_session_peer( + ssl_session, CLIENT_PAYLOAD, CLIENT_PAYLOAD_SIZE) != 0) + { + PRINT(TLS_SERVER " Read from client failed\n"); + break; + } - PRINT(TLS_SERVER "<---- Write to client:\n"); - if (write_to_session_peer( - ssl_session, SERVER_PAYLOAD, strlen(SERVER_PAYLOAD)) != 0) - { - PRINT(TLS_SERVER " Write to client failed\n"); - goto exit; - } + PRINT(TLS_SERVER "<---- Write to client:\n"); + if (write_to_session_peer( + ssl_session, SERVER_PAYLOAD, strlen(SERVER_PAYLOAD)) != 0) + { + PRINT(TLS_SERVER " Write to client failed\n"); + break; + } - if (keep_server_up) - goto waiting_for_connection_request; + ret = 0; + } while(keep_server_up); - ret = 0; -exit: return ret; } diff --git a/SampleCode/SampleAttestedTLS/server_tdx/server.cpp b/SampleCode/SampleAttestedTLS/server_tdx/server.cpp index 0dd50b397..aec64eeba 100644 --- a/SampleCode/SampleAttestedTLS/server_tdx/server.cpp +++ b/SampleCode/SampleAttestedTLS/server_tdx/server.cpp @@ -38,21 +38,23 @@ int main(int argc, const char* argv[]) int keep_server_up = 0; // should be bool type, 0 false, 1 true /* Check argument count */ - if (argc != 2) + if (argc == 3) { - if (argc == 3) + if (strcmp(argv[2], LOOP_OPTION) != 0) { - if (strcmp(argv[2], LOOP_OPTION) != 0) - { - goto print_usage; - } - else - { - keep_server_up = 1; - goto read_port; - } + printf( + "Usage: %s -port: [%s]\n", + argv[0], + LOOP_OPTION); + return 1; } - print_usage: + else + { + keep_server_up = 1; + } + } + else if (argc != 2) + { printf( "Usage: %s -port: [%s]\n", argv[0], @@ -60,21 +62,22 @@ int main(int argc, const char* argv[]) return 1; } -read_port: // read port parameter + char* option = (char*)"-port:"; + size_t param_len = 0; + param_len = strlen(option); + if (strncmp(argv[1], option, param_len) == 0) { - char* option = (char*)"-port:"; - size_t param_len = 0; - param_len = strlen(option); - if (strncmp(argv[1], option, param_len) == 0) - { - server_port = (char*)(argv[1] + param_len); - } - else - { - fprintf(stderr, "Unknown option %s\n", argv[1]); - goto print_usage; - } + server_port = (char*)(argv[1] + param_len); + } + else + { + fprintf(stderr, "Unknown option %s\n", argv[1]); + printf( + "Usage: %s -port: [%s]\n", + argv[0], + LOOP_OPTION); + return 1; } printf("server port = %s\n", server_port); diff --git a/SampleCode/SampleAttestedTLS/sgxenv.mk b/SampleCode/SampleAttestedTLS/sgxenv.mk index 82ffe6788..b6289bed7 100644 --- a/SampleCode/SampleAttestedTLS/sgxenv.mk +++ b/SampleCode/SampleAttestedTLS/sgxenv.mk @@ -81,7 +81,12 @@ else App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG endif -SGXSSL_U_Library_Name := sgx_usgxssl + +ifeq ($(SGX_DEBUG), 1) + SGXSSL_U_Library_Name := sgx_usgxssld +else + SGXSSL_U_Library_Name := sgx_usgxssl +endif SGXSSL_U_Link_Libraries := -L$(SGXSSL_PKG_PATH)/lib64 -Wl,--whole-archive -l$(SGXSSL_U_Library_Name) -Wl,--no-whole-archive SGXTLS_U_Link_Libraries := -lsgx_utls @@ -94,10 +99,15 @@ App_Link_Flags := $(SGX_COMMON_CFLAGS) $(SGXSSL_U_Link_Libraries) -L$(SGX_LIBRAR Trts_Library_Name := sgx_trts Service_Library_Name := sgx_tservice -SGXSSL_Library_Name := sgx_tsgxssl -OpenSSL_SSL_Library_Name := sgx_tsgxssl_ssl -OpenSSL_Crypto_Library_Name := sgx_tsgxssl_crypto - +ifeq ($(SGX_DEBUG), 1) + SGXSSL_Library_Name := sgx_tsgxssld + OpenSSL_SSL_Library_Name := sgx_tsgxssl_ssld + OpenSSL_Crypto_Library_Name := sgx_tsgxssl_cryptod +else + SGXSSL_Library_Name := sgx_tsgxssl + OpenSSL_SSL_Library_Name := sgx_tsgxssl_ssl + OpenSSL_Crypto_Library_Name := sgx_tsgxssl_crypto +endif SGX_TLS_Library_Name := sgx_ttls SGX_TVL_Library_Name := sgx_dcap_tvl @@ -113,7 +123,7 @@ else Enclave_C_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -ffunction-sections -fdata-sections -fstack-protector-strong endif -Enclave_C_Flags += $(Enclave_Include_Paths) +Enclave_C_Flags += $(Enclave_Include_Paths) Enclave_Cpp_Flags := $(Enclave_C_Flags) -std=c++11 -nostdinc++ SgxSSL_Link_Libraries := -L$(SGXSSL_PKG_PATH)/lib64 -Wl,--whole-archive -l$(SGXSSL_Library_Name) -Wl,--no-whole-archive \ diff --git a/SampleCode/SampleEnclave/README.txt b/SampleCode/SampleEnclave/README.txt index 9e2ba15d7..07c1b6df7 100644 --- a/SampleCode/SampleEnclave/README.txt +++ b/SampleCode/SampleEnclave/README.txt @@ -81,18 +81,16 @@ HeapMaxSize, HeapInitSize, HeapMinSize ------------------------------------------------- Sample configuration files for the Sample Enclave ------------------------------------------------- -Below configurations are applicable on EDMM supported platforms with either EDMM supported -kernels or EDMM unsupported kernels. If the signed enclave is launched on an EDMM supported -platform with an EDMM supported kernel, it will be loaded with EDMM enabled. The following -configuration descriptions are only suitable for the case that the signed enclave is -launched on an EDMM supported platform with an EDMM supported kernel: +With below configurations, if the signed enclave is launched on a SGX2 platform +with SGX2 supported kernel, it will be loaded with EDMM enabled. Otherwise, it +will behave in way of SGX1. config.01.xml: There is no dynamic thread, no dynamic heap expansion. config.02.xml: There is no dynamic thread. But dynamic heap expansion can happen. config.03.xml: There are dynamic threads. For a dynamic thread, there's no stack expansion. config.04.xml: There are dynamic threads. For a dynamic thread, stack will expanded as necessary. -Below configuration is only workable on EDMM supported platforms with EDMM supported kernels: +Below configuration is only workable on a SGX2 platform with SGX2 supported kernel: config.05.xml: There is a user region where users could operate on. diff --git a/common/inc/internal/metadata.h b/common/inc/internal/metadata.h index 31065856b..e6c52ec52 100644 --- a/common/inc/internal/metadata.h +++ b/common/inc/internal/metadata.h @@ -38,7 +38,7 @@ /* version of metadata */ #define MAJOR_VERSION 3 //MAJOR_VERSION should not larger than 0ffffffff -#define MINOR_VERSION 0 //MINOR_VERSION should not larger than 0ffffffff +#define MINOR_VERSION 1 //MINOR_VERSION should not larger than 0ffffffff #define SGX_2_ELRANGE_MAJOR_VERSION 13 #define SGX_1_ELRANGE_MAJOR_VERSION 11 diff --git a/common/inc/internal/se_cpu_feature_defs_ext.h b/common/inc/internal/se_cpu_feature_defs_ext.h index ccea4734c..68b32e76d 100644 --- a/common/inc/internal/se_cpu_feature_defs_ext.h +++ b/common/inc/internal/se_cpu_feature_defs_ext.h @@ -135,10 +135,7 @@ typedef enum { #define CPU_ATOM2 0x26 #define CPU_ATOM3 0x27 - - -#define CPU_FAMILY(x) (((x) >> 8) & 0xf) -#define CPU_MODEL(x) (((x) >> 4) & 0xf) +#define CPU_MODEL(x) ((((x) >> 12) & 0xf0U) | (((x) >> 4) & 0xfU)) #define CPU_STEPPING(x) (((x) >> 0) & 0xf) #define CPU_HAS_MMX(x) (((x) & 0x00800000) != 0) diff --git a/common/inc/internal/se_trace.h b/common/inc/internal/se_trace.h index 0a0a2961a..412c8fc0f 100644 --- a/common/inc/internal/se_trace.h +++ b/common/inc/internal/se_trace.h @@ -41,6 +41,7 @@ typedef enum { + SE_TRACE_NONE, SE_TRACE_ERROR, SE_TRACE_WARNING, SE_TRACE_NOTICE, @@ -49,15 +50,20 @@ typedef enum #ifndef SE_DEBUG_LEVEL /* Each module need define their own SE_DEBUG_LEVEL */ -#define SE_DEBUG_LEVEL SE_TRACE_ERROR +__attribute__((weak)) se_trace_t sgx_trace_loglevel = SE_TRACE_NONE; +#else +__attribute__((weak)) se_trace_t sgx_trace_loglevel = (se_trace_t)SE_DEBUG_LEVEL; #endif - #ifdef __cplusplus extern "C" { #endif void se_trace_internal(int debug_level, const char *fmt, ...); void sgx_proc_log_report_default(int channel, int debug_level, const char* fmt, ...); void __attribute__((weak)) sgx_proc_log_report(int level, const char* format, ...); + +typedef void (*sgx_logging_callback_t)(int level, const char* message); + +__attribute__((weak)) sgx_logging_callback_t sgx_trace_logger_callback = NULL; #ifdef __cplusplus } #endif @@ -65,22 +71,17 @@ void __attribute__((weak)) sgx_proc_log_report(int level, const char* format, . /* For libraries, we usually define DISABLE_TRACE to disable any trace. */ /* For apps, we usually enable trace. */ -#ifdef DISABLE_TRACE -#define SE_TRACE(...) -#define se_trace(...) -#define se_trace_verbose(...) -#else /* DISABLE_TRACE */ #define se_trace_verbose(debug_level, fmt, ...) \ do { \ se_trace_t trace_level = debug_level; \ - if(trace_level <= SE_DEBUG_LEVEL) \ + if(trace_level <= sgx_trace_loglevel) \ se_trace_internal(trace_level, "[%s %s:%d] " fmt, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \ }while(0) #define se_trace(debug_level, fmt, ...) \ do { \ se_trace_t trace_level = debug_level; \ - if(trace_level <= SE_DEBUG_LEVEL) \ + if(trace_level <= sgx_trace_loglevel) \ se_trace_internal(trace_level, fmt, ##__VA_ARGS__); \ }while(0) @@ -88,14 +89,12 @@ void __attribute__((weak)) sgx_proc_log_report(int level, const char* format, . /* New code should use SE_TRACE_DEBUG, SE_TRACE_NOTICE, SE_TRACE_WARNING, SE_TRACE_ERROR */ #define SE_TRACE(debug_level, fmt, ...) \ se_trace_verbose(debug_level, fmt, ##__VA_ARGS__) -#endif/* DISABLE_TRACE */ -/* SE_TRACE_DEBUG and SE_TRACE_NOTICE print the debug information plus message. */ +/* Print the debug information plus message. */ #define SE_TRACE_DEBUG(fmt, ...) se_trace_verbose(SE_TRACE_DEBUG, fmt, ##__VA_ARGS__) #define SE_TRACE_NOTICE(fmt, ...) se_trace_verbose(SE_TRACE_NOTICE, fmt, ##__VA_ARGS__) -//SE_TRACE_WARNING and SE_TRACE_ERROR only print message. -#define SE_TRACE_WARNING(fmt, ...) se_trace(SE_TRACE_WARNING, fmt, ##__VA_ARGS__) -#define SE_TRACE_ERROR(fmt, ...) se_trace(SE_TRACE_ERROR, fmt, ##__VA_ARGS__) +#define SE_TRACE_WARNING(fmt, ...) se_trace_verbose(SE_TRACE_WARNING, fmt, ##__VA_ARGS__) +#define SE_TRACE_ERROR(fmt, ...) se_trace_verbose(SE_TRACE_ERROR, fmt, ##__VA_ARGS__) /* SE_PROD_LOG will output message to stdout by default in production mode. When the executable is running as daemon, it will output to syslog. */ diff --git a/common/inc/internal/se_version.h b/common/inc/internal/se_version.h index 06999ebcb..f2b7c65fe 100644 --- a/common/inc/internal/se_version.h +++ b/common/inc/internal/se_version.h @@ -31,25 +31,25 @@ #ifndef _SE_VERSION_H_ #define _SE_VERSION_H_ -#define STRFILEVER "2.21.100.1" +#define STRFILEVER "2.22.100.3" #define SGX_MAJOR_VERSION 2 -#define SGX_MINOR_VERSION 21 +#define SGX_MINOR_VERSION 22 #define SGX_REVISION_VERSION 100 #define MAKE_VERSION_UINT(major,minor,rev) (((uint64_t)major)<<32 | ((uint64_t)minor) << 16 | rev) #define VERSION_UINT MAKE_VERSION_UINT(SGX_MAJOR_VERSION, SGX_MINOR_VERSION, SGX_REVISION_VERSION) #define COPYRIGHT "Copyright (C) 2023 Intel Corporation" -#define UAE_SERVICE_VERSION "2.3.220.1" -#define URTS_VERSION "2.0.104.1" -#define ENCLAVE_COMMON_VERSION "1.2.104.1" -#define LAUNCH_VERSION "1.0.122.1" -#define EPID_VERSION "1.0.122.1" -#define QUOTE_EX_VERSION "1.1.122.1" +#define UAE_SERVICE_VERSION "2.3.221.3" +#define URTS_VERSION "2.0.105.3" +#define ENCLAVE_COMMON_VERSION "1.2.105.3" +#define LAUNCH_VERSION "1.0.123.3" +#define EPID_VERSION "1.0.123.3" +#define QUOTE_EX_VERSION "1.1.123.3" -#define PCE_VERSION "1.19.100.1" -#define LE_VERSION "1.19.100.1" -#define QE_VERSION "1.19.100.1" -#define PVE_VERSION "1.19.100.1" +#define PCE_VERSION "1.22.100.1" +#define LE_VERSION "1.22.100.1" +#define QE_VERSION "1.22.100.1" +#define PVE_VERSION "1.22.100.1" #endif diff --git a/common/inc/sgx_ecp_types.h b/common/inc/sgx_ecp_types.h index 4b69028ef..48e689118 100644 --- a/common/inc/sgx_ecp_types.h +++ b/common/inc/sgx_ecp_types.h @@ -35,11 +35,10 @@ #define _SGX_ECP_TYPES_H_ #include +#include "sgx_tcrypto.h" #pragma pack(push, 1) -#include "sgx_tcrypto.h" - #ifndef SGX_FEBITSIZE #define SGX_FEBITSIZE 256 #endif diff --git a/common/inc/sgx_error.h b/common/inc/sgx_error.h index 4df716970..a2f471a66 100644 --- a/common/inc/sgx_error.h +++ b/common/inc/sgx_error.h @@ -120,6 +120,7 @@ typedef enum _status_t SGX_ERROR_INVALID_ATT_KEY_CERT_DATA = SGX_MK_ERROR(0x8004), /* TThe data returned by the platform library's sgx_get_quote_config() is invalid.*/ SGX_ERROR_PLATFORM_CERT_UNAVAILABLE = SGX_MK_ERROR(0x8005), /* The PCK Cert for the platform is not available.*/ + SGX_ERROR_TLS_X509_INVALID_EXTENSION = SGX_MK_ERROR(0x9001), /* error of RA-TLS x509 invalid extension */ SGX_INTERNAL_ERROR_ENCLAVE_CREATE_INTERRUPTED = SGX_MK_ERROR(0xF001), /* The ioctl for enclave_create unexpectedly failed with EINTR. */ } sgx_status_t; diff --git a/common/inc/sgx_key.h b/common/inc/sgx_key.h index 0291fe4b8..6be442113 100644 --- a/common/inc/sgx_key.h +++ b/common/inc/sgx_key.h @@ -51,7 +51,7 @@ /* Key Policy */ #define SGX_KEYPOLICY_MRENCLAVE 0x0001 /* Derive key using the enclave's ENCLAVE measurement register */ -#define SGX_KEYPOLICY_MRSIGNER 0x0002 /* Derive key using the enclave's SINGER measurement register */ +#define SGX_KEYPOLICY_MRSIGNER 0x0002 /* Derive key using the enclave's SIGNER measurement register */ #define SGX_KEYPOLICY_NOISVPRODID 0x0004 /* Derive key without the enclave's ISVPRODID */ #define SGX_KEYPOLICY_CONFIGID 0x0008 /* Derive key with the enclave's CONFIGID */ #define SGX_KEYPOLICY_ISVFAMILYID 0x0010 /* Derive key with the enclave's ISVFAMILYID */ diff --git a/common/inc/sgx_tprotected_fs.edl b/common/inc/sgx_tprotected_fs.edl index b6f0b8c3f..020ab7dc1 100644 --- a/common/inc/sgx_tprotected_fs.edl +++ b/common/inc/sgx_tprotected_fs.edl @@ -31,17 +31,15 @@ enclave { from "sgx_tstdc.edl" import *; + from "sgx_pthread.edl" import *; untrusted { - void* u_sgxprotectedfs_exclusive_file_open([in, string] const char* filename, uint8_t read_only, [out] int64_t* file_size, [out] int32_t* error_code); - uint8_t u_sgxprotectedfs_check_if_file_exists([in, string] const char* filename); - int32_t u_sgxprotectedfs_fread_node([user_check] void* f, uint64_t node_number, [out, size=node_size] uint8_t* buffer, uint32_t node_size); - int32_t u_sgxprotectedfs_fwrite_node([user_check] void* f, uint64_t node_number, [in, size=node_size] uint8_t* buffer, uint32_t node_size); - int32_t u_sgxprotectedfs_fclose([user_check] void* f); - uint8_t u_sgxprotectedfs_fflush([user_check] void* f); + int8_t u_sgxprotectedfs_check_if_file_exists([in, string] const char* filename); + uint8_t* u_sgxprotectedfs_exclusive_file_map([in, string] const char* filename, uint8_t read_only, [out] int64_t* file_size, [out] int32_t* error_code); + int32_t u_sgxprotectedfs_file_remap([in, string] const char* filename, [in, out] uint8_t** file_addr, int64_t old_size, int64_t new_size); + int32_t u_sgxprotectedfs_file_unmap([user_check] uint8_t* file_addr, int64_t file_size); int32_t u_sgxprotectedfs_remove([in, string] const char* filename); - void* u_sgxprotectedfs_recovery_file_open([in, string] const char* filename); - uint8_t u_sgxprotectedfs_fwrite_recovery_node([user_check] void* f, [in, count=data_length] uint8_t* data, uint32_t data_length); - int32_t u_sgxprotectedfs_do_file_recovery([in, string] const char* filename, [in, string] const char* recovery_filename, uint32_t node_size); + uint8_t u_sgxprotectedfs_fwrite_recovery_file([user_check] uint8_t* fileaddress, [in, string] const char* filename, [in, count=length] uint64_t* recovery_list, uint64_t length); + int32_t u_sgxprotectedfs_do_file_recovery([in, string] const char* filename, [in, string] const char* recovery_filename); }; }; diff --git a/common/inc/sgx_tprotected_fs.h b/common/inc/sgx_tprotected_fs.h index 3a37e28b0..eb00ad1f0 100644 --- a/common/inc/sgx_tprotected_fs.h +++ b/common/inc/sgx_tprotected_fs.h @@ -173,6 +173,25 @@ int64_t SGXAPI sgx_ftell(SGX_FILE* stream); int32_t SGXAPI sgx_fseek(SGX_FILE* stream, int64_t offset, int origin); +/* sgx_fset_parallel_level + * Purpose: set number of threads can be used in file flush + * To achieve the best performance, please only use when write large files (>10M), + * and with a customized cache size (i.e. use sgx_fopen_ex to open file) + * For the reference, test result on ICX server + * - cache size 10M ~ 100M , use 16 ~ 32 threads + * - cache size > 100M, use more than 32 threads + * + * Parameters: + * stream - [IN] the file handle (opened with sgx_fopen or sgx_fopen_auto_key) + * max_threads_number - [IN] number of threads can be used in file flush + * It must NOT exceed the TCS number in enclave configuration + * + * Return value: + * int32_t - result, 0 - success, 1 - there was an error, thread number is 0 +*/ +int32_t SGXAPI sgx_fset_parallel_level(SGX_FILE* stream, uint32_t max_threads_number); + + /* sgx_fflush * Purpose: force actual write of all the cached data to the disk (see c++ fflush documentation for more details). * diff --git a/common/inc/sgx_tseal.h b/common/inc/sgx_tseal.h index eb70f4211..1436f3058 100644 --- a/common/inc/sgx_tseal.h +++ b/common/inc/sgx_tseal.h @@ -56,7 +56,7 @@ typedef struct _aes_gcm_data_t typedef struct _sealed_data_t { sgx_key_request_t key_request; /* 00: The key request used to obtain the sealing key */ - uint32_t plain_text_offset; /* 64: Offset within aes_data.playload to the start of the optional additional MAC text */ + uint32_t plain_text_offset; /* 64: Offset within aes_data.payload to the start of the optional additional MAC text */ uint8_t reserved[12]; /* 68: Reserved bits */ sgx_aes_gcm_data_t aes_data; /* 80: Data structure holding the AES/GCM related data */ } sgx_sealed_data_t; diff --git a/common/src/crypto_cmac_128.cpp b/common/src/crypto_cmac_128.cpp index 339aed124..2da4b112a 100644 --- a/common/src/crypto_cmac_128.cpp +++ b/common/src/crypto_cmac_128.cpp @@ -32,6 +32,9 @@ #include "crypto_wrapper.h" #include #include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#endif #include #include #include @@ -42,6 +45,57 @@ sgx_status_t sgx_cmac128_msg(const sgx_key_128bit_t key, const uint8_t *p_src, u { return SGX_ERROR_INVALID_PARAMETER; } +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + OSSL_LIB_CTX *lib_ctx = NULL; + EVP_MAC *mac = NULL; + EVP_MAC_CTX *mctx = NULL; + OSSL_PARAM params[2] = {OSSL_PARAM_END, OSSL_PARAM_END}; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + char cipher_name[] = "AES-128-CBC"; + size_t mac_len = 0; + do + { + if ((lib_ctx = OSSL_LIB_CTX_new()) == NULL) + { + ret = SGX_ERROR_OUT_OF_MEMORY; + break; + } + if ((mac = EVP_MAC_fetch(lib_ctx, "CMAC", NULL)) == NULL) + { + break; + } + if ((mctx = EVP_MAC_CTX_new(mac)) == NULL) + { + ret = SGX_ERROR_OUT_OF_MEMORY; + break; + } + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, cipher_name, sizeof(cipher_name)); + + if ((!EVP_MAC_init(mctx, key, sizeof(sgx_key_128bit_t), params))) + { + break; + } + if (!EVP_MAC_update(mctx, p_src, src_len)) + { + break; + } + if (!EVP_MAC_final(mctx, (uint8_t *)p_mac, &mac_len, sizeof(sgx_mac_t))) + { + break; + } + if(mac_len != sizeof(sgx_mac_t)) + { + break; + } + ret = SGX_SUCCESS; + } while (0); + + EVP_MAC_CTX_free(mctx); + EVP_MAC_free(mac); + OSSL_LIB_CTX_free(lib_ctx); + + return ret; +#else CMAC_CTX *cmac_ctx = NULL; size_t mac_len; @@ -59,13 +113,17 @@ sgx_status_t sgx_cmac128_msg(const sgx_key_128bit_t key, const uint8_t *p_src, u CMAC_CTX_free(cmac_ctx); return SGX_ERROR_UNEXPECTED; } - if(!CMAC_Final(cmac_ctx, (uint8_t *)p_mac, &mac_len)) + if(!CMAC_Final(cmac_ctx, (uint8_t *)p_mac, &mac_len)) { CMAC_CTX_free(cmac_ctx); return SGX_ERROR_UNEXPECTED; } CMAC_CTX_free(cmac_ctx); - assert(mac_len == sizeof(sgx_mac_t)); - return SGX_SUCCESS; + if(mac_len != sizeof(sgx_mac_t)) + { + return SGX_ERROR_UNEXPECTED; + } + return SGX_SUCCESS; +#endif } diff --git a/common/src/se_trace.c b/common/src/se_trace.c index 40c0df26b..09907ca55 100644 --- a/common/src/se_trace.c +++ b/common/src/se_trace.c @@ -52,6 +52,19 @@ void se_trace_internal(int debug_level, const char *fmt, ...) va_list args; va_start(args, fmt); + if (sgx_trace_logger_callback && debug_level) + { + char message[2500]; // to make sure the full URL can be logged. + vsnprintf(message, sizeof(message), fmt, args); + va_end(args); + + // ensure buf is always null-terminated + message[sizeof(message) - 1] = 0; + + sgx_trace_logger_callback(debug_level - 1 , message); + return; + } + if (SE_TRACE_NOTICE == debug_level) vfprintf(stdout, fmt, args); else diff --git a/docker/build/tdx-qgs.dockerfile b/docker/build/tdx-qgs.dockerfile index 461f132e9..2bbbffe55 100644 --- a/docker/build/tdx-qgs.dockerfile +++ b/docker/build/tdx-qgs.dockerfile @@ -28,18 +28,18 @@ # -FROM quay.io/centos/centos:stream8 as qgs-builder +FROM quay.io/centos/centos:stream9 as qgs-builder +RUN dnf -y install 'dnf-command(config-manager)' +RUN dnf config-manager --set-enabled crb RUN dnf -y groupinstall 'Development Tools' -RUN dnf -y install --enablerepo=powertools ocaml ocaml-ocamlbuild wget python3 \ - openssl-devel libcurl-devel protobuf-devel cmake createrepo yum-utils \ - dos2unix pkgconf boost-devel protobuf-c-compiler protobuf-c-devel \ - protobuf-lite-devel +RUN dnf -y install epel-release epel-next-release ocaml ocaml-ocamlbuild wget python openssl-devel libcurl-devel \ + protobuf-devel cmake createrepo yum-utils dos2unix pkgconf boost-devel \ + protobuf-lite-devel perl # We assume this docker file is invoked with root at the top of linux-sgx repo, see shell scripts for example. WORKDIR /linux-sgx COPY . . -RUN alternatives --set python /usr/bin/python3 RUN make sdk_install_pkg_no_mitigation WORKDIR /opt/intel @@ -50,7 +50,7 @@ ENV BUILD_PLATFORM="docker" RUN make rpm_local_repo -FROM quay.io/centos/centos:stream8 as qgs +FROM quay.io/centos/centos:stream9 as qgs WORKDIR /installer diff --git a/download_prebuilt.sh b/download_prebuilt.sh index 0b3506d28..17d3c75d7 100755 --- a/download_prebuilt.sh +++ b/download_prebuilt.sh @@ -33,11 +33,11 @@ top_dir=`dirname $0` out_dir=$top_dir -optlib_name=optimized_libs_2.21.tar.gz -ae_file_name=prebuilt_ae_2.21.tar.gz +optlib_name=optimized_libs_2.22.tar.gz +ae_file_name=prebuilt_ae_2.22.tar.gz binutils_file_name=as.ld.objdump.r4.tar.gz -checksum_file=SHA256SUM_prebuilt_2.21.cfg -server_url_path=https://download.01.org/intel-sgx/sgx-linux/2.21 +checksum_file=SHA256SUM_prebuilt_2.22.cfg +server_url_path=https://download.01.org/intel-sgx/sgx-linux/2.22 server_optlib_url=$server_url_path/$optlib_name server_ae_url=$server_url_path/$ae_file_name server_binutils_url=$server_url_path/$binutils_file_name diff --git a/external/cbor/Makefile b/external/cbor/Makefile new file mode 100644 index 000000000..cc9589396 --- /dev/null +++ b/external/cbor/Makefile @@ -0,0 +1,128 @@ +# +# Copyright (C) 2011-2023 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# + +# build 2 librarys of libcbor : +# libcbor.a run in untrusted +# libsgx_cbor.a run in trusted + + +include ../../buildenv.mk + +C_ENCLAVE_FLAGS = $(ENCLAVE_CFLAGS) + +CXX_ENCLAVE_FLAGS = $(C_ENCLAVE_FLAGS) +CXX_ENCLAVE_FLAGS := $(subst -nostdinc,, $(CXX_ENCLAVE_FLAGS)) +CXX_ENCLAVE_FLAGS += -nostdinc++ + +# cbor in untrusted +CBOR_SRC = libcbor +RAW_LIBCBOR = ./untrusted/lib/libcbor.a +CBOR_DIR = ./untrusted +CBOR_LIB = $(CBOR_DIR)/lib +CBOR_LIB64 = $(CBOR_DIR)/lib64 +CBOR_INCLUDE = $(CBOR_DIR)/include + +# cbor in trusted +SGX_CBOR_SRC = sgx_libcbor +SGX_LIBCBOR = ./trusted/lib/libsgx_cbor.a +SGX_CBOR_DIR = ./trusted +SGX_CBOR_LIB = $(SGX_CBOR_DIR)/lib +SGX_CBOR_LIB64 = $(SGX_CBOR_DIR)/lib64 +SGX_CBOR_INCLUDE = $(SGX_CBOR_DIR)/include + +CBOR_CONFIG = -DCMAKE_BUILD_TYPE=Release +#ifdef DEBUG +# CBOR_CONFIG = -DCMAKE_BUILD_TYPE=Debug +#endif + +SGX_CBOR_CONFIG = $(CBOR_CONFIG) -DSGX_PROGRAM_SEARCH_PATH="$(EXT_BINUTILS_DIR)" + +CHECK_SOURCE := +NEED_PATCH := +ifeq ("$(wildcard $(CBOR_SRC)/src/cbor.h)", "") + CHECK_SOURCE := prepare_code + NEED_PATCH := apply_patch +else ifeq ("$(wildcard $(SGX_CBOR_SRC)/src/cbor.h)", "") + CHECK_SOURCE := checkout_branch + NEED_PATCH := apply_patch +endif + +.PHONY: all prepare_code apply_patch checkout_branch cbor_trusted cbor_untrusted + +all: $(CHECK_SOURCE) $(NEED_PATCH) cbor_trusted cbor_untrusted + @test -f $(RAW_LIBCBOR) && test -f $(SGX_LIBCBOR) && echo "build complete" + +prepare_code: +ifeq ($(shell git rev-parse --is-inside-work-tree 2> /dev/null), true) + git submodule update -f --init --recursive -- $(CBOR_SRC) && cd $(CBOR_SRC) && git checkout v0.10.2 && cd .. +else + rm -rf $(CBOR_SRC) && git clone -b v0.10.2 https://github.com/PJK/libcbor.git --depth 1 $(CBOR_SRC) +endif + +checkout_branch: + cd $(CBOR_SRC) && git checkout v0.10.2 && cd .. + +apply_patch: $(CHECK_SOURCE) + cp $(CBOR_SRC) $(SGX_CBOR_SRC) -r + cd $(CBOR_SRC) && git apply ../raw_cbor.patch && cd .. + cd $(SGX_CBOR_SRC) && git apply ../sgx_cbor.patch && cd .. + +$(CBOR_SRC)/build: $(NEED_PATCH) + @test -d $@ || mkdir -p $@ + +$(SGX_CBOR_SRC)/build: $(NEED_PATCH) + @test -d $@ || mkdir -p $@ + +cbor_untrusted: $(CBOR_SRC)/build + @echo "make and make install" + @cd $(CBOR_SRC)/build && cmake ../ $(CBOR_CONFIG) && $(MAKE) && make install + # in case of cbor lib name is installed as lib64 on CentOS + if [ -d $(CBOR_LIB64) ]; then \ + mv $(CBOR_LIB64) $(CBOR_LIB); \ + fi + +cbor_trusted: $(SGX_CBOR_SRC)/build + @echo "make and make install" + @cd $(SGX_CBOR_SRC)/build && cmake ../ $(SGX_CBOR_CONFIG) -DCMAKE_C_ENCLAVE_FLAGS="$(C_ENCLAVE_FLAGS)" && $(MAKE) && make install && cd ../.. + #in case of cbor lib is installed as lib64 on CentOS + if [ -d $(SGX_CBOR_LIB64) ]; then \ + mv $(SGX_CBOR_LIB64) $(SGX_CBOR_LIB); \ + fi + mv $(SGX_CBOR_LIB)/libcbor.a $(SGX_LIBCBOR) + +.PHONY: clean +clean: + rm -fr $(CBOR_SRC)/build $(SGX_CBOR_SRC)/build $(CBOR_DIR) $(SGX_CBOR_DIR) + +.PHONY: rebuild +rebuild: + $(MAKE) clean + $(MAKE) all diff --git a/external/cbor/libcbor b/external/cbor/libcbor new file mode 160000 index 000000000..efa6c0886 --- /dev/null +++ b/external/cbor/libcbor @@ -0,0 +1 @@ +Subproject commit efa6c0886bae46bdaef9b679f61f4b9d8bc296ae diff --git a/external/cbor/raw_cbor.patch b/external/cbor/raw_cbor.patch new file mode 100644 index 000000000..b8d33ca6d --- /dev/null +++ b/external/cbor/raw_cbor.patch @@ -0,0 +1,26 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 04122d9..387ebc8 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -34,7 +34,7 @@ if(WITH_TESTS) + add_definitions(-DWITH_TESTS) + endif(WITH_TESTS) + +-option(WITH_EXAMPLES "Build examples" ON) ++option(WITH_EXAMPLES "Build examples" OFF) + + option(HUGE_FUZZ "[TEST] Fuzz through 8GB of data in the test. Do not use with memory instrumentation!" OFF) + if(HUGE_FUZZ) +@@ -163,6 +163,12 @@ else() + message(STATUS "LTO is not enabled") + endif(use_lto) + ++message("cmake current binary dir:"${CMAKE_CURRENT_BINARY_DIR}) ++# make installation dir first ++execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ++ ${CMAKE_CURRENT_BINARY_DIR}/../../untrusted) ++set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/../../untrusted) ++ + add_subdirectory(src) + if(use_lto) + set_property(DIRECTORY src PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) diff --git a/external/cbor/sgx_cbor.patch b/external/cbor/sgx_cbor.patch new file mode 100644 index 000000000..938b4666f --- /dev/null +++ b/external/cbor/sgx_cbor.patch @@ -0,0 +1,85 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 5c0a784..0a4c4fc 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -25,7 +25,7 @@ if(CBOR_CUSTOM_ALLOC) + "Please remove CBOR_CUSTOM_ALLOC from your build configuation.") + endif(CBOR_CUSTOM_ALLOC) + +-option(CBOR_PRETTY_PRINTER "Include a pretty-printing routine" ON) ++option(CBOR_PRETTY_PRINTER "Include a pretty-printing routine" OFF) + set(CBOR_BUFFER_GROWTH "2" CACHE STRING "Factor for buffer growth & shrinking") + set(CBOR_MAX_STACK_SIZE "2048" CACHE STRING "maximum size for decoding context stack") + +@@ -34,7 +34,7 @@ if(WITH_TESTS) + add_definitions(-DWITH_TESTS) + endif(WITH_TESTS) + +-option(WITH_EXAMPLES "Build examples" ON) ++option(WITH_EXAMPLES "Build examples" OFF) + + option(HUGE_FUZZ "[TEST] Fuzz through 8GB of data in the test. Do not use with memory instrumentation!" OFF) + if(HUGE_FUZZ) +@@ -163,6 +163,12 @@ else() + message(STATUS "LTO is not enabled") + endif(use_lto) + ++message("cmake current binary dir:"${CMAKE_CURRENT_BINARY_DIR}) ++# need to build installation path ++execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ++ ${CMAKE_CURRENT_BINARY_DIR}/../../trusted) ++set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/../../trusted) ++ + add_subdirectory(src) + if(use_lto) + set_property(DIRECTORY src PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 72a0c90..69e82ac 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -8,9 +8,13 @@ set(CMAKE_SKIP_BUILD_RPATH FALSE) + if (NOT DEFINED CMAKE_MACOSX_RPATH) + set(CMAKE_MACOSX_RPATH 0) + endif() ++set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_ENCLAVE_FLAGS}") + + add_library(cbor ${SOURCES}) + target_include_directories(cbor PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) ++target_include_directories(cbor PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../../../common/inc/tlibc) ++target_include_directories(cbor PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../../../common/inc) ++target_compile_options(cbor PRIVATE -nostdinc -fPIC) + + # Explicitly link math.h if necessary + check_function_exists(ldexp LDEXP_AVAILABLE) +diff --git a/src/cbor.h b/src/cbor.h +index 46ef8f2..2260c26 100644 +--- a/src/cbor.h ++++ b/src/cbor.h +@@ -61,12 +61,12 @@ _CBOR_NODISCARD CBOR_EXPORT cbor_item_t* cbor_load( + */ + _CBOR_NODISCARD CBOR_EXPORT cbor_item_t* cbor_copy(cbor_item_t* item); + +-#if CBOR_PRETTY_PRINTER ++/*#if CBOR_PRETTY_PRINTER + #include + + CBOR_EXPORT void cbor_describe(cbor_item_t* item, FILE* out); + #endif +- ++*/ + #ifdef __cplusplus + } + #endif +diff --git a/src/cbor/configuration.h.in b/src/cbor/configuration.h.in +index 0052a15..0732ec6 100644 +--- a/src/cbor/configuration.h.in ++++ b/src/cbor/configuration.h.in +@@ -7,7 +7,7 @@ + + #define CBOR_BUFFER_GROWTH ${CBOR_BUFFER_GROWTH} + #define CBOR_MAX_STACK_SIZE ${CBOR_MAX_STACK_SIZE} +-#cmakedefine01 CBOR_PRETTY_PRINTER ++//#cmakedefine01 CBOR_PRETTY_PRINTER + + #define CBOR_RESTRICT_SPECIFIER ${CBOR_RESTRICT_SPECIFIER} + #define CBOR_INLINE_SPECIFIER ${CBOR_INLINE_SPECIFIER} diff --git a/external/dcap_source b/external/dcap_source index 6882afad8..8a407331e 160000 --- a/external/dcap_source +++ b/external/dcap_source @@ -1 +1 @@ -Subproject commit 6882afad8644c27db162b40994402c8ad2a7fb32 +Subproject commit 8a407331e0d38be89a64d9eac54ab764792fb490 diff --git a/external/sgx-emm/Makefile b/external/sgx-emm/Makefile index e04122240..873ec8cad 100644 --- a/external/sgx-emm/Makefile +++ b/external/sgx-emm/Makefile @@ -70,7 +70,7 @@ ifeq ($(shell git rev-parse --is-inside-work-tree 2> /dev/null), true) git submodule update -f --init --recursive -- $(EMM_DIR) else $(RM) -rf $(EMM_DIR) - git clone -b sgx-emm-1.0.2 https://github.com/intel/sgx-emm.git --depth 1 $(EMM_DIR) + git clone -b sgx-emm-1.0.3 https://github.com/intel/sgx-emm.git --depth 1 $(EMM_DIR) endif clean: diff --git a/external/sgx-emm/emm_src b/external/sgx-emm/emm_src index eb4d16c45..893dcbc4e 160000 --- a/external/sgx-emm/emm_src +++ b/external/sgx-emm/emm_src @@ -1 +1 @@ -Subproject commit eb4d16c459a27b1aa4e77fa4b2104dc537e2d001 +Subproject commit 893dcbc4e1452f9c20fbe31785a9054acc0cc867 diff --git a/external/sgxssl/prepare_sgxssl.sh b/external/sgxssl/prepare_sgxssl.sh index 24a4e5eb7..8a89f598b 100755 --- a/external/sgxssl/prepare_sgxssl.sh +++ b/external/sgxssl/prepare_sgxssl.sh @@ -32,16 +32,16 @@ top_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" openssl_out_dir=$top_dir/openssl_source -openssl_ver=1.1.1u +openssl_ver=3.0.10 openssl_ver_name=openssl-$openssl_ver sgxssl_github_archive=https://github.com/intel/intel-sgx-ssl/archive -sgxssl_file_name=lin_2.21_1.1.1u +sgxssl_file_name=3.0_Rev1 build_script=$top_dir/Linux/build_openssl.sh server_url_path=https://www.openssl.org/source -full_openssl_url=$server_url_path/old/1.1.1/$openssl_ver_name.tar.gz +full_openssl_url=$server_url_path/old/3.0/$openssl_ver_name.tar.gz -sgxssl_chksum=b83c6f98041eb77df209cef91b77b68a8cbd861e5617fe1bf087398042e5ace6 -openssl_chksum=e2f8d84b523eecd06c7be7626830370300fbcc15386bf5142d72758f6963ebc6 +sgxssl_chksum=6371dbe25acdc5a3bbb2978a0a559ad2eefd713b9bbf5d3a45236229c9cc53b6 +openssl_chksum=1761d4f5b13a1028b9b6f3d4b8e17feb0cedc9370f6afe61d7193d2cdce83323 rm -f check_sum_sgxssl.txt check_sum_openssl.txt if [ ! -f $build_script ]; then wget $sgxssl_github_archive/$sgxssl_file_name.zip -P $top_dir || exit 1 diff --git a/linux/installer/bin/install-sgx-sdk.bin.tmpl b/linux/installer/bin/install-sgx-sdk.bin.tmpl index 63256555e..3bd39ca96 100755 --- a/linux/installer/bin/install-sgx-sdk.bin.tmpl +++ b/linux/installer/bin/install-sgx-sdk.bin.tmpl @@ -69,6 +69,8 @@ select_install_path() } +umask 022 + prev= for option do @@ -115,7 +117,6 @@ fi USER_INPUT_PATH=$(cd "$USER_INPUT_PATH"; pwd -P) PATH=/usr/bin:/bin:$PATH -umask 022 SDKPKG=`mktemp -t sgx-sdk-pkg.XXXXXX` SDK_TEMP_FOLDER=`mktemp -d sgx-sdk-XXXXXX -p /tmp` diff --git a/linux/installer/deb/sgx-aesm-service/sgx-aesm-service-1.0/debian/control b/linux/installer/deb/sgx-aesm-service/sgx-aesm-service-1.0/debian/control index 6265879ad..7f4315479 100644 --- a/linux/installer/deb/sgx-aesm-service/sgx-aesm-service-1.0/debian/control +++ b/linux/installer/deb/sgx-aesm-service/sgx-aesm-service-1.0/debian/control @@ -37,12 +37,12 @@ Description: Unified Quote Plugin for Intel(R) Software Guard Extensions AESM Se Package: libsgx-aesm-ecdsa-plugin Architecture: amd64 -Depends: ${shlibs:Depends}, ${misc:Depends}, sgx-aesm-service(>= @dep_version@), libsgx-qe3-logic(>= 1.18), libsgx-aesm-pce-plugin(>= @dep_version@) +Depends: ${shlibs:Depends}, ${misc:Depends}, sgx-aesm-service(>= @dep_version@), libsgx-qe3-logic(>= 1.19), libsgx-aesm-pce-plugin(>= @dep_version@) Description: ECDSA Quote Plugin for Intel(R) Software Guard Extensions AESM Service Package: libsgx-aesm-pce-plugin Architecture: amd64 -Depends: ${shlibs:Depends}, ${misc:Depends}, sgx-aesm-service(>= @dep_version@), libsgx-pce-logic(>= 1.18), libsgx-ae-pce(>= @dep_version@) +Depends: ${shlibs:Depends}, ${misc:Depends}, sgx-aesm-service(>= @dep_version@), libsgx-pce-logic(>= 1.19), libsgx-ae-pce(>= @dep_version@) Description: PCE Plugin for Intel(R) Software Guard Extensions AESM Service Package: libsgx-ae-pce diff --git a/linux/installer/rpm/sgx-aesm-service/libsgx-aesm-ecdsa-plugin.spec b/linux/installer/rpm/sgx-aesm-service/libsgx-aesm-ecdsa-plugin.spec index 7c302e511..e69ee1923 100644 --- a/linux/installer/rpm/sgx-aesm-service/libsgx-aesm-ecdsa-plugin.spec +++ b/linux/installer/rpm/sgx-aesm-service/libsgx-aesm-ecdsa-plugin.spec @@ -38,7 +38,7 @@ Version: @version@ Release: 1%{?dist} Summary: ECDSA Quote Plugin for Intel(R) Software Guard Extensions AESM Service Group: Development/System -Requires: sgx-aesm-service >= %{version}-%{release} libsgx-qe3-logic >= 1.18 libsgx-aesm-pce-plugin >= %{version}-%{release} +Requires: sgx-aesm-service >= %{version}-%{release} libsgx-qe3-logic >= 1.19 libsgx-aesm-pce-plugin >= %{version}-%{release} License: BSD License URL: https://github.com/intel/linux-sgx diff --git a/linux/installer/rpm/sgx-aesm-service/libsgx-aesm-pce-plugin.spec b/linux/installer/rpm/sgx-aesm-service/libsgx-aesm-pce-plugin.spec index bafc6e64f..f6d75526e 100644 --- a/linux/installer/rpm/sgx-aesm-service/libsgx-aesm-pce-plugin.spec +++ b/linux/installer/rpm/sgx-aesm-service/libsgx-aesm-pce-plugin.spec @@ -38,7 +38,7 @@ Version: @version@ Release: 1%{?dist} Summary: PCE Plugin for Intel(R) Software Guard Extensions AESM Service Group: Development/System -Requires: sgx-aesm-service >= %{version}-%{release} libsgx-pce-logic >= 1.18 +Requires: sgx-aesm-service >= %{version}-%{release} libsgx-pce-logic >= 1.19 License: BSD License URL: https://github.com/intel/linux-sgx diff --git a/linux/reproducibility/build_and_launch_docker.sh b/linux/reproducibility/build_and_launch_docker.sh index 7ed67c3ef..494d3ced7 100755 --- a/linux/reproducibility/build_and_launch_docker.sh +++ b/linux/reproducibility/build_and_launch_docker.sh @@ -75,8 +75,8 @@ mount_dir="/linux-sgx" sdk_installer="" sgx_src="" -default_sdk_installer=sgx_linux_x64_sdk_reproducible_2.21.100.1.bin -default_sdk_installer_url=https://download.01.org/intel-sgx/sgx-linux/2.21/distro/nix_reproducibility/$default_sdk_installer +default_sdk_installer=sgx_linux_x64_sdk_reproducible_2.22.100.1.bin +default_sdk_installer_url=https://download.01.org/intel-sgx/sgx-linux/2.22/distro/nix_reproducibility/$default_sdk_installer usage() @@ -177,7 +177,7 @@ prepare_sgx_src() if [ "$sgx_src" != "" ]; then mkdir -p "$sgx_repo" && cp -a "$sgx_src/." "$sgx_repo" else - git clone -b sgx_2.21_reproducible https://github.com/intel/linux-sgx.git $sgx_repo + git clone -b sgx_2.22_reproducible https://github.com/intel/linux-sgx.git $sgx_repo fi cd "$sgx_repo" && make preparation diff --git a/psw/ae/aesm_service/source/CMakeLists.txt b/psw/ae/aesm_service/source/CMakeLists.txt index a77d53fb8..ffc1bee7c 100644 --- a/psw/ae/aesm_service/source/CMakeLists.txt +++ b/psw/ae/aesm_service/source/CMakeLists.txt @@ -63,8 +63,6 @@ if(SGX_DISABLE_PSE) add_definitions("-DSGX_DISABLE_PSE") endif() -add_definitions("-DOPENSSL_API_COMPAT=10101") - set(CMAKE_CXX_STANDARD_REQUIRED 1) set(CMAKE_CXX_STANDARD 11) set(CMAKE_SKIP_BUILD_RPATH true) @@ -173,3 +171,4 @@ ADD_SUBDIRECTORY(core) ADD_SUBDIRECTORY(bundles) ADD_SUBDIRECTORY(qcnl) ADD_SUBDIRECTORY(qpl) +ADD_SUBDIRECTORY(qcnl/pck_cert_selection) diff --git a/psw/ae/aesm_service/source/bundles/linux_network_service_bundle/CMakeLists.txt b/psw/ae/aesm_service/source/bundles/linux_network_service_bundle/CMakeLists.txt index 63fc1f1a8..3f244b8b8 100644 --- a/psw/ae/aesm_service/source/bundles/linux_network_service_bundle/CMakeLists.txt +++ b/psw/ae/aesm_service/source/bundles/linux_network_service_bundle/CMakeLists.txt @@ -29,12 +29,6 @@ # # -find_package(CURL REQUIRED) -if(CURL_FOUND) - message ("CURL found") -else() - message (FATAL_ERROR "Cannot find CURL") -endif() get_filename_component(bundle ${CMAKE_CURRENT_SOURCE_DIR} NAME) aux_source_directory(. _srcs) CreateBundle(${bundle} ${_srcs}) @@ -49,5 +43,5 @@ target_include_directories(${bundle} PRIVATE ${PROJECT_SOURCE_DIR}/../../../../external/epid-sdk ) -target_link_libraries(${bundle} ${CURL_LIBRARIES} oal utils) +target_link_libraries(${bundle} oal utils) set_property(TARGET ${bundle} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-z,defs") diff --git a/psw/ae/aesm_service/source/bundles/linux_network_service_bundle/aesm_http_msg.cpp b/psw/ae/aesm_service/source/bundles/linux_network_service_bundle/aesm_http_msg.cpp index a280fef67..448e39fdb 100644 --- a/psw/ae/aesm_service/source/bundles/linux_network_service_bundle/aesm_http_msg.cpp +++ b/psw/ae/aesm_service/source/bundles/linux_network_service_bundle/aesm_http_msg.cpp @@ -34,6 +34,7 @@ #include "aesm_encode.h" #include "oal.h" #include "se_wrapper.h" +#include "se_thread.h" #include "prof_fun.h" #include "aesm_proxy_type.h" #include "aesm_network.h" @@ -41,6 +42,7 @@ #include "util.h" #include +#include #ifndef INTERNET_DEFAULT_HTTP_PORT #define INTERNET_DEFAULT_HTTP_PORT 80 #endif @@ -56,6 +58,122 @@ typedef struct _network_malloc_info_t{ uint32_t size; }network_malloc_info_t; +#define LIBCURL_NAME "libcurl.so" +#define LIBCURL4_NAME LIBCURL_NAME".4" + +static se_mutex_t g_dlopen_mutex; +static void *g_dlopen_handle = NULL; + +static CURLcode (*f_global_init)(long) = NULL; +static CURL *(*f_easy_init)(void) = NULL; +static struct curl_slist *(*f_slist_append)(struct curl_slist *, const char *) = NULL; +static CURLcode (*f_easy_setopt)(CURL *, CURLoption, ...) = NULL; +static CURLcode (*f_easy_getinfo)(CURL *curl, CURLINFO info, ...) = NULL; +static CURLcode (*f_easy_perform)(CURL *) = NULL; +static void (*f_easy_cleanup)(CURL *) = NULL; +static void (*f_global_cleanup)(void) = NULL; +static const char* (*f_easy_strerror)(CURLcode) = NULL; +static void (*f_slist_free_all)(struct curl_slist *) = NULL; + +static void __attribute__((constructor)) _sgx__qcnl_ql_init() +{ + se_mutex_init(&g_dlopen_mutex); +} + +static void __attribute__((destructor)) _sgx_qcnl_fini(void) { + if (g_dlopen_handle != NULL) { + dlclose(g_dlopen_handle); + g_dlopen_handle = NULL; + } + se_mutex_destroy(&g_dlopen_mutex); +} + +ae_error_t prepare_curl() { + static bool libcurl_ready = false; + if (libcurl_ready) + return AE_SUCCESS; + + ae_error_t ret = AE_FAILURE; + se_mutex_lock(&g_dlopen_mutex); + do { + if (libcurl_ready) { + ret = AE_SUCCESS; + break; + } + + const char* libcurl_name = LIBCURL_NAME; + // With the dlopen (RTLD_DEEPBIND) for libcurl, it forces the libcurl to look up symbols in its dependencies. + g_dlopen_handle = dlopen(LIBCURL_NAME, RTLD_LAZY | RTLD_DEEPBIND); + if (NULL == g_dlopen_handle) { + libcurl_name = LIBCURL4_NAME; + g_dlopen_handle = dlopen(LIBCURL4_NAME, RTLD_LAZY | RTLD_DEEPBIND); + if (NULL == g_dlopen_handle) { + AESM_DBG_ERROR("Cannot open shared library %s or %s.", LIBCURL_NAME, LIBCURL4_NAME); + break; + } + } + f_global_init = (CURLcode(*)(long))dlsym(g_dlopen_handle, "curl_global_init"); + if (dlerror() != NULL || !f_global_init) { + AESM_DBG_ERROR("Cannot dlsym curl_global_init in %s.", libcurl_name); + break; + } + f_easy_init = (CURL * (*)(void)) dlsym(g_dlopen_handle, "curl_easy_init"); + if (dlerror() != NULL || !f_easy_init) { + AESM_DBG_ERROR("Cannot dlsym curl_easy_init in %s.", libcurl_name); + break; + } + f_slist_append = (struct curl_slist * (*)(struct curl_slist *, const char *)) + dlsym(g_dlopen_handle, "curl_slist_append"); + if (dlerror() != NULL || !f_slist_append) { + AESM_DBG_ERROR("Cannot dlsym curl_slist_append in %s.", libcurl_name); + break; + } + f_easy_setopt = (CURLcode(*)(CURL *, CURLoption, ...))dlsym(g_dlopen_handle, "curl_easy_setopt"); + if (dlerror() != NULL || !f_easy_setopt) { + AESM_DBG_ERROR("Cannot dlsym curl_easy_setopt in %s.", libcurl_name); + break; + } + f_easy_getinfo = (CURLcode(*)(CURL *, CURLINFO, ...))dlsym(g_dlopen_handle, "curl_easy_getinfo"); + if (dlerror() != NULL || !f_easy_getinfo) { + AESM_DBG_ERROR("Cannot dlsym curl_easy_getinfo in %s.", libcurl_name); + break; + } + f_easy_perform = (CURLcode(*)(CURL *))dlsym(g_dlopen_handle, "curl_easy_perform"); + if (dlerror() != NULL || !f_easy_perform) { + AESM_DBG_ERROR("Cannot dlsym curl_easy_perform in %s.", libcurl_name); + break; + } + f_easy_cleanup = (void (*)(CURL *))dlsym(g_dlopen_handle, "curl_easy_cleanup"); + if (dlerror() != NULL || !f_easy_cleanup) { + AESM_DBG_ERROR("Cannot dlsym curl_easy_cleanup in %s.", libcurl_name); + break; + } + f_global_cleanup = (void (*)(void))dlsym(g_dlopen_handle, "curl_global_cleanup"); + if (dlerror() != NULL || !f_global_cleanup) { + AESM_DBG_ERROR("Cannot dlsym curl_global_cleanup in %s.", libcurl_name); + break; + } + f_easy_strerror = (const char *(*)(CURLcode))dlsym(g_dlopen_handle, "curl_easy_strerror"); + if (dlerror() != NULL || !f_easy_strerror) { + AESM_DBG_ERROR("Cannot dlsym curl_easy_strerror in %s.", libcurl_name); + break; + } + f_slist_free_all = (void (*)(curl_slist *))dlsym(g_dlopen_handle, "curl_slist_free_all"); + if (dlerror() != NULL || !f_slist_free_all) { + AESM_DBG_ERROR("Cannot dlsym curl_slist_free_all in %s.", libcurl_name); + break; + } + + f_global_init(CURL_GLOBAL_DEFAULT); + libcurl_ready = true; + ret = AE_SUCCESS; + } while(0); + + se_mutex_unlock(&g_dlopen_mutex); + return ret; +} + + static size_t write_callback(void *ptr, size_t size, size_t nmemb, void *stream) { network_malloc_info_t* s=reinterpret_cast(stream); @@ -110,24 +228,24 @@ static ae_error_t http_network_init(CURL **curl, const char *url, bool is_ocsp) return AE_FAILURE; } - *curl = curl_easy_init(); + *curl = f_easy_init(); if(!*curl){ AESM_DBG_ERROR("fail to init curl handle"); return AE_FAILURE; } - if((cc=curl_easy_setopt(*curl, CURLOPT_URL, url_path.c_str()))!=CURLE_OK){ + if((cc=f_easy_setopt(*curl, CURLOPT_URL, url_path.c_str()))!=CURLE_OK){ AESM_DBG_ERROR("fail error code %d in set url %s",(int)cc, url_path.c_str()); - curl_easy_cleanup(*curl); + f_easy_cleanup(*curl); return AE_FAILURE; } - (void)curl_easy_setopt(*curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + (void)f_easy_setopt(*curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); //setting proxy now if(urls.proxy_type == AESM_PROXY_TYPE_DIRECT_ACCESS){ AESM_DBG_TRACE("use no proxy"); - (void)curl_easy_setopt(*curl, CURLOPT_NOPROXY , "*"); + (void)f_easy_setopt(*curl, CURLOPT_NOPROXY , "*"); }else if(urls.proxy_type == AESM_PROXY_TYPE_MANUAL_PROXY){ AESM_DBG_TRACE("use manual proxy %s",urls.aesm_proxy); - (void)curl_easy_setopt(*curl, CURLOPT_PROXY, urls.aesm_proxy); + (void)f_easy_setopt(*curl, CURLOPT_PROXY, urls.aesm_proxy); } return AE_SUCCESS; } @@ -147,14 +265,14 @@ static ae_error_t http_network_send_data(CURL *curl, const char *req_msg, uint32 uint32_t start = 0, end = 0; char* p_header = NULL; if(is_ocsp){ - tmp = curl_slist_append(headers, "Accept: application/ocsp-response"); + tmp = f_slist_append(headers, "Accept: application/ocsp-response"); if(tmp==NULL){ AESM_DBG_ERROR("fail in add accept ocsp-response header"); ae_ret = AE_FAILURE; goto fini; } headers = tmp; - tmp = curl_slist_append(headers, "Content-Type: application/ocsp-request"); + tmp = f_slist_append(headers, "Content-Type: application/ocsp-request"); if(tmp == NULL){ AESM_DBG_ERROR("fail in add content type ocsp-request"); ae_ret = AE_FAILURE; @@ -164,7 +282,7 @@ static ae_error_t http_network_send_data(CURL *curl, const char *req_msg, uint32 AESM_DBG_TRACE("ocsp request"); } else{ - tmp = curl_slist_append(headers, "Content-Type: text/plain"); + tmp = f_slist_append(headers, "Content-Type: text/plain"); if(tmp == NULL){ AESM_DBG_ERROR("fail in add content type text/plain"); ae_ret = AE_FAILURE; @@ -179,53 +297,53 @@ static ae_error_t http_network_send_data(CURL *curl, const char *req_msg, uint32 ae_ret = AE_FAILURE; goto fini; } - tmp = curl_slist_append(headers, buf); + tmp = f_slist_append(headers, buf); if(tmp == NULL){ AESM_DBG_ERROR("fail to add content-length header"); ae_ret = AE_FAILURE; goto fini; } headers=tmp; - if((cc=curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers))!=CURLE_OK){ + if((cc=f_easy_setopt(curl, CURLOPT_HTTPHEADER, headers))!=CURLE_OK){ AESM_DBG_ERROR("fail to set http header:%d",(int)cc); ae_ret = AE_FAILURE; goto fini; } if(method == POST){ - if((cc=curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req_msg))!=CURLE_OK){ + if((cc=f_easy_setopt(curl, CURLOPT_POSTFIELDS, req_msg))!=CURLE_OK){ AESM_DBG_ERROR("fail to set POST fields:%d",(int)cc); ae_ret = AE_FAILURE; goto fini; } - if((cc=curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, msg_size))!=CURLE_OK){ + if((cc=f_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, msg_size))!=CURLE_OK){ AESM_DBG_ERROR("fail to set POST fields size:%d",(int)cc); ae_ret = AE_FAILURE; goto fini; } } - if((cc=curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback))!=CURLE_OK){ + if((cc=f_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback))!=CURLE_OK){ AESM_DBG_ERROR("Fail to set callback function:%d",(int)cc); ae_ret = AE_FAILURE; goto fini; } - if((cc=curl_easy_setopt(curl, CURLOPT_WRITEDATA, reinterpret_cast(&malloc_info_resp)))!=CURLE_OK){ + if((cc=f_easy_setopt(curl, CURLOPT_WRITEDATA, reinterpret_cast(&malloc_info_resp)))!=CURLE_OK){ AESM_DBG_ERROR("fail to set write back function parameter:%d",(int)cc); ae_ret = AE_FAILURE; goto fini; } - if((cc=curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_callback))!=CURLE_OK){ + if((cc=f_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_callback))!=CURLE_OK){ AESM_DBG_ERROR("Fail to set callback function:%d",(int)cc); ae_ret = AE_FAILURE; goto fini; } - if((cc=curl_easy_setopt(curl, CURLOPT_HEADERDATA, reinterpret_cast(&malloc_info_header)))!=CURLE_OK){ + if((cc=f_easy_setopt(curl, CURLOPT_HEADERDATA, reinterpret_cast(&malloc_info_header)))!=CURLE_OK){ AESM_DBG_ERROR("fail to set write back function parameter:%d",(int)cc); ae_ret = AE_FAILURE; goto fini; } - if((cc=curl_easy_perform(curl))!=CURLE_OK){ + if((cc=f_easy_perform(curl))!=CURLE_OK){ AESM_DBG_ERROR("fail in connect:%d",(int)cc); ae_ret = OAL_NETWORK_UNAVAILABLE_ERROR; goto fini; @@ -233,7 +351,7 @@ static ae_error_t http_network_send_data(CURL *curl, const char *req_msg, uint32 // Check HTTP response code // For example, if the remote file does not exist, curl may return CURLE_OK but the http response code // indicates an error has occured - if((cc=curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &resp_code))!=CURLE_OK || resp_code>=400){ + if((cc=f_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &resp_code))!=CURLE_OK || resp_code>=400){ AESM_DBG_ERROR("Response code error:%d", resp_code); ae_ret = AE_FAILURE; goto fini; @@ -279,7 +397,7 @@ static ae_error_t http_network_send_data(CURL *curl, const char *req_msg, uint32 fini: if(headers!=NULL){ - curl_slist_free_all(headers); + f_slist_free_all(headers); } if (ae_ret != AE_SUCCESS) { if(malloc_info_resp.base){ @@ -295,7 +413,7 @@ static ae_error_t http_network_send_data(CURL *curl, const char *req_msg, uint32 static void http_network_fini(CURL *curl) { if(curl!=NULL) - curl_easy_cleanup(curl); + f_easy_cleanup(curl); } diff --git a/psw/ae/aesm_service/source/bundles/linux_network_service_bundle/aesm_network.h b/psw/ae/aesm_service/source/bundles/linux_network_service_bundle/aesm_network.h index a2d111468..bf6136116 100644 --- a/psw/ae/aesm_service/source/bundles/linux_network_service_bundle/aesm_network.h +++ b/psw/ae/aesm_service/source/bundles/linux_network_service_bundle/aesm_network.h @@ -40,6 +40,7 @@ * Description: Definition for interface of HTTP/HTTPS network communication used in AESM */ +ae_error_t prepare_curl(); /*Function to send data to a server and receive the response *@server_url: provide the url of the server diff --git a/psw/ae/aesm_service/source/bundles/linux_network_service_bundle/linux_network_service_bundle.cpp b/psw/ae/aesm_service/source/bundles/linux_network_service_bundle/linux_network_service_bundle.cpp index d28a759c5..6476db44a 100644 --- a/psw/ae/aesm_service/source/bundles/linux_network_service_bundle/linux_network_service_bundle.cpp +++ b/psw/ae/aesm_service/source/bundles/linux_network_service_bundle/linux_network_service_bundle.cpp @@ -135,7 +135,7 @@ class LinuxNetworkServiceImp : public INetworkService public: ae_error_t start() { - return AE_SUCCESS; + return prepare_curl(); } void stop() @@ -180,7 +180,6 @@ class Activator : public BundleActivator { void Start(BundleContext ctx) { - CURLcode curl_code = curl_global_init(CURL_GLOBAL_DEFAULT); auto service = std::make_shared(); ctx.RegisterService(service); } diff --git a/psw/ae/aesm_service/source/common/ssl_compat_wrapper.h b/psw/ae/aesm_service/source/common/ssl_compat_wrapper.h index d6cbb1c0a..3ff1db2cb 100644 --- a/psw/ae/aesm_service/source/common/ssl_compat_wrapper.h +++ b/psw/ae/aesm_service/source/common/ssl_compat_wrapper.h @@ -41,19 +41,6 @@ extern "C" { #endif -#if OPENSSL_VERSION_NUMBER < 0x10100000L - -int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); - -EVP_MD_CTX *EVP_MD_CTX_new(void); -void EVP_MD_CTX_free(EVP_MD_CTX *ctx); - -void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); -int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); -BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret); - -#endif - void crypto_initialize(); void crypto_cleanup(); diff --git a/psw/ae/aesm_service/source/core/AESMLogicWrapper.cpp b/psw/ae/aesm_service/source/core/AESMLogicWrapper.cpp index 973e7d462..2ef12fed8 100644 --- a/psw/ae/aesm_service/source/core/AESMLogicWrapper.cpp +++ b/psw/ae/aesm_service/source/core/AESMLogicWrapper.cpp @@ -638,8 +638,6 @@ aesm_error_t AESMLogicWrapper::sgxRegister(uint8_t *buf, uint32_t buf_size, uint } } -#include "ssl_compat_wrapper.h" - ae_error_t AESMLogicWrapper::service_start() { try @@ -717,8 +715,6 @@ ae_error_t AESMLogicWrapper::service_start() return AE_FAILURE; } - crypto_initialize(); - AESM_DBG_INFO("aesm service is starting"); { @@ -770,7 +766,6 @@ void AESMLogicWrapper::service_stop() network_service->stop(); g_fw.Stop(); g_fw.WaitForStop(std::chrono::seconds(5)); - crypto_cleanup(); AESM_DBG_INFO("aesm service down"); } diff --git a/psw/ae/aesm_service/source/qcnl/CMakeLists.txt b/psw/ae/aesm_service/source/qcnl/CMakeLists.txt index c8e9509f8..299ed470f 100644 --- a/psw/ae/aesm_service/source/qcnl/CMakeLists.txt +++ b/psw/ae/aesm_service/source/qcnl/CMakeLists.txt @@ -29,12 +29,6 @@ # # -find_package(CURL REQUIRED) -if(CURL_FOUND) - message ("CURL found") -else() - message (FATAL_ERROR "Cannot find CURL") -endif() aux_source_directory(${PROJECT_SOURCE_DIR}/../../../../external/dcap_source/QuoteGeneration/qcnl _srcs) aux_source_directory(${PROJECT_SOURCE_DIR}/../../../../external/dcap_source/QuoteGeneration/qcnl/linux _srcs) add_library(sgx_default_qcnl_wrapper SHARED ${_srcs}) @@ -55,21 +49,13 @@ target_include_directories(sgx_default_qcnl_wrapper PRIVATE ${PROJECT_SOURCE_DIR}/../../../../external/dcap_source/tools/PCKCertSelection/include ) -add_custom_target(PCKCertSelectionLib - COMMAND make -f ${PROJECT_SOURCE_DIR}/../../../../external/dcap_source/tools/PCKCertSelection/PCKCertSelectionLib/Makefile.static_lib - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/../../../../external/dcap_source/tools/PCKCertSelection/PCKCertSelectionLib -) - -add_library(PCKCertSelectionStaticLib STATIC IMPORTED ${PROJECT_SOURCE_DIR}/../../../../external/dcap_source/tools/PCKCertSelection/static_out/libPCKCertSelection.a) -set_target_properties(PCKCertSelectionStaticLib PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/../../../../external/dcap_source/tools/PCKCertSelection/static_out/libPCKCertSelection.a) -add_dependencies(PCKCertSelectionStaticLib PCKCertSelectionLib) +add_dependencies(sgx_default_qcnl_wrapper PCKCertSelection) set_property(TARGET sgx_default_qcnl_wrapper APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-z,defs") set_property(TARGET sgx_default_qcnl_wrapper APPEND_STRING PROPERTY LINK_DEPENDS ${PROJECT_SOURCE_DIR}/../../../../external/dcap_source/QuoteGeneration/qcnl/linux/sgx_default_qcnl.lds ) - target_link_libraries(sgx_default_qcnl_wrapper - ${CURL_LIBRARIES} crypto PCKCertSelectionStaticLib + oal crypto ${CMAKE_CURRENT_BINARY_DIR}/../lib/libPCKCertSelection.a ) diff --git a/psw/ae/aesm_service/source/qcnl/pck_cert_selection/CMakeLists.txt b/psw/ae/aesm_service/source/qcnl/pck_cert_selection/CMakeLists.txt new file mode 100644 index 000000000..e51106752 --- /dev/null +++ b/psw/ae/aesm_service/source/qcnl/pck_cert_selection/CMakeLists.txt @@ -0,0 +1,133 @@ +# +# Copyright (C) 2011-2021 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# + +set(pck_cert_selection_dir + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../external/dcap_source/tools/PCKCertSelection/PCKCertSelectionLib +) + +set(CMAKE_CXX_FLAGS "-DATTESTATIONPARSERS_STATIC -DPCK_CERT_SELECTION_WITH_COMPONENT -DIS_STATIC_LIB") + + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -fvisibility=hidden -fvisibility-inlines-hidden -Werror -DLINUX -m64 -fstack-protector -D_FORTIFY_SOURCE=2 -UDEBUG -DNDEBUG -ffunction-sections -fdata-sections -Wall -Wextra -Winit-self -Wpointer-arith -Wreturn-type -Waddress -Wsequence-point -Wformat-security -Wmissing-include-dirs -Wfloat-equal -Wundef -Wshadow -Wcast-align -Wconversion -Wredundant-decls -DITT_ARCH_IA64 -std=c++14") + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(QVL_DIR "${pck_cert_selection_dir}/../../../QuoteVerification/QVL/Src") +# QG root directory +# include the se_version.h file from there + +set(QG_DIR "${pck_cert_selection_dir}/../../../QuoteGeneration") +# openssl include dir +set(OPENSSL_INC "${pck_cert_selection_dir}/../../../prebuilt/openssl/inc") +# openssl lib dir +set(OPENSSL_LIB "${pck_cert_selection_dir}/../../../prebuilt/openssl/lib/linux64") + +# JSON parser include dir +set(JSON_INC "${QVL_DIR}/ThirdParty/rapidjson/include") + +# QVL Attestation Parsers include directory +set(PARSERS_INC "${QVL_DIR}/AttestationParsers/include") +set(PARSERS_COMM_INC "${QVL_DIR}/AttestationCommons/include") +set(PARSERS_UTIL_INC "${QVL_DIR}/AttestationCommons/include/Utils") + + + +######## Library Settings ######## + +# QVL Attestation Parsers source dirs +set(PARSERS_DIR "${QVL_DIR}/AttestationParsers/src") +set(PARSERS_COMM_DIR "${QVL_DIR}/AttestationCommons/src") +set(JSON_DIR "${PARSERS_DIR}/Json") +set(X509_DIR "${PARSERS_DIR}/X509") +set(HELPERS_DIR "${PARSERS_DIR}/OpensslHelpers") +set(UTILS_DIR "${PARSERS_COMM_DIR}/Utils") +set(VER_DIR "${QG_DIR}/common/inc/internal") + +# source files from QVL Attestation Parsers dirs +set(PARSER_CPP_FILES + ${PARSERS_DIR}/ParserUtils.cpp + ) +set(X509_CPP_FILES + ${X509_DIR}/Certificate.cpp + ${X509_DIR}/DistinguishedName.cpp + ${X509_DIR}/Extension.cpp + ${X509_DIR}/PckCertificate.cpp + ${X509_DIR}/Signature.cpp + ${X509_DIR}/Tcb.cpp + ${X509_DIR}/Validity.cpp + ) +set(HELPERS_CPP_FILES + ${HELPERS_DIR}/OidUtils.cpp + ) +set(JSON_CPP_FILES + ${JSON_DIR}/JsonParser.cpp + ${JSON_DIR}/TcbInfo.cpp + ${JSON_DIR}/TcbLevel.cpp + ${JSON_DIR}/TdxModule.cpp + ${JSON_DIR}/TcbComponent.cpp + ${JSON_DIR}/TdxModuleTcb.cpp + ${JSON_DIR}/TdxModuleTcbLevel.cpp + ${JSON_DIR}/TdxModuleIdentity.cpp + ) +set(UTILS_CPP_FILES + ${UTILS_DIR}/GMTime.cpp + ${UTILS_DIR}/TimeUtils.cpp + ) +set(LOCAL_CPP_FILES + ${pck_cert_selection_dir}/pck_sorter.cpp + ${pck_cert_selection_dir}/pck_cert_selection.cpp + ${pck_cert_selection_dir}/config_selector.cpp + ${pck_cert_selection_dir}/tcb_manager.cpp +) + + +add_library(PCKCertSelection STATIC + ${PARSER_CPP_FILES} + ${X509_CPP_FILES} + ${HELPERS_CPP_FILES} + ${JSON_CPP_FILES} + ${UTILS_CPP_FILES} + ${LOCAL_CPP_FILES} +) + +# add the path to the search path for include files +target_include_directories(PCKCertSelection PRIVATE + ${OPENSSL_INC} + ${JSON_INC} + ${PARSERS_INC} + ${PARSERS_COMM_INC} + ${PARSERS_DIR} + ${VER_DIR} + ${PARSERS_UTIL_INC} + ${pck_cert_selection_dir}/../include +) + diff --git a/psw/ae/aesm_service/source/utils/CMakeLists.txt b/psw/ae/aesm_service/source/utils/CMakeLists.txt index 2f83b4142..a3843bdf2 100644 --- a/psw/ae/aesm_service/source/utils/CMakeLists.txt +++ b/psw/ae/aesm_service/source/utils/CMakeLists.txt @@ -29,16 +29,11 @@ # # -find_package(OpenSSL REQUIRED) -if(OPENSSL_FOUND) - message ("OpenSSL found") -else() - message (FATAL_ERROR "Cannot find OPENSSL") -endif() aux_source_directory(. _srcs) add_library(utils SHARED ${_srcs} "../../../../../common/src/sgx_read_rand.cpp" - "../../../../../common/src/sgx_memset_s.cpp") + "../../../../../common/src/sgx_memset_s.cpp" + "../../../../../common/src/crypto_cmac_128.cpp") target_include_directories(utils PRIVATE ${PROJECT_SOURCE_DIR}/common @@ -50,6 +45,7 @@ target_include_directories(utils PRIVATE ${PROJECT_SOURCE_DIR}/../../../../external/epid-sdk ${PROJECT_SOURCE_DIR}/../../../../external/rdrand ${PROJECT_SOURCE_DIR}/../../data/constants/linux + ${PROJECT_SOURCE_DIR}/../../../../external/dcap_source/prebuilt/openssl/inc ) target_compile_definitions(utils PRIVATE @@ -59,7 +55,7 @@ target_compile_definitions(utils PRIVATE set_property(TARGET utils APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-z,defs") target_link_libraries(utils - ${OPENSSL_LIBRARIES} + ${PROJECT_SOURCE_DIR}/../../../../external/dcap_source/prebuilt/openssl/lib/linux64/libcrypto.a oal ${CMAKE_SOURCE_DIR}/../../../../external/rdrand/src/librdrand.a ) diff --git a/psw/ae/aesm_service/source/utils/crypto_cmac128.cpp b/psw/ae/aesm_service/source/utils/crypto_cmac128.cpp index 1c63540a6..6d6a7cc64 100644 --- a/psw/ae/aesm_service/source/utils/crypto_cmac128.cpp +++ b/psw/ae/aesm_service/source/utils/crypto_cmac128.cpp @@ -33,6 +33,8 @@ #include "string.h" #include "ssl_crypto.h" #include +#include "crypto_wrapper.h" + /* Message Authentication - Rijndael 128 CMAC * Parameters: @@ -44,63 +46,7 @@ sgx_status_t sgx_rijndael128_cmac_msg(const sgx_cmac_128bit_key_t *p_key, const uint8_t *p_src, uint32_t src_len, sgx_cmac_128bit_tag_t *p_mac) { - void* pState = NULL; - - if ((p_key == NULL) || (p_src == NULL) || (p_mac == NULL)) - { - return SGX_ERROR_INVALID_PARAMETER; - } - - size_t mactlen; - sgx_status_t ret = SGX_ERROR_UNEXPECTED; - - do { - //create a new ctx of CMAC - // - pState = CMAC_CTX_new(); - if (pState == NULL) - { - ret = SGX_ERROR_OUT_OF_MEMORY; - break; - } - - // init CMAC ctx with the corresponding size, key and AES alg. - // - if (!CMAC_Init((CMAC_CTX*)pState, (const void *)p_key, SGX_CMAC_KEY_SIZE, EVP_aes_128_cbc(), NULL)) - { - break; - } - - // perform CMAC hash on p_src - // - if (!CMAC_Update((CMAC_CTX *)pState, p_src, src_len)) - { - break; - } - - // finalize CMAC hashing - // - if (!CMAC_Final((CMAC_CTX*)pState, (unsigned char*)p_mac, &mactlen)) - { - break; - } - - //validate mac size - // - if (mactlen != SGX_CMAC_MAC_SIZE) - { - break; - } - - ret = SGX_SUCCESS; - } while (0); - - // we're done, clear and free CMAC ctx - // - if (pState) - { - CMAC_CTX_free((CMAC_CTX*)pState); - } - return ret; + static_assert(SGX_MAC_SIZE == SGX_CMAC_MAC_SIZE); + return sgx_cmac128_msg((const uint8_t *)p_key, p_src, src_len, (sgx_mac_t *)p_mac); } diff --git a/psw/ae/aesm_service/source/utils/crypto_ecc.cpp b/psw/ae/aesm_service/source/utils/crypto_ecc.cpp index 3ec8623aa..615eb6dd5 100644 --- a/psw/ae/aesm_service/source/utils/crypto_ecc.cpp +++ b/psw/ae/aesm_service/source/utils/crypto_ecc.cpp @@ -36,6 +36,8 @@ #include #include #include +#include +#include /* * Elliptic Curve Cryptography - Based on GF(p), 256 bit @@ -82,6 +84,102 @@ sgx_status_t sgx_ecc256_close_context(sgx_ecc_state_handle_t ecc_handle) return SGX_SUCCESS; } +static EVP_PKEY *get_pub_key_from_coords(const sgx_ec256_public_t *p_public, sgx_ecc_state_handle_t ecc_handle) +{ + EVP_PKEY *evp_key = NULL; + EVP_PKEY_CTX *pkey_ctx = NULL; + BIGNUM *bn_pub_x = NULL; + BIGNUM *bn_pub_y = NULL; + EC_POINT *point = NULL; + EC_GROUP *group = (EC_GROUP *)ecc_handle; + OSSL_PARAM_BLD *params_build = NULL; + OSSL_PARAM *params = NULL; + const char *curvename = NULL; + int nid = 0; + size_t key_len; + unsigned char pub_key[SGX_ECP256_KEY_SIZE+4]; + + do { + // converts the x value of public key, represented as positive integer in little-endian into a BIGNUM + bn_pub_x = BN_lebin2bn((unsigned char*)p_public->gx, sizeof(p_public->gx), bn_pub_x); + if (NULL == bn_pub_x) { + break; + } + // converts the y value of public key, represented as positive integer in little-endian into a BIGNUM + bn_pub_y = BN_lebin2bn((unsigned char*)p_public->gy, sizeof(p_public->gy), bn_pub_y); + if (NULL == bn_pub_y) { + break; + } + // creates new point and assigned the group object that the point relates to + point = EC_POINT_new(group); + if (NULL == point) { + break; + } + + // sets point based on public key's x,y coordinates + if (1 != EC_POINT_set_affine_coordinates(group, point, bn_pub_x, bn_pub_y, NULL)) { + break; + } + + // check point if the point is on curve + if (1 != EC_POINT_is_on_curve(group, point, NULL)) { + break; + } + + // convert point to octet string + key_len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, pub_key, sizeof(pub_key), NULL); + if (key_len == 0) { + break; + } + + // build OSSL_PARAM + params_build = OSSL_PARAM_BLD_new(); + if (NULL == params_build) { + break; + } + nid = EC_GROUP_get_curve_name((EC_GROUP *)ecc_handle); + if (nid == NID_undef) { + break; + } + curvename = OBJ_nid2sn(nid); + if (curvename == NULL) { + break; + } + if (1 != OSSL_PARAM_BLD_push_utf8_string(params_build, "group", curvename, 0)) { + break; + } + if (1 != OSSL_PARAM_BLD_push_octet_string(params_build, OSSL_PKEY_PARAM_PUB_KEY, pub_key, key_len)) { + break; + } + params = OSSL_PARAM_BLD_to_param(params_build); + if (NULL == params) { + break; + } + + // get pkey from params + pkey_ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + if (NULL == pkey_ctx) { + break; + } + if (1 != EVP_PKEY_fromdata_init(pkey_ctx)) { + break; + } + if (1 != EVP_PKEY_fromdata(pkey_ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params)) { + EVP_PKEY_free(evp_key); + evp_key = NULL; + } + } while(0); + + BN_clear_free(bn_pub_x); + BN_clear_free(bn_pub_y); + EC_POINT_clear_free(point); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(params_build); + EVP_PKEY_CTX_free(pkey_ctx); + + return evp_key; +} + /* Verifies the signature for the given data based on the public key * * Parameters: @@ -104,14 +202,13 @@ sgx_status_t sgx_ecdsa_verify(const uint8_t *p_data, { return SGX_ERROR_INVALID_PARAMETER; } - - EC_KEY *public_key = NULL; - BIGNUM *bn_pub_x = NULL; - BIGNUM *bn_pub_y = NULL; BIGNUM *bn_r = NULL; BIGNUM *bn_s = NULL; - EC_POINT *public_point = NULL; + EVP_PKEY *evp_pkey = NULL; ECDSA_SIG *ecdsa_sig = NULL; + EVP_MD_CTX *evp_md_ctx = NULL; + unsigned char *sig = NULL; + int siglen = 0; unsigned char digest[SGX_SHA256_HASH_SIZE] = { 0 }; sgx_status_t retval = SGX_ERROR_UNEXPECTED; int valid = 0; @@ -120,22 +217,11 @@ sgx_status_t sgx_ecdsa_verify(const uint8_t *p_data, do { - // converts the x value of public key, represented as positive integer in little-endian into a BIGNUM - // - bn_pub_x = BN_lebin2bn((unsigned char*)p_public->gx, sizeof(p_public->gx), 0); - if (NULL == bn_pub_x) + evp_pkey = get_pub_key_from_coords(p_public, ecc_handle); + if (NULL == evp_pkey) { break; } - - // converts the y value of public key, represented as positive integer in little-endian into a BIGNUM - // - bn_pub_y = BN_lebin2bn((unsigned char*)p_public->gy, sizeof(p_public->gy), 0); - if (NULL == bn_pub_y) - { - break; - } - // converts the x value of the signature, represented as positive integer in little-endian into a BIGNUM // bn_r = BN_lebin2bn((unsigned char*)p_signature->x, sizeof(p_signature->x), 0); @@ -152,89 +238,54 @@ sgx_status_t sgx_ecdsa_verify(const uint8_t *p_data, break; } - // creates new point and assigned the group object that the point relates to + // allocates a new ECDSA_SIG structure (note: this function also allocates the BIGNUMs) and initialize it // - public_point = EC_POINT_new((EC_GROUP*)ecc_handle); - if (public_point == NULL) + ecdsa_sig = ECDSA_SIG_new(); + if (NULL == ecdsa_sig) { retval = SGX_ERROR_OUT_OF_MEMORY; break; } - // sets point based on public key's x,y coordinates - // - if (1 != EC_POINT_set_affine_coordinates_GFp((EC_GROUP*)ecc_handle, public_point, bn_pub_x, bn_pub_y, NULL)) - { - break; - } - - // check point if the point is on curve - // - if (1 != EC_POINT_is_on_curve((EC_GROUP*)ecc_handle, public_point, NULL)) - { - break; - } - - // create empty ecc key + // setes the r and s values of ecdsa_sig + // calling this function transfers the memory management of the values to the ECDSA_SIG object, + // and therefore the values that have been passed in should not be freed directly after this function has been called // - public_key = EC_KEY_new(); - if (NULL == public_key) + if (1 != ECDSA_SIG_set0(ecdsa_sig, bn_r, bn_s)) { - retval = SGX_ERROR_OUT_OF_MEMORY; break; } - // sets ecc key group (set curve) - // - if (1 != EC_KEY_set_group(public_key, (EC_GROUP*)ecc_handle)) + siglen = i2d_ECDSA_SIG(ecdsa_sig, &sig); + if(siglen <= 0) { break; } - // uses the created point to set the public key value + // verifies that the signature ecdsa_sig is a valid ECDSA signature using EVP_DigestVerify // - if (1 != EC_KEY_set_public_key(public_key, public_point)) + evp_md_ctx = EVP_MD_CTX_new(); + if(NULL == evp_md_ctx) { break; } - - /* generates digest of p_data */ - if (NULL == SHA256((const unsigned char *)p_data, data_size, (unsigned char *)digest)) + if(1 != EVP_DigestVerifyInit(evp_md_ctx, NULL, NULL, NULL, evp_pkey)) { break; } - - // allocates a new ECDSA_SIG structure (note: this function also allocates the BIGNUMs) and initialize it - // - ecdsa_sig = ECDSA_SIG_new(); - if (NULL == ecdsa_sig) + if(1 != EVP_DigestVerifyUpdate(evp_md_ctx, p_data, data_size)) { - retval = SGX_ERROR_OUT_OF_MEMORY; - break; - } - - // setes the r and s values of ecdsa_sig - // calling this function transfers the memory management of the values to the ECDSA_SIG object, - // and therefore the values that have been passed in should not be freed directly after this function has been called - // - if (1 != ECDSA_SIG_set0(ecdsa_sig, bn_r, bn_s)) - { - ECDSA_SIG_free(ecdsa_sig); - ecdsa_sig = NULL; break; } - - // verifies that the signature ecdsa_sig is a valid ECDSA signature of the hash value digest of size SGX_SHA256_HASH_SIZE using the public key public_key - // - valid = ECDSA_do_verify(digest, SGX_SHA256_HASH_SIZE, ecdsa_sig, public_key); - if (-1 == valid) + valid = EVP_DigestVerifyFinal(evp_md_ctx, sig, siglen); + if (valid < 0) { break; } // sets the p_result based on ECDSA_do_verify result // - if (valid) + if (valid == 1) { *p_result = SGX_EC_VALID; } @@ -242,25 +293,23 @@ sgx_status_t sgx_ecdsa_verify(const uint8_t *p_data, retval = SGX_SUCCESS; } while(0); - if (bn_pub_x) - BN_clear_free(bn_pub_x); - if (bn_pub_y) - BN_clear_free(bn_pub_y); - if (public_point) - EC_POINT_clear_free(public_point); if (ecdsa_sig) { ECDSA_SIG_free(ecdsa_sig); bn_r = NULL; bn_s = NULL; } - if (public_key) - EC_KEY_free(public_key); if (bn_r) BN_clear_free(bn_r); if (bn_s) BN_clear_free(bn_s); + if (evp_pkey) + EVP_PKEY_free(evp_pkey); + if (evp_md_ctx) + EVP_MD_CTX_free(evp_md_ctx); + if (sig) + OPENSSL_free(sig); return retval; } diff --git a/psw/ae/aesm_service/source/utils/crypto_rsa.cpp b/psw/ae/aesm_service/source/utils/crypto_rsa.cpp index 16971d82e..5ed449b64 100644 --- a/psw/ae/aesm_service/source/utils/crypto_rsa.cpp +++ b/psw/ae/aesm_service/source/utils/crypto_rsa.cpp @@ -33,6 +33,8 @@ #include "ssl_compat_wrapper.h" #include #include +#include +#include #include #include #include @@ -43,54 +45,51 @@ sgx_status_t sgx_create_rsa_pub1_key(int mod_size, int exp_size, const unsigned { return SGX_ERROR_INVALID_PARAMETER; } - EVP_PKEY *rsa_key = NULL; - RSA *rsa_ctx = NULL; sgx_status_t ret_code = SGX_ERROR_UNEXPECTED; - BIGNUM* n = NULL; - BIGNUM* e = NULL; - - do + BIGNUM *n = NULL; + BIGNUM *e = NULL; + OSSL_PARAM_BLD *bld = NULL; + OSSL_PARAM *params = NULL; + EVP_PKEY_CTX *pctx = NULL; + do { - //convert input buffers to BNs + pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + NULL_BREAK(pctx); + + bld = OSSL_PARAM_BLD_new(); + NULL_BREAK(bld); + + // convert input buffers to BNs // n = BN_lebin2bn(le_n, mod_size, n); BN_CHECK_BREAK(n); e = BN_lebin2bn(le_e, exp_size, e); BN_CHECK_BREAK(e); - - // allocates and initializes an RSA key structure - // - rsa_ctx = RSA_new(); - rsa_key = EVP_PKEY_new(); - - if (rsa_ctx == NULL || rsa_key == NULL || !EVP_PKEY_assign_RSA(rsa_key, rsa_ctx)) - { - RSA_free(rsa_ctx); - rsa_ctx = NULL; + if (!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, n)) + break; + if (!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, e)) + break; + params = OSSL_PARAM_BLD_to_param(bld); + NULL_BREAK(params); + if (EVP_PKEY_fromdata_init(pctx) < 1) + break; + // rsa_key will be created in this function + if (EVP_PKEY_fromdata(pctx, &rsa_key, EVP_PKEY_PUBLIC_KEY, params) < 1) break; - } - - //set n, e values of RSA key - //Calling set functions transfers the memory management of input BNs to the RSA object, - //and therefore the values that have been passed in should not be freed by the caller after these functions has been called. - // - if (!RSA_set0_key(rsa_ctx, n, e, NULL)) - { - break; - } - *new_pub_key = rsa_key; ret_code = SGX_SUCCESS; + *new_pub_key = rsa_key; } while (0); - if (ret_code != SGX_SUCCESS) - { EVP_PKEY_free(rsa_key); - BN_clear_free(n); - BN_clear_free(e); - } + EVP_PKEY_CTX_free(pctx); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(bld); + BN_free(n); + BN_free(e); return ret_code; + } diff --git a/psw/ae/aesm_service/source/utils/ssl_compat_wrapper.cpp b/psw/ae/aesm_service/source/utils/ssl_compat_wrapper.cpp index 04fda2e10..4f3782a18 100644 --- a/psw/ae/aesm_service/source/utils/ssl_compat_wrapper.cpp +++ b/psw/ae/aesm_service/source/utils/ssl_compat_wrapper.cpp @@ -35,113 +35,11 @@ #include #include -#if OPENSSL_VERSION_NUMBER < 0x10100000L - -static void *OPENSSL_zalloc(size_t num) -{ - void *ret = OPENSSL_malloc(num); - - if (ret != NULL) - memset(ret, 0, num); - return ret; -} - - -int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) -{ - /* If the fields n and e in r are NULL, the corresponding input - * parameters MUST be non-NULL for n and e. d may be - * left NULL (in case only the public key is used). - */ - if (r == NULL - || (r->n == NULL && n == NULL) - || (r->e == NULL && e == NULL)) - return 0; - - if (n != NULL) - { - BN_free(r->n); - r->n = n; - } - if (e != NULL) - { - BN_free(r->e); - r->e = e; - } - if (d != NULL) - { - BN_free(r->d); - r->d = d; - } - - return 1; -} - -EVP_MD_CTX *EVP_MD_CTX_new(void) -{ - return (EVP_MD_CTX *)OPENSSL_zalloc(sizeof(EVP_MD_CTX)); -} - -void EVP_MD_CTX_free(EVP_MD_CTX *ctx) -{ - EVP_MD_CTX_cleanup(ctx); - OPENSSL_free(ctx); -} - -void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) - { - if (pr != NULL) - *pr = sig->r; - if (ps != NULL) - *ps = sig->s; - } - - int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) - { - if (r == NULL || s == NULL) - return 0; - BN_clear_free(sig->r); - BN_clear_free(sig->s); - sig->r = r; - sig->s = s; - return 1; - } - -BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret) -{ - unsigned char *le_s = (unsigned char *)malloc(len); - if(le_s == NULL) - return NULL; - for(unsigned int i = 0; i< len; i++) - { - le_s[i] = s[len - 1 - i]; - } - BIGNUM *res = BN_bin2bn(le_s, len, ret); - free(le_s); - return res; -} - -#endif - - void crypto_initialize() { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); -#else - OPENSSL_init_crypto(0, NULL); -#endif - } void crypto_cleanup() { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - ERR_remove_thread_state(NULL); - ERR_free_strings(); -#endif } diff --git a/psw/ae/data/prebuilt/README.md b/psw/ae/data/prebuilt/README.md index 36945727b..8e69f3d49 100644 --- a/psw/ae/data/prebuilt/README.md +++ b/psw/ae/data/prebuilt/README.md @@ -1,11 +1,11 @@ # LE source code -The LE is part of Intel(R) Software Guard Extensions for Linux\* OS which is published in [linux-sgx](https://github.com/intel/linux-sgx/) Github repository. The libsgx_le.signed.so in prebuilt package is built by [le](https://github.com/intel/linux-sgx/tree/master/psw/ae/le) with branch [sgx_2.19_reproducible](https://github.com/intel/linux-sgx/tree/sgx_2.19_reproducible) and signed by Intel. +The LE is part of Intel(R) Software Guard Extensions for Linux\* OS which is published in [linux-sgx](https://github.com/intel/linux-sgx/) Github repository. The libsgx_le.signed.so in prebuilt package is built by [le](https://github.com/intel/linux-sgx/tree/master/psw/ae/le) with branch [sgx_2.22_reproducible](https://github.com/intel/linux-sgx/tree/sgx_2.22_reproducible) and signed by Intel. # PVE source code -The PVE is part of Intel(R) Software Guard Extensions for Linux\* OS which is published in [linux-sgx](https://github.com/intel/linux-sgx/) Github repository. The libsgx_pve.signed.so in prebuilt package is built by [pve](https://github.com/intel/linux-sgx/tree/master/psw/ae/pve) with branch [sgx_2.19_reproducible](https://github.com/intel/linux-sgx/tree/sgx_2.19_reproducible) and signed by Intel. +The PVE is part of Intel(R) Software Guard Extensions for Linux\* OS which is published in [linux-sgx](https://github.com/intel/linux-sgx/) Github repository. The libsgx_pve.signed.so in prebuilt package is built by [pve](https://github.com/intel/linux-sgx/tree/master/psw/ae/pve) with branch [sgx_2.22_reproducible](https://github.com/intel/linux-sgx/tree/sgx_2.22_reproducible) and signed by Intel. # PCE source code -The PCE is part of Intel(R) Software Guard Extensions for Linux\* OS which is published in [linux-sgx](https://github.com/intel/linux-sgx/) Github repository. The libsgx_pce.signed.so in prebuilt package is built by [pce](https://github.com/intel/linux-sgx/tree/master/psw/ae/pce) with branch [sgx_2.19_reproducible](https://github.com/intel/linux-sgx/tree/sgx_2.19_reproducible) and signed by Intel. +The PCE is part of Intel(R) Software Guard Extensions for Linux\* OS which is published in [linux-sgx](https://github.com/intel/linux-sgx/) Github repository. The libsgx_pce.signed.so in prebuilt package is built by [pce](https://github.com/intel/linux-sgx/tree/master/psw/ae/pce) with branch [sgx_2.22_reproducible](https://github.com/intel/linux-sgx/tree/sgx_2.22_reproducible) and signed by Intel. # QE source code -The QE is part of Intel(R) Software Guard Extensions for Linux\* OS which is published in [linux-sgx](https://github.com/intel/linux-sgx/) Github repository. The libsgx_qe.signed.so in prebuilt package is built by [qe](https://github.com/intel/linux-sgx/tree/master/psw/ae/qe) with branch [sgx_2.19_reproducible](https://github.com/intel/linux-sgx/tree/sgx_2.19_reproducible) and signed by Intel. +The QE is part of Intel(R) Software Guard Extensions for Linux\* OS which is published in [linux-sgx](https://github.com/intel/linux-sgx/) Github repository. The libsgx_qe.signed.so in prebuilt package is built by [qe](https://github.com/intel/linux-sgx/tree/master/psw/ae/qe) with branch [sgx_2.22_reproducible](https://github.com/intel/linux-sgx/tree/sgx_2.22_reproducible) and signed by Intel. diff --git a/psw/ae/data/prebuilt/le_prod_css.bin b/psw/ae/data/prebuilt/le_prod_css.bin index 809ec4a20308ddcaad08526bb7c37c7f74cccb39..c7f2596ca1f054ee3ff19a80cc4c345135ed04cf 100644 GIT binary patch delta 1243 zcmV<11SI>A4v-Fz6ao_ou@>$De{X6{>0yj>U{hDiCYBgvIB8ei8P_1q_xDlVjAL*A;c zC0?;0E@eY`(*1wqKnJk&0k#_LDJWSC#RZnsUY^8SxtO(D5*Jq*sd~&kDtEJ$P^ zUqVyjF$djM^ri`b7!^lRf74mfyH*}JbZNeRp~}oN&Td%=V-Dl_%zXe2v#b7;(7_7@ z>GC$@ugJ%r6RCkT=b^wI>F6N(j+p%h)^w*+2E8s1)kGcv4#AP{_icv6iu=0vljATY z?K4>LvObHEfW}FJf)-t_Ce3Y+wN;f3+vS+00000|NsC0 zkuemLpaUQv=+Ib{KYc<7CV{9Y^lnC3l={mF3Svt_CfWd-C4Vrjkue~DAOHpc00000 z0000000000PJI#>cegj0(gnip_|jNV9TztxJEB98wpLme3WviR}bYp-9-@7uencWf@dT}P&#gx1=>c43`>#dl0dUPBm%#UenD$^L*NpI2sG7DJzKVnI}YrH(|gYLl>8PLLKN zG$|k{dRTqb)5 zxyu_7g*X;4`8LAQMbIUn;m)g}Cp)P6xX=F0-!uv%qD$~M`qH+S*bB3r%^Q6;wx|94 z0Qa%{?EIObbGuo8$El1Liq^-Q5Cf-n`c?}`Q`nsQu6al@$Xuj$w;&zvB!hieYc#;HLNPz>b0dp0Wn^ zOhhmg1}@Yviji@|cqxxCW2Q73?s1;THiFLphy<{{4LHM?Vq0yaJT@GFtjwHCe?H$xAb0;<3a)AAc< z1d0f!JM4@4q%lsA1A%7kuB=qpEYqK#!gNG?vlPu11HplO=UFdrX(+Vh1!=q6ICL7b Fs}#{ZT(bZG delta 1243 zcmV<11SI>A4v-Fz6aoVRu@>$De`=A1QfD8`oPK)lHypmZbR{&jqda91(CN%g+X2?! z`Tw_GZ;Jn3rd{Ynf6e3{D+5s;zZR6!gUyF@sqjjGQgCZO5p5Y*6OJX=-^27B+G~fR*ND8&qTSKr<;vLZ+aF&$$U++Ih~lGjcyWs^tm!~Gze2s?kNUwh9C ztD2D{w9FPHbVC5ag6KXv+tMV6Bv1}|^wg(!y@<;Szr>xg#S^PKXz&%sQ`_75cqlUF z&jZ|i0Ao?;$P=UC7o$i=f1&E8*Ch1ZW!aLtKE8u9Ft+bv#q^P|_VE*(h!4|tST-aN zlyStAZ`b$-j3qodfhpT3%6NqexB*yl8_kx+*+|@|$?~1cbRqin%5~qV03(ImOR4gT zirl0i{|@RHeh~Ji_`MajlO7^V5nzRJyvuqN1`!H&ehauB`h7xo3mD@K00000|NsC0 zkuemLpaUQv%3m1o2CK3|5q;<^yIW87Q5$9AEW*!A-q*4*Q3fkwkue~DAOHmb00000 z0000000000N8Fw_+vm-QTIzuL{YJL(Kc zsB2M4Lluu+qtoqo?6*InE)(_%}&6sY*fSohIli2Ew zhJYU-xnUGZq69taXj|xmtzVSfDYz#OpLuX;Yo{T5Ax$0LnW~K0?Q8QMCA6%$ zVic@EwMtsP6zEV>Jc-eT{Y#^gOF1M^3j?ixQ6o8O>}2=N!^!FDM0gIVcZjRBD>a=9 zyk9uPP3<=;Bp!!K&@a7lXUQ$v(2Q1%4gQ;n$fAubbtHiF&qEeR={zQG@PbQ5npl8QJJWB^SE$2HyfU zObFQ(I#d*YUF=g6OdA^aU(mE5?7Ei*XM*SZszX%0NusizX|vxluJsHp`1nW% F1p_c^UE2Tv diff --git a/psw/ae/pce/config.xml b/psw/ae/pce/config.xml index 374295b82..272d12b07 100644 --- a/psw/ae/pce/config.xml +++ b/psw/ae/pce/config.xml @@ -3,7 +3,7 @@ 1 0 0x1 - 0xE + 0xF 1 0 1 diff --git a/psw/ae/pve/config.xml b/psw/ae/pve/config.xml index a0e0abfea..1ba94fbb4 100644 --- a/psw/ae/pve/config.xml +++ b/psw/ae/pve/config.xml @@ -3,7 +3,7 @@ 1 0 0x1 - 0xE + 0xF 1 0 1 diff --git a/psw/ae/pve/helper.cpp b/psw/ae/pve/helper.cpp index f4ce8dc60..d391d6f47 100644 --- a/psw/ae/pve/helper.cpp +++ b/psw/ae/pve/helper.cpp @@ -244,6 +244,7 @@ pve_status_t sgx_error_to_pve_error(sgx_status_t status) sgx_status_t sgx_aes_gcm128_enc_inplace_update( sgx_aes_state_handle_t aes_gcm_state, uint8_t *buf, uint32_t buf_len) { + //For defense in depth, we add extra constrain that buf_len should not be too large if ((buf == NULL) || (aes_gcm_state == NULL) || (buf_len >= INT_MAX) || (buf_len == 0)) { return SGX_ERROR_INVALID_PARAMETER; @@ -252,13 +253,6 @@ sgx_status_t sgx_aes_gcm128_enc_inplace_update( sgx_aes_state_handle_t aes_gcm_s uint8_t block[BLOCK_SIZE]; memset(block, 0, sizeof(block)); - //In PvE, we should only use code with buf_len not too large. - //The code in following loop will have integer overflow if buf_len is larger than or equal to 2^32-BLOCK_SIZE. (off+=BLOCK_SIZE) - //For defense in depth, we add extra constrain that buf_len should not be too large - if (buf_len > (1U << 31)) { - return SGX_ERROR_UNEXPECTED; - } - //encrypt input buffer inplace. each round encrypt BLOCK_SIZE bytes // for (off = 0; off < buf_len; off += BLOCK_SIZE) { diff --git a/psw/ae/qe/config.xml b/psw/ae/qe/config.xml index 04c1e0873..97e9ee501 100644 --- a/psw/ae/qe/config.xml +++ b/psw/ae/qe/config.xml @@ -3,7 +3,7 @@ 0 0 0x1 - 0xE + 0xF 1 0 1 diff --git a/psw/enclave_common/sgx_enclave_common.cpp b/psw/enclave_common/sgx_enclave_common.cpp index fa351dd5b..b13d912e0 100644 --- a/psw/enclave_common/sgx_enclave_common.cpp +++ b/psw/enclave_common/sgx_enclave_common.cpp @@ -500,8 +500,8 @@ static void enclave_set_provision_access(int hdevice, void* enclave_base) { SE_TRACE(SE_TRACE_WARNING, "\nSGX_IOC_ENCLAVE_SET_ATTRIBUTE, failed: errno = %d\n", errno); } + close(hdev_prov); } - close(hdev_prov); } else { diff --git a/psw/enclave_common/sgx_enclave_common.lds b/psw/enclave_common/sgx_enclave_common.lds index d10e4811e..568155989 100644 --- a/psw/enclave_common/sgx_enclave_common.lds +++ b/psw/enclave_common/sgx_enclave_common.lds @@ -10,6 +10,8 @@ global: enclave_alloc; enclave_modify; enclave_get_features; + sgx_trace_logger_callback; + sgx_trace_loglevel; local: *; }; diff --git a/psw/uae_service/linux/libsgx_epid.lds b/psw/uae_service/linux/libsgx_epid.lds index 44f89ac60..80292428c 100644 --- a/psw/uae_service/linux/libsgx_epid.lds +++ b/psw/uae_service/linux/libsgx_epid.lds @@ -7,6 +7,8 @@ global: sgx_check_update_status; sgx_get_extended_epid_group_id; sgx_calc_quote_size; + sgx_trace_logger_callback; + sgx_trace_loglevel; local: *; }; diff --git a/psw/uae_service/linux/libsgx_launch.lds b/psw/uae_service/linux/libsgx_launch.lds index 1a629f40d..8167aa5aa 100644 --- a/psw/uae_service/linux/libsgx_launch.lds +++ b/psw/uae_service/linux/libsgx_launch.lds @@ -4,6 +4,8 @@ global: sgx_get_whitelist_size; sgx_get_whitelist; sgx_register_wl_cert_chain; + sgx_trace_logger_callback; + sgx_trace_loglevel; local: *; }; diff --git a/psw/uae_service/linux/libsgx_quote_ex.lds b/psw/uae_service/linux/libsgx_quote_ex.lds index 043f78962..5080a5740 100644 --- a/psw/uae_service/linux/libsgx_quote_ex.lds +++ b/psw/uae_service/linux/libsgx_quote_ex.lds @@ -6,6 +6,8 @@ global: sgx_get_quote_ex; sgx_get_supported_att_key_id_num; sgx_get_supported_att_key_ids; + sgx_trace_logger_callback; + sgx_trace_loglevel; local: *; }; diff --git a/psw/uae_service/linux/uae_service.lds b/psw/uae_service/linux/uae_service.lds index 5c6afbd16..49e50e70a 100644 --- a/psw/uae_service/linux/uae_service.lds +++ b/psw/uae_service/linux/uae_service.lds @@ -17,6 +17,8 @@ global: sgx_get_quote_ex; sgx_get_supported_att_key_id_num; sgx_get_supported_att_key_ids; + sgx_trace_logger_callback; + sgx_trace_loglevel; local: *; }; diff --git a/psw/urts/cpu_features_ext.cpp b/psw/urts/cpu_features_ext.cpp index e7e05b960..077aa0234 100644 --- a/psw/urts/cpu_features_ext.cpp +++ b/psw/urts/cpu_features_ext.cpp @@ -39,7 +39,7 @@ static uint64_t get_bit_from_feature_id(FeatureId feature_id) { - assert(feature_id >= c_feature_none); + assert(feature_id > c_feature_none); if (feature_id < c_feature_end) { diff --git a/psw/urts/enclave.cpp b/psw/urts/enclave.cpp index 820e5ffc8..2be904db3 100644 --- a/psw/urts/enclave.cpp +++ b/psw/urts/enclave.cpp @@ -61,6 +61,7 @@ CEnclave::CEnclave() , m_destroyed(false) , m_version(0) , m_ocall_table(NULL) + , m_pthread_tid(0) , m_pthread_is_valid(false) , m_new_thread_event(NULL) , m_sealed_key(NULL) @@ -142,7 +143,7 @@ sgx_status_t CEnclave::initialize(const se_file_t& file, CLoader &ldr, const ui return SGX_ERROR_OUT_OF_MEMORY; memcpy_s(m_enclave_info.lpFileName, name_len, file.name, name_len); - m_enclave_info.unicode = file.unicode?0:1; + m_enclave_info.unicode = file.unicode?1:0; m_enclave_info.file_name_size = name_len; } diff --git a/psw/urts/enclave_creator_hw_com.cpp b/psw/urts/enclave_creator_hw_com.cpp index d556b0eb6..42216f372 100644 --- a/psw/urts/enclave_creator_hw_com.cpp +++ b/psw/urts/enclave_creator_hw_com.cpp @@ -166,15 +166,31 @@ int EnclaveCreatorHW::get_misc_attr(sgx_misc_attribute_t *sgx_misc_attr, metadat } } //if the enclave requires aex notify support, need to check the platform supports edeccssa or not - if(((secs_attr->flags & SGX_FLAGS_AEX_NOTIFY) != false) && (is_edeccssa_supported() == false)) + if(((secs_attr->flags & SGX_FLAGS_AEX_NOTIFY) == SGX_FLAGS_AEX_NOTIFY) && (is_edeccssa_supported() == false)) { SE_TRACE(SE_TRACE_WARNING, "the enclave requires AEX Notify support, but the platform doesn't support EDECCSSA.\n"); return SGX_ERROR_UNEXPECTED; } - // try to use maximum ablity of cpu - sgx_misc_attr->misc_select = se_cap.misc_select & enclave_css->body.misc_select; + //if the enclave requires aex notify support, need to check the platform supports avx or not + if(((secs_attr->flags & SGX_FLAGS_AEX_NOTIFY) == SGX_FLAGS_AEX_NOTIFY) && ((secs_attr->xfrm & SGX_XFRM_AVX) != SGX_XFRM_AVX)) + { + SE_TRACE(SE_TRACE_WARNING, "the enclave requires AEX Notify support, but the platform doesn't support AVX.\n"); + return SGX_ERROR_UNEXPECTED; + } + // try to use maximum ablity of cpu + SE_TRACE(SE_TRACE_DEBUG, "se_cap.misc_select: 0x%x\n", se_cap.misc_select); + SE_TRACE(SE_TRACE_DEBUG, "enclave_css->body.misc_select: 0x%x\n", enclave_css->body.misc_select); + SE_TRACE(SE_TRACE_DEBUG, "enclave_css->body.misc_mask: 0x%x\n", enclave_css->body.misc_mask); + SE_TRACE(SE_TRACE_DEBUG, "metadata->desired_misc_select: 0x%x\n", metadata->desired_misc_select); + sgx_misc_attr->misc_select = se_cap.misc_select & (enclave_css->body.misc_select | metadata->desired_misc_select); + + if ((sgx_misc_attr->misc_select & enclave_css->body.misc_mask) != + (enclave_css->body.misc_select & enclave_css->body.misc_mask)) + { + return SGX_ERROR_INVALID_MISC; + } return SGX_SUCCESS; } diff --git a/psw/urts/linux/urts.cpp b/psw/urts/linux/urts.cpp index 17c82de4b..22b37bf02 100644 --- a/psw/urts/linux/urts.cpp +++ b/psw/urts/linux/urts.cpp @@ -217,7 +217,7 @@ static bool get_metadata_internal(BinParser *parser, metadata_t **metadata) //assume AE only contains one metadata *metadata = GET_PTR(metadata_t, base_addr, meta_rva); - if(metadata == NULL) + if(*metadata == NULL) { return false; } diff --git a/psw/urts/linux/urts.lds b/psw/urts/linux/urts.lds index 44897f21e..02b98ed69 100644 --- a/psw/urts/linux/urts.lds +++ b/psw/urts/linux/urts.lds @@ -18,6 +18,8 @@ sgx_create_enclave_from_buffer_ex; sgx_set_switchless_itf; sgx_get_metadata; + sgx_trace_logger_callback; + sgx_trace_loglevel; local: *; }; diff --git a/psw/urts/linux/urts_internal.lds b/psw/urts/linux/urts_internal.lds index b2a0f716b..0877dc51f 100644 --- a/psw/urts/linux/urts_internal.lds +++ b/psw/urts/linux/urts_internal.lds @@ -21,6 +21,8 @@ sgx_get_metadata; sgx_set_switchless_itf; init_get_launch_token; + sgx_trace_logger_callback; + sgx_trace_loglevel; local: *; }; diff --git a/psw/urts/parser/elfparser.cpp b/psw/urts/parser/elfparser.cpp index 21979d575..9a5cfc720 100644 --- a/psw/urts/parser/elfparser.cpp +++ b/psw/urts/parser/elfparser.cpp @@ -534,9 +534,7 @@ bool build_regular_sections(const uint8_t* start_addr, const ElfW(Ehdr) *elf_hdr = (const ElfW(Ehdr) *)start_addr; const ElfW(Phdr) *prg_hdr = GET_PTR(ElfW(Phdr), start_addr, elf_hdr->e_phoff); uint64_t virtual_size = 0, alignment = 0, aligned_virtual_size = 0; -#ifndef DISABLE_TRACE unsigned section_count = 1; /* Definition only used with se_trace(SE_TRACE_DEBUG) below */ -#endif if (get_meta_property(start_addr, elf_hdr, metadata_offset, metadata_block_size) == false) return false; diff --git a/psw/urts/parser/update_global_data.hxx b/psw/urts/parser/update_global_data.hxx index 57457a1c8..347d2d2fc 100644 --- a/psw/urts/parser/update_global_data.hxx +++ b/psw/urts/parser/update_global_data.hxx @@ -142,9 +142,7 @@ namespace { layout->rva + 4096 * layout->page_count); } else { -#ifndef DISABLE_TRACE layout_group_t *layout_grp = reinterpret_cast(layout); -#endif se_trace(SE_TRACE_DEBUG, "\tEntry Id(%2u) = %4u, %-16s, ", entry_cnt, entry_id, layout_id_str[entry_id & ~(GROUP_FLAG)]); se_trace(SE_TRACE_DEBUG, "Entry Count = %4u, ", layout_grp->entry_count); se_trace(SE_TRACE_DEBUG, "Load Times = %u, ", layout_grp->load_times); diff --git a/psw/urts/urts_com.h b/psw/urts/urts_com.h index b234aa0da..18a6a6a20 100644 --- a/psw/urts/urts_com.h +++ b/psw/urts/urts_com.h @@ -289,8 +289,8 @@ static int __create_enclave(BinParser &parser, uint32_t enclave_version = SDK_VERSION_1_5; uint64_t urts_version = META_DATA_MAKE_VERSION(MAJOR_VERSION,MINOR_VERSION); // metadata->version has already been validated during load_encalve_ex() - if (MAJOR_VERSION_OF_METADATA(metadata->version) % SGX_MAJOR_VERSION_GAP == MAJOR_VERSION_OF_METADATA(urts_version)% SGX_MAJOR_VERSION_GAP && - MINOR_VERSION_OF_METADATA(metadata->version) >= MINOR_VERSION_OF_METADATA(urts_version)) + if (MAJOR_VERSION_OF_METADATA(metadata->version) % SGX_MAJOR_VERSION_GAP == + MAJOR_VERSION_OF_METADATA(urts_version)% SGX_MAJOR_VERSION_GAP) { enclave_version = SDK_VERSION_3_0; } diff --git a/sdk/ec_dh_lib/ec_dh.cpp b/sdk/ec_dh_lib/ec_dh.cpp index 05c4cb1e2..7bcd28124 100644 --- a/sdk/ec_dh_lib/ec_dh.cpp +++ b/sdk/ec_dh_lib/ec_dh.cpp @@ -1014,7 +1014,8 @@ static sgx_status_t LAv2_generate_message3(const sgx_dh_msg2_t *msg2, bufcat(*A, ps).sha256(&rpt_data); sgx_report_t rpt; - sgx_create_report(&ti, &rpt_data, &rpt); + if (SGX_SUCCESS != (se_ret = sgx_create_report(&ti, &rpt_data, &rpt))) + return se_ret; msg3->msg3_body.report = rpt; sgx_cmac_state_handle_t cmac; diff --git a/sdk/edger8r/linux/CodeGen.ml b/sdk/edger8r/linux/CodeGen.ml index 3da0795a2..355341421 100644 --- a/sdk/edger8r/linux/CodeGen.ml +++ b/sdk/edger8r/linux/CodeGen.ml @@ -675,7 +675,7 @@ let gen_ufunc_proto (uf: Ast.untrusted_func) = let cconv_str = "SGX_" ^ Ast.get_call_conv_str uf.Ast.uf_fattr.Ast.fa_convention in let func_name = uf.Ast.uf_fdecl.Ast.fname in let plist_str = get_plist_str uf.Ast.uf_fdecl in - let func_guard = sprintf "%s_DEFINED__" (String.uppercase func_name) in + let func_guard = sprintf "%s_DEFINED__" (String.uppercase_ascii func_name) in sprintf "#ifndef %s\n#define %s\n%s%s SGX_UBRIDGE(%s, %s, (%s));\n#endif" func_guard func_guard dllimport ret_tystr cconv_str func_name plist_str @@ -704,7 +704,7 @@ let ms_writer out_chan ec = (* Generate untrusted header for enclave *) let gen_untrusted_header (ec: enclave_content) = let header_fname = get_uheader_name ec.file_shortnm in - let guard_macro = sprintf "%s_U_H__" (String.uppercase ec.enclave_name) in + let guard_macro = sprintf "%s_U_H__" (String.uppercase_ascii ec.enclave_name) in let preemble_code = let include_list = gen_include_list (ec.include_list @ !untrusted_headers) in gen_uheader_preemble guard_macro include_list @@ -737,7 +737,7 @@ let gen_theader_preemble (guard: string) (inclist: string) = (* Generate trusted header for enclave *) let gen_trusted_header (ec: enclave_content) = let header_fname = get_theader_name ec.file_shortnm in - let guard_macro = sprintf "%s_T_H__" (String.uppercase ec.enclave_name) in + let guard_macro = sprintf "%s_T_H__" (String.uppercase_ascii ec.enclave_name) in let guard_code = let include_list = gen_include_list (ec.include_list @ !trusted_headers) in gen_theader_preemble guard_macro include_list in diff --git a/sdk/edger8r/linux/Makefile b/sdk/edger8r/linux/Makefile index 527db5acf..8b7a1cfb3 100644 --- a/sdk/edger8r/linux/Makefile +++ b/sdk/edger8r/linux/Makefile @@ -31,22 +31,13 @@ include ../../../buildenv.mk -OCAML_VERSION_MAJOR=$(shell ocamlopt -version | head -n 1 | cut -d . -f 1) -OCAML_VERSION_MINOR=$(shell ocamlopt -version | head -n 1 | cut -d . -f 2) -OCAML_VERSION=$(OCAML_VERSION_MAJOR)$(OCAML_VERSION_MINOR) - .PHONY: all all: build | $(BUILD_DIR) @$(CP) $(CUR_DIR)/_build/Edger8r.native $(BUILD_DIR)/sgx_edger8r .PHONY: build build: -# ocaml 4.02 - added support for PIC -ifeq ($(shell test $(OCAML_VERSION) -lt 402 && echo 1), 1) - ocamlbuild -lflag -ccopt -lflag "-Wl,-z,now" -no-links -libs str,unix Edger8r.native -else ocamlbuild -cflags -ccopt,-fpie -lflags -runtime-variant,_pic,-ccopt,-pie,-ccopt -lflag "-Wl,-z,now" -no-links -libs str,unix Edger8r.native -endif $(BUILD_DIR): @$(MKDIR) $@ diff --git a/sdk/edger8r/linux/Util.ml b/sdk/edger8r/linux/Util.ml index 43a37e0a9..e0d3d7bfb 100644 --- a/sdk/edger8r/linux/Util.ml +++ b/sdk/edger8r/linux/Util.ml @@ -114,7 +114,7 @@ let rec parse_cmdline (progname: string) (cmdargs: string list) = match args with [] -> () | op :: ops -> - match String.lowercase op with + match String.lowercase_ascii op with "--use-prefix" -> use_pref := true; local_parser ops | "--header-only"-> hd_only := true; local_parser ops | "--untrusted" -> untrusted := true; local_parser ops diff --git a/sdk/protected_fs/sgx_tprotected_fs/file_flush.cpp b/sdk/protected_fs/sgx_tprotected_fs/file_flush.cpp index f0c37550a..9b454177f 100644 --- a/sdk/protected_fs/sgx_tprotected_fs/file_flush.cpp +++ b/sdk/protected_fs/sgx_tprotected_fs/file_flush.cpp @@ -29,6 +29,8 @@ * */ +#include +#include #include "sgx_tprotected_fs.h" #include "sgx_tprotected_fs_t.h" #include "protected_fs_file.h" @@ -56,7 +58,7 @@ bool protected_fs_file::flush() return false; } - result = internal_flush(true); + result = internal_flush(); if (result == false) { assert(file_status != SGX_FILE_STATUS_OK); @@ -70,7 +72,7 @@ bool protected_fs_file::flush() } -bool protected_fs_file::internal_flush(bool flush_to_disk) +bool protected_fs_file::internal_flush() { if (need_writing == false) // no changes at all return true; @@ -83,7 +85,7 @@ bool protected_fs_file::internal_flush(bool flush_to_disk) return false; } - if (_RECOVERY_HOOK_(1) || set_update_flag(flush_to_disk) != true) + if (_RECOVERY_HOOK_(1) || set_update_flag() != true) { file_status = SGX_FILE_STATUS_FLUSH_ERROR; return false; @@ -91,24 +93,14 @@ bool protected_fs_file::internal_flush(bool flush_to_disk) if (_RECOVERY_HOOK_(2) || update_all_data_and_mht_nodes() != true) { - clear_update_flag(); - file_status = SGX_FILE_STATUS_CRYPTO_ERROR; // this is something that shouldn't happen, can't fix this... + file_status = SGX_FILE_STATUS_WRITE_TO_DISK_FAILED; return false; } } if (_RECOVERY_HOOK_(3) || update_meta_data_node() != true) { - clear_update_flag(); - - file_status = SGX_FILE_STATUS_CRYPTO_ERROR; // this is something that shouldn't happen, can't fix this... - return false; - } - - if (_RECOVERY_HOOK_(4) || write_all_changes_to_disk(flush_to_disk) != true) - { - file_status = SGX_FILE_STATUS_WRITE_TO_DISK_FAILED; // special case, need only to repeat write_all_changes_to_disk in order to repair it - + file_status = SGX_FILE_STATUS_WRITE_TO_DISK_FAILED; return false; } @@ -116,7 +108,7 @@ bool protected_fs_file::internal_flush(bool flush_to_disk) /* this is causing problems when we delete and create the file rapidly we will just leave the file, and re-write it every time - u_sgxprotectedfs_recovery_file_open opens it with 'w' so it is truncated + u_sgxprotectedfs_fwrite_recovery_file opens it with 'w' so it is truncated if (encrypted_part_plain.size > MD_USER_DATA_SIZE) { erase_recovery_file(); @@ -129,20 +121,11 @@ bool protected_fs_file::internal_flush(bool flush_to_disk) bool protected_fs_file::write_recovery_file() { - void* recovery_file = NULL; sgx_status_t status; uint8_t result = 0; - int32_t result32 = 0; - - status = u_sgxprotectedfs_recovery_file_open(&recovery_file, recovery_filename); - if (status != SGX_SUCCESS || recovery_file == NULL) - { - last_error = status != SGX_SUCCESS ? status : SGX_ERROR_FILE_CANT_OPEN_RECOVERY_FILE; - return false; - } + std::vector vec; void* data = NULL; - recovery_node_t* recovery_node = NULL; for (data = cache.get_first() ; data != NULL ; data = cache.get_next()) { @@ -152,7 +135,7 @@ bool protected_fs_file::write_recovery_file() if (file_data_node->need_writing == false || file_data_node->new_node == true) continue; - recovery_node = &file_data_node->recovery_node; + vec.push_back(file_data_node->physical_node_number); } else { @@ -161,105 +144,207 @@ bool protected_fs_file::write_recovery_file() if (file_mht_node->need_writing == false || file_mht_node->new_node == true) continue; - recovery_node = &file_mht_node->recovery_node; - } - - status = u_sgxprotectedfs_fwrite_recovery_node(&result, recovery_file, (uint8_t*)recovery_node, sizeof(recovery_node_t)); - if (status != SGX_SUCCESS || result != 0) - { - u_sgxprotectedfs_fclose(&result32, recovery_file); - u_sgxprotectedfs_remove(&result32, recovery_filename); - last_error = status != SGX_SUCCESS ? status : SGX_ERROR_FILE_CANT_WRITE_RECOVERY_FILE; - return false; + vec.push_back(file_mht_node->physical_node_number); } } if (root_mht.need_writing == true && root_mht.new_node == false) - { - status = u_sgxprotectedfs_fwrite_recovery_node(&result, recovery_file, (uint8_t*)&root_mht.recovery_node, sizeof(recovery_node_t)); - if (status != SGX_SUCCESS || result != 0) - { - u_sgxprotectedfs_fclose(&result32, recovery_file); - u_sgxprotectedfs_remove(&result32, recovery_filename); - last_error = status != SGX_SUCCESS ? status : SGX_ERROR_FILE_CANT_WRITE_RECOVERY_FILE; - return false; - } - } + vec.push_back(root_mht.physical_node_number); + + vec.push_back(meta_data_node_number); - status = u_sgxprotectedfs_fwrite_recovery_node(&result, recovery_file, (uint8_t*)&meta_data_recovery_node, sizeof(recovery_node_t)); + status = u_sgxprotectedfs_fwrite_recovery_file(&result, file_addr, recovery_filename, (uint64_t*)&vec[0], vec.size()); if (status != SGX_SUCCESS || result != 0) { - u_sgxprotectedfs_fclose(&result32, recovery_file); - u_sgxprotectedfs_remove(&result32, recovery_filename); last_error = status != SGX_SUCCESS ? status : SGX_ERROR_FILE_CANT_WRITE_RECOVERY_FILE; return false; } - u_sgxprotectedfs_fclose(&result32, recovery_file); // TODO - check result - return true; } -bool protected_fs_file::set_update_flag(bool flush_to_disk) +bool protected_fs_file::set_update_flag() { - sgx_status_t status; - uint8_t result; - int32_t result32; - - file_meta_data.plain_part.update_flag = 1; - status = u_sgxprotectedfs_fwrite_node(&result32, file, 0, (uint8_t*)&file_meta_data, NODE_SIZE); - file_meta_data.plain_part.update_flag = 0; // turn it off in memory. at the end of the flush, when we'll write the meta-data to disk, this flag will also be cleared there. - if (status != SGX_SUCCESS || result32 != 0) + if (file_addr == NULL || real_file_size < NODE_SIZE) { - last_error = (status != SGX_SUCCESS) ? status : - (result32 != -1) ? result32 : EIO; + last_error = EIO; return false; } - if (flush_to_disk == true) + file_meta_data.plain_part.update_flag = 1; + memcpy(file_addr, &file_meta_data, NODE_SIZE); + file_meta_data.plain_part.update_flag = 0; // turn it off in memory. at the end of the flush, when we'll write the meta-data to disk, this flag will also be cleared there. + + return true; +} + + +// sort function, we need the mht nodes sorted before we start to update their gmac's +bool mht_order(const file_mht_node_t* first, const file_mht_node_t* second) +{// higher (lower tree level) node number first + return first->mht_node_number > second->mht_node_number; +} + + +// 1. encrypt the changed data +// 2. set the IV+GMAC in the parent MHT +// [3. set the need_writing flag for all the parents] +void* update_data_nodes(void* thread_input) +{ + thread_input_t* input = (thread_input_t*)thread_input; + uint8_t* addr = input->addr; + uint8_t* empty_iv = input->empty_iv; + thread_queue_t* que_elm; + file_data_node_t* data_node; + file_mht_node_t* mht_node; + gcm_crypto_data_t* gcm_crypto_data; + uint8_t* file_data_node_addr; + sgx_status_t status; + + while (true) { - status = u_sgxprotectedfs_fflush(&result, file); - if (status != SGX_SUCCESS || result != 0) + if (input->queue->empty()) + return NULL; + que_elm = input->queue->front(); + input->queue->pop(); + + data_node = (file_data_node_t*)que_elm->node; + gcm_crypto_data = &data_node->parent->plain.data_nodes_crypto[data_node->data_node_number % ATTACHED_DATA_NODES_COUNT]; + file_data_node_addr = addr + NODE_SIZE * data_node->physical_node_number; + + // encrypt the data, this also saves the gmac of the operation in the mht crypto node + status = sgx_rijndael128GCM_encrypt(&que_elm->key, data_node->plain.data, NODE_SIZE, file_data_node_addr, + empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac); + if (status != SGX_SUCCESS) { - last_error = status != SGX_SUCCESS ? status : SGX_ERROR_FILE_FLUSH_FAILED; - u_sgxprotectedfs_fwrite_node(&result32, file, 0, (uint8_t*)&file_meta_data, NODE_SIZE); // try to clear the update flag, in the OS cache at least... - return false; + input->error = status; + memset_s(que_elm->key, sizeof(sgx_aes_gcm_128bit_key_t), 0, sizeof(sgx_aes_gcm_128bit_key_t)); // clear key in memroy + delete que_elm; + return data_node; } - } + memcpy(gcm_crypto_data->key, que_elm->key, sizeof(sgx_aes_gcm_128bit_key_t)); // save the key used for this encryption + memset_s(que_elm->key, sizeof(sgx_aes_gcm_128bit_key_t), 0, sizeof(sgx_aes_gcm_128bit_key_t)); // clear key in memroy + delete que_elm; - return true; + data_node->need_writing = false; + data_node->new_node = false; + + mht_node = data_node->parent; + // this loop should do nothing, add it here just to be safe + while (mht_node->mht_node_number != 0) + { + assert(mht_node->need_writing == true); + mht_node->need_writing = true; // just in case, for release + mht_node = mht_node->parent; + } + } } -// this function is called if we had an error after we updated the update flag -// in normal flow, the flag is cleared when the meta-data is written to disk -void protected_fs_file::clear_update_flag() +bool protected_fs_file::multi_thread_update_data_nodes() { - uint8_t result; + uint64_t max_tnum = parallel_flush_level - 1; + pthread_t threads[max_tnum]; + thread_input_t thread_inputs[max_tnum]; + uint32_t tnum = 0; int32_t result32; + std::queue queue[max_tnum]; + thread_queue_t* queue_element; + file_data_node_t* data_node; + uint64_t node_cnt = 0; + + // should not happen, for safety purpose + assert(last_error == 0); + if (last_error) + return false; - if (_RECOVERY_HOOK_(3)) - return; - assert(file_meta_data.plain_part.update_flag == 0); - u_sgxprotectedfs_fwrite_node(&result32, file, 0, (uint8_t*)&file_meta_data, NODE_SIZE); - u_sgxprotectedfs_fflush(&result, file); -} + // generate all the encryption keys in advance; save each key and data node + for (void* node = cache.get_first(); node != NULL; node = cache.get_next()) + { + data_node = (file_data_node_t*)node; + if (data_node->type == FILE_DATA_NODE_TYPE) // type is in the same offset in both node types + { + if (data_node->need_writing == true) + { + if (derive_random_node_key(data_node->physical_node_number) == false) + break; + try { + queue_element = new thread_queue_t; + } + catch (std::bad_alloc& e) { + (void)e; // remove warning + last_error = ENOMEM; + break; + } + queue_element->node = node; + memcpy(queue_element->key, cur_key, sizeof(sgx_aes_gcm_128bit_key_t)); // save the key to local for parallel computing + queue[node_cnt++ % max_tnum].push(queue_element); + } + } + } + + // if error occurs in key generation or create queue element + if (last_error != 0) + { + for (uint32_t i = 0; i < max_tnum; i++) + { + while (!queue[i].empty()) + { + memset_s(queue[i].front()->key, sizeof(sgx_aes_gcm_128bit_key_t), 0, sizeof(sgx_aes_gcm_128bit_key_t)); // clear key in memroy + delete queue[i].front(); + queue[i].pop(); + } + } + return false; + } + // start threads and record number of threads created + for (tnum = 0; tnum < max_tnum && tnum < node_cnt; tnum++) + { + thread_inputs[tnum] = {0, file_addr, empty_iv, &queue[tnum]}; + result32 = pthread_create(&threads[tnum], NULL, &update_data_nodes, &thread_inputs[tnum]); + if (result32 != 0) + { + last_error = (result32 == EAGAIN) ? SGX_ERROR_OUT_OF_TCS : result32; + break; + } + } -// sort function, we need the mht nodes sorted before we start to update their gmac's -bool mht_order(const file_mht_node_t* first, const file_mht_node_t* second) -{// higher (lower tree level) node number first - return first->mht_node_number > second->mht_node_number; + // wait threads to complete; if error occurs, only record the last thread error + for (uint32_t i = 0; i < tnum; i++) + { + void* res; + result32 = pthread_join(threads[i], &res); + if (last_error == 0 && (result32 != 0 || res != NULL)) + last_error = (result32 != 0) ? result32 : thread_inputs[i].error; + } + + // in case of error, queue may not be cleared + for (uint32_t i = 0; i < tnum; i++) + { + while (!queue[i].empty()) + { + memset_s(queue[i].front()->key, sizeof(sgx_aes_gcm_128bit_key_t), 0, sizeof(sgx_aes_gcm_128bit_key_t)); // clear key in memroy + delete queue[i].front(); + queue[i].pop(); + } + } + + if (last_error != 0) + return false; + + return true; } -bool protected_fs_file::update_all_data_and_mht_nodes() +bool protected_fs_file::single_thread_update_data_nodes() { - std::list mht_list; - std::list::iterator mht_list_it; - file_mht_node_t* file_mht_node; + gcm_crypto_data_t* gcm_crypto_data; + uint8_t* file_data_node_addr; + file_data_node_t* data_node; + file_mht_node_t* mht_node; sgx_status_t status; void* data = cache.get_first(); @@ -270,17 +355,18 @@ bool protected_fs_file::update_all_data_and_mht_nodes() { if (((file_data_node_t*)data)->type == FILE_DATA_NODE_TYPE) // type is in the same offset in both node types { - file_data_node_t* data_node = (file_data_node_t*)data; + data_node = (file_data_node_t*)data; if (data_node->need_writing == true) { if (derive_random_node_key(data_node->physical_node_number) == false) return false; - gcm_crypto_data_t* gcm_crypto_data = &data_node->parent->plain.data_nodes_crypto[data_node->data_node_number % ATTACHED_DATA_NODES_COUNT]; + gcm_crypto_data = &data_node->parent->plain.data_nodes_crypto[data_node->data_node_number % ATTACHED_DATA_NODES_COUNT]; + file_data_node_addr = file_addr + NODE_SIZE * data_node->physical_node_number; // encrypt the data, this also saves the gmac of the operation in the mht crypto node - status = sgx_rijndael128GCM_encrypt(&cur_key, data_node->plain.data, NODE_SIZE, data_node->encrypted.cipher, + status = sgx_rijndael128GCM_encrypt(&cur_key, data_node->plain.data, NODE_SIZE, file_data_node_addr, empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac); if (status != SGX_SUCCESS) { @@ -290,18 +376,68 @@ bool protected_fs_file::update_all_data_and_mht_nodes() memcpy(gcm_crypto_data->key, cur_key, sizeof(sgx_aes_gcm_128bit_key_t)); // save the key used for this encryption - file_mht_node = data_node->parent; + data_node->need_writing = false; + data_node->new_node = false; + + mht_node = data_node->parent; // this loop should do nothing, add it here just to be safe - while (file_mht_node->mht_node_number != 0) + while (mht_node->mht_node_number != 0) { - assert(file_mht_node->need_writing == true); - file_mht_node->need_writing = true; // just in case, for release - file_mht_node = file_mht_node->parent; + assert(mht_node->need_writing == true); + mht_node->need_writing = true; // just in case, for release + mht_node = mht_node->parent; } } } data = cache.get_next(); } + return true; +} + + +bool protected_fs_file::update_all_data_and_mht_nodes() +{ + std::list mht_list; + std::list::iterator mht_list_it; + file_mht_node_t* file_mht_node; + int32_t result32 = -1; + sgx_status_t status; + uint64_t max_node_number = 0; + void* data = cache.get_first(); + + // find the max physical node number and remap + while (data != NULL) + { + if (((file_data_node_t*)data)->type == FILE_DATA_NODE_TYPE) // type is in the same offset in both node types + { + file_data_node_t* data_node = (file_data_node_t*)data; + if (data_node->need_writing == true) + max_node_number = (max_node_number > data_node->physical_node_number) ? max_node_number : data_node->physical_node_number; + } + data = cache.get_next(); + } + if ((uint64_t)real_file_size < NODE_SIZE * (max_node_number + 1)) + { + status = u_sgxprotectedfs_file_remap(&result32, file_name, &file_addr, real_file_size, NODE_SIZE * (max_node_number + 1)); + if (status != SGX_SUCCESS || result32 != 0) + { + last_error = (status != SGX_SUCCESS) ? status : + (result32 != -1) ? result32 : EIO; + return false; + } + real_file_size = NODE_SIZE * (max_node_number + 1); + } + + if (parallel_flush_level <= 1) + { + if (single_thread_update_data_nodes() == false) + return false; + } + else + { + if (multi_thread_update_data_nodes() == false) + return false; + } // add all the mht nodes that needs writing to a list data = cache.get_first(); @@ -327,6 +463,7 @@ bool protected_fs_file::update_all_data_and_mht_nodes() file_mht_node = *mht_list_it; gcm_crypto_data_t* gcm_crypto_data = &file_mht_node->parent->plain.mht_nodes_crypto[(file_mht_node->mht_node_number - 1) % CHILD_MHT_NODES_COUNT]; + uint8_t* file_mht_node_addr = file_addr + NODE_SIZE * file_mht_node->physical_node_number; if (derive_random_node_key(file_mht_node->physical_node_number) == false) { @@ -334,7 +471,7 @@ bool protected_fs_file::update_all_data_and_mht_nodes() return false; } - status = sgx_rijndael128GCM_encrypt(&cur_key, (const uint8_t*)&file_mht_node->plain, NODE_SIZE, file_mht_node->encrypted.cipher, + status = sgx_rijndael128GCM_encrypt(&cur_key, (const uint8_t*)&file_mht_node->plain, NODE_SIZE, file_mht_node_addr, empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac); if (status != SGX_SUCCESS) { @@ -345,6 +482,9 @@ bool protected_fs_file::update_all_data_and_mht_nodes() memcpy(gcm_crypto_data->key, cur_key, sizeof(sgx_aes_gcm_128bit_key_t)); // save the key used for this gmac + file_mht_node->need_writing = false; + file_mht_node->new_node = false; + mht_list.pop_front(); } @@ -352,7 +492,7 @@ bool protected_fs_file::update_all_data_and_mht_nodes() if (derive_random_node_key(root_mht.physical_node_number) == false) return false; - status = sgx_rijndael128GCM_encrypt(&cur_key, (const uint8_t*)&root_mht.plain, NODE_SIZE, root_mht.encrypted.cipher, + status = sgx_rijndael128GCM_encrypt(&cur_key, (const uint8_t*)&root_mht.plain, NODE_SIZE, file_addr + NODE_SIZE, empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &encrypted_part_plain.mht_gmac); if (status != SGX_SUCCESS) { @@ -362,6 +502,9 @@ bool protected_fs_file::update_all_data_and_mht_nodes() memcpy(&encrypted_part_plain.mht_key, cur_key, sizeof(sgx_aes_gcm_128bit_key_t)); // save the key used for this gmac + root_mht.need_writing = false; + root_mht.new_node = false; + return true; } @@ -389,99 +532,7 @@ bool protected_fs_file::update_meta_data_node() return false; } - return true; -} - - -bool protected_fs_file::write_all_changes_to_disk(bool flush_to_disk) -{ - uint8_t result; - int32_t result32; - sgx_status_t status; - - if (encrypted_part_plain.size > MD_USER_DATA_SIZE && root_mht.need_writing == true) - { - void* data = NULL; - uint8_t* data_to_write; - uint64_t node_number; - file_data_node_t* file_data_node; - file_mht_node_t* file_mht_node; - - for (data = cache.get_first() ; data != NULL ; data = cache.get_next()) - { - file_data_node = NULL; - file_mht_node = NULL; - - if (((file_data_node_t*)data)->type == FILE_DATA_NODE_TYPE) // type is in the same offset in both node types - { - file_data_node = (file_data_node_t*)data; - if (file_data_node->need_writing == false) - continue; - - data_to_write = (uint8_t*)&file_data_node->encrypted; - node_number = file_data_node->physical_node_number; - } - else - { - file_mht_node = (file_mht_node_t*)data; - assert(file_mht_node->type == FILE_MHT_NODE_TYPE); - if (file_mht_node->need_writing == false) - continue; - - data_to_write = (uint8_t*)&file_mht_node->encrypted; - node_number = file_mht_node->physical_node_number; - } - - status = u_sgxprotectedfs_fwrite_node(&result32, file, node_number, data_to_write, NODE_SIZE); - if (status != SGX_SUCCESS || result32 != 0) - { - last_error = (status != SGX_SUCCESS) ? status : - (result32 != -1) ? result32 : EIO; - return false; - } - - // data written - clear the need_writing and the new_node flags (for future transactions, this node it no longer 'new' and should be written to recovery file) - if (file_data_node != NULL) - { - file_data_node->need_writing = false; - file_data_node->new_node = false; - } - else - { - file_mht_node->need_writing = false; - file_mht_node->new_node = false; - } - - } - - status = u_sgxprotectedfs_fwrite_node(&result32, file, 1, (uint8_t*)&root_mht.encrypted, NODE_SIZE); - if (status != SGX_SUCCESS || result32 != 0) - { - last_error = (status != SGX_SUCCESS) ? status : - (result32 != -1) ? result32 : EIO; - return false; - } - root_mht.need_writing = false; - root_mht.new_node = false; - } - - status = u_sgxprotectedfs_fwrite_node(&result32, file, 0, (uint8_t*)&file_meta_data, NODE_SIZE); - if (status != SGX_SUCCESS || result32 != 0) - { - last_error = (status != SGX_SUCCESS) ? status : - (result32 != -1) ? result32 : EIO; - return false; - } - - if (flush_to_disk == true) - { - status = u_sgxprotectedfs_fflush(&result, file); - if (status != SGX_SUCCESS || result != 0) - { - last_error = status != SGX_SUCCESS ? status : SGX_ERROR_FILE_FLUSH_FAILED; - return false; - } - } + memcpy(file_addr, &file_meta_data, NODE_SIZE); return true; } @@ -498,3 +549,13 @@ void protected_fs_file::erase_recovery_file() status = u_sgxprotectedfs_remove(&result32, recovery_filename); (void)status; // don't care if it succeeded or failed...just remove the warning } + + +int32_t protected_fs_file::set_parallel_flush_level(uint32_t max_threads_number) +{ + if (max_threads_number == 0) + return 1; + + parallel_flush_level = max_threads_number; + return 0; +} diff --git a/sdk/protected_fs/sgx_tprotected_fs/file_init.cpp b/sdk/protected_fs/sgx_tprotected_fs/file_init.cpp index 60f19b366..b266f62c0 100644 --- a/sdk/protected_fs/sgx_tprotected_fs/file_init.cpp +++ b/sdk/protected_fs/sgx_tprotected_fs/file_init.cpp @@ -32,7 +32,7 @@ #include "sgx_tprotected_fs.h" #include "sgx_tprotected_fs_t.h" #include "protected_fs_file.h" - +#include #include // remove the file path if it's there, leave only the filename, null terminated @@ -70,7 +70,7 @@ bool protected_fs_file::cleanup_filename(const char* src, char* dest) protected_fs_file::protected_fs_file(const char* filename, const char* mode, const sgx_aes_gcm_128bit_key_t* import_key, const sgx_aes_gcm_128bit_key_t* kdk_key, const uint32_t cache_page) { sgx_status_t status = SGX_SUCCESS; - uint8_t result = 0; + int8_t result = 0; int32_t result32 = 0; init_fields(cache_page); @@ -143,9 +143,9 @@ protected_fs_file::protected_fs_file(const char* filename, const char* mode, con } status = u_sgxprotectedfs_check_if_file_exists(&result, filename); // if result == 1 --> file exists - if (status != SGX_SUCCESS) + if (status != SGX_SUCCESS || result < 0) { - last_error = status; + last_error = (status != SGX_SUCCESS) ? status : -result; return; } @@ -163,9 +163,10 @@ protected_fs_file::protected_fs_file(const char* filename, const char* mode, con // re-check status = u_sgxprotectedfs_check_if_file_exists(&result, filename); - if (status != SGX_SUCCESS || result == 1) + if (status != SGX_SUCCESS || result < 0 || result == 1) { last_error = (status != SGX_SUCCESS) ? status : + (result < 0) ? -result : (saved_errno != 0) ? saved_errno : EACCES; return; } @@ -187,8 +188,9 @@ protected_fs_file::protected_fs_file(const char* filename, const char* mode, con read_only = (open_mode.read == 1 && open_mode.update == 0); // read only files can be opened simultaneously by many enclaves do { - status = u_sgxprotectedfs_exclusive_file_open(&file, filename, read_only, &real_file_size, &result32); - if (status != SGX_SUCCESS || file == NULL) + // here real_file_size=0 is used as a flag to indicate a new file is created, althrough the actural size of a new file is NODE_SIZE + status = u_sgxprotectedfs_exclusive_file_map(&file_addr, filename, read_only, &real_file_size, &result32); + if (status != SGX_SUCCESS || file_addr == NULL) { last_error = (status != SGX_SUCCESS) ? status : (result32 != 0) ? result32 : EACCES; @@ -207,6 +209,8 @@ protected_fs_file::protected_fs_file(const char* filename, const char* mode, con break; } + strncpy(file_name, filename, FULLNAME_MAX_LEN - 1); + file_name[FULLNAME_MAX_LEN - 1] = '\0'; strncpy(recovery_filename, filename, FULLNAME_MAX_LEN - 1); // copy full file name recovery_filename[FULLNAME_MAX_LEN - 1] = '\0'; // just to be safe size_t full_name_len = strnlen(recovery_filename, RECOVERY_FILE_MAX_LEN); @@ -227,7 +231,8 @@ protected_fs_file::protected_fs_file(const char* filename, const char* mode, con offset = encrypted_part_plain.size; } else - {// new file + {// new file, real_file_size==0 + real_file_size = NODE_SIZE; // now match with the actural file size if (init_new_file(clean_filename) == false) break; } @@ -238,10 +243,10 @@ protected_fs_file::protected_fs_file(const char* filename, const char* mode, con if (file_status != SGX_FILE_STATUS_OK) { - if (file != NULL) + if (file_addr != NULL) { - u_sgxprotectedfs_fclose(&result32, file); // we don't care about the result - file = NULL; + u_sgxprotectedfs_file_unmap(&result32, file_addr, real_file_size); // we don't care about the result + file_addr = NULL; } } } @@ -263,17 +268,19 @@ void protected_fs_file::init_fields(const uint32_t cache_page) root_mht.need_writing = false; offset = 0; - file = NULL; + file_addr = NULL; end_of_file = false; need_writing = false; read_only = 0; file_status = SGX_FILE_STATUS_NOT_INITIALIZED; last_error = SGX_SUCCESS; - real_file_size = 0; + real_file_size = -1; open_mode.raw = 0; use_user_kdk_key = 0; master_key_count = 0; + parallel_flush_level = 1; + file_name[0] = '\0'; recovery_filename[0] = '\0'; max_cache_page = cache_page; @@ -343,7 +350,7 @@ bool protected_fs_file::file_recovery(const char* filename) int32_t result32 = 0; int64_t new_file_size = 0; - status = u_sgxprotectedfs_fclose(&result32, file); + status = u_sgxprotectedfs_file_unmap(&result32, file_addr, real_file_size); if (status != SGX_SUCCESS || result32 != 0) { last_error = (status != SGX_SUCCESS) ? status : @@ -351,9 +358,9 @@ bool protected_fs_file::file_recovery(const char* filename) return false; } - file = NULL; + file_addr = NULL; - status = u_sgxprotectedfs_do_file_recovery(&result32, filename, recovery_filename, NODE_SIZE); + status = u_sgxprotectedfs_do_file_recovery(&result32, filename, recovery_filename); if (status != SGX_SUCCESS || result32 != 0) { last_error = (status != SGX_SUCCESS) ? status : @@ -361,8 +368,8 @@ bool protected_fs_file::file_recovery(const char* filename) return false; } - status = u_sgxprotectedfs_exclusive_file_open(&file, filename, read_only, &new_file_size, &result32); - if (status != SGX_SUCCESS || file == NULL) + status = u_sgxprotectedfs_exclusive_file_map(&file_addr, filename, read_only, &new_file_size, &result32); + if (status != SGX_SUCCESS || file_addr == NULL) { last_error = (status != SGX_SUCCESS) ? status : (result32 != 0) ? result32 : EACCES; @@ -376,13 +383,12 @@ bool protected_fs_file::file_recovery(const char* filename) return false; } - status = u_sgxprotectedfs_fread_node(&result32, file, 0, (uint8_t*)&file_meta_data, NODE_SIZE); - if (status != SGX_SUCCESS || result32 != 0) + if (real_file_size < NODE_SIZE) { - last_error = (status != SGX_SUCCESS) ? status : - (result32 != -1) ? result32 : EIO; + last_error = EIO; return false; } + memcpy(&file_meta_data, file_addr, NODE_SIZE); return true; } @@ -391,16 +397,13 @@ bool protected_fs_file::file_recovery(const char* filename) bool protected_fs_file::init_existing_file(const char* filename, const char* clean_filename, const sgx_aes_gcm_128bit_key_t* import_key) { sgx_status_t status; - int32_t result32; - // read meta-data node - status = u_sgxprotectedfs_fread_node(&result32, file, 0, (uint8_t*)&file_meta_data, NODE_SIZE); - if (status != SGX_SUCCESS || result32 != 0) + if (file_addr == NULL || real_file_size < NODE_SIZE) { - last_error = (status != SGX_SUCCESS) ? status : - (result32 != -1) ? result32 : EIO; + last_error = EIO; return false; } + memcpy(&file_meta_data, file_addr, NODE_SIZE); if (file_meta_data.plain_part.file_id != SGX_FILE_ID) {// such a file exists, but it is not an SGX file @@ -465,18 +468,15 @@ bool protected_fs_file::init_existing_file(const char* filename, const char* cle if (encrypted_part_plain.size > MD_USER_DATA_SIZE) { - // read the root node of the mht - status = u_sgxprotectedfs_fread_node(&result32, file, 1, root_mht.encrypted.cipher, NODE_SIZE); - if (status != SGX_SUCCESS || result32 != 0) + if (file_addr == NULL || (real_file_size < NODE_SIZE * 2)) { - last_error = (status != SGX_SUCCESS) ? status : - (result32 != -1) ? result32 : EIO; + last_error = EIO; return false; } // this also verifies the root mht gmac against the gmac in the meta-data encrypted part status = sgx_rijndael128GCM_decrypt(&encrypted_part_plain.mht_key, - root_mht.encrypted.cipher, NODE_SIZE, (uint8_t*)&root_mht.plain, + file_addr + NODE_SIZE, NODE_SIZE, (uint8_t*)&root_mht.plain, empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &encrypted_part_plain.mht_gmac); if (status != SGX_SUCCESS) { @@ -500,8 +500,12 @@ bool protected_fs_file::init_new_file(const char* clean_filename) file_meta_data.plain_part.use_user_kdk_key = use_user_kdk_key; strncpy(encrypted_part_plain.clean_filename, clean_filename, FILENAME_MAX_LEN); - - need_writing = true; + + if (_RECOVERY_HOOK_(4) || update_meta_data_node() != true) + { + file_status = SGX_FILE_STATUS_WRITE_TO_DISK_FAILED; + return false; + } return true; } @@ -563,15 +567,15 @@ bool protected_fs_file::pre_close(sgx_key_128bit_t* key, bool import) } else // file_status == SGX_FILE_STATUS_OK { - internal_flush(/*false,*/ true); + internal_flush(); } if (file_status != SGX_FILE_STATUS_OK) retval = false; - if (file != NULL) + if (file_addr != NULL) { - status = u_sgxprotectedfs_fclose(&result32, file); + status = u_sgxprotectedfs_file_unmap(&result32, file_addr, real_file_size); if (status != SGX_SUCCESS || result32 != 0) { last_error = (status != SGX_SUCCESS) ? status : @@ -579,7 +583,7 @@ bool protected_fs_file::pre_close(sgx_key_128bit_t* key, bool import) retval = false; } - file = NULL; + file_addr = NULL; } if (file_status == SGX_FILE_STATUS_OK && diff --git a/sdk/protected_fs/sgx_tprotected_fs/file_other.cpp b/sdk/protected_fs/sgx_tprotected_fs/file_other.cpp index e702a2d69..da1c9f141 100644 --- a/sdk/protected_fs/sgx_tprotected_fs/file_other.cpp +++ b/sdk/protected_fs/sgx_tprotected_fs/file_other.cpp @@ -173,6 +173,7 @@ void protected_fs_file::clear_error() if (file_status == SGX_FILE_STATUS_NOT_INITIALIZED || file_status == SGX_FILE_STATUS_CLOSED || + file_status == SGX_FILE_STATUS_WRITE_TO_DISK_FAILED || file_status == SGX_FILE_STATUS_CRYPTO_ERROR || file_status == SGX_FILE_STATUS_CORRUPTED || file_status == SGX_FILE_STATUS_MEMORY_CORRUPTED) // can't fix these... @@ -183,18 +184,9 @@ void protected_fs_file::clear_error() if (file_status == SGX_FILE_STATUS_FLUSH_ERROR) { - if (internal_flush(/*false,*/ true) == true) + if (internal_flush() == true) file_status = SGX_FILE_STATUS_OK; } - - if (file_status == SGX_FILE_STATUS_WRITE_TO_DISK_FAILED) - { - if (write_all_changes_to_disk(true) == true) - { - need_writing = false; - file_status = SGX_FILE_STATUS_OK; - } - } if (file_status == SGX_FILE_STATUS_OK) { @@ -219,7 +211,7 @@ int32_t protected_fs_file::clear_cache() } else // file_status == SGX_FILE_STATUS_OK { - internal_flush(/*false,*/ true); + internal_flush(); } if (file_status != SGX_FILE_STATUS_OK) // clearing the cache might lead to losing un-saved data diff --git a/sdk/protected_fs/sgx_tprotected_fs/file_read_write.cpp b/sdk/protected_fs/sgx_tprotected_fs/file_read_write.cpp index 78860d983..f58042ca4 100644 --- a/sdk/protected_fs/sgx_tprotected_fs/file_read_write.cpp +++ b/sdk/protected_fs/sgx_tprotected_fs/file_read_write.cpp @@ -400,7 +400,7 @@ file_data_node_t* protected_fs_file::get_data_node() } else { - if (internal_flush(/*false,*/ false) == false) // error, can't flush cache, file status changed to error + if (internal_flush() == false) // error, can't flush cache, file status changed to error { assert(file_status != SGX_FILE_STATUS_OK); if (file_status == SGX_FILE_STATUS_OK) @@ -453,7 +453,6 @@ file_data_node_t* protected_fs_file::read_data_node() uint64_t data_node_number; uint64_t physical_node_number; file_mht_node_t* file_mht_node; - int32_t result32; sgx_status_t status; get_node_numbers(offset, NULL, &data_node_number, NULL, &physical_node_number); @@ -482,19 +481,18 @@ file_data_node_t* protected_fs_file::read_data_node() file_data_node->physical_node_number = physical_node_number; file_data_node->parent = file_mht_node; - status = u_sgxprotectedfs_fread_node(&result32, file, file_data_node->physical_node_number, file_data_node->encrypted.cipher, NODE_SIZE); - if (status != SGX_SUCCESS || result32 != 0) + if (file_addr == NULL || real_file_size < 0 || ((uint64_t)real_file_size < NODE_SIZE * (file_data_node->physical_node_number + 1))) { delete file_data_node; - last_error = (status != SGX_SUCCESS) ? status : - (result32 != -1) ? result32 : EIO; + last_error = EIO; return NULL; } + uint8_t* file_data_node_addr = file_addr + NODE_SIZE * file_data_node->physical_node_number; gcm_crypto_data_t* gcm_crypto_data = &file_data_node->parent->plain.data_nodes_crypto[file_data_node->data_node_number % ATTACHED_DATA_NODES_COUNT]; // this function decrypt the data _and_ checks the integrity of the data against the gmac - status = sgx_rijndael128GCM_decrypt(&gcm_crypto_data->key, file_data_node->encrypted.cipher, NODE_SIZE, file_data_node->plain.data, empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac); + status = sgx_rijndael128GCM_decrypt(&gcm_crypto_data->key, file_data_node_addr, NODE_SIZE, file_data_node->plain.data, empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac); if (status != SGX_SUCCESS) { delete file_data_node; @@ -589,7 +587,6 @@ file_mht_node_t* protected_fs_file::append_mht_node(uint64_t mht_node_number) file_mht_node_t* protected_fs_file::read_mht_node(uint64_t mht_node_number) { - int32_t result32; sgx_status_t status; if (mht_node_number == 0) @@ -619,20 +616,19 @@ file_mht_node_t* protected_fs_file::read_mht_node(uint64_t mht_node_number) file_mht_node->mht_node_number = mht_node_number; file_mht_node->physical_node_number = physical_node_number; file_mht_node->parent = parent_file_mht_node; - - status = u_sgxprotectedfs_fread_node(&result32, file, file_mht_node->physical_node_number, file_mht_node->encrypted.cipher, NODE_SIZE); - if (status != SGX_SUCCESS || result32 != 0) + + if (file_addr == NULL || real_file_size < 0 || ((uint64_t)real_file_size < NODE_SIZE * (file_mht_node->physical_node_number + 1))) { delete file_mht_node; - last_error = (status != SGX_SUCCESS) ? status : - (result32 != -1) ? result32 : EIO; + last_error = EIO; return NULL; } + uint8_t* file_mht_node_addr = file_addr + NODE_SIZE * file_mht_node->physical_node_number; gcm_crypto_data_t* gcm_crypto_data = &file_mht_node->parent->plain.mht_nodes_crypto[(file_mht_node->mht_node_number - 1) % CHILD_MHT_NODES_COUNT]; // this function decrypt the data _and_ checks the integrity of the data against the gmac - status = sgx_rijndael128GCM_decrypt(&gcm_crypto_data->key, file_mht_node->encrypted.cipher, NODE_SIZE, (uint8_t*)&file_mht_node->plain, empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac); + status = sgx_rijndael128GCM_decrypt(&gcm_crypto_data->key, file_mht_node_addr, NODE_SIZE, (uint8_t*)&file_mht_node->plain, empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac); if (status != SGX_SUCCESS) { delete file_mht_node; diff --git a/sdk/protected_fs/sgx_tprotected_fs/lru_cache.cpp b/sdk/protected_fs/sgx_tprotected_fs/lru_cache.cpp index 60626ec94..07bda300c 100644 --- a/sdk/protected_fs/sgx_tprotected_fs/lru_cache.cpp +++ b/sdk/protected_fs/sgx_tprotected_fs/lru_cache.cpp @@ -185,6 +185,9 @@ void* lru_cache::get_next() if (list.size() == 0) return NULL; + if (m_it == list.end()) + return NULL; + ++m_it; if (m_it == list.end()) diff --git a/sdk/protected_fs/sgx_tprotected_fs/protected_fs_file.h b/sdk/protected_fs/sgx_tprotected_fs/protected_fs_file.h index eebf481da..c46059fee 100644 --- a/sdk/protected_fs/sgx_tprotected_fs/protected_fs_file.h +++ b/sdk/protected_fs/sgx_tprotected_fs/protected_fs_file.h @@ -39,7 +39,7 @@ #include "sgx_error.h" #include "sgx_tcrypto.h" #include "errno.h" - +#include #include #include "sgx_tprotected_fs.h" @@ -80,6 +80,22 @@ typedef union } open_mode_t; +typedef struct _thread_queue +{ + sgx_aes_gcm_128bit_key_t key; + void* node; +} thread_queue_t; + + +typedef struct _thread_input +{ + uint32_t error; + uint8_t* addr; + uint8_t* empty_iv; + std::queue* queue; +} thread_input_t; + + #define FILE_MHT_NODE_TYPE 1 #define FILE_DATA_NODE_TYPE 2 @@ -102,13 +118,7 @@ typedef struct _file_mht_node struct _file_mht_node* parent; bool need_writing; bool new_node; - union { - struct { - uint64_t physical_node_number; - encrypted_node_t encrypted; // the actual data from the disk - }; - recovery_node_t recovery_node; - }; + uint64_t physical_node_number; /* from here the structures are different */ mht_node_t plain; // decrypted data } file_mht_node_t; @@ -122,13 +132,7 @@ typedef struct _file_data_node file_mht_node_t* parent; bool need_writing; bool new_node; - union { - struct { - uint64_t physical_node_number; - encrypted_node_t encrypted; // the actual data from the disk - }; - recovery_node_t recovery_node; - }; + uint64_t physical_node_number; /* from here the structures are different */ data_node_t plain; // decrypted data } file_data_node_t; @@ -137,19 +141,16 @@ typedef struct _file_data_node class protected_fs_file { private: - union { - struct { - uint64_t meta_data_node_number; // for recovery purpose, so it is easy to write this node - meta_data_node_t file_meta_data; // actual data from disk's meta data node - }; - recovery_node_t meta_data_recovery_node; + struct { + uint64_t meta_data_node_number; // for recovery purpose, so it is easy to write this node + meta_data_node_t file_meta_data; // actual data from disk's meta data node }; meta_data_encrypted_t encrypted_part_plain; // encrypted part of meta data node, decrypted file_mht_node_t root_mht; // the root of the mht is always needed (for files bigger than 3KB) - FILE* file; // OS's FILE pointer + uint8_t* file_addr; // start address of the memory mapped from file open_mode_t open_mode; uint8_t read_only; @@ -165,6 +166,8 @@ class protected_fs_file sgx_thread_mutex_t mutex; + uint32_t parallel_flush_level; + uint8_t use_user_kdk_key; sgx_aes_gcm_128bit_key_t user_kdk_key; // recieved from user, used instead of the seal key @@ -172,6 +175,7 @@ class protected_fs_file sgx_aes_gcm_128bit_key_t session_master_key; uint32_t master_key_count; + char file_name[FULLNAME_MAX_LEN]; // used for u_sgxprotectedfs_file_remap char recovery_filename[RECOVERY_FILE_MAX_LEN]; // might include full path to the file lru_cache cache; @@ -202,13 +206,13 @@ class protected_fs_file file_mht_node_t* read_mht_node(uint64_t mht_node_number); file_mht_node_t* append_mht_node(uint64_t mht_node_number); bool write_recovery_file(); - bool set_update_flag(bool flush_to_disk); - void clear_update_flag(); + bool set_update_flag(); + bool multi_thread_update_data_nodes(); + bool single_thread_update_data_nodes(); bool update_all_data_and_mht_nodes(); bool update_meta_data_node(); - bool write_all_changes_to_disk(bool flush_to_disk); void erase_recovery_file(); - bool internal_flush(bool flush_to_disk); + bool internal_flush(); public: protected_fs_file(const char* filename, const char* mode, const sgx_aes_gcm_128bit_key_t* import_key, const sgx_aes_gcm_128bit_key_t* kdk_key, const uint32_t cache_page); @@ -218,6 +222,7 @@ class protected_fs_file size_t read(void* ptr, size_t size, size_t count); int64_t tell(); int seek(int64_t new_offset, int origin); + int32_t set_parallel_flush_level(uint32_t max_threads_number); bool get_eof(); uint32_t get_error(); void clear_error(); diff --git a/sdk/protected_fs/sgx_tprotected_fs/protected_fs_nodes.h b/sdk/protected_fs/sgx_tprotected_fs/protected_fs_nodes.h index ccd97e725..4852c2db8 100644 --- a/sdk/protected_fs/sgx_tprotected_fs/protected_fs_nodes.h +++ b/sdk/protected_fs/sgx_tprotected_fs/protected_fs_nodes.h @@ -130,19 +130,6 @@ typedef struct _data_node COMPILE_TIME_ASSERT(sizeof_data_node_t, sizeof(data_node_t) == 4096); -typedef struct _encrypted_node -{ - uint8_t cipher[NODE_SIZE]; -} encrypted_node_t; - -COMPILE_TIME_ASSERT(sizeof_encrypted_node_t, sizeof(encrypted_node_t) == 4096); - -typedef struct _recovery_node -{ - uint64_t physical_node_number; - uint8_t node_data[NODE_SIZE]; -} recovery_node_t; - #pragma pack(pop) #endif // _PROTECTED_FS_NODES_H_ diff --git a/sdk/protected_fs/sgx_tprotected_fs/sgx_tprotected_fs.cpp b/sdk/protected_fs/sgx_tprotected_fs/sgx_tprotected_fs.cpp index bcb93a3a7..3df190469 100644 --- a/sdk/protected_fs/sgx_tprotected_fs/sgx_tprotected_fs.cpp +++ b/sdk/protected_fs/sgx_tprotected_fs/sgx_tprotected_fs.cpp @@ -134,6 +134,17 @@ int32_t sgx_fseek(SGX_FILE* stream, int64_t offset, int origin) } +int32_t sgx_fset_parallel_level(SGX_FILE* stream, uint32_t max_threads_number) +{ + if (stream == NULL) + return -1; + + protected_fs_file* file = (protected_fs_file*)stream; + + return file->set_parallel_flush_level(max_threads_number); +} + + int32_t sgx_fflush(SGX_FILE* stream) { if (stream == NULL) diff --git a/sdk/protected_fs/sgx_uprotected_fs/sgx_uprotected_fs.cpp b/sdk/protected_fs/sgx_uprotected_fs/sgx_uprotected_fs.cpp index d38cb46a7..6653eab00 100644 --- a/sdk/protected_fs/sgx_uprotected_fs/sgx_uprotected_fs.cpp +++ b/sdk/protected_fs/sgx_uprotected_fs/sgx_uprotected_fs.cpp @@ -36,11 +36,13 @@ #include #include +#include #include #include #include #include "sgx_tprotected_fs_u.h" +#include "../sgx_tprotected_fs/protected_fs_nodes.h" #include @@ -51,14 +53,31 @@ #endif -void* u_sgxprotectedfs_exclusive_file_open(const char* filename, uint8_t read_only, int64_t* file_size, int32_t* error_code) +int8_t u_sgxprotectedfs_check_if_file_exists(const char* filename) { - FILE* f = NULL; + struct stat stat_st; + + memset(&stat_st, 0, sizeof(struct stat)); + + if (filename == NULL || strnlen(filename, 1) == 0) + { + DEBUG_PRINT("filename is NULL or empty\n"); + return -EINVAL; + } + + return (stat(filename, &stat_st) == 0); +} + + +uint8_t* u_sgxprotectedfs_exclusive_file_map(const char* filename, uint8_t read_only, int64_t* file_size, int32_t* error_code) +{ + void* f_addr = NULL; + int64_t f_size = 0; int result = 0; int fd = -1; mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; struct stat stat_st; - + memset(&stat_st, 0, sizeof(struct stat)); if (filename == NULL || strnlen(filename, 1) == 0) @@ -72,7 +91,7 @@ void* u_sgxprotectedfs_exclusive_file_open(const char* filename, uint8_t read_on fd = open(filename, O_CREAT | (read_only ? O_RDONLY : O_RDWR) | O_LARGEFILE, mode); // create the file if it doesn't exists, read-only/read-write if (fd == -1) { - DEBUG_PRINT("open returned %d, errno %d\n", result, errno); + DEBUG_PRINT("open returned -1, errno %d\n", errno); *error_code = errno; return NULL; } @@ -99,192 +118,116 @@ void* u_sgxprotectedfs_exclusive_file_open(const char* filename, uint8_t read_on assert(result == 0); return NULL; } - - // convert the file handle to standard 'C' API file pointer - f = fdopen(fd, read_only ? "rb" : "r+b"); - if (f == NULL) + + f_size = stat_st.st_size; + if (f_size == 0) // in case of new file, append size of node_size { - DEBUG_PRINT("fdopen returned NULL\n"); - *error_code = errno; + result = ftruncate(fd, NODE_SIZE); + if (result != 0) + { + DEBUG_PRINT("ftruncate returned %d, errno %d\n", result, errno); + *error_code = errno; + flock(fd, LOCK_UN); + result = close(fd); + assert(result == 0); + return NULL; + } + + f_size = NODE_SIZE; + } + + f_addr = mmap(NULL, f_size, PROT_READ | (read_only ? 0 : PROT_WRITE), MAP_SHARED, fd, 0); + if (f_addr == MAP_FAILED) + { + DEBUG_PRINT("mmap returned MAP_FAILED, errno %d\n", errno); flock(fd, LOCK_UN); result = close(fd); assert(result == 0); return NULL; } + result = close(fd); + if (result != 0) + { + DEBUG_PRINT("close returned %d, errno: %d\n", result, errno); + munmap(f_addr, f_size); + flock(fd, LOCK_UN); + return NULL; + } + if (file_size != NULL) - *file_size = stat_st.st_size; + *file_size = stat_st.st_size; // file_size=0 to indicate new file, althrough actural size is NODE_SIZE - return f; + return (uint8_t*)f_addr; } -uint8_t u_sgxprotectedfs_check_if_file_exists(const char* filename) +int32_t u_sgxprotectedfs_file_remap(const char* filename, uint8_t** file_addr, int64_t old_size, int64_t new_size) { - struct stat stat_st; - - memset(&stat_st, 0, sizeof(struct stat)); + void* f_new_addr = NULL; + int result = 0; if (filename == NULL || strnlen(filename, 1) == 0) { DEBUG_PRINT("filename is NULL or empty\n"); - return 1; - } - - return (stat(filename, &stat_st) == 0); -} - - -int32_t u_sgxprotectedfs_fread_node(void* f, uint64_t node_number, uint8_t* buffer, uint32_t node_size) -{ - FILE* file = (FILE*)f; - uint64_t offset = node_number * node_size; - int result = 0; - size_t size = 0; - - if (file == NULL) - { - DEBUG_PRINT("file is NULL\n"); return -1; } - if ((result = fseeko(file, offset, SEEK_SET)) != 0) - { - DEBUG_PRINT("fseeko returned %d\n", result); - if (errno != 0) - { - int err = errno; - return err; - } - else - return -1; - } - - if ((size = fread(buffer, node_size, 1, file)) != 1) + if (file_addr == NULL || *file_addr == NULL) { - int err = ferror(file); - if (err != 0) - { - DEBUG_PRINT("fread returned %ld [!= 1], ferror: %d\n", size, err); - return err; - } - else if (errno != 0) - { - err = errno; - DEBUG_PRINT("fread returned %ld [!= 1], errno: %d\n", size, err); - return err; - } - else - { - DEBUG_PRINT("fread returned %ld [!= 1], no error code\n", size); - return -1; - } + DEBUG_PRINT("file address is NULL\n"); + return -1; } - return 0; -} - - -int32_t u_sgxprotectedfs_fwrite_node(void* f, uint64_t node_number, uint8_t* buffer, uint32_t node_size) -{ - FILE* file = (FILE*)f; - uint64_t offset = node_number * node_size; - int result = 0; - size_t size = 0; - - if (file == NULL) + if (new_size == old_size) { - DEBUG_PRINT("file is NULL\n"); + DEBUG_PRINT("file size not changed\n"); return -1; } - if ((result = fseeko(file, offset, SEEK_SET)) != 0) + result = truncate(filename, new_size); + if (result != 0) { - DEBUG_PRINT("fseeko returned %d\n", result); - if (errno != 0) - { - int err = errno; - return err; - } - else - return -1; + int err = errno; + DEBUG_PRINT("truncate returned %d, errno %d\n", result, err); + return err ? err : -1; } - if ((size = fwrite(buffer, node_size, 1, file)) != 1) + f_new_addr = mremap(*file_addr, old_size, new_size, MREMAP_MAYMOVE); + if (f_new_addr == MAP_FAILED) { - DEBUG_PRINT("fwrite returned %ld [!= 1]\n", size); - int err = ferror(file); - if (err != 0) - return err; - else if (errno != 0) - { - err = errno; - return err; - } - else - return -1; + int err = errno; + DEBUG_PRINT("mremap returned MAP_FAILED, errno %d\n", err); + return err ? err : -1; } + *file_addr = (uint8_t*)f_new_addr; + return 0; } -int32_t u_sgxprotectedfs_fclose(void* f) +int32_t u_sgxprotectedfs_file_unmap(uint8_t* file_addr, int64_t file_size) { - FILE* file = (FILE*)f; int result = 0; - int fd = 0; - if (file == NULL) + if (file_addr == NULL) { - DEBUG_PRINT("file is NULL\n"); + DEBUG_PRINT("file address is NULL\n"); return -1; } - // closing the file handle should also remove the lock, but we try to remove it explicitly - fd = fileno(file); - if (fd == -1) - DEBUG_PRINT("fileno returned -1\n"); - else - flock(fd, LOCK_UN); - - if ((result = fclose(file)) != 0) + if ((result = munmap(file_addr, file_size)) != 0) { - if (errno != 0) - { - int err = errno; - DEBUG_PRINT("fclose returned %d, errno: %d\n", result, err); - return err; - } - DEBUG_PRINT("fclose returned %d\n", result); - return -1; + int err = errno; + DEBUG_PRINT("munmap returned %d, errno: %d\n", result, err); + return err ? err : -1; } return 0; } -uint8_t u_sgxprotectedfs_fflush(void* f) -{ - FILE* file = (FILE*)f; - int result; - - if (file == NULL) - { - DEBUG_PRINT("file is NULL\n"); - return 1; - } - - if ((result = fflush(file)) != 0) - { - DEBUG_PRINT("fflush returned %d\n", result); - return 1; - } - - return 0; -} - - int32_t u_sgxprotectedfs_remove(const char* filename) { int result; @@ -308,16 +251,18 @@ int32_t u_sgxprotectedfs_remove(const char* filename) #define MILISECONDS_SLEEP_FOPEN 10 #define MAX_FOPEN_RETRIES 10 -void* u_sgxprotectedfs_recovery_file_open(const char* filename) +uint8_t u_sgxprotectedfs_fwrite_recovery_file(uint8_t* fileaddress, const char* filename, uint64_t* recovery_list, uint64_t length) { FILE* f = NULL; + size_t count = 0; + int result = 0; if (filename == NULL || strnlen(filename, 1) == 0) { DEBUG_PRINT("recovery filename is NULL or empty\n"); - return NULL; + return 1; } - + for (int i = 0; i < MAX_FOPEN_RETRIES; i++) { f = fopen(filename, "wb"); @@ -325,31 +270,40 @@ void* u_sgxprotectedfs_recovery_file_open(const char* filename) break; usleep(MILISECONDS_SLEEP_FOPEN); } + if (f == NULL) { DEBUG_PRINT("fopen (%s) returned NULL\n", filename); - return NULL; + return 1; } - - return f; -} - - -uint8_t u_sgxprotectedfs_fwrite_recovery_node(void* f, uint8_t* data, uint32_t data_length) -{ - FILE* file = (FILE*)f; - if (file == NULL) + for (uint64_t i = 0; i < length; i++) { - DEBUG_PRINT("file is NULL\n"); - return 1; + // write physical_node_number of recovery_node + if ((count = fwrite(recovery_list + i, 1, sizeof(uint64_t), f)) != sizeof(uint64_t)) + { + DEBUG_PRINT("fwrite returned %ld instead of %ld\n", count, sizeof(uint64_t)); + result = fclose(f); + assert(result == 0); + result = remove(filename); + assert(result == 0); + return 1; + } + // write node_data of the recovery_node + if ((count = fwrite(fileaddress + recovery_list[i] * NODE_SIZE, 1, NODE_SIZE, f)) != NODE_SIZE) + { + DEBUG_PRINT("fwrite returned %ld instead of %d\n", count, NODE_SIZE); + result = fclose(f); + assert(result == 0); + result = remove(filename); + assert(result == 0); + return 1; + } } - - // recovery nodes are written sequentially - size_t count = fwrite(data, 1, data_length, file); - if (count != data_length) + + if ((result = fclose(f)) != 0) { - DEBUG_PRINT("fwrite returned %ld instead of %d\n", count, data_length); + DEBUG_PRINT("fclose returned %d\n", result); return 1; } @@ -357,13 +311,13 @@ uint8_t u_sgxprotectedfs_fwrite_recovery_node(void* f, uint8_t* data, uint32_t d } -int32_t u_sgxprotectedfs_do_file_recovery(const char* filename, const char* recovery_filename, uint32_t node_size) +int32_t u_sgxprotectedfs_do_file_recovery(const char* filename, const char* recovery_filename) { FILE* recovery_file = NULL; FILE* source_file = NULL; int32_t ret = -1; uint32_t nodes_count = 0; - uint32_t recovery_node_size = (uint32_t)(sizeof(uint64_t)) + node_size; // node offset + data + uint32_t recovery_node_size = (uint32_t)(sizeof(uint64_t)) + NODE_SIZE; // node offset + data uint64_t file_size = 0; int err = 0; int result = 0; @@ -451,7 +405,7 @@ int32_t u_sgxprotectedfs_do_file_recovery(const char* filename, const char* reco } // seek the regular file to the required offset - if ((result = fseeko(source_file, (*((uint64_t*)recovery_node)) * node_size, SEEK_SET)) != 0) + if ((result = fseeko(source_file, (*((uint64_t*)recovery_node)) * NODE_SIZE, SEEK_SET)) != 0) { DEBUG_PRINT("fseeko returned %d\n", result); if (errno != 0) @@ -460,7 +414,7 @@ int32_t u_sgxprotectedfs_do_file_recovery(const char* filename, const char* reco } // write down the original data from the recovery file - if ((count = fwrite(&recovery_node[sizeof(uint64_t)], node_size, 1, source_file)) != 1) + if ((count = fwrite(&recovery_node[sizeof(uint64_t)], NODE_SIZE, 1, source_file)) != 1) { DEBUG_PRINT("fwrite returned %ld [!= 1]\n", count); err = ferror(source_file); @@ -502,7 +456,10 @@ int32_t u_sgxprotectedfs_do_file_recovery(const char* filename, const char* reco } if (ret == 0) - remove(recovery_filename); + { + result = remove(recovery_filename); + assert(result == 0); + } return ret; } diff --git a/sdk/sign_tool/SignTool/Makefile b/sdk/sign_tool/SignTool/Makefile index f9ce24796..88f4d919f 100644 --- a/sdk/sign_tool/SignTool/Makefile +++ b/sdk/sign_tool/SignTool/Makefile @@ -31,13 +31,20 @@ include ../../../buildenv.mk -CXXFLAGS += -Werror -CFLAGS += -Werror - -CFLAGS += -fpie -DOPENSSL_API_COMPAT=10101 -CXXFLAGS += -fpie -DOPENSSL_API_COMPAT=10101 +FLAGS = -fpie -Werror + +ifdef DEBUG +FLAGS += -DSE_DEBUG_LEVEL=SE_TRACE_DEBUG +else +FLAGS += -DSE_DEBUG_LEVEL=SE_TRACE_ERROR +endif +CFLAGS += $(FLAGS) +CXXFLAGS += $(FLAGS) LDFLAGS := -pie $(COMMON_LDFLAGS) -Wno-odr +PREBUILT_OPENSSL_DIR := $(LINUX_EXTERNAL_DIR)/dcap_source/prebuilt/openssl +CRYPTO_LIB := -L$(PREBUILT_OPENSSL_DIR)/lib/linux64 -lcrypto + INC += $(ADDED_INC) INC += -I$(COMMON_DIR)/inc \ -I$(COMMON_DIR)/inc/internal \ @@ -46,7 +53,8 @@ INC += -I$(COMMON_DIR)/inc \ -I$(LINUX_PSW_DIR)/urts \ -I$(LINUX_PSW_DIR)/urts/linux \ -I$(LINUX_EXTERNAL_DIR)/tinyxml2 \ - -I$(LINUX_PSW_DIR)/urts/parser + -I$(LINUX_PSW_DIR)/urts/parser \ + -I$(PREBUILT_OPENSSL_DIR)/inc DIR1 := $(LINUX_EXTERNAL_DIR)/tinyxml2/ DIR2 := $(COMMON_DIR)/src/ @@ -81,7 +89,7 @@ all: sgx_sign | $(BUILD_DIR) $(BUILD_DIR): @$(MKDIR) $@ -sgx_sign: PRIVATE_LDLIBS := -lpthread -lenclaveparser -lcrypto +sgx_sign: PRIVATE_LDLIBS := -lpthread -lenclaveparser $(CRYPTO_LIB) sgx_sign: PRIVATE_LDFLAGS := -L$(LINUX_PSW_DIR)/urts/parser $(LDFLAGS) sgx_sign: $(OBJS) enclaveparser diff --git a/sdk/sign_tool/SignTool/manage_metadata.cpp b/sdk/sign_tool/SignTool/manage_metadata.cpp index 56ce09daa..6b5a37549 100644 --- a/sdk/sign_tool/SignTool/manage_metadata.cpp +++ b/sdk/sign_tool/SignTool/manage_metadata.cpp @@ -186,8 +186,8 @@ bool parse_metadata_file(const char *xmlpath, xml_parameter_t *parameter, int pa } CMetadata::CMetadata(metadata_t *metadata, BinParser *parser) - : m_metadata(metadata) - , m_parser(parser), m_rva(0), m_gd_size(0), m_gd_template(NULL) + : m_meta_verions(0), m_metadata(metadata), m_parser(parser) + , m_rva(0), m_gd_size(0), m_gd_template(NULL) { memset(m_metadata, 0, sizeof(metadata_t)); memset(&m_create_param, 0, sizeof(m_create_param)); @@ -408,10 +408,12 @@ bool CMetadata::modify_metadata(const xml_parameter_t *parameter) m_metadata->tcs_policy = (uint32_t)parameter[TCSPOLICY].value; m_metadata->magic_num = METADATA_MAGIC; - m_metadata->desired_misc_select = 0; + m_metadata->desired_misc_select = (uint32_t)parameter[MISCSELECT].value; m_metadata->tcs_min_pool = (uint32_t)parameter[TCSMINPOOL].value; - m_metadata->enclave_css.body.misc_select = (uint32_t)parameter[MISCSELECT].value; - m_metadata->enclave_css.body.misc_mask = (uint32_t)parameter[MISCMASK].value; + m_metadata->enclave_css.body.misc_select = (uint32_t)parameter[MISCSELECT].value & + (uint32_t)parameter[MISCMASK].value; + m_metadata->enclave_css.body.misc_mask = (uint32_t)parameter[MISCMASK].value; + //store the elrange config for further check m_elrange_config_entry.enclave_image_address = parameter[ENCLAVEIMAGEADDRESS].value; @@ -1606,10 +1608,16 @@ sgx_misc_select_t CMetadata::get_config_misc_mask() return m_metadata->enclave_css.body.misc_mask; } +sgx_misc_select_t CMetadata::get_config_desired_misc_select() +{ + return m_metadata->desired_misc_select; +} + bool CMetadata::check_config() { uint32_t misc_select_0 = (uint32_t)get_config_misc_select() & 1u; uint32_t misc_mask_0 = (uint32_t)get_config_misc_mask() & 1u; + uint32_t desired_misc_select_0 = (uint32_t)get_config_desired_misc_select() & 1u; bool has_rts_dynamic = rts_dynamic(); bool has_user_dynamic = user_dynamic(); @@ -1634,7 +1642,7 @@ bool CMetadata::check_config() if (has_rts_dynamic) { - if (misc_select_0 == 0) + if (desired_misc_select_0 == 0) { // SGX1 metadata only m_meta_verions = 1u; @@ -1646,13 +1654,14 @@ bool CMetadata::check_config() { // SGX2 metadata only m_meta_verions = 1u << 1; + se_trace(SE_TRACE_ERROR, "\033[0;32mINFO: SGX2 only enclave, can only run on SGX2 platform.\n\033[0m"); } else { // SGX1 and SGX2 metadata m_meta_verions = (1u << 1) | 1u; + se_trace(SE_TRACE_ERROR, "\033[0;32mINFO: Enclave can run on both SGX1 and SGX2 platforms. Only on SGX2 platform can it take advantage of dynamic features.\n\033[0m"); } - se_trace(SE_TRACE_ERROR, "\033[0;32mINFO: Enclave configuration 'MiscSelect' and 'MiscSelectMask' will prevent enclave from running on SGX1 platform. To make it run on SGX1 platform, suggest to set MiscSelect[0]=0.\n\033[0m"); return true; } diff --git a/sdk/sign_tool/SignTool/manage_metadata.h b/sdk/sign_tool/SignTool/manage_metadata.h index 84f5a076b..5e66e0646 100644 --- a/sdk/sign_tool/SignTool/manage_metadata.h +++ b/sdk/sign_tool/SignTool/manage_metadata.h @@ -113,6 +113,7 @@ class CMetadata: private Uncopyable bool user_dynamic(); sgx_misc_select_t get_config_misc_select(); sgx_misc_select_t get_config_misc_mask(); + sgx_misc_select_t get_config_desired_misc_select(); uint8_t get_meta_versions() { return m_meta_verions; } private: bool get_time(uint32_t *date); diff --git a/sdk/sign_tool/SignTool/parse_key_file.cpp b/sdk/sign_tool/SignTool/parse_key_file.cpp index 15e350732..2d0704d26 100644 --- a/sdk/sign_tool/SignTool/parse_key_file.cpp +++ b/sdk/sign_tool/SignTool/parse_key_file.cpp @@ -40,57 +40,81 @@ #include "parse_key_file.h" #include "se_trace.h" #include "util_st.h" +#include "util.h" #include #include #include #include #include +#include +#include - -#if OPENSSL_VERSION_NUMBER < 0x10100000L -void RSA_get0_key(const RSA *rsa, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) +bool rsa_get_bn(EVP_PKEY *pkey, BIGNUM **n, BIGNUM **e, BIGNUM **d) { - assert(rsa != NULL); - - if(n != NULL) - *n = rsa->n; - if(e != NULL) - *e = rsa->e; - if(d != NULL) - *d = rsa->d; + if (n) + { + if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, n) == 0) + { + return false; + } + } + if (e) + { + if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, e) == 0) + { + return false; + } + } + if (d) + { + if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_D, d) == 0) + { + return false; + } + } + return true; } -#endif +void rsa_free_bn(BIGNUM *n, BIGNUM *e, BIGNUM *d) +{ + if(n) + BN_free(n); + if(e) + BN_free(e); + if(d) + BN_free(d); +} //parse_key_file(): // parse the RSA key file //Return Value: // true: success // false: fail -bool parse_key_file(int mode, const char *key_path, RSA **prsa, int *pkey_type) +bool parse_key_file(int mode, const char *key_path, EVP_PKEY **pkey, int *pkey_type) { - assert(prsa != NULL && pkey_type != NULL); + assert(pkey != NULL && pkey_type != NULL); if(key_path == NULL) { *pkey_type = NO_KEY; return false; } - FILE *fp = fopen(key_path, "rb"); - if(fp == NULL) + BIO* rsa_bio = BIO_new_file(key_path, "r"); + if(rsa_bio == NULL) { se_trace(SE_TRACE_ERROR, OPEN_FILE_ERROR, key_path); - return false; + return false; } + + EVP_PKEY *key = NULL; int key_type = UNIDENTIFIABLE_KEY; - RSA *rsa = NULL; if(mode == SIGN) { - rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); - fclose(fp); - if(!rsa) + key = PEM_read_bio_PrivateKey(rsa_bio, NULL, NULL, NULL); + BIO_free(rsa_bio); + if(!key) { se_trace(SE_TRACE_ERROR, KEY_FORMAT_ERROR); return false; @@ -99,9 +123,9 @@ bool parse_key_file(int mode, const char *key_path, RSA **prsa, int *pkey_type) } else if(mode == CATSIG) { - rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL); - fclose(fp); - if(!rsa) + key = PEM_read_bio_PUBKEY(rsa_bio, NULL, NULL, NULL); + BIO_free(rsa_bio); + if(!key) { se_trace(SE_TRACE_ERROR, KEY_FORMAT_ERROR); return false; @@ -111,17 +135,22 @@ bool parse_key_file(int mode, const char *key_path, RSA **prsa, int *pkey_type) else { se_trace(SE_TRACE_ERROR, "ERROR: Invalid command\n %s", USAGE_STRING); - fclose(fp); + BIO_free(rsa_bio); return false; } // Check the key size and exponent - const BIGNUM *n = NULL, *e = NULL; - RSA_get0_key(rsa, &n, &e, NULL); + BIGNUM *n = NULL, *e = NULL; + if(rsa_get_bn(key, &n, &e, NULL) == false) + { + EVP_PKEY_free(key); + return false; + } if(BN_num_bytes(n) != N_SIZE_IN_BYTES) { se_trace(SE_TRACE_ERROR, INVALID_KEYSIZE_ERROR); - RSA_free(rsa); + EVP_PKEY_free(key); + rsa_free_bn(n, e, NULL); return false; } char *p = BN_bn2dec(e); @@ -129,12 +158,13 @@ bool parse_key_file(int mode, const char *key_path, RSA **prsa, int *pkey_type) { se_trace(SE_TRACE_ERROR, INVALID_EXPONENT_ERROR); OPENSSL_free(p); - RSA_free(rsa); + EVP_PKEY_free(key); + rsa_free_bn(n, e, NULL); return false; } - + rsa_free_bn(n, e, NULL); OPENSSL_free(p); - *prsa = rsa; + *pkey = key; *pkey_type = key_type; return true; } diff --git a/sdk/sign_tool/SignTool/parse_key_file.h b/sdk/sign_tool/SignTool/parse_key_file.h index 5522d04e6..9ce4ca0d6 100644 --- a/sdk/sign_tool/SignTool/parse_key_file.h +++ b/sdk/sign_tool/SignTool/parse_key_file.h @@ -48,10 +48,9 @@ typedef enum _key_type_t PUBLIC_KEY } key_type_t; -#if OPENSSL_VERSION_NUMBER < 0x10100000L -void RSA_get0_key(const RSA *rsa, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d); -#endif +bool rsa_get_bn(EVP_PKEY *pkey, BIGNUM **n, BIGNUM **e, BIGNUM **d); +void rsa_free_bn(BIGNUM *n, BIGNUM *e, BIGNUM *d); -bool parse_key_file(int mode, const char *key_path, RSA **prsa, int *pkey_type); +bool parse_key_file(int mode, const char *key_path, EVP_PKEY **pkey, int *pkey_type); #endif diff --git a/sdk/sign_tool/SignTool/sign_tool.cpp b/sdk/sign_tool/SignTool/sign_tool.cpp index 7bf0ee057..c20c2a3e0 100644 --- a/sdk/sign_tool/SignTool/sign_tool.cpp +++ b/sdk/sign_tool/SignTool/sign_tool.cpp @@ -110,11 +110,7 @@ static int load_enclave(BinParser *parser, metadata_t *metadata) static int open_file(const char* dllpath) { - FILE *fp = fopen(dllpath, "rb"); - if (fp == NULL) - return THE_INVALID_HANDLE; - - return fileno(fp); + return open(dllpath, O_RDONLY); } static void close_handle(int fd) @@ -259,24 +255,28 @@ static bool measure_enclave(uint8_t *hash, const char *dllpath, const xml_parame // fill the enclave_css_t structure with enclave_hash // If the 'rsa' is not null, fill the key part // If the path[UNSIGNED] != NULL, update the header.date(CATSIG mode) -static bool fill_enclave_css(const RSA *rsa, const char **path, +static bool fill_enclave_css(const EVP_PKEY *pkey, const char **path, const uint8_t *enclave_hash, enclave_css_t *css) { assert(enclave_hash != NULL && path != NULL && css != NULL); - //if rsa is not NULL, fill the public key part - if(rsa) + //if pkey is not NULL, fill the public key part + if(pkey) { - const BIGNUM *e = NULL, *n = NULL; - RSA_get0_key(rsa, &n, &e, NULL); + BIGNUM *e = NULL, *n = NULL; + rsa_get_bn((EVP_PKEY*)pkey, &n, &e, NULL); + //RSA_get0_key(rsa, &n, &e, NULL); int exponent_size = BN_num_bytes(e); int modulus_size = BN_num_bytes(n); if(modulus_size > SE_KEY_SIZE) + { + rsa_free_bn(n, e, NULL); return false; + } unsigned char *modulus = (unsigned char *)malloc(SE_KEY_SIZE); if(modulus == NULL) - { + {rsa_free_bn(n, e, NULL); return false; } memset(modulus, 0, SE_KEY_SIZE); @@ -285,19 +285,23 @@ static bool fill_enclave_css(const RSA *rsa, const char **path, modulus_size = (uint32_t)(ROUND_TO(modulus_size, sizeof(uint32_t)) / sizeof(uint32_t)); if(exponent_size != 0x1 || modulus_size != 0x60) { + rsa_free_bn(n, e, NULL); free(modulus); return false; } if(BN_bn2bin(n, modulus) != SE_KEY_SIZE) { + rsa_free_bn(n, e, NULL); free(modulus); return false; } if(BN_bn2bin(e, (unsigned char *)&css->key.exponent) != 1) { + rsa_free_bn(n, e, NULL); free(modulus); return false; } + rsa_free_bn(n, e, NULL); for(unsigned int i = 0; i < SE_KEY_SIZE; i++) { css->key.modulus[i] = modulus[SE_KEY_SIZE -i - 1]; @@ -428,10 +432,10 @@ static bool calc_RSAq1q2(int length_s, const uint8_t *data_s, int length_m, cons } -static bool create_signature(const RSA *rsa, const char *sigpath, enclave_css_t *enclave_css) +static bool create_signature(const EVP_PKEY *pkey, const char *sigpath, enclave_css_t *enclave_css) { assert(enclave_css != NULL); - assert(!(rsa == NULL && sigpath == NULL) && !(rsa != NULL && sigpath != NULL)); + assert(!(pkey == NULL && sigpath == NULL) && !(pkey != NULL && sigpath != NULL)); uint8_t signature[SIGNATURE_SIZE]; // keep the signature in big endian memset(signature, 0, SIGNATURE_SIZE); @@ -469,13 +473,38 @@ static bool create_signature(const RSA *rsa, const char *sigpath, enclave_css_t free(temp_buffer); return false; } - - size_t siglen; - int ret = RSA_sign(NID_sha256, hash, hash_size, signature, (unsigned int *)&siglen, const_cast(rsa)); free(temp_buffer); - if(ret != 1) + size_t siglen; + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new((EVP_PKEY *)pkey, NULL); + if(!ctx) + { + return false; + } + if (EVP_PKEY_sign_init(ctx) <= 0 || + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0 || + EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0) + { + EVP_PKEY_CTX_free(ctx); return false; + } + if(EVP_PKEY_sign(ctx, NULL, &siglen, hash, hash_size) <= 0) + { + EVP_PKEY_CTX_free(ctx); + return false; + } + if(SIGNATURE_SIZE != siglen) + { + EVP_PKEY_CTX_free(ctx); + return false; + } + if(EVP_PKEY_sign(ctx, signature, &siglen, hash, hash_size) <= 0) + { + EVP_PKEY_CTX_free(ctx); + return false; + } + EVP_PKEY_CTX_free(ctx); } + for(int i = 0; ikey.signature)[i] = signature[SIGNATURE_SIZE-1-i]; @@ -496,9 +525,9 @@ static bool create_signature(const RSA *rsa, const char *sigpath, enclave_css_t return res; } -static bool verify_signature(const RSA *rsa, const enclave_css_t *enclave_css) +static bool verify_signature(const EVP_PKEY *pkey, const enclave_css_t *enclave_css) { - assert(rsa != NULL && enclave_css != NULL); + assert(pkey != NULL && enclave_css != NULL); size_t buffer_size = sizeof(enclave_css->header) + sizeof(enclave_css->body); uint8_t *temp_buffer = (uint8_t *)malloc(buffer_size * sizeof(char)); if(NULL == temp_buffer) @@ -524,11 +553,22 @@ static bool verify_signature(const RSA *rsa, const enclave_css_t *enclave_css) { signature[i] = enclave_css->key.signature[SIGNATURE_SIZE-1-i]; } - if(1 != RSA_verify(NID_sha256, hash, hash_size, signature, SIGNATURE_SIZE, const_cast(rsa))) + + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new((EVP_PKEY *)pkey, NULL); + if(!ctx) { return false; } - return true; + if(EVP_PKEY_verify_init(ctx) <= 0 || + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0 || + EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0) + { + EVP_PKEY_CTX_free(ctx); + return false; + } + int ret = EVP_PKEY_verify(ctx, signature, SIGNATURE_SIZE, hash, hash_size); + EVP_PKEY_CTX_free(ctx); + return ret == 1 ? true : false; } static bool gen_enclave_signing_file(const enclave_css_t *enclave_css, const char *outpath) @@ -758,7 +798,7 @@ static bool cmdline_parse(unsigned int argc, char *argv[], int *mode, const char // and then write the whole out file with body+header+hash // CATSIG- need to fill the enclave_css_t(include key), read the signature from the sigpath, // and then update the metadata in the out file -static bool generate_output(int mode, int ktype, const uint8_t *enclave_hash, const RSA *rsa, metadata_t *metadata, +static bool generate_output(int mode, int ktype, const uint8_t *enclave_hash, const EVP_PKEY *pkey, metadata_t *metadata, const char **path) { assert(enclave_hash != NULL && metadata != NULL && path != NULL); @@ -767,17 +807,17 @@ static bool generate_output(int mode, int ktype, const uint8_t *enclave_hash, co { case SIGN: { - if(ktype != PRIVATE_KEY || !rsa) + if(ktype != PRIVATE_KEY || !pkey) { se_trace(SE_TRACE_ERROR, LACK_PRI_KEY_ERROR); return false; } - if(false == fill_enclave_css(rsa, path, enclave_hash, &(metadata->enclave_css))) + if(false == fill_enclave_css(pkey, path, enclave_hash, &(metadata->enclave_css))) { return false; } - if(false == create_signature(rsa, NULL, &(metadata->enclave_css))) + if(false == create_signature(pkey, NULL, &(metadata->enclave_css))) { return false; } @@ -798,13 +838,13 @@ static bool generate_output(int mode, int ktype, const uint8_t *enclave_hash, co } case CATSIG: { - if(ktype != PUBLIC_KEY || !rsa) + if(ktype != PUBLIC_KEY || !pkey) { se_trace(SE_TRACE_ERROR, LACK_PUB_KEY_ERROR); return false; } - if(false == fill_enclave_css(rsa, path, enclave_hash, &(metadata->enclave_css))) + if(false == fill_enclave_css(pkey, path, enclave_hash, &(metadata->enclave_css))) { return false; } @@ -1346,16 +1386,11 @@ int main(int argc, char* argv[]) size_t parameter_count = sizeof(parameter)/sizeof(parameter[0]); uint64_t meta_offset = 0; uint32_t option_flag_bits = 0; - RSA *rsa = NULL; + EVP_PKEY *pkey = NULL; memset(&metadata_raw, 0, sizeof(metadata_raw)); uint8_t meta_versions = 0; -#if OPENSSL_VERSION_NUMBER < 0x10100000L - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); -#else OPENSSL_init_crypto(0, NULL); -#endif //Parse command line if(cmdline_parse(argc, argv, &mode, path, &option_flag_bits) == false) @@ -1389,7 +1424,7 @@ int main(int argc, char* argv[]) goto clear_return; } //Parse the key file - if(parse_key_file(mode, path[KEY], &rsa, &key_type) == false && key_type != NO_KEY) + if(parse_key_file(mode, path[KEY], &pkey, &key_type) == false && key_type != NO_KEY) { goto clear_return; } @@ -1404,7 +1439,7 @@ int main(int argc, char* argv[]) se_trace(SE_TRACE_ERROR, OVERALL_ERROR); goto clear_return; } - if((generate_output(mode, key_type, enclave_hash, rsa, metadata, path)) == false) + if((generate_output(mode, key_type, enclave_hash, pkey, metadata, path)) == false) { se_trace(SE_TRACE_ERROR, OVERALL_ERROR); goto clear_return; @@ -1413,7 +1448,7 @@ int main(int argc, char* argv[]) //to verify if(mode == SIGN || mode == CATSIG) { - if(verify_signature(rsa, &(metadata->enclave_css)) == false) + if(verify_signature(pkey, &(metadata->enclave_css)) == false) { se_trace(SE_TRACE_ERROR, OVERALL_ERROR); goto clear_return; @@ -1449,19 +1484,13 @@ int main(int argc, char* argv[]) res = 0; clear_return: - if(rsa) - RSA_free(rsa); + if(pkey) + EVP_PKEY_free(pkey); if(res == -1 && path[OUTPUT]) remove(path[OUTPUT]); if(res == -1 && path[DUMPFILE]) remove(path[DUMPFILE]); if(res == -1 && path[CSSFILE]) remove(path[CSSFILE]); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - ERR_remove_thread_state(NULL); - ERR_free_strings(); -#endif return res; } diff --git a/sdk/simulation/tinst/deriv.cpp b/sdk/simulation/tinst/deriv.cpp index 3be7c25ca..40a94179d 100644 --- a/sdk/simulation/tinst/deriv.cpp +++ b/sdk/simulation/tinst/deriv.cpp @@ -85,14 +85,14 @@ const uint8_t* get_base_key(uint16_t key_name) // Compute the CMAC of derivation data with corresponding base key // and save it to `okey'. -void derive_key(const derivation_data_t* dd, sgx_key_128bit_t okey) +sgx_status_t derive_key(const derivation_data_t* dd, sgx_key_128bit_t okey) { - sgx_rijndael128_cmac_msg((const sgx_cmac_128bit_key_t*)(get_base_key(dd->key_name)), + return sgx_rijndael128_cmac_msg((const sgx_cmac_128bit_key_t*)(get_base_key(dd->key_name)), dd->ddbuf, dd->size, (sgx_cmac_128bit_tag_t*)okey); } // Compute the CMAC of a `buf' with a given `key'. -void cmac(const sgx_key_128bit_t *key, const uint8_t* buf, int buf_len, sgx_mac_t* cmac) +sgx_status_t cmac(const sgx_key_128bit_t *key, const uint8_t* buf, int buf_len, sgx_mac_t* cmac) { - sgx_rijndael128_cmac_msg((const sgx_cmac_128bit_key_t*)key, buf, buf_len, cmac); + return sgx_rijndael128_cmac_msg((const sgx_cmac_128bit_key_t*)key, buf, buf_len, cmac); } diff --git a/sdk/simulation/tinst/deriv.h b/sdk/simulation/tinst/deriv.h index 21d0c2e90..7c7e292ff 100644 --- a/sdk/simulation/tinst/deriv.h +++ b/sdk/simulation/tinst/deriv.h @@ -154,7 +154,7 @@ const uint8_t* get_base_key(uint16_t key_name); * @param dd - the pointer to derive data * @param okey - the output derived key */ -void derive_key(const derivation_data_t* dd, sgx_key_128bit_t okey); +sgx_status_t derive_key(const derivation_data_t* dd, sgx_key_128bit_t okey); /** Compute the CMAC of a buffer. * @param key - the key used to compute the CMAC @@ -162,7 +162,7 @@ void derive_key(const derivation_data_t* dd, sgx_key_128bit_t okey); * @param buf_len - length of the buffer in Bytes * @param cmac - the pointer to the output buffer to store CMAC */ -void cmac(const sgx_key_128bit_t *key, const uint8_t* buf, int buf_len, sgx_mac_t* cmac); +sgx_status_t cmac(const sgx_key_128bit_t *key, const uint8_t* buf, int buf_len, sgx_mac_t* cmac); #ifdef __cplusplus } diff --git a/sdk/simulation/tinst/t_instructions.cpp b/sdk/simulation/tinst/t_instructions.cpp index 71771c2cb..97287c326 100644 --- a/sdk/simulation/tinst/t_instructions.cpp +++ b/sdk/simulation/tinst/t_instructions.cpp @@ -352,12 +352,12 @@ static void _EREPORT(const sgx_target_info_t* ti, const sgx_report_data_t* rd, s sgx_key_128bit_t tmp_report_key; memset(tmp_report_key, 0, sizeof(tmp_report_key)); - derive_key(&dd, tmp_report_key); + GP_ON(SGX_SUCCESS != derive_key(&dd, tmp_report_key)); // call cryptographic CMAC function // CMAC data are *NOT* including MAC and KEYID - cmac(&tmp_report_key, reinterpret_cast(&tmp_report.body), - sizeof(tmp_report.body), &tmp_report.mac); + GP_ON(SGX_SUCCESS != cmac(&tmp_report_key, reinterpret_cast(&tmp_report.body), + sizeof(tmp_report.body), &tmp_report.mac)); memcpy(report, &tmp_report, sizeof(sgx_report_t)); } diff --git a/sdk/simulation/trtssim/linux/Makefile b/sdk/simulation/trtssim/linux/Makefile index 7b23a807d..bcb68e5d4 100644 --- a/sdk/simulation/trtssim/linux/Makefile +++ b/sdk/simulation/trtssim/linux/Makefile @@ -67,11 +67,10 @@ TRTS1_OBJS := init_enclave.o \ trts_xsave.o \ init_optimized_lib.o \ trts_add_trim.o \ - trts_aex.o \ trts_emm_sim.o TRTS2_OBJS := trts_nsp.o -TRTS_OBJS := $(TRTS1_OBJS) $(TRTS2_OBJS) ctd.o +TRTS_OBJS := $(TRTS1_OBJS) $(TRTS2_OBJS) TINST_OBJS := t_instructions.o \ deriv.o @@ -82,7 +81,6 @@ TLS_OBJS := get_tcs.o \ restore_tls.o TLDR_ASM_OBJS := trts_pic.o \ - trts_mitigation.o \ metadata_sec.o \ xsave_gnu.o \ thunk.o @@ -93,15 +91,6 @@ TLDR_C_OBJS := elf_parser.o \ TLDR_OBJS := $(TLDR_ASM_OBJS) $(TLDR_C_OBJS) -ctd.o: $(TRTS_DIR)/ctd.c - $(CC) -mavx2 -O3 -masm=intel $(filter-out -O2,$(CFLAGS)) $(TCFLAGS) -c $< -o $@ \ - -I$(COMMON_DIR)/inc/ \ - -I$(COMMON_DIR)/inc/tlibc/ \ - -I$(COMMON_DIR)/inc/internal \ - -I$(LINUX_SDK_DIR)/trts/ \ - -I$(LINUX_SDK_DIR)/pthread/ \ - -I$(LINUX_SDK_DIR)/tlibcxx/include - LIBTRTS := libsgx_trts_sim.a vpath %.cpp $(TRTS_DIR):$(TINST_DIR) diff --git a/sdk/simulation/uae_service_sim/linux/Makefile b/sdk/simulation/uae_service_sim/linux/Makefile index b8826cd83..cb673f147 100644 --- a/sdk/simulation/uae_service_sim/linux/Makefile +++ b/sdk/simulation/uae_service_sim/linux/Makefile @@ -37,6 +37,9 @@ PLATFORM_VERSION:= $(shell awk '$$2 ~ /PLATFORM_VERSION/ { print substr($$3, 2, EPID_VERSION:= $(shell awk '$$2 ~ /EPID_VERSION/ { print substr($$3, 2, length($$3) - 2); }' $(COMMON_DIR)/inc/internal/se_version.h) QUOTE_EX_VERSION:= $(shell awk '$$2 ~ /QUOTE_EX_VERSION/ { print substr($$3, 2, length($$3) - 2); }' $(COMMON_DIR)/inc/internal/se_version.h) +PREBUILT_OPENSSL_DIR := $(LINUX_EXTERNAL_DIR)/dcap_source/prebuilt/openssl +CRYPTO_LIB := -L$(PREBUILT_OPENSSL_DIR)/lib/linux64 -lcrypto + INCLUDES := -I.. \ -I$(COMMON_DIR)/inc \ -I$(COMMON_DIR)/inc/internal \ @@ -47,11 +50,12 @@ INCLUDES := -I.. \ -I$(LINUX_EXTERNAL_DIR)/rdrand/ \ -I$(LINUX_PSW_DIR)/ae/inc \ -I$(LINUX_PSW_DIR)/ae/inc/internal \ - -I$(LINUX_PSW_DIR)/ae/common + -I$(LINUX_PSW_DIR)/ae/common \ + -I$(PREBUILT_OPENSSL_DIR)/inc -CXXFLAGS += -Wall -fPIC $(INCLUDES) -Werror -g -DOPENSSL_API_COMPAT=10101 $(CET_FLAGS) -CFLAGS := $(filter-out -fPIC -Werror, $(CFLAGS)) -Wall $(INCLUDES) -DOPENSSL_API_COMPAT=10101 $(CET_FLAGS) +CXXFLAGS += -Wall -fPIC $(INCLUDES) -Werror -g $(CET_FLAGS) +CFLAGS := $(filter-out -fPIC -Werror, $(CFLAGS)) -Wall $(INCLUDES) $(CET_FLAGS) RDRAND_LIBDIR := $(LINUX_EXTERNAL_DIR)/rdrand/src @@ -59,7 +63,7 @@ RDRAND_MAKEFILE := $(RDRAND_LIBDIR)/Makefile EXTERNAL_LIB += -L$(RDRAND_LIBDIR) -lrdrand EXTERNAL_LIB += -L$(RDRAND_LIBDIR) -lrt -EXTERNAL_LIB += -ldl -lcrypto +EXTERNAL_LIB += -ldl $(CRYPTO_LIB) vpath %.cpp $(LINUX_PSW_DIR)/ae/common \ $(LINUX_SDK_DIR)/simulation/urtssim \ diff --git a/sdk/simulation/uae_service_sim/linux/libsgx_epid.lds b/sdk/simulation/uae_service_sim/linux/libsgx_epid.lds index 44f89ac60..80292428c 100644 --- a/sdk/simulation/uae_service_sim/linux/libsgx_epid.lds +++ b/sdk/simulation/uae_service_sim/linux/libsgx_epid.lds @@ -7,6 +7,8 @@ global: sgx_check_update_status; sgx_get_extended_epid_group_id; sgx_calc_quote_size; + sgx_trace_logger_callback; + sgx_trace_loglevel; local: *; }; diff --git a/sdk/simulation/uae_service_sim/linux/libsgx_quote_ex.lds b/sdk/simulation/uae_service_sim/linux/libsgx_quote_ex.lds index fd3b3828a..11489fc23 100644 --- a/sdk/simulation/uae_service_sim/linux/libsgx_quote_ex.lds +++ b/sdk/simulation/uae_service_sim/linux/libsgx_quote_ex.lds @@ -6,6 +6,8 @@ global: sgx_get_quote_ex; sgx_get_supported_att_key_id_num; sgx_get_supported_att_key_ids; + sgx_trace_logger_callback; + sgx_trace_loglevel; local: *; }; diff --git a/sdk/simulation/uae_service_sim/linux/libsgx_uae_service.lds b/sdk/simulation/uae_service_sim/linux/libsgx_uae_service.lds index c97938d4e..5ce7ade4c 100644 --- a/sdk/simulation/uae_service_sim/linux/libsgx_uae_service.lds +++ b/sdk/simulation/uae_service_sim/linux/libsgx_uae_service.lds @@ -18,6 +18,8 @@ global: sgx_get_quote_ex; sgx_get_supported_att_key_id_num; sgx_get_supported_att_key_ids; + sgx_trace_logger_callback; + sgx_trace_loglevel; local: *; }; diff --git a/sdk/simulation/uinst/u_instructions.cpp b/sdk/simulation/uinst/u_instructions.cpp index 26e5fa438..83e37bf37 100644 --- a/sdk/simulation/uinst/u_instructions.cpp +++ b/sdk/simulation/uinst/u_instructions.cpp @@ -62,6 +62,7 @@ static uintptr_t _EADD (page_info_t* pi, void* epc_lin_addr); static uintptr_t _EREMOVE(const void* epc_lin_addr); extern "C" void* get_td_addr(void); extern "C" bool get_elrange_start_address(void* base_address, uint64_t &elrange_start_address); +extern "C" void save_xregs(void* addr); static __thread uintptr_t _dtv_u = 0; @@ -79,15 +80,6 @@ static __thread uintptr_t _dtv_u = 0; #define mcp_same_size(dst_ptr, src_ptr, size) memcpy_s(dst_ptr, size, src_ptr, size) -static void fxsave_regs(char *addr) -{ - asm volatile("fxsave %0" : : "m" (*addr)); -} -static void fxrstor_regs(char *addr) -{ - asm volatile("fxrstor %0" : : "m" (*addr)); -} - static struct sigaction g_old_sigact[_NSIG]; void call_old_handler(int signum, void* siginfo, void *priv) { @@ -527,8 +519,6 @@ void _SE3(uintptr_t xax, uintptr_t xbx, // Returning from this function enters the enclave return; case SE_ERESUME: - char buf[512] __attribute((aligned (16))); - fxsave_regs(buf); SE_TRACE(SE_TRACE_DEBUG, "ERESUME instruction\n"); // xbx contains the address of a TCS tcs = reinterpret_cast(xbx); @@ -559,8 +549,8 @@ void _SE3(uintptr_t xax, uintptr_t xbx, + (tcs->cssa+1) * secs->ssa_frame_size * SE_PAGE_SIZE - sizeof(ssa_gpr_t)); - mcp_same_size((char*)((size_t)p_ssa_gpr + sizeof(ssa_gpr_t) - secs->ssa_frame_size * SE_PAGE_SIZE), buf, sizeof(buf)); - fxrstor_regs(buf); + save_xregs((char*)((size_t)p_ssa_gpr + sizeof(ssa_gpr_t) - secs->ssa_frame_size * SE_PAGE_SIZE)); + regs.xax = p_ssa_gpr->REG(ax); regs.xbx = p_ssa_gpr->REG(bx); regs.xdx = p_ssa_gpr->REG(dx); diff --git a/sdk/simulation/urtssim/enclave_creator_sim.cpp b/sdk/simulation/urtssim/enclave_creator_sim.cpp index dfad04d02..e2e56227b 100644 --- a/sdk/simulation/urtssim/enclave_creator_sim.cpp +++ b/sdk/simulation/urtssim/enclave_creator_sim.cpp @@ -53,26 +53,9 @@ __attribute__((constructor)) static void init_openssl(void) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); -#else OPENSSL_init_crypto(0, NULL); -#endif } -__attribute__((destructor)) -static void cleanup_openssl(void) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - ERR_remove_thread_state(NULL); - ERR_free_strings(); -#endif -} - - static Mutex s_enclave_info_mutex; static std::maps_enclave_elrange_map; diff --git a/sdk/simulation/urtssim/linux/Makefile b/sdk/simulation/urtssim/linux/Makefile index d9a434508..c5027233f 100644 --- a/sdk/simulation/urtssim/linux/Makefile +++ b/sdk/simulation/urtssim/linux/Makefile @@ -44,6 +44,9 @@ endif CXXFLAGS += -fPIC -DSE_SIM -Werror -g $(CET_FLAGS) CFLAGS += -fPIC -DSE_SIM -Werror -g $(CET_FLAGS) +PREBUILT_OPENSSL_DIR := $(LINUX_EXTERNAL_DIR)/dcap_source/prebuilt/openssl +CRYPTO_LIB := -L$(PREBUILT_OPENSSL_DIR)/lib/linux64 -lcrypto + CPPFLAGS += $(ADDED_INC) #for ubuntu 11 and later version CPPFLAGS += -I$(COMMON_DIR)/inc \ -I$(COMMON_DIR)/inc/internal/linux \ @@ -51,7 +54,8 @@ CPPFLAGS += -I$(COMMON_DIR)/inc \ -I$(LINUX_PSW_DIR)/urts \ -I$(LINUX_PSW_DIR)/urts/parser \ -I$(VTUNE_DIR)/include \ - -I$(VTUNE_DIR)/sdk/src/ittnotify + -I$(VTUNE_DIR)/sdk/src/ittnotify \ + -I$(PREBUILT_OPENSSL_DIR)/inc CPPFLAGS += -I$(COMMON_DIR)/inc/internal \ -I$(LINUX_PSW_DIR)/urts/linux \ @@ -124,7 +128,7 @@ LIBURTSSIM_SHARED := libsgx_urts_sim.so LIBURTSSIM_DEBUG := libsgx_urts_sim.so.debug LIBURTS_DEPLOY := libsgx_urts_deploy.so -LDLIBS += -lwrapper -lcrypto -Wl,-Bdynamic -Wl,-Bsymbolic -lsgx_uae_service_sim +LDLIBS += -lwrapper $(CRYPTO_LIB) -Wl,-Bdynamic -Wl,-Bsymbolic -lsgx_uae_service_sim SONAME = $(LIBURTSSIM_SHARED) .PHONY: all diff --git a/sdk/switchless/sgx_tswitchless/sgx_ocall_switchless.c b/sdk/switchless/sgx_tswitchless/sgx_ocall_switchless.c index bb26ef654..4fe36c5db 100644 --- a/sdk/switchless/sgx_tswitchless/sgx_ocall_switchless.c +++ b/sdk/switchless/sgx_tswitchless/sgx_ocall_switchless.c @@ -89,6 +89,16 @@ sgx_status_t sgx_ocall_switchless(const unsigned int index, void* ms) if (sgx_is_enclave_crashed()) return SGX_ERROR_ENCLAVE_CRASHED; + /* Global object initialization (init_global_object) happens before + * g_uswitchless_handle is initialized (via sl_init_switchless). + * Some ctors invoke syscalls via switchless ocalls. This causes + * init_tswitchless_ocall_mngr to be invoked with sl_call_once prematurely, + * returning -1. Subsequent invokations will always return -1, such that + * switchless ocalls never happen. A simple solution is to fallback to + * traditional ocalls until g_uswitchless_handle has been initialized. */ + if (g_uswitchless_handle == NULL) + return sgx_ocall(index, ms); + /* If Switchless SGX is not enabled at enclave creation, then switchless OCalls * fallback to the traditional OCalls */ if (sl_call_once(&g_init_ocall_mngr_done, init_tswitchless_ocall_mngr, NULL)) diff --git a/sdk/tlibcrypto/ipp/sgx_aes_gcm.cpp b/sdk/tlibcrypto/ipp/sgx_aes_gcm.cpp index f57efc895..218fcb0b3 100644 --- a/sdk/tlibcrypto/ipp/sgx_aes_gcm.cpp +++ b/sdk/tlibcrypto/ipp/sgx_aes_gcm.cpp @@ -58,6 +58,7 @@ sgx_status_t sgx_rijndael128GCM_encrypt(const sgx_aes_gcm_128bit_key_t *p_key, c IppStatus error_code = ippStsNoErr; IppsAES_GCMState* pState = NULL; int ippStateSize = 0; + const int noise_level = 1; if ((p_key == NULL) || ((src_len > 0) && (p_dst == NULL)) || ((src_len > 0) && (p_src == NULL)) || (p_out_mac == NULL) || (iv_len != SGX_AESGCM_IV_SIZE) || ((aad_len > 0) && (p_aad == NULL)) @@ -89,6 +90,13 @@ sgx_status_t sgx_rijndael128GCM_encrypt(const sgx_aes_gcm_128bit_key_t *p_key, c default: return SGX_ERROR_UNEXPECTED; } } + error_code = ippsAES_GCMSetupNoise(noise_level, pState); + if(error_code != ippStsNoErr) + { + memset_s(pState, ippStateSize, 0, ippStateSize); + free(pState); + return SGX_ERROR_UNEXPECTED; + } error_code = ippsAES_GCMStart(p_iv, SGX_AESGCM_IV_SIZE, p_aad, aad_len, pState); if (error_code != ippStsNoErr) { @@ -144,6 +152,7 @@ sgx_status_t sgx_rijndael128GCM_decrypt(const sgx_aes_gcm_128bit_key_t *p_key, c uint8_t l_tag[SGX_AESGCM_MAC_SIZE]; IppsAES_GCMState* pState = NULL; int ippStateSize = 0; + const int noise_level = 1; if ((p_key == NULL) || ((src_len > 0) && (p_dst == NULL)) || ((src_len > 0) && (p_src == NULL)) || (p_in_mac == NULL) || (iv_len != SGX_AESGCM_IV_SIZE) || ((aad_len > 0) && (p_aad == NULL)) @@ -178,6 +187,13 @@ sgx_status_t sgx_rijndael128GCM_decrypt(const sgx_aes_gcm_128bit_key_t *p_key, c default: return SGX_ERROR_UNEXPECTED; } } + error_code = ippsAES_GCMSetupNoise(noise_level, pState); + if(error_code != ippStsNoErr) + { + memset_s(pState, ippStateSize, 0, ippStateSize); + free(pState); + return SGX_ERROR_UNEXPECTED; + } error_code = ippsAES_GCMStart(p_iv, SGX_AESGCM_IV_SIZE, p_aad, aad_len, pState); if (error_code != ippStsNoErr) { @@ -247,6 +263,7 @@ sgx_status_t sgx_aes_gcm128_enc_init(const uint8_t *key, const uint8_t *iv, uint sgx_status_t ret = SGX_ERROR_UNEXPECTED; IppStatus status = ippStsNoErr; IppsAES_GCMState *p_state = NULL; + const int noise_level = 1; do { status = ippsAES_GCMGetSize(&state_size); @@ -260,7 +277,8 @@ sgx_status_t sgx_aes_gcm128_enc_init(const uint8_t *key, const uint8_t *iv, uint status = ippsAES_GCMInit(key, 16, p_state, state_size); ERROR_BREAK(status); - + status = ippsAES_GCMSetupNoise(noise_level, p_state); + ERROR_BREAK(status); status = ippsAES_GCMStart(iv, iv_len, aad, aad_len, p_state); ERROR_BREAK(status); diff --git a/sdk/tlibcrypto/ipp/sgx_cmac128.cpp b/sdk/tlibcrypto/ipp/sgx_cmac128.cpp index bb4134981..fb4886a2f 100644 --- a/sdk/tlibcrypto/ipp/sgx_cmac128.cpp +++ b/sdk/tlibcrypto/ipp/sgx_cmac128.cpp @@ -49,6 +49,7 @@ sgx_status_t sgx_rijndael128_cmac_msg(const sgx_cmac_128bit_key_t *p_key, const IppsAES_CMACState* pState = NULL; int ippStateSize = 0; IppStatus error_code = ippStsNoErr; + const int noise_level = 1; if ((p_key == NULL) || (p_src == NULL) || (p_mac == NULL)) { @@ -78,6 +79,13 @@ sgx_status_t sgx_rijndael128_cmac_msg(const sgx_cmac_128bit_key_t *p_key, const default: return SGX_ERROR_UNEXPECTED; } } + error_code = ippsAES_CMACSetupNoise(noise_level, pState); + if(error_code != ippStsNoErr) + { + memset_s(pState, ippStateSize, 0, ippStateSize); + free(pState); + return SGX_ERROR_UNEXPECTED; + } error_code = ippsAES_CMACUpdate((const Ipp8u *)p_src, src_len, pState); if (error_code != ippStsNoErr) { @@ -142,6 +150,7 @@ sgx_status_t sgx_cmac128_init(const sgx_cmac_128bit_key_t *p_key, sgx_cmac_state IppsAES_CMACState* pState = NULL; int ippStateSize = 0; IppStatus error_code = ippStsNoErr; + const int noise_level = 1; error_code = ippsAES_CMACGetSize(&ippStateSize); if (error_code != ippStsNoErr) { @@ -158,7 +167,6 @@ sgx_status_t sgx_cmac128_init(const sgx_cmac_128bit_key_t *p_key, sgx_cmac_state // Clear state before free. memset_s(pState, ippStateSize, 0, ippStateSize); free(pState); - *p_cmac_handle = NULL; switch (error_code) { case ippStsMemAllocErr: return SGX_ERROR_OUT_OF_MEMORY; @@ -167,6 +175,13 @@ sgx_status_t sgx_cmac128_init(const sgx_cmac_128bit_key_t *p_key, sgx_cmac_state default: return SGX_ERROR_UNEXPECTED; } } + error_code = ippsAES_CMACSetupNoise(noise_level, pState); + if(error_code != ippStsNoErr) + { + memset_s(pState, ippStateSize, 0, ippStateSize); + free(pState); + return SGX_ERROR_UNEXPECTED; + } *p_cmac_handle = pState; return SGX_SUCCESS; } diff --git a/sdk/tlibcrypto/sgx_common_init_ipp.cpp b/sdk/tlibcrypto/sgx_common_init_ipp.cpp index b63a064e5..76f972896 100644 --- a/sdk/tlibcrypto/sgx_common_init_ipp.cpp +++ b/sdk/tlibcrypto/sgx_common_init_ipp.cpp @@ -101,12 +101,12 @@ extern "C" sgx_status_t init_ipp_cpuid(uint64_t cpu_feature_indicator) { ippCpuFeatures |= ippCPUID_RDSEED; } - if ((cpu_feature_indicator & CPU_FEATURE_SHA) == CPU_FEATURE_SHA) + if ((cpu_feature_indicator & CPU_FEATURE_SHA) == CPU_FEATURE_SHA) { ippCpuFeatures |= ippCPUID_SHA; } - - // AVX512 + + // AVX512 if ((cpu_feature_indicator & CPU_FEATURE_AVX512F) == CPU_FEATURE_AVX512F) { ippCpuFeatures |= ippCPUID_AVX512F; @@ -148,11 +148,26 @@ extern "C" sgx_status_t init_ipp_cpuid(uint64_t cpu_feature_indicator) { ippCpuFeatures |= ippCPUID_AVX512_4FMADDPS; } - + if((cpu_feature_indicator & CPU_FEATURE_VAES) == CPU_FEATURE_VAES) + { + ippCpuFeatures |= ippCPUID_AVX512VAES; + } if ((cpu_feature_indicator & CPU_FEATURE_AVX512IFMA52) == CPU_FEATURE_AVX512IFMA52) { ippCpuFeatures |= ippCPUID_AVX512IFMA; } + if ((cpu_feature_indicator & CPU_FEATURE_GFNI) == CPU_FEATURE_GFNI) + { + ippCpuFeatures |= ippCPUID_AVX512GFNI; + } + if((cpu_feature_indicator & CPU_FEATURE_AVX512_VBMI2) == CPU_FEATURE_AVX512_VBMI2) + { + ippCpuFeatures |= ippCPUID_AVX512VBMI2; + } + if((cpu_feature_indicator & CPU_FEATURE_VPCLMULQDQ) == CPU_FEATURE_VPCLMULQDQ) + { + ippCpuFeatures |= ippCPUID_AVX512VCLMUL; + } } else { diff --git a/sdk/tlibcrypto/sgxssl/sgx_cmac128.cpp b/sdk/tlibcrypto/sgxssl/sgx_cmac128.cpp index f4ab1bd8a..28fae2604 100644 --- a/sdk/tlibcrypto/sgxssl/sgx_cmac128.cpp +++ b/sdk/tlibcrypto/sgxssl/sgx_cmac128.cpp @@ -35,6 +35,8 @@ #include "se_tcrypto_common.h" #include "openssl/cmac.h" #include "openssl/err.h" +#include +#include /* Message Authentication - Rijndael 128 CMAC * Parameters: @@ -46,46 +48,52 @@ sgx_status_t sgx_rijndael128_cmac_msg(const sgx_cmac_128bit_key_t *p_key, const uint8_t *p_src, uint32_t src_len, sgx_cmac_128bit_tag_t *p_mac) { - void* pState = NULL; + OSSL_LIB_CTX *lib_ctx = NULL; + EVP_MAC *mac = NULL; + EVP_MAC_CTX *mctx = NULL; + OSSL_PARAM params[2] = {OSSL_PARAM_END, OSSL_PARAM_END}; + char cipher_name[] = "AES-128-CBC"; + size_t mac_len = 0; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + if ((p_key == NULL) || (p_src == NULL) || (p_mac == NULL)) { return SGX_ERROR_INVALID_PARAMETER; } - size_t mactlen; - sgx_status_t ret = SGX_ERROR_UNEXPECTED; - do { - //create a new ctx of CMAC - // - pState = CMAC_CTX_new(); - if (pState == NULL) { + if ((lib_ctx = OSSL_LIB_CTX_new()) == NULL) + { ret = SGX_ERROR_OUT_OF_MEMORY; break; } - - // init CMAC ctx with the corresponding size, key and AES alg. - // - if (!CMAC_Init((CMAC_CTX*)pState, (const void *)p_key, SGX_CMAC_KEY_SIZE, EVP_aes_128_cbc(), NULL)) { + if ((mac = EVP_MAC_fetch(lib_ctx, "CMAC", NULL)) == NULL) + { + ret = SGX_ERROR_OUT_OF_MEMORY; break; } - // perform CMAC hash on p_src - // - if (!CMAC_Update((CMAC_CTX *)pState, p_src, src_len)) { + if ((mctx = EVP_MAC_CTX_new(mac)) == NULL) { + ret = SGX_ERROR_OUT_OF_MEMORY; break; } - // finalize CMAC hashing - // - if (!CMAC_Final((CMAC_CTX*)pState, (unsigned char*)p_mac, &mactlen)) { + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, cipher_name, sizeof(cipher_name)); + + if ((!EVP_MAC_init(mctx, (const uint8_t *)p_key, sizeof(sgx_key_128bit_t), params))) { break; } - + if (!EVP_MAC_update(mctx, p_src, src_len)) { + break; + } + if (!EVP_MAC_final(mctx, (uint8_t *)p_mac, &mac_len, sizeof(sgx_mac_t))) { + break; + } + //validate mac size // - if (mactlen != SGX_CMAC_MAC_SIZE) { - break; + if (mac_len != SGX_CMAC_MAC_SIZE) { + break; } ret = SGX_SUCCESS; @@ -93,9 +101,10 @@ sgx_status_t sgx_rijndael128_cmac_msg(const sgx_cmac_128bit_key_t *p_key, const // we're done, clear and free CMAC ctx // - if (pState) { - CMAC_CTX_free((CMAC_CTX*)pState); - } + EVP_MAC_CTX_free(mctx); + EVP_MAC_free(mac); + OSSL_LIB_CTX_free(lib_ctx); + return ret; } @@ -103,44 +112,59 @@ sgx_status_t sgx_rijndael128_cmac_msg(const sgx_cmac_128bit_key_t *p_key, const * Parameters: * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h * Inputs: sgx_cmac_128bit_key_t *p_key - Pointer to the key used in encryption/decryption operation -* Output: sgx_cmac_state_handle_t *p_cmac_handle - Pointer to the handle of the CMAC state */ +* Output: sgx_cmac_state_handle_t *p_cmac_handle - Pointer to the handle of the EVP_MAC_CTX state */ sgx_status_t sgx_cmac128_init(const sgx_cmac_128bit_key_t *p_key, sgx_cmac_state_handle_t* p_cmac_handle) - { + OSSL_LIB_CTX *lib_ctx = NULL; + EVP_MAC *mac = NULL; + EVP_MAC_CTX *mctx = NULL; + OSSL_PARAM params[2] = {OSSL_PARAM_END, OSSL_PARAM_END}; + char cipher_name[] = "AES-128-CBC"; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + if ((p_key == NULL) || (p_cmac_handle == NULL)) { return SGX_ERROR_INVALID_PARAMETER; } - sgx_status_t ret = SGX_ERROR_UNEXPECTED; - void* pState = NULL; - do { - // create CMAC ctx - // - pState = CMAC_CTX_new(); - if (pState == NULL) { + if ((lib_ctx = OSSL_LIB_CTX_new()) == NULL) + { ret = SGX_ERROR_OUT_OF_MEMORY; break; } + if ((mac = EVP_MAC_fetch(lib_ctx, "CMAC", NULL)) == NULL) + { + break; + } - //init CMAC ctx - // - if (!CMAC_Init((CMAC_CTX*)pState, (const void *)p_key, SGX_CMAC_KEY_SIZE, EVP_aes_128_cbc(), NULL)) { - CMAC_CTX_free((CMAC_CTX*)pState); + if ((mctx = EVP_MAC_CTX_new(mac)) == NULL) { + ret = SGX_ERROR_OUT_OF_MEMORY; break; } - *p_cmac_handle = pState; + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, cipher_name, sizeof(cipher_name)); + + if ((!EVP_MAC_init(mctx, (const uint8_t *)p_key, sizeof(sgx_key_128bit_t), params))) { + break; + } + + *p_cmac_handle = mctx; ret = SGX_SUCCESS; } while (0); + EVP_MAC_free(mac); + OSSL_LIB_CTX_free(lib_ctx); + if (ret != SGX_SUCCESS) { + EVP_MAC_CTX_free(mctx); + } return ret; } /* Updates CMAC has calculation based on the input message * Parameters: * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error. -* Input: sgx_cmac_state_handle_t cmac_handle - Handle to the CMAC state +* Input: sgx_cmac_state_handle_t cmac_handle - Handle to the EVP_MAC_CTX state * uint8_t *p_src - Pointer to the input stream to be hashed * uint32_t src_len - Length of the input stream to be hashed */ sgx_status_t sgx_cmac128_update(const uint8_t *p_src, uint32_t src_len, sgx_cmac_state_handle_t cmac_handle) @@ -150,7 +174,7 @@ sgx_status_t sgx_cmac128_update(const uint8_t *p_src, uint32_t src_len, sgx_cmac return SGX_ERROR_INVALID_PARAMETER; } - if (!CMAC_Update((CMAC_CTX *)cmac_handle, p_src, src_len)) { + if (!EVP_MAC_update((EVP_MAC_CTX *)cmac_handle, p_src, src_len)) { return SGX_ERROR_UNEXPECTED; } return SGX_SUCCESS; @@ -159,7 +183,7 @@ sgx_status_t sgx_cmac128_update(const uint8_t *p_src, uint32_t src_len, sgx_cmac /* Returns Hash calculation * Parameters: * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h -* Input: sgx_cmac_state_handle_t cmac_handle - Handle to the CMAC state +* Input: sgx_cmac_state_handle_t cmac_handle - Handle to the EVP_MAC_CTX state * Output: sgx_cmac_128bit_tag_t *p_hash - Resultant hash from operation */ sgx_status_t sgx_cmac128_final(sgx_cmac_state_handle_t cmac_handle, sgx_cmac_128bit_tag_t *p_hash) @@ -171,7 +195,7 @@ sgx_status_t sgx_cmac128_final(sgx_cmac_state_handle_t cmac_handle, sgx_cmac_128 size_t mactlen; - if (!CMAC_Final((CMAC_CTX*)cmac_handle, (unsigned char*)p_hash, &mactlen)) { + if (!EVP_MAC_final((EVP_MAC_CTX*)cmac_handle, (unsigned char*)p_hash, &mactlen, sizeof(sgx_mac_t))) { return SGX_ERROR_UNEXPECTED; } return SGX_SUCCESS; @@ -181,14 +205,15 @@ sgx_status_t sgx_cmac128_final(sgx_cmac_state_handle_t cmac_handle, sgx_cmac_128 /* Clean up the CMAC state * Parameters: * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h -* Input: sgx_cmac_state_handle_t cmac_handle - Handle to the CMAC state */ +* Input: sgx_cmac_state_handle_t cmac_handle - Handle to the EVP_MAC_CTX state */ sgx_status_t sgx_cmac128_close(sgx_cmac_state_handle_t cmac_handle) { if (cmac_handle == NULL) { return SGX_ERROR_INVALID_PARAMETER; } - CMAC_CTX* pState = (CMAC_CTX*)cmac_handle; - CMAC_CTX_free(pState); + EVP_MAC_CTX* pState = (EVP_MAC_CTX*)cmac_handle; + EVP_MAC_CTX_free(pState); + cmac_handle = NULL; return SGX_SUCCESS; } diff --git a/sdk/tlibcrypto/sgxssl/sgx_ecc256.cpp b/sdk/tlibcrypto/sgxssl/sgx_ecc256.cpp index 873cacfd3..2dc229343 100644 --- a/sdk/tlibcrypto/sgxssl/sgx_ecc256.cpp +++ b/sdk/tlibcrypto/sgxssl/sgx_ecc256.cpp @@ -34,10 +34,169 @@ #include #include #include +#include +#include #include "sgx_tcrypto.h" #include "ssl_wrapper.h" #define POINT_NOT_ON_CURVE 0x1012606b +EVP_PKEY *get_priv_key_from_bin(const sgx_ec256_private_t *p_private, sgx_ecc_state_handle_t ecc_handle) +{ + EVP_PKEY *evp_key = NULL; + EVP_PKEY_CTX *pkey_ctx = NULL; + BIGNUM *bn_priv = NULL; + OSSL_PARAM_BLD *params_build = NULL; + OSSL_PARAM *params = NULL; + const char *curvename = NULL; + int nid = 0; + + do { + bn_priv = BN_lebin2bn((unsigned char*)p_private->r, sizeof(sgx_ec256_private_t), 0); + if (bn_priv == NULL) { + break; + } + // build OSSL_PARAM + nid = EC_GROUP_get_curve_name((EC_GROUP *)ecc_handle); + if (nid == NID_undef) { + break; + } + curvename = OBJ_nid2sn(nid); + if (curvename == NULL) { + break; + } + params_build = OSSL_PARAM_BLD_new(); + if ( !params_build) { + break; + } + if ( 1 != OSSL_PARAM_BLD_push_utf8_string(params_build, "group", curvename, 0)) { + break; + } + if ( 1 != OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_PRIV_KEY, bn_priv)) { + break; + } + params = OSSL_PARAM_BLD_to_param(params_build); + if ( NULL == params ) { + break; + } + + // get pkey from param + pkey_ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + if (NULL == pkey_ctx) { + break; + } + if ( 1 != EVP_PKEY_fromdata_init(pkey_ctx) ) { + break; + } + if ( 1 != EVP_PKEY_fromdata(pkey_ctx, &evp_key, EVP_PKEY_KEYPAIR, params) ) { + EVP_PKEY_free(evp_key); + evp_key = NULL; + } + } while(0); + + BN_clear_free(bn_priv); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(params_build); + EVP_PKEY_CTX_free(pkey_ctx); + + return evp_key; +} + +EVP_PKEY *get_pub_key_from_coords(const sgx_ec256_public_t *p_public, sgx_ecc_state_handle_t ecc_handle) +{ + EVP_PKEY *evp_key = NULL; + EVP_PKEY_CTX *pkey_ctx = NULL; + BIGNUM *bn_pub_x = NULL; + BIGNUM *bn_pub_y = NULL; + EC_POINT *point = NULL; + EC_GROUP *group = (EC_GROUP *)ecc_handle; + OSSL_PARAM_BLD *params_build = NULL; + OSSL_PARAM *params = NULL; + const char *curvename = NULL; + int nid = 0; + size_t key_len; + unsigned char pub_key[SGX_ECP256_KEY_SIZE+4]; + + do { + // converts the x value of public key, represented as positive integer in little-endian into a BIGNUM + bn_pub_x = BN_lebin2bn((unsigned char*)p_public->gx, sizeof(p_public->gx), bn_pub_x); + if (NULL == bn_pub_x) { + break; + } + // converts the y value of public key, represented as positive integer in little-endian into a BIGNUM + bn_pub_y = BN_lebin2bn((unsigned char*)p_public->gy, sizeof(p_public->gy), bn_pub_y); + if (NULL == bn_pub_y) { + break; + } + // creates new point and assigned the group object that the point relates to + point = EC_POINT_new(group); + if (NULL == point) { + break; + } + + // sets point based on public key's x,y coordinates + if (1 != EC_POINT_set_affine_coordinates(group, point, bn_pub_x, bn_pub_y, NULL)) { + break; + } + + // check point if the point is on curve + if (1 != EC_POINT_is_on_curve(group, point, NULL)) { + break; + } + + // convert point to octet string + key_len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, pub_key, sizeof(pub_key), NULL); + if (key_len == 0) { + break; + } + + // build OSSL_PARAM + params_build = OSSL_PARAM_BLD_new(); + if (NULL == params_build) { + break; + } + nid = EC_GROUP_get_curve_name((EC_GROUP *)ecc_handle); + if (nid == NID_undef) { + break; + } + curvename = OBJ_nid2sn(nid); + if (curvename == NULL) { + break; + } + if (1 != OSSL_PARAM_BLD_push_utf8_string(params_build, "group", curvename, 0)) { + break; + } + if (1 != OSSL_PARAM_BLD_push_octet_string(params_build, OSSL_PKEY_PARAM_PUB_KEY, pub_key, key_len)) { + break; + } + params = OSSL_PARAM_BLD_to_param(params_build); + if (NULL == params) { + break; + } + + // get pkey from params + pkey_ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + if (NULL == pkey_ctx) { + break; + } + if (1 != EVP_PKEY_fromdata_init(pkey_ctx)) { + break; + } + if (1 != EVP_PKEY_fromdata(pkey_ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params)) { + EVP_PKEY_free(evp_key); + evp_key = NULL; + } + } while(0); + + BN_clear_free(bn_pub_x); + BN_clear_free(bn_pub_y); + EC_POINT_clear_free(point); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(params_build); + EVP_PKEY_CTX_free(pkey_ctx); + + return evp_key; +} + /* * Elliptic Curve Cryptography - Based on GF(p), 256 bit */ @@ -92,74 +251,64 @@ sgx_status_t sgx_ecc256_create_key_pair(sgx_ec256_private_t *p_private, return SGX_ERROR_INVALID_PARAMETER; } - EC_GROUP *ec_group = (EC_GROUP*) ecc_handle; - EC_KEY *ec_key = NULL; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *pkey_ctx = NULL; BIGNUM *pub_k_x = NULL; BIGNUM *pub_k_y = NULL; - const EC_POINT *public_k = NULL; - const BIGNUM *private_k = NULL; + BIGNUM *private_k = NULL; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + OSSL_PARAM params[2]; + const char *curvename = NULL; + int nid = 0; do { - // create new EC key - // - ec_key = EC_KEY_new(); - if (NULL == ec_key) { - ret = SGX_ERROR_OUT_OF_MEMORY; + // build OSSL_PARAM + nid = EC_GROUP_get_curve_name((EC_GROUP *)ecc_handle); + if (nid == NID_undef) { break; } - - // set key's group (curve) - // - if (0 == EC_KEY_set_group (ec_key, ec_group)) { + curvename = OBJ_nid2sn(nid); + if (curvename == NULL) { break; } - // generate key pair, based on the curve set - // - if (0 == EC_KEY_generate_key(ec_key)) { - break; - } + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, (char*)curvename, 0); + params[1] = OSSL_PARAM_construct_end(); - pub_k_x = BN_new(); - pub_k_y = BN_new(); - if (NULL == pub_k_x || NULL == pub_k_y) { + // generate key + pkey_ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + if (NULL == pkey_ctx) { ret = SGX_ERROR_OUT_OF_MEMORY; break; } + if (EVP_PKEY_keygen_init(pkey_ctx) <= 0) { + break; + } + if (!EVP_PKEY_CTX_set_params(pkey_ctx, params)) { + break; + } + if (EVP_PKEY_generate(pkey_ctx, &pkey) <= 0) { + break; + } - // This OPENSSL API doesn't validate user's parameters // get public and private keys - // - public_k = EC_KEY_get0_public_key(ec_key); - if (NULL == public_k) { + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &private_k)) { break; } - - private_k = EC_KEY_get0_private_key(ec_key); - if (NULL == private_k) { + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &pub_k_x)) { break; } - - // extract two BNs representing the public key - // - if (!EC_POINT_get_affine_coordinates(ec_group, public_k, pub_k_x, pub_k_y, NULL)) { + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &pub_k_y)) { break; } - // convert private key BN to little-endian unsigned char form - // if (-1 == BN_bn2lebinpad(private_k, (unsigned char*)p_private, SGX_ECP256_KEY_SIZE)) { break; } - - // convert public key BN to little-endian unsigned char form - // if (-1 == BN_bn2lebinpad(pub_k_x, (unsigned char*)p_public->gx, SGX_ECP256_KEY_SIZE)) { break; } - // convert public key BN to little-endian unsigned char form - // if (-1 == BN_bn2lebinpad(pub_k_y, (unsigned char*)p_public->gy, SGX_ECP256_KEY_SIZE)) { break; } @@ -169,17 +318,17 @@ sgx_status_t sgx_ecc256_create_key_pair(sgx_ec256_private_t *p_private, if (SGX_SUCCESS != ret) { // in case of error, clear output buffers - // memset_s(p_private, sizeof(p_private), 0, sizeof(p_private)); memset_s(p_public->gx, sizeof(p_public->gx), 0, sizeof(p_public->gx)); memset_s(p_public->gy, sizeof(p_public->gy), 0, sizeof(p_public->gy)); } //free temp data - // - EC_KEY_free(ec_key); BN_clear_free(pub_k_x); BN_clear_free(pub_k_y); + BN_clear_free(private_k); + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(pkey_ctx); return ret; } @@ -261,7 +410,6 @@ sgx_status_t sgx_ecc256_check_point(const sgx_ec256_public_t *p_point, return retval; } - /* Computes DH shared key based on private B key (local) and remote public Ga Key * Parameters: * Return: sgx_status_t - SGX_SUCCESS or failure as defined sgx_error.h @@ -280,86 +428,54 @@ sgx_status_t sgx_ecc256_compute_shared_dhkey(const sgx_ec256_private_t *p_privat } sgx_status_t ret = SGX_ERROR_UNEXPECTED; - EC_GROUP *ec_group = (EC_GROUP*) ecc_handle; - EC_POINT *point_pubA = NULL; - EC_KEY* private_key = NULL; - BIGNUM *BN_dh_privB = NULL; - BIGNUM *pubA_gx = NULL; - BIGNUM *pubA_gy = NULL; BIGNUM *tmp = NULL; + EVP_PKEY *pkey_peer = NULL; + EVP_PKEY *pkey_local = NULL; + EVP_PKEY_CTX *pctx = NULL; + size_t shared_key_len = 0; do { // get BN from public key and private key // - BN_dh_privB = BN_lebin2bn((unsigned char*)p_private_b->r, sizeof(sgx_ec256_private_t), 0); - if (BN_dh_privB == NULL) { - break; - } - - pubA_gx = BN_lebin2bn((unsigned char*)p_public_ga->gx, sizeof(sgx_ec256_private_t), 0); - if (pubA_gx == NULL) { - break; - } - - pubA_gy = BN_lebin2bn((unsigned char*)p_public_ga->gy, sizeof(sgx_ec256_private_t), 0); - if (pubA_gy == NULL) { - break; - } - - // set point based on pub key x and y - // - point_pubA = EC_POINT_new(ec_group); - if (point_pubA == NULL) { - ret = SGX_ERROR_OUT_OF_MEMORY; + pkey_peer = get_pub_key_from_coords(p_public_ga, ecc_handle); + if( !pkey_peer) { break; } - - // create point (public key) based on public key's x,y coordinates - // - if (EC_POINT_set_affine_coordinates(ec_group, point_pubA, pubA_gx, pubA_gy, NULL) != 1) { + pkey_local = get_priv_key_from_bin(p_private_b, ecc_handle); + if( !pkey_local) { break; } - // check point if valid, point is on curve + // calculate shared dh key // - if (EC_POINT_is_on_curve(ec_group, point_pubA, NULL) != 1) { + pctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey_local, NULL); + if (!pctx) { + ret = SGX_ERROR_OUT_OF_MEMORY; break; } - // create empty shared key BN - // - private_key = EC_KEY_new(); - if (private_key == NULL) { - ret = SGX_ERROR_OUT_OF_MEMORY; + if (EVP_PKEY_derive_init(pctx) <= 0) { break; } - - // init private key group (set curve) - // - if (EC_KEY_set_group (private_key, ec_group) != 1) { + if (EVP_PKEY_derive_set_peer(pctx, pkey_peer) <= 0) { break; } - // init private key with BN value - // - if (EC_KEY_set_private_key(private_key, BN_dh_privB) != 1) { + if (EVP_PKEY_derive(pctx, NULL, &shared_key_len) <= 0 + || shared_key_len != sizeof(sgx_ec256_dh_shared_t) ) { break; } - // calculate shared dh key - // - size_t shared_key_len = sizeof(sgx_ec256_dh_shared_t); - shared_key_len = ECDH_compute_key(&(p_shared_key->s), shared_key_len, point_pubA, private_key, NULL); - if (shared_key_len <= 0) { + if (EVP_PKEY_derive(pctx, (unsigned char *)(p_shared_key->s), &shared_key_len) <= 0) { break; } // convert big endian to little endian // tmp = BN_bin2bn((unsigned char*)&(p_shared_key->s), sizeof(sgx_ec256_dh_shared_t), 0); - if (tmp == NULL) { - break; - } + if (tmp == NULL) { + break; + } if (BN_bn2lebinpad(tmp, p_shared_key->s, sizeof(sgx_ec256_dh_shared_t)) == -1) { break; } @@ -372,11 +488,9 @@ sgx_status_t sgx_ecc256_compute_shared_dhkey(const sgx_ec256_private_t *p_privat // clear and free memory // - EC_POINT_clear_free(point_pubA); - EC_KEY_free(private_key); - BN_clear_free(BN_dh_privB); - BN_clear_free(pubA_gx); - BN_clear_free(pubA_gy); + EVP_PKEY_free(pkey_peer); + EVP_PKEY_free(pkey_local); + EVP_PKEY_CTX_free(pctx); BN_clear_free(tmp); return ret; @@ -392,93 +506,93 @@ sgx_status_t sgx_ecc256_compute_shared_dhkey(const sgx_ec256_private_t *p_privat */ sgx_status_t sgx_ecc256_calculate_pub_from_priv(const sgx_ec256_private_t *p_att_priv_key, sgx_ec256_public_t *p_att_pub_key) { - if ((p_att_priv_key == NULL) || (p_att_pub_key == NULL)) { - return SGX_ERROR_INVALID_PARAMETER; - } - - sgx_status_t ret = SGX_ERROR_UNEXPECTED; - EC_GROUP* ec_group = NULL; - EC_POINT *pub_ec_point = NULL; - BIGNUM *bn_o = NULL; - BIGNUM *bn_x = NULL; - BIGNUM *bn_y = NULL; - BN_CTX *tmp = NULL; - - do { - //create empty BNs - // - bn_x = BN_new(); - if (NULL == bn_x) { - ret = SGX_ERROR_OUT_OF_MEMORY; - break; - } - bn_y = BN_new(); - if (NULL == bn_y) { - ret = SGX_ERROR_OUT_OF_MEMORY; - break; - } - tmp = BN_CTX_new(); - if (NULL == tmp) { - ret = SGX_ERROR_OUT_OF_MEMORY; - break; - } - - //init bn_o with private key value - // - bn_o = BN_lebin2bn((const unsigned char*)p_att_priv_key, (int)sizeof(sgx_ec256_private_t), bn_o); - BN_CHECK_BREAK(bn_o); - - //create a new ecc group and initialize it to NID_X9_62_prime256v1 curve - // - ec_group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); - if (ec_group == NULL) { - break; - } - - //create a new EC point - // - pub_ec_point = EC_POINT_new(ec_group); - if (pub_ec_point == NULL) { - break; - } - - //calculate public key (point) based on private key. (pub = priv * curve_griup) - // - if (!EC_POINT_mul(ec_group, pub_ec_point, bn_o, NULL, NULL, tmp)) { - break; - } - - //retrieve x and y coordinates into BNs - // - if (!EC_POINT_get_affine_coordinates(ec_group, pub_ec_point, bn_x, bn_y, tmp)) { - break; - } - - //convert the absolute value of BNs into little-endian buffers - // - if (!BN_bn2lebinpad(bn_x, p_att_pub_key->gx, BN_num_bytes(bn_x))) { - break; - } - - if (!BN_bn2lebinpad(bn_y, p_att_pub_key->gy, BN_num_bytes(bn_y))) { - break; - } - - ret = SGX_SUCCESS; - } while (0); - - //in case of failure clear public key - // - if (ret != SGX_SUCCESS) { - (void)memset_s(p_att_pub_key, sizeof(sgx_ec256_public_t), 0, sizeof(sgx_ec256_public_t)); - } - - BN_clear_free(bn_o); - BN_clear_free(bn_x); - BN_clear_free(bn_y); - BN_CTX_free(tmp); - EC_GROUP_clear_free(ec_group); - EC_POINT_clear_free(pub_ec_point); - - return ret; + if ((p_att_priv_key == NULL) || (p_att_pub_key == NULL)) { + return SGX_ERROR_INVALID_PARAMETER; + } + + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + EC_GROUP* ec_group = NULL; + EC_POINT *pub_ec_point = NULL; + BIGNUM *bn_o = NULL; + BIGNUM *bn_x = NULL; + BIGNUM *bn_y = NULL; + BN_CTX *tmp = NULL; + + do { + //create empty BNs + // + bn_x = BN_new(); + if (NULL == bn_x) { + ret = SGX_ERROR_OUT_OF_MEMORY; + break; + } + bn_y = BN_new(); + if (NULL == bn_y) { + ret = SGX_ERROR_OUT_OF_MEMORY; + break; + } + tmp = BN_CTX_new(); + if (NULL == tmp) { + ret = SGX_ERROR_OUT_OF_MEMORY; + break; + } + + //init bn_o with private key value + // + bn_o = BN_lebin2bn((const unsigned char*)p_att_priv_key, (int)sizeof(sgx_ec256_private_t), bn_o); + BN_CHECK_BREAK(bn_o); + + //create a new ecc group and initialize it to NID_X9_62_prime256v1 curve + // + ec_group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); + if (ec_group == NULL) { + break; + } + + //create a new EC point + // + pub_ec_point = EC_POINT_new(ec_group); + if (pub_ec_point == NULL) { + break; + } + + //calculate public key (point) based on private key. (pub = priv * curve_griup) + // + if (!EC_POINT_mul(ec_group, pub_ec_point, bn_o, NULL, NULL, tmp)) { + break; + } + + //retrieve x and y coordinates into BNs + // + if (!EC_POINT_get_affine_coordinates(ec_group, pub_ec_point, bn_x, bn_y, tmp)) { + break; + } + + //convert the absolute value of BNs into little-endian buffers + // + if (!BN_bn2lebinpad(bn_x, p_att_pub_key->gx, BN_num_bytes(bn_x))) { + break; + } + + if (!BN_bn2lebinpad(bn_y, p_att_pub_key->gy, BN_num_bytes(bn_y))) { + break; + } + + ret = SGX_SUCCESS; + } while (0); + + //in case of failure clear public key + // + if (ret != SGX_SUCCESS) { + (void)memset_s(p_att_pub_key, sizeof(sgx_ec256_public_t), 0, sizeof(sgx_ec256_public_t)); + } + + BN_clear_free(bn_o); + BN_clear_free(bn_x); + BN_clear_free(bn_y); + BN_CTX_free(tmp); + EC_GROUP_free(ec_group); + EC_POINT_clear_free(pub_ec_point); + + return ret; } diff --git a/sdk/tlibcrypto/sgxssl/sgx_ecc256_ecdsa.cpp b/sdk/tlibcrypto/sgxssl/sgx_ecc256_ecdsa.cpp index e70918b56..9cb8cedf3 100644 --- a/sdk/tlibcrypto/sgxssl/sgx_ecc256_ecdsa.cpp +++ b/sdk/tlibcrypto/sgxssl/sgx_ecc256_ecdsa.cpp @@ -34,10 +34,13 @@ #include #include #include +#include #include "ssl_wrapper.h" #include "se_memcpy.h" #include "sgx_tcrypto.h" +extern EVP_PKEY *get_priv_key_from_bin(const sgx_ec256_private_t *p_private, sgx_ecc_state_handle_t ecc_handle); +extern EVP_PKEY *get_pub_key_from_coords(const sgx_ec256_public_t *p_public, sgx_ecc_state_handle_t ecc_handle); /* Computes signature for data based on private key * Parameters: * Return: sgx_status_t - SGX_SUCCESS or failure as defined sgx_error.h @@ -57,55 +60,51 @@ sgx_status_t sgx_ecdsa_sign(const uint8_t *p_data, return SGX_ERROR_INVALID_PARAMETER; } - EC_KEY *private_key = NULL; - BIGNUM *bn_priv = NULL; + EVP_PKEY *private_key = NULL; + EVP_MD_CTX *mctx = NULL; ECDSA_SIG *ecdsa_sig = NULL; const BIGNUM *r = NULL; const BIGNUM *s = NULL; - unsigned char digest[SGX_SHA256_HASH_SIZE] = { 0 }; + unsigned char *sig_data = NULL; + unsigned char *sig_tmp = NULL; int written_bytes = 0; - int sig_size = 0; - int max_sig_size = 0; + size_t sig_size = 0; sgx_status_t retval = SGX_ERROR_UNEXPECTED; do { - // converts the r value of private key, represented as positive integer in little-endian into a BIGNUM - // - bn_priv = BN_lebin2bn((unsigned char*)p_private->r, sizeof(p_private->r), 0); - if (NULL == bn_priv) { + private_key = get_priv_key_from_bin(p_private, ecc_handle); + if (!private_key) { break; } - // create empty ecc key - // - private_key = EC_KEY_new(); - if (NULL == private_key) { - retval = SGX_ERROR_OUT_OF_MEMORY; + mctx = EVP_MD_CTX_new(); + if(!mctx) { break; } - - // sets ecc key group (set curve) - // - if (1 != EC_KEY_set_group(private_key, (EC_GROUP*)ecc_handle)) { + if(1 != EVP_DigestSignInit(mctx, NULL, EVP_sha256(), NULL, private_key)) { break; } - // uses bn_priv to set the ecc private key - // - if (1 != EC_KEY_set_private_key(private_key, bn_priv)) { + if(1 != EVP_DigestSignUpdate(mctx, p_data, data_size)) { break; } - - /* generates digest of p_data */ - if (NULL == SHA256((const unsigned char *)p_data, data_size, (unsigned char *)digest)) { + if(1 != EVP_DigestSignFinal(mctx, NULL, &sig_size)) { break; } - - // computes a digital signature of the SGX_SHA256_HASH_SIZE bytes hash value dgst using the private EC key private_key. - // the signature is returned as a newly allocated ECDSA_SIG structure. - // - ecdsa_sig = ECDSA_do_sign(digest, SGX_SHA256_HASH_SIZE, private_key); + sig_data = (unsigned char*)OPENSSL_malloc(sig_size); + if (sig_data == NULL) { + break; + } + if(1 != EVP_DigestSignFinal(mctx, sig_data, &sig_size)) { + break; + } + ecdsa_sig = ECDSA_SIG_new(); if (NULL == ecdsa_sig) { + retval = SGX_ERROR_OUT_OF_MEMORY; + break; + } + sig_tmp = sig_data; + if(NULL == d2i_ECDSA_SIG(&ecdsa_sig, (const unsigned char **)&sig_tmp, sig_size)) { break; } @@ -118,7 +117,6 @@ sgx_status_t sgx_ecdsa_sign(const uint8_t *p_data, if (0 >= written_bytes) { break; } - sig_size = written_bytes; // converts the s BIGNUM of the signature to little endian buffer, bounded with the len of out buffer // @@ -126,31 +124,18 @@ sgx_status_t sgx_ecdsa_sign(const uint8_t *p_data, if (0 >= written_bytes) { break; } - sig_size += written_bytes; - - // returns the maximum length of a DER encoded ECDSA signature created with the private EC key. - // - max_sig_size = ECDSA_size(private_key); - if (max_sig_size <= 0) { - break; - } - - // checks if the signature size not larger than the max len of valid signature - // this check if done for validity, not for overflow. - // - if (sig_size > max_sig_size) { - break; - } retval = SGX_SUCCESS; } while(0); - if (bn_priv) - BN_clear_free(bn_priv); + if (sig_data) + OPENSSL_free(sig_data); if (ecdsa_sig) ECDSA_SIG_free(ecdsa_sig); if (private_key) - EC_KEY_free(private_key); + EVP_PKEY_free(private_key); + if (mctx) + EVP_MD_CTX_free(mctx); return retval; } @@ -162,16 +147,15 @@ sgx_status_t sgx_ecdsa_verify(const uint8_t *p_data, uint8_t *p_result, sgx_ecc_state_handle_t ecc_handle) { - if ((ecc_handle == NULL) || (p_public == NULL) || (p_signature == NULL) || - (p_data == NULL) || (data_size < 1) || (p_result == NULL)) - { - return SGX_ERROR_INVALID_PARAMETER; - } - unsigned char digest[SGX_SHA256_HASH_SIZE] = { 0 }; - - /* generates digest of p_data */ - SHA256((const unsigned char *)p_data, data_size, (unsigned char *)digest); - return (sgx_ecdsa_verify_hash(digest, p_public, p_signature, p_result, ecc_handle)); + if ((ecc_handle == NULL) || (p_public == NULL) || (p_signature == NULL) || + (p_data == NULL) || (data_size < 1) || (p_result == NULL)) { + return SGX_ERROR_INVALID_PARAMETER; + } + unsigned char digest[SGX_SHA256_HASH_SIZE] = { 0 }; + + /* generates digest of p_data */ + SHA256((const unsigned char *)p_data, data_size, (unsigned char *)digest); + return (sgx_ecdsa_verify_hash(digest, p_public, p_signature, p_result, ecc_handle)); } @@ -182,40 +166,27 @@ sgx_status_t sgx_ecdsa_verify_hash(const uint8_t *p_data, sgx_ecc_state_handle_t ecc_handle) { if ((ecc_handle == NULL) || (p_public == NULL) || (p_signature == NULL) || - (p_data == NULL) || (p_result == NULL)) - { + (p_data == NULL) || (p_result == NULL)) { return SGX_ERROR_INVALID_PARAMETER; } - EC_KEY *public_key = NULL; - BIGNUM *bn_pub_x = NULL; - BIGNUM *bn_pub_y = NULL; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *public_key = NULL; BIGNUM *bn_r = NULL; BIGNUM *bn_s = NULL; - BIGNUM *prev_bn_r = NULL; - BIGNUM *prev_bn_s = NULL; - EC_POINT *public_point = NULL; ECDSA_SIG *ecdsa_sig = NULL; + unsigned char *sig_data = NULL; + size_t sig_size = 0; sgx_status_t retval = SGX_ERROR_UNEXPECTED; - int valid = 0; + int ret = -1; *p_result = SGX_EC_INVALID_SIGNATURE; do { - // converts the x value of public key, represented as positive integer in little-endian into a BIGNUM - // - bn_pub_x = BN_lebin2bn((unsigned char*)p_public->gx, sizeof(p_public->gx), 0); - if (NULL == bn_pub_x) { + public_key = get_pub_key_from_coords(p_public, ecc_handle); + if(NULL == public_key) { break; } - - // converts the y value of public key, represented as positive integer in little-endian into a BIGNUM - // - bn_pub_y = BN_lebin2bn((unsigned char*)p_public->gy, sizeof(p_public->gy), 0); - if (NULL == bn_pub_y) { - break; - } - // converts the x value of the signature, represented as positive integer in little-endian into a BIGNUM // bn_r = BN_lebin2bn((unsigned char*)p_signature->x, sizeof(p_signature->x), 0); @@ -230,47 +201,6 @@ sgx_status_t sgx_ecdsa_verify_hash(const uint8_t *p_data, break; } - // creates new point and assigned the group object that the point relates to - // - public_point = EC_POINT_new((EC_GROUP*)ecc_handle); - if (public_point == NULL) { - retval = SGX_ERROR_OUT_OF_MEMORY; - break; - } - - // sets point based on public key's x,y coordinates - // - if (1 != EC_POINT_set_affine_coordinates((EC_GROUP*)ecc_handle, public_point, bn_pub_x, bn_pub_y, NULL)) { - break; - } - - // check point if the point is on curve - // - if (1 != EC_POINT_is_on_curve((EC_GROUP*)ecc_handle, public_point, NULL)) { - break; - } - - // create empty ecc key - // - public_key = EC_KEY_new(); - if (NULL == public_key) { - retval = SGX_ERROR_OUT_OF_MEMORY; - break; - } - - // sets ecc key group (set curve) - // - if (1 != EC_KEY_set_group(public_key, (EC_GROUP*)ecc_handle)) { - break; - } - - // uses the created point to set the public key value - // - if (1 != EC_KEY_set_public_key(public_key, public_point)) { - break; - } - - // allocates a new ECDSA_SIG structure (note: this function also allocates the BIGNUMs) and initialize it // @@ -280,13 +210,6 @@ sgx_status_t sgx_ecdsa_verify_hash(const uint8_t *p_data, break; } - // free internal allocated BIGBNUMs - ECDSA_SIG_get0(ecdsa_sig, (const BIGNUM **)&prev_bn_r, (const BIGNUM **)&prev_bn_s); - if (prev_bn_r) - BN_clear_free(prev_bn_r); - if (prev_bn_s) - BN_clear_free(prev_bn_s); - // setes the r and s values of ecdsa_sig // calling this function transfers the memory management of the values to the ECDSA_SIG object, // and therefore the values that have been passed in should not be freed directly after this function has been called @@ -296,36 +219,42 @@ sgx_status_t sgx_ecdsa_verify_hash(const uint8_t *p_data, ecdsa_sig = NULL; break; } - - // verifies that the signature ecdsa_sig is a valid ECDSA signature of the hash value digest of size SGX_SHA256_HASH_SIZE using the public key public_key - // - valid = ECDSA_do_verify(p_data, SGX_SHA256_HASH_SIZE, ecdsa_sig, public_key); - if (-1 == valid) { + sig_size = i2d_ECDSA_SIG(ecdsa_sig, &sig_data); + if (sig_size <= 0) { + break; + } + ctx = EVP_PKEY_CTX_new(public_key, NULL); + if (!ctx) { + break; + } + if (1 != EVP_PKEY_verify_init(ctx)) { + break; + } + if (1 != EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256())) { + break; + } + ret = EVP_PKEY_verify(ctx, sig_data, sig_size, p_data, SGX_SHA256_HASH_SIZE); + if (ret < 0) { break; } - // sets the p_result based on ECDSA_do_verify result + // sets the p_result based on verification result // - if (valid) { + if (ret == 1) *p_result = SGX_EC_VALID; - } retval = SGX_SUCCESS; } while(0); - if (bn_pub_x) - BN_clear_free(bn_pub_x); - if (bn_pub_y) - BN_clear_free(bn_pub_y); - if (public_point) - EC_POINT_clear_free(public_point); - if (ecdsa_sig) { + if (ecdsa_sig) { ECDSA_SIG_free(ecdsa_sig); bn_r = NULL; bn_s = NULL; } + if (ctx) + EVP_PKEY_CTX_free(ctx); if (public_key) - EC_KEY_free(public_key); + EVP_PKEY_free(public_key); if (bn_r) BN_clear_free(bn_r); if (bn_s) diff --git a/sdk/tlibcrypto/sgxssl/sgx_hmac.cpp b/sdk/tlibcrypto/sgxssl/sgx_hmac.cpp index b24d48962..92734b120 100644 --- a/sdk/tlibcrypto/sgxssl/sgx_hmac.cpp +++ b/sdk/tlibcrypto/sgxssl/sgx_hmac.cpp @@ -35,6 +35,8 @@ #include "se_tcrypto_common.h" #include "openssl/hmac.h" #include "openssl/err.h" +#include +#include /* Message Authentication - HMAC 256 * Parameters: @@ -49,9 +51,9 @@ sgx_status_t sgx_hmac_sha256_msg(const unsigned char *p_src, int src_len, const unsigned char *p_key, int key_len, unsigned char *p_mac, int mac_len) { - if ((p_src == NULL) || (p_key == NULL) || (p_mac == NULL) || (src_len <= 0) || (key_len <= 0) || (mac_len <= 0)) { - return SGX_ERROR_INVALID_PARAMETER; - } + if ((p_src == NULL) || (p_key == NULL) || (p_mac == NULL) || (src_len <= 0) || (key_len <= 0) || (mac_len <= 0)) { + return SGX_ERROR_INVALID_PARAMETER; + } sgx_status_t ret = SGX_ERROR_UNEXPECTED; unsigned char *ret_mac = NULL; @@ -79,38 +81,53 @@ sgx_status_t sgx_hmac_sha256_msg(const unsigned char *p_src, int src_len, const * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h * Inputs: const unsigned char *p_key - Pointer to the key used in message authentication operation * int key_len - Key length -* Output: sgx_hmac_state_handle_t *p_hmac_handle - Pointer to the initialized HMAC state handle +* Output: sgx_hmac_state_handle_t *p_hmac_handle - Pointer to the initialized EVP_MAC_CTX state handle */ sgx_status_t sgx_hmac256_init(const unsigned char *p_key, int key_len, sgx_hmac_state_handle_t *p_hmac_handle) { + OSSL_LIB_CTX *lib_ctx = NULL; + EVP_MAC *mac = NULL; + EVP_MAC_CTX *mctx = NULL; + OSSL_PARAM params[2] = {OSSL_PARAM_END, OSSL_PARAM_END}; + char digest_name[] = "SHA256"; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + if ((p_key == NULL) || (key_len <= 0) || (p_hmac_handle == NULL)) { return SGX_ERROR_INVALID_PARAMETER; } - sgx_status_t ret = SGX_ERROR_UNEXPECTED; - void* pState = NULL; - do { - // create HMAC ctx - // - pState = HMAC_CTX_new(); - if (pState == NULL) { + if ((lib_ctx = OSSL_LIB_CTX_new()) == NULL) + { + ret = SGX_ERROR_OUT_OF_MEMORY; + break; + } + if ((mac = EVP_MAC_fetch(lib_ctx, "HMAC", NULL)) == NULL) + { ret = SGX_ERROR_OUT_OF_MEMORY; break; } - //init HMAC ctx - // - if (!HMAC_Init_ex((HMAC_CTX*)pState, (const void *)p_key, key_len, EVP_sha256(), NULL)) { + if ((mctx = EVP_MAC_CTX_new(mac)) == NULL) { + ret = SGX_ERROR_OUT_OF_MEMORY; + break; + } + + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, digest_name, sizeof(digest_name)); + + if ((!EVP_MAC_init(mctx, (const uint8_t *)p_key, sizeof(sgx_key_128bit_t), params))) { break; } - *p_hmac_handle = pState; + *p_hmac_handle = mctx; ret = SGX_SUCCESS; } while (0); + + EVP_MAC_free(mac); + OSSL_LIB_CTX_free(lib_ctx); if (ret != SGX_SUCCESS) { - sgx_hmac256_close((sgx_hmac_state_handle_t)pState); + EVP_MAC_CTX_free(mctx); } return ret; @@ -121,17 +138,17 @@ sgx_status_t sgx_hmac256_init(const unsigned char *p_key, int key_len, sgx_hmac_ * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error. * Input: uint8_t *p_src - Pointer to the input stream to be hashed * int src_len - Length of input stream to be hashed -* sgx_hmac_state_handle_t hmac_handle - Handle to the HMAC state +* sgx_hmac_state_handle_t hmac_handle - Handle to the EVP_MAC_CTX state */ sgx_status_t sgx_hmac256_update(const uint8_t *p_src, int src_len, sgx_hmac_state_handle_t hmac_handle) { - if ((p_src == NULL) || (src_len <= 0) || (hmac_handle == NULL)) { - return SGX_ERROR_INVALID_PARAMETER; - } - sgx_status_t ret = SGX_ERROR_UNEXPECTED; + if ((p_src == NULL) || (src_len <= 0) || (hmac_handle == NULL)) { + return SGX_ERROR_INVALID_PARAMETER; + } + sgx_status_t ret = SGX_ERROR_UNEXPECTED; do { - if (!HMAC_Update((HMAC_CTX *)hmac_handle, p_src, src_len)) { + if (!EVP_MAC_update((EVP_MAC_CTX *)hmac_handle, p_src, src_len)) { break; } @@ -144,7 +161,7 @@ sgx_status_t sgx_hmac256_update(const uint8_t *p_src, int src_len, sgx_hmac_stat /* Returns calculated hash * Parameters: * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h -* Input: sgx_hmac_state_handle_t hmac_handle - Handle to the HMAC state +* Input: sgx_hmac_state_handle_t hmac_handle - Handle to the EVP_MAC_CTX state * int hash_len - Expected MAC length * Output: unsigned char *p_hash - Resultant hash from HMAC operation */ @@ -154,10 +171,10 @@ sgx_status_t sgx_hmac256_final(unsigned char *p_hash, int hash_len, sgx_hmac_sta return SGX_ERROR_INVALID_PARAMETER; } sgx_status_t ret = SGX_ERROR_UNEXPECTED; - unsigned int mactlen; + size_t mactlen; do { - if (!HMAC_Final((HMAC_CTX*)hmac_handle, (unsigned char*)p_hash, &mactlen)) { + if (!EVP_MAC_final((EVP_MAC_CTX*)hmac_handle, (unsigned char*)p_hash, &mactlen, hash_len)) { break; } if (mactlen != (size_t)hash_len) { @@ -178,13 +195,13 @@ sgx_status_t sgx_hmac256_final(unsigned char *p_hash, int hash_len, sgx_hmac_sta /* Clean up and free the HMAC state * Parameters: * Return: sgx_status_t - SGX_SUCCESS -* Input: sgx_hmac_state_handle_t hmac_handle - Handle to the HMAC state +* Input: sgx_hmac_state_handle_t hmac_handle - Handle to the EVP_MAC_CTX state * */ sgx_status_t sgx_hmac256_close(sgx_hmac_state_handle_t hmac_handle) { if (hmac_handle != NULL) { - HMAC_CTX* pState = (HMAC_CTX*)hmac_handle; - HMAC_CTX_free(pState); + EVP_MAC_CTX* pState = (EVP_MAC_CTX*)hmac_handle; + EVP_MAC_CTX_free(pState); hmac_handle = NULL; } diff --git a/sdk/tlibcrypto/sgxssl/sgx_rsa3072.cpp b/sdk/tlibcrypto/sgxssl/sgx_rsa3072.cpp index ff406681d..5ff5b8d51 100644 --- a/sdk/tlibcrypto/sgxssl/sgx_rsa3072.cpp +++ b/sdk/tlibcrypto/sgxssl/sgx_rsa3072.cpp @@ -44,73 +44,19 @@ sgx_status_t sgx_rsa3072_sign(const uint8_t * p_data, sgx_rsa3072_signature_t * p_signature) { if ((p_data == NULL) || (data_size < 1) || (p_key == NULL) || - (p_signature == NULL)) - { + (p_signature == NULL)) { return SGX_ERROR_INVALID_PARAMETER; } sgx_status_t retval = SGX_ERROR_UNEXPECTED; - RSA *priv_rsa_key = NULL; EVP_PKEY* priv_pkey = NULL; - BIGNUM *n = NULL; - BIGNUM *d = NULL; - BIGNUM *e = NULL; EVP_MD_CTX* ctx = NULL; const EVP_MD* sha256_md = NULL; size_t siglen = SGX_RSA3072_KEY_SIZE; - int ret = 0; do { - // converts the modulus value of rsa key, represented as positive integer in little-endian into a BIGNUM - // - n = BN_lebin2bn((const unsigned char *)p_key->mod, sizeof(p_key->mod), 0); - if (n == NULL) { - break; - } - - // converts the private exp value of rsa key, represented as positive integer in little-endian into a BIGNUM - // - d = BN_lebin2bn((const unsigned char *)p_key->d, sizeof(p_key->d), 0); - if (d == NULL) { - break; - } - - // converts the public exp value of rsa key, represented as positive integer in little-endian into a BIGNUM - // - e = BN_lebin2bn((const unsigned char *)p_key->e, sizeof(p_key->e), 0); - if (e == NULL) { - break; - } - - // allocates and initializes an RSA key structure - // - priv_rsa_key = RSA_new(); - if (priv_rsa_key == NULL) { - retval = SGX_ERROR_OUT_OF_MEMORY; - break; - } - - // sets the modulus, private exp and public exp values of the RSA key - // - if (RSA_set0_key(priv_rsa_key, n, e, d) != 1) { - BN_clear_free(n); - BN_clear_free(d); - BN_clear_free(e); - break; - } - - // allocates an empty EVP_PKEY structure - // - priv_pkey = EVP_PKEY_new(); - if (priv_pkey == NULL) { - retval = SGX_ERROR_OUT_OF_MEMORY; - break; - } - - // set the referenced key to pub_rsa_key, however these use the supplied key internally and so key will be freed when the parent pkey is freed - // - if (EVP_PKEY_assign_RSA(priv_pkey, priv_rsa_key) != 1) { - RSA_free(priv_rsa_key); + if (SGX_SUCCESS != sgx_create_rsa_priv1_key(sizeof(p_key->mod), sizeof(p_key->e), sizeof(p_key->d), p_key->mod, p_key->e, p_key->d, (void **)&priv_pkey) + || NULL == priv_pkey) { break; } @@ -143,8 +89,7 @@ sgx_status_t sgx_rsa3072_sign(const uint8_t * p_data, // signs the data in ctx places the signature in p_signature. // - ret = EVP_DigestSignFinal(ctx, (unsigned char *)p_signature, &siglen);//fails - if (ret <= 0) { + if (EVP_DigestSignFinal(ctx, (unsigned char *)p_signature, &siglen) <= 0) { //fails break; } @@ -161,23 +106,7 @@ sgx_status_t sgx_rsa3072_sign(const uint8_t * p_data, EVP_MD_CTX_free(ctx); if (priv_pkey) { EVP_PKEY_free(priv_pkey); - priv_rsa_key = NULL; - n = NULL; - d = NULL; - e = NULL; - } - if (priv_rsa_key) { - RSA_free(priv_rsa_key); - n = NULL; - d = NULL; - e = NULL; } - if (n) - BN_clear_free(n); - if (d) - BN_clear_free(d); - if (e) - BN_clear_free(e); return retval; } @@ -189,64 +118,19 @@ sgx_status_t sgx_rsa3072_verify(const uint8_t *p_data, sgx_rsa_result_t *p_result) { if ((p_data == NULL) || (data_size < 1) || (p_public == NULL) || - (p_signature == NULL) || (p_result == NULL)) - { + (p_signature == NULL) || (p_result == NULL)) { return SGX_ERROR_INVALID_PARAMETER; } *p_result = SGX_RSA_INVALID_SIGNATURE; sgx_status_t retval = SGX_ERROR_UNEXPECTED; int verified = 0; - RSA *pub_rsa_key = NULL; EVP_PKEY *pub_pkey = NULL; - BIGNUM *n = NULL; - BIGNUM *e = NULL; const EVP_MD* sha256_md = NULL; EVP_MD_CTX *ctx = NULL; do { - // converts the modulus value of rsa key, represented as positive integer in little-endian into a BIGNUM - // - n = BN_lebin2bn((const unsigned char *)p_public->mod, sizeof(p_public->mod), 0); - if (n == NULL) { - break; - } - - // converts the public exp value of rsa key, represented as positive integer in little-endian into a BIGNUM - // - e = BN_lebin2bn((const unsigned char *)p_public->exp, sizeof(p_public->exp), 0); - if (e == NULL) { - break; - } - - // allocates and initializes an RSA key structure - // - pub_rsa_key = RSA_new(); - if (pub_rsa_key == NULL) { - retval = SGX_ERROR_OUT_OF_MEMORY; - break; - } - - // sets the modulus and public exp values of the RSA key - // - if (RSA_set0_key(pub_rsa_key, n, e, NULL) != 1) { - BN_clear_free(n); - BN_clear_free(e); - break; - } - - // allocates an empty EVP_PKEY structure - // - pub_pkey = EVP_PKEY_new(); - if (pub_pkey == NULL) { - retval = SGX_ERROR_OUT_OF_MEMORY; - break; - } - - // set the referenced key to pub_rsa_key, however these use the supplied key internally and so key will be freed when the parent pkey is freed - // - if (EVP_PKEY_assign_RSA(pub_pkey, pub_rsa_key) != 1) { - RSA_free(pub_rsa_key); + if (SGX_SUCCESS != sgx_create_rsa_pub1_key(sizeof(p_public->mod), sizeof(p_public->exp), p_public->mod, p_public->exp, (void**)&pub_pkey)) { break; } @@ -258,7 +142,7 @@ sgx_status_t sgx_rsa3072_verify(const uint8_t *p_data, break; } - // return EVP_MD structures for SHA256 digest algorithm */ + // return EVP_MD structures for SHA256 digest algorithm // sha256_md = EVP_sha256(); if (sha256_md == NULL) { @@ -295,19 +179,7 @@ sgx_status_t sgx_rsa3072_verify(const uint8_t *p_data, EVP_MD_CTX_free(ctx); if (pub_pkey) { EVP_PKEY_free(pub_pkey); - pub_rsa_key = NULL; - n = NULL; - e = NULL; } - if (pub_rsa_key) { - RSA_free(pub_rsa_key); - n = NULL; - e = NULL; - } - if (n) - BN_clear_free(n); - if (e) - BN_clear_free(e); return retval; } @@ -321,7 +193,6 @@ sgx_status_t sgx_rsa3072_sign_ex(const uint8_t * p_data, sgx_status_t retval = SGX_ERROR_UNEXPECTED; sgx_rsa_result_t result = SGX_RSA_INVALID_SIGNATURE; - if (p_public == NULL) return sgx_rsa3072_sign(p_data, data_size, p_key, p_signature); @@ -336,3 +207,4 @@ sgx_status_t sgx_rsa3072_sign_ex(const uint8_t * p_data, } return retval; } + diff --git a/sdk/tlibcrypto/sgxssl/sgx_rsa_encryption.cpp b/sdk/tlibcrypto/sgxssl/sgx_rsa_encryption.cpp index c77fb741a..96e254707 100644 --- a/sdk/tlibcrypto/sgxssl/sgx_rsa_encryption.cpp +++ b/sdk/tlibcrypto/sgxssl/sgx_rsa_encryption.cpp @@ -47,6 +47,8 @@ #include #include #include +#include +#include #include "ssl_wrapper.h" sgx_status_t sgx_create_rsa_key_pair(int n_byte_size, int e_byte_size, unsigned char *p_n, unsigned char *p_d, unsigned char *p_e, @@ -59,7 +61,8 @@ sgx_status_t sgx_create_rsa_key_pair(int n_byte_size, int e_byte_size, unsigned } sgx_status_t ret_code = SGX_ERROR_UNEXPECTED; - RSA* rsa_ctx = NULL; + EVP_PKEY* pkey = NULL; + EVP_PKEY_CTX* pkey_ctx = NULL; BIGNUM* bn_n = NULL; BIGNUM* bn_e = NULL; BIGNUM* tmp_bn_e = NULL; @@ -73,32 +76,55 @@ sgx_status_t sgx_create_rsa_key_pair(int n_byte_size, int e_byte_size, unsigned do { //create new rsa ctx // - rsa_ctx = RSA_new(); - if (rsa_ctx == NULL) { + pkey_ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + if (pkey_ctx == NULL) { ret_code = SGX_ERROR_OUT_OF_MEMORY; break; } + if (EVP_PKEY_keygen_init(pkey_ctx) <= 0) { + break; + } //generate rsa key pair, with n_byte_size*8 mod size and p_e exponent // tmp_bn_e = BN_lebin2bn(p_e, e_byte_size, tmp_bn_e); BN_CHECK_BREAK(tmp_bn_e); - if (RSA_generate_key_ex(rsa_ctx, n_byte_size * 8, tmp_bn_e, NULL) != 1) { - break; + if (EVP_PKEY_CTX_set_rsa_keygen_bits(pkey_ctx, n_byte_size * 8) <= 0) { + break; } - - //validate RSA key size match input parameter n size - // - int gen_rsa_size = RSA_size(rsa_ctx); - if (gen_rsa_size != n_byte_size) { + if (EVP_PKEY_CTX_set1_rsa_keygen_pubexp(pkey_ctx, tmp_bn_e) <= 0) { + break; + } + if (EVP_PKEY_generate(pkey_ctx, &pkey) <= 0) { break; } //get RSA key internal values // - RSA_get0_key(rsa_ctx, (const BIGNUM**)(&bn_n), (const BIGNUM**)(&bn_e), (const BIGNUM**)(&bn_d)); - RSA_get0_factors(rsa_ctx, (const BIGNUM**)(&bn_p), (const BIGNUM**)(&bn_q)); - RSA_get0_crt_params(rsa_ctx, (const BIGNUM**)(&bn_dmp1), (const BIGNUM**)(&bn_dmq1), (const BIGNUM**)(&bn_iqmp)); + if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn_n) == 0) { + break; + } + if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn_e) == 0) { + break; + } + if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_D, &bn_d) == 0) { + break; + } + if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_FACTOR1, &bn_p) == 0) { + break; + } + if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_FACTOR2, &bn_q) == 0) { + break; + } + if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_EXPONENT1, &bn_dmp1) == 0) { + break; + } + if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_EXPONENT2, &bn_dmq1) == 0) { + break; + } + if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, &bn_iqmp) == 0) { + break; + } //copy the generated key to input pointers // @@ -118,8 +144,17 @@ sgx_status_t sgx_create_rsa_key_pair(int n_byte_size, int e_byte_size, unsigned //free rsa ctx (RSA_free also free related BNs obtained in RSA_get functions) // - RSA_free(rsa_ctx); + EVP_PKEY_CTX_free(pkey_ctx); + EVP_PKEY_free(pkey); BN_clear_free(tmp_bn_e); + BN_clear_free(bn_n); + BN_clear_free(bn_d); + BN_clear_free(bn_e); + BN_clear_free(bn_p); + BN_clear_free(bn_q); + BN_clear_free(bn_dmp1); + BN_clear_free(bn_dmq1); + BN_clear_free(bn_iqmp); return ret_code; } @@ -134,9 +169,8 @@ sgx_status_t sgx_create_rsa_priv2_key(int mod_size, int exp_size, const unsigned return SGX_ERROR_INVALID_PARAMETER; } - bool rsa_memory_manager = 0; + EVP_PKEY_CTX* rsa_ctx = NULL; EVP_PKEY *rsa_key = NULL; - RSA *rsa_ctx = NULL; sgx_status_t ret_code = SGX_ERROR_UNEXPECTED; BIGNUM* n = NULL; BIGNUM* e = NULL; @@ -147,6 +181,8 @@ sgx_status_t sgx_create_rsa_priv2_key(int mod_size, int exp_size, const unsigned BIGNUM* q = NULL; BIGNUM* p = NULL; BN_CTX* tmp_ctx = NULL; + OSSL_PARAM_BLD *param_build = NULL; + OSSL_PARAM *params = NULL; do { tmp_ctx = BN_CTX_new(); @@ -193,39 +229,31 @@ sgx_status_t sgx_create_rsa_priv2_key(int mod_size, int exp_size, const unsigned // allocates and initializes an RSA key structure // - rsa_ctx = RSA_new(); - rsa_key = EVP_PKEY_new(); - - //EVP_PKEY_assign_RSA() use the supplied key internally and so if this call succeed, key will be freed when the parent pkey is freed. - // - if (rsa_ctx == NULL || rsa_key == NULL || !EVP_PKEY_assign_RSA(rsa_key, rsa_ctx)) { - RSA_free(rsa_ctx); - rsa_key = NULL; + rsa_ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + if (rsa_ctx == NULL) { + ret_code = SGX_ERROR_OUT_OF_MEMORY; break; } - - //setup RSA key with input values - //Calling set functions transfers the memory management of the values to the RSA object, - //and therefore the values that have been passed in should not be freed by the caller after these functions has been called. - // - if (!RSA_set0_factors(rsa_ctx, p, q)) { + param_build = OSSL_PARAM_BLD_new(); + if (param_build == NULL) { break; } - rsa_memory_manager = 1; - if (!RSA_set0_crt_params(rsa_ctx, dmp1, dmq1, iqmp)) { - BN_clear_free(n); - BN_clear_free(e); - BN_clear_free(d); - BN_clear_free(dmp1); - BN_clear_free(dmq1); - BN_clear_free(iqmp); + if( !OSSL_PARAM_BLD_push_BN(param_build, "n", n) + || !OSSL_PARAM_BLD_push_BN(param_build, "e", e) + || !OSSL_PARAM_BLD_push_BN(param_build, "d", d) + || !OSSL_PARAM_BLD_push_BN(param_build, "rsa-factor1", p) + || !OSSL_PARAM_BLD_push_BN(param_build, "rsa-factor2", q) + || !OSSL_PARAM_BLD_push_BN(param_build, "rsa-exponent1", dmp1) + || !OSSL_PARAM_BLD_push_BN(param_build, "rsa-exponent2", dmq1) + || !OSSL_PARAM_BLD_push_BN(param_build, "rsa-coefficient1", iqmp) + || (params = OSSL_PARAM_BLD_to_param(param_build)) == NULL) { break; } - - if (!RSA_set0_key(rsa_ctx, n, e, d)) { - BN_clear_free(n); - BN_clear_free(e); - BN_clear_free(d); + if( EVP_PKEY_fromdata_init(rsa_ctx) <= 0) { + break; + } + if( EVP_PKEY_fromdata(rsa_ctx, &rsa_key, EVP_PKEY_KEYPAIR, params) <= 0) { + EVP_PKEY_free(rsa_key); break; } @@ -233,26 +261,19 @@ sgx_status_t sgx_create_rsa_priv2_key(int mod_size, int exp_size, const unsigned ret_code = SGX_SUCCESS; } while (0); + OSSL_PARAM_BLD_free(param_build); + OSSL_PARAM_free(params); + EVP_PKEY_CTX_free(rsa_ctx); + BN_clear_free(n); + BN_clear_free(e); + BN_clear_free(d); + BN_clear_free(dmp1); + BN_clear_free(dmq1); + BN_clear_free(iqmp); + BN_clear_free(q); + BN_clear_free(p); BN_CTX_free(tmp_ctx); - //in case of failure, free allocated BNs and RSA struct - // - if (ret_code != SGX_SUCCESS) { - //BNs were not assigned to rsa ctx yet, user code must free allocated BNs - // - if (!rsa_memory_manager) { - BN_clear_free(n); - BN_clear_free(e); - BN_clear_free(d); - BN_clear_free(dmp1); - BN_clear_free(dmq1); - BN_clear_free(iqmp); - BN_clear_free(q); - BN_clear_free(p); - } - EVP_PKEY_free(rsa_key); - } - return ret_code; } @@ -263,10 +284,12 @@ sgx_status_t sgx_create_rsa_pub1_key(int mod_size, int exp_size, const unsigned } EVP_PKEY *rsa_key = NULL; - RSA *rsa_ctx = NULL; + EVP_PKEY_CTX *rsa_ctx = NULL; sgx_status_t ret_code = SGX_ERROR_UNEXPECTED; BIGNUM* n = NULL; BIGNUM* e = NULL; + OSSL_PARAM_BLD *param_build = NULL; + OSSL_PARAM *params = NULL; do { //convert input buffers to BNs @@ -276,33 +299,37 @@ sgx_status_t sgx_create_rsa_pub1_key(int mod_size, int exp_size, const unsigned e = BN_lebin2bn(le_e, exp_size, e); BN_CHECK_BREAK(e); - // allocates and initializes an RSA key structure - // - rsa_ctx = RSA_new(); - rsa_key = EVP_PKEY_new(); - - if (rsa_ctx == NULL || rsa_key == NULL || !EVP_PKEY_assign_RSA(rsa_key, rsa_ctx)) { - RSA_free(rsa_ctx); - rsa_ctx = NULL; + rsa_ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + if (rsa_ctx == NULL) { + ret_code = SGX_ERROR_OUT_OF_MEMORY; break; } - - //set n, e values of RSA key - //Calling set functions transfers the memory management of input BNs to the RSA object, - //and therefore the values that have been passed in should not be freed by the caller after these functions has been called. - // - if (!RSA_set0_key(rsa_ctx, n, e, NULL)) { + param_build = OSSL_PARAM_BLD_new(); + if (param_build == NULL) { + break; + } + if( !OSSL_PARAM_BLD_push_BN(param_build, "n", n) + || !OSSL_PARAM_BLD_push_BN(param_build, "e", e) + || (params = OSSL_PARAM_BLD_to_param(param_build)) == NULL) { + break; + } + if( EVP_PKEY_fromdata_init(rsa_ctx) <= 0) { break; } + if( EVP_PKEY_fromdata(rsa_ctx, &rsa_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) { + EVP_PKEY_free(rsa_key); + break; + } + *new_pub_key1 = rsa_key; ret_code = SGX_SUCCESS; } while (0); - if (ret_code != SGX_SUCCESS) { - EVP_PKEY_free(rsa_key); - BN_clear_free(n); - BN_clear_free(e); - } + EVP_PKEY_CTX_free(rsa_ctx); + OSSL_PARAM_BLD_free(param_build); + OSSL_PARAM_free(params); + BN_clear_free(n); + BN_clear_free(e); return ret_code; } @@ -434,11 +461,13 @@ sgx_status_t sgx_create_rsa_priv1_key(int n_byte_size, int e_byte_size, int d_by } EVP_PKEY *rsa_key = NULL; - RSA *rsa_ctx = NULL; + EVP_PKEY_CTX *rsa_ctx = NULL; sgx_status_t ret_code = SGX_ERROR_UNEXPECTED; BIGNUM* n = NULL; BIGNUM* e = NULL; BIGNUM* d = NULL; + OSSL_PARAM_BLD *param_build = NULL; + OSSL_PARAM *params = NULL; do { //convert input buffers to BNs @@ -450,24 +479,26 @@ sgx_status_t sgx_create_rsa_priv1_key(int n_byte_size, int e_byte_size, int d_by d = BN_lebin2bn(le_d, d_byte_size, d); BN_CHECK_BREAK(d); - // allocates and initializes an RSA key structure - // - rsa_ctx = RSA_new(); - rsa_key = EVP_PKEY_new(); - - //EVP_PKEY_assign_RSA() use the supplied key internally and so if this call succeed, key will be freed when the parent pkey is freed. - // - if (rsa_ctx == NULL || rsa_key == NULL || !EVP_PKEY_assign_RSA(rsa_key, rsa_ctx)) { - RSA_free(rsa_ctx); - rsa_ctx = NULL; + rsa_ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + if (rsa_ctx == NULL) { + ret_code = SGX_ERROR_OUT_OF_MEMORY; break; } - - //set n, e, d values of RSA key - //Calling set functions transfers the memory management of input BNs to the RSA object, - //and therefore the values that have been passed in should not be freed by the caller after these functions has been called. - // - if (!RSA_set0_key(rsa_ctx, n, e, d)) { + param_build = OSSL_PARAM_BLD_new(); + if (param_build == NULL) { + break; + } + if( !OSSL_PARAM_BLD_push_BN(param_build, "n", n) + || !OSSL_PARAM_BLD_push_BN(param_build, "e", e) + || !OSSL_PARAM_BLD_push_BN(param_build, "d", d) + || (params = OSSL_PARAM_BLD_to_param(param_build)) == NULL) { + break; + } + if( EVP_PKEY_fromdata_init(rsa_ctx) <= 0) { + break; + } + if( EVP_PKEY_fromdata(rsa_ctx, &rsa_key, EVP_PKEY_KEYPAIR, params) <= 0) { + EVP_PKEY_free(rsa_key); break; } @@ -475,12 +506,12 @@ sgx_status_t sgx_create_rsa_priv1_key(int n_byte_size, int e_byte_size, int d_by ret_code = SGX_SUCCESS; } while (0); - if (ret_code != SGX_SUCCESS) { - EVP_PKEY_free(rsa_key); - BN_clear_free(n); - BN_clear_free(e); - BN_clear_free(d); - } + EVP_PKEY_CTX_free(rsa_ctx); + OSSL_PARAM_BLD_free(param_build); + OSSL_PARAM_free(params); + BN_clear_free(n); + BN_clear_free(e); + BN_clear_free(d); return ret_code; } diff --git a/sdk/trts/trts_aex.cpp b/sdk/trts/trts_aex.cpp index 984c07f05..242c9735f 100644 --- a/sdk/trts/trts_aex.cpp +++ b/sdk/trts/trts_aex.cpp @@ -80,6 +80,13 @@ sgx_status_t SGXAPI sgx_register_aex_handler(sgx_aex_mitigation_node_t *aex_node { if (aex_node == NULL || handler == NULL) return SGX_ERROR_INVALID_PARAMETER; + + auto aex_enabled = get_ssa_aexnotify(); + //temporary disabled aex-notify to avoid being interupted during register handler + if(aex_enabled) + { + sgx_set_ssa_aexnotify(0); + } thread_data_t *thread_data = get_thread_data(); sgx_aex_mitigation_node_t *head = (sgx_aex_mitigation_node_t *)thread_data->aex_mitigation_list; @@ -90,6 +97,10 @@ sgx_status_t SGXAPI sgx_register_aex_handler(sgx_aex_mitigation_node_t *aex_node thread_data->aex_mitigation_list = (sys_word_t) head; + if(aex_enabled) + { + sgx_set_ssa_aexnotify(1); + } return SGX_SUCCESS; } @@ -97,13 +108,23 @@ sgx_status_t SGXAPI sgx_unregister_aex_handler(sgx_aex_mitigation_fn_t handler) { if(handler == NULL) return SGX_ERROR_INVALID_PARAMETER; + sgx_status_t ret = SGX_SUCCESS; + auto aex_enabled = get_ssa_aexnotify(); + //temporary disabled aex-notify to avoid being interupted during unregister handler + if(aex_enabled) + { + sgx_set_ssa_aexnotify(0); + } // Search and find out the aex_node corresponding to the handler thread_data_t *thread_data = get_thread_data(); sgx_aex_mitigation_node_t *node = (sgx_aex_mitigation_node_t *)thread_data->aex_mitigation_list; sgx_aex_mitigation_node_t *prev_node = NULL; if(node == NULL) - return SGX_ERROR_UNEXPECTED; + { + ret = SGX_ERROR_UNEXPECTED; + goto clean_return; + } while(node) { @@ -127,9 +148,15 @@ sgx_status_t SGXAPI sgx_unregister_aex_handler(sgx_aex_mitigation_fn_t handler) } else // node not found { - return SGX_ERROR_INVALID_PARAMETER; + ret = SGX_ERROR_INVALID_PARAMETER; + goto clean_return; } - return SGX_SUCCESS; + clean_return: + if(aex_enabled) + { + sgx_set_ssa_aexnotify(1); + } + return ret; } diff --git a/sdk/trts/trts_ecall.cpp b/sdk/trts/trts_ecall.cpp index a4ea8e2a6..772b33613 100644 --- a/sdk/trts/trts_ecall.cpp +++ b/sdk/trts/trts_ecall.cpp @@ -70,6 +70,7 @@ __attribute__((weak)) void _pthread_tls_destructors(void) {} extern "C" __attribute__((weak)) void tc_set_idle() {} +extern int g_aexnotify_supported; // is_ecall_allowed() // check the index in the dynamic entry table @@ -352,6 +353,11 @@ sgx_status_t do_init_thread(void *tcs, bool enclave_init) thread_data->flags = SGX_UTILITY_THREAD; } #ifndef SE_SIM + if(g_aexnotify_supported == 1) + { + thread_data->aex_notify_flag = 1; + } + if (thread_first_init) { if (EDMM_supported && (enclave_init || is_dynamic_thread(tcs))) diff --git a/sdk/trts/trts_veh.cpp b/sdk/trts/trts_veh.cpp index 11504d49d..a30f1ed30 100644 --- a/sdk/trts/trts_veh.cpp +++ b/sdk/trts/trts_veh.cpp @@ -191,14 +191,15 @@ int sgx_unregister_exception_handler(void *handler) return status; } -extern "C" __attribute__((regparm(1))) void second_phase(sgx_exception_info_t *info, - void *new_sp, void *second_phase_handler_addr); - // continue_execution(sgx_exception_info_t *info): // try to restore the thread context saved in info to current execution context. extern "C" __attribute__((regparm(1))) void continue_execution(sgx_exception_info_t *info); extern "C" void restore_xregs(uint8_t *buf); +#ifndef SE_SIM +extern "C" __attribute__((regparm(1))) void second_phase(sgx_exception_info_t *info, + void *new_sp, void *second_phase_handler_addr); + extern "C" void constant_time_apply_sgxstep_mitigation_and_continue_execution(sgx_exception_info_t *info, uintptr_t ssa_aexnotify_addr, uintptr_t stack_tickle_pages, uintptr_t code_tickle_page, uintptr_t data_tickle_address, uintptr_t c3_byte_address); @@ -308,12 +309,11 @@ static void apply_constant_time_sgxstep_mitigation_and_continue_execution(sgx_ex stack_tickle_pages, code_tickle_page, data_tickle_address, c3_byte_address); } +#endif // the 2nd phrase exception handing, which traverse registered exception handlers. // if the exception can be handled, then continue execution // otherwise, throw abortion, go back to 1st phrase, and call the default handler. -// if the exception can be handled, then continue execution -// otherwise, throw abortion, go back to 1st phrase, and call the default handler. extern "C" __attribute__((regparm(1))) void internal_handle_exception(sgx_exception_info_t *info) { int status = EXCEPTION_CONTINUE_SEARCH; @@ -323,15 +323,19 @@ extern "C" __attribute__((regparm(1))) void internal_handle_exception(sgx_except uintptr_t *nhead = NULL; uintptr_t *ntmp = NULL; uintptr_t xsp = 0; + uint8_t *xsave_in_ssa = (uint8_t*)ROUND_TO_PAGE(thread_data->first_ssa_gpr) - ROUND_TO_PAGE(get_xsave_size() + sizeof(ssa_gpr_t)); // AEX Notify allows this handler to handle interrupts if (info == NULL) { goto failed_end; } - else if (info->exception_valid == 0) { + + memcpy_s(info->xsave_area, info->xsave_size, xsave_in_ssa, info->xsave_size); + + if (info->exception_valid == 0) { goto exception_handling_end; } - + if (thread_data->exception_flag < 0) goto failed_end; thread_data->exception_flag++; @@ -421,6 +425,7 @@ extern "C" __attribute__((regparm(1))) void internal_handle_exception(sgx_except } exception_handling_end: +#ifndef SE_SIM //instruction triggering the exception will be executed again. if(info->do_aex_mitigation == 1) { @@ -431,6 +436,7 @@ extern "C" __attribute__((regparm(1))) void internal_handle_exception(sgx_except apply_constant_time_sgxstep_mitigation_and_continue_execution(info); } else +#endif { //instruction triggering the exception will be executed again. restore_xregs(info->xsave_area); @@ -468,7 +474,6 @@ extern "C" sgx_status_t trts_handle_exception(void *tcs) sgx_exception_info_t *info = NULL; uintptr_t sp_u, sp, *new_sp = NULL; size_t size = 0; - uint8_t *ssa_xsave = NULL; bool is_exception_handled = false; if ((thread_data == NULL) || (tcs == NULL)) goto default_handler; @@ -550,33 +555,32 @@ extern "C" sgx_status_t trts_handle_exception(void *tcs) return SGX_ERROR_STACK_OVERRUN; } - if(ssa_gpr->exit_info.valid == 1) + /* try to allocate memory dynamically */ + if((size_t)sp < thread_data->stack_commit_addr) { + int ret = -1; + size_t page_aligned_delta = 0; /* try to allocate memory dynamically */ - if((size_t)sp < thread_data->stack_commit_addr) - { - int ret = -1; - size_t page_aligned_delta = 0; - /* try to allocate memory dynamically */ - page_aligned_delta = ROUND_TO(thread_data->stack_commit_addr - (size_t)sp, SE_PAGE_SIZE); - if ((thread_data->stack_commit_addr > page_aligned_delta) - && ((thread_data->stack_commit_addr - page_aligned_delta) >= thread_data->stack_limit_addr)) - { - ret = expand_stack_by_pages((void *)(thread_data->stack_commit_addr - page_aligned_delta), (page_aligned_delta >> SE_PAGE_SHIFT)); - } - if (ret == 0) - { - thread_data->stack_commit_addr -= page_aligned_delta; - is_exception_handled = true; // The exception has been handled in the 1st phase exception handler - goto handler_end; - } - else - { - set_enclave_state(ENCLAVE_CRASHED); - return SGX_ERROR_STACK_OVERRUN; - } + page_aligned_delta = ROUND_TO(thread_data->stack_commit_addr - (size_t)sp, SE_PAGE_SIZE); + if ((thread_data->stack_commit_addr > page_aligned_delta) + && ((thread_data->stack_commit_addr - page_aligned_delta) >= thread_data->stack_limit_addr)) + { + ret = expand_stack_by_pages((void *)(thread_data->stack_commit_addr - page_aligned_delta), + (page_aligned_delta >> SE_PAGE_SHIFT)); + } + if (ret == 0) + { + thread_data->stack_commit_addr -= page_aligned_delta; + is_exception_handled = true; // The exception has been handled in the 1st phase exception handler + goto handler_end; + } + else + { + set_enclave_state(ENCLAVE_CRASHED); + return SGX_ERROR_STACK_OVERRUN; } } + if (size_t(&Lereport_inst) == ssa_gpr->REG(ip) && SE_EREPORT == ssa_gpr->REG(ax)) { // Handle the exception raised by EREPORT instruction @@ -607,8 +611,6 @@ extern "C" sgx_status_t trts_handle_exception(void *tcs) info->exception_vector = (sgx_exception_vector_t)ssa_gpr->exit_info.vector; info->exception_type = (sgx_exception_type_t)ssa_gpr->exit_info.exit_type; info->xsave_size = thread_data->xsave_size; - ssa_xsave = (uint8_t*)ROUND_TO_PAGE(thread_data->first_ssa_gpr) - ROUND_TO_PAGE(get_xsave_size() + sizeof(ssa_gpr_t)); - memcpy_s(info->xsave_area, info->xsave_size, ssa_xsave, info->xsave_size); info->cpu_context.REG(ax) = ssa_gpr->REG(ax); info->cpu_context.REG(cx) = ssa_gpr->REG(cx); diff --git a/sdk/ttls/Makefile b/sdk/ttls/Makefile index 3b41a05df..1e7e757dd 100644 --- a/sdk/ttls/Makefile +++ b/sdk/ttls/Makefile @@ -45,6 +45,8 @@ endif SGX_QV_PATH ?= ../../external/dcap_source/QuoteVerification PREBUILT_OPENSSL_PATH ?= $(SGX_QV_PATH)/../prebuilt/openssl +CBOR_PATH ?= $(LINUX_EXTERNAL_DIR)/cbor +CBOR_RELATIVE_PATH ?= ../../external/cbor INCLUDE += -I$(COMMON_DIR)/inc/tlibc \ -I$(COMMON_DIR)/inc/internal \ @@ -56,7 +58,8 @@ INCLUDE += -I$(COMMON_DIR)/inc/tlibc \ -I$(SGX_QV_PATH)/../QuoteGeneration/pce_wrapper/inc \ -I$(SGX_QV_PATH)/dcap_tvl \ -include./tsgxsslio.h \ - -I$(PREBUILT_OPENSSL_PATH)/inc + -I$(PREBUILT_OPENSSL_PATH)/inc \ + -I$(CBOR_PATH)/trusted/include INCLUDE_TDX := $(filter-out -I$(PREBUILT_OPENSSL_PATH)/inc,$(INCLUDE)) CXXFLAGS_TDX := $(CXXFLAGS) $(COMMON_FLAGS) $(COMMON_LDFLAGS) -fPIC -Werror -Wno-unused-parameter -g @@ -70,6 +73,11 @@ SRC := $(wildcard *.cpp) OBJ := $(sort $(SRC:.cpp=.o)) OBJ_TDX := $(addprefix tdx_, $(OBJ)) +LIBSGX_CBOR = libsgx_cbor.a +LIBCBOR = libcbor.a +LIBSGX_CBOR_PATH = $(CBOR_PATH)/trusted/lib +LIBCBOR_PATH = $(CBOR_PATH)/untrusted/lib + LIBNAME := libsgx_ttls.a LIBNAME_TDX := libtdx_tls.a @@ -78,6 +86,7 @@ all: $(LIBNAME) $(LIBNAME_TDX) | $(BUILD_DIR) $(CP) $(LIBNAME) $| $(CP) $(LIBNAME_TDX) $| + $(TLSNAME)_t.h: $(EDLFILE) $(EDGER8R) $(EDGER8R) --trusted --header-only --search-path $(TOP_DIR)/common/inc $< @@ -86,16 +95,30 @@ $(EDGER8R): $(LIBNAME): $(OBJ) $(AR) rs $@ $(OBJ) + $(MKDIR) $(BUILD_DIR)/.libsgx_cbor + $(RM) $(BUILD_DIR)/.libsgx_cbor/* && cd $(BUILD_DIR)/.libsgx_cbor && $(AR) x $(LIBSGX_CBOR_PATH)/$(LIBSGX_CBOR) + $(AR) rs $@ $(BUILD_DIR)/.libsgx_cbor/*.o + @$(RM) -r $(BUILD_DIR)/.libsgx_cbor $(LIBNAME_TDX): $(OBJ_TDX) - $(AR) rs $@ $^ - -$(OBJ): $(TLSNAME)_t.h -$(OBJ): %.o :%.cpp + $(AR) rs $@ $(OBJ_TDX) + $(MKDIR) $(BUILD_DIR)/.libcbor + $(RM) $(BUILD_DIR)/.libcbor/* && cd $(BUILD_DIR)/.libcbor && $(AR) x $(LIBCBOR_PATH)/$(LIBCBOR) + $(AR) rs $@ $(BUILD_DIR)/.libcbor/*.o + @$(RM) -r $(BUILD_DIR)/.libcbor + +$(OBJ): $(TLSNAME)_t.h +$(OBJ): %.o :%.cpp $(LIBSGX_CBOR) $(CXX) $(CXXFLAGS) $(INCLUDE) -c $< -o $@ -$(OBJ_TDX): tdx_%.o :%.cpp +$(OBJ_TDX): tdx_%.o :%.cpp $(LIBCBOR) $(CXX) $(CXXFLAGS_TDX) $(INCLUDE_TDX) -DTDX_ENV -c $< -o $@ +$(LIBSGX_CBOR): + @test -f $(LIBSGX_CBOR_PATH)/$(LIBSGX_CBOR) || $(MAKE) -C $(CBOR_RELATIVE_PATH) cbor_trusted + +$(LIBCBOR): + @test -f $(LIBCBOR_PATH)/$(LIBCBOR) || $(MAKE) -C $(CBOR_RELATIVE_PATH) cbor_untrusted + .PHONY: clean clean: @$(RM) *.o @@ -104,6 +127,7 @@ clean: @$(RM) $(LIBNAME) $(BUILD_DIR)/$(LIBNAME) @$(RM) $(LIBNAME_TDX) $(BUILD_DIR)/$(LIBNAME_TDX) $(MAKE) -C $(EDGER8R_DIR) clean + $(MAKE) -C $(CBOR_PATH) clean .PHONY: rebuild rebuild: diff --git a/sdk/ttls/cert_generator.cpp b/sdk/ttls/cert_generator.cpp index 9c5a327e6..c9615e1ea 100644 --- a/sdk/ttls/cert_generator.cpp +++ b/sdk/ttls/cert_generator.cpp @@ -152,10 +152,11 @@ static sgx_status_t sgx_gen_custom_x509_cert( X509_EXTENSION* ext = NULL; ASN1_OBJECT* obj = NULL; ASN1_OCTET_STRING* data = NULL; + ASN1_OBJECT* cbor_obj = NULL; + ASN1_OCTET_STRING* cbor_data = NULL; BASIC_CONSTRAINTS* bc = NULL; unsigned char* buf = NULL; unsigned char* p = NULL; - char* oid = NULL; char date_str[16]; int len = 0; int ret = 0; @@ -303,6 +304,27 @@ static sgx_status_t sgx_gen_custom_x509_cert( if (!X509_EXTENSION_create_by_OBJ(&ext, obj, 0, data)) break; + ret = X509_add_ext(x509cert, ext, -1); + SSL_ERR_BREAK(ret, SGX_ERROR_UNEXPECTED); + X509_EXTENSION_free(ext); + ext = NULL; + + cbor_data = ASN1_OCTET_STRING_new(); + SSL_ERR_BREAK(cbor_data, SGX_ERROR_UNEXPECTED); + + // add the tcg tagged evidence extension + ret = ASN1_OCTET_STRING_set( + cbor_data, + (const unsigned char*)config->evidence_buf, + (int)config->evidence_size); + SSL_ERR_BREAK(ret, SGX_ERROR_UNEXPECTED); + + cbor_obj = OBJ_txt2obj(config->ext_tcg_tagged_oid, 1); + SSL_ERR_BREAK(cbor_obj, SGX_ERROR_UNEXPECTED); + + if (!X509_EXTENSION_create_by_OBJ(&ext, cbor_obj, 0, cbor_data)) + break; + ret = X509_add_ext(x509cert, ext, -1); SSL_ERR_BREAK(ret, SGX_ERROR_UNEXPECTED); @@ -343,6 +365,12 @@ static sgx_status_t sgx_gen_custom_x509_cert( ASN1_OBJECT_free(obj); if (data) ASN1_OCTET_STRING_free(data); + if (cbor_obj) + ASN1_OBJECT_free(cbor_obj); + if (cbor_data) + { + ASN1_OCTET_STRING_free(cbor_data); + } if (bc) BASIC_CONSTRAINTS_free(bc); if (subject_issuer_key_pair) @@ -352,11 +380,6 @@ static sgx_status_t sgx_gen_custom_x509_cert( free(buf); buf = NULL; } - if (oid) - { - free(oid); - oid = NULL; - } p = NULL; return result; @@ -365,6 +388,8 @@ static sgx_status_t sgx_gen_custom_x509_cert( sgx_status_t generate_x509_self_signed_certificate( const unsigned char* oid, size_t oid_size, + const unsigned char* tcg_tagged_oid, + size_t tcg_tagged_oid_size, const unsigned char *subject_name, const uint8_t *p_prv_key, size_t prv_key_size, @@ -372,6 +397,8 @@ sgx_status_t generate_x509_self_signed_certificate( size_t pub_key_size, const uint8_t* p_quote_buf, size_t quote_size, + const uint8_t* p_evidence, + size_t evidence_size, uint8_t **output_cert, size_t *output_cert_size) { @@ -395,10 +422,14 @@ sgx_status_t generate_x509_self_signed_certificate( config.quote_buf_size = quote_size; config.ext_oid = (char*)oid; config.ext_oid_size = oid_size; + config.ext_tcg_tagged_oid = (char*)tcg_tagged_oid; + config.ext_tcg_tagged_oid_size = tcg_tagged_oid_size; + config.evidence_buf = (uint8_t*)p_evidence; + config.evidence_size = evidence_size; do { // allocate memory for cert output buffer and leave room for paddings - sgx_cert_size = quote_size + pub_key_size + SGX_MIN_CERT_SIZE; + sgx_cert_size = evidence_size + quote_size + pub_key_size + SGX_MIN_CERT_SIZE; cert_buf = (uint8_t*)malloc(sgx_cert_size); if (cert_buf == NULL) break; diff --git a/sdk/ttls/cert_header.h b/sdk/ttls/cert_header.h index 054210be6..61e2ad59b 100644 --- a/sdk/ttls/cert_header.h +++ b/sdk/ttls/cert_header.h @@ -32,7 +32,6 @@ #include #include "sgx_error.h" - #define SGX_CERT_MAGIC 0xa7a55f4322919317 #define SGX_CERT_CHAIN_MAGIC 0xa87e5d8e25671870 #define SGX_CRL_MAGIC 0x8f062e782b5760b2 @@ -41,8 +40,26 @@ #define SGX_RSA_PRIVATE_KEY_MAGIC 0xba24987b29769828 #define SGX_RSA_PUBLIC_KEY_MAGIC 0x92f1fdf6c81b4aaa + +// legacy intel sgx oid string for backward compatibility // joint-ise-ccitt (2) country (16) usa (840) org (1) intel (113741) sgx (13.1) #define X509_OID_FOR_QUOTE_STRING "1.2.840.113741.1.13.1" +/* standard TCG DICE "tagged evidence" OID (2.23.133.5.4.9) */ +#define TCG_DICE_TAGGED_OID_STR "2.23.133.5.4.9" +const char g_evidence_oid[] = TCG_DICE_TAGGED_OID_STR; +const size_t g_evidence_oid_size = sizeof(g_evidence_oid); + +/* attestation evidence data tags, https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml */ +#define TCG_DICE_TAGGED_EVIDENCE_TEE_QUOTE_CBOR_TAG 60000 +/* hash IDs per IANA: https://www.iana.org/assignments/named-information/named-information.xhtml */ +#define IANA_NAMED_INFO_HASH_ALG_REGISTRY_RESERVED 0 +#define IANA_NAMED_INFO_HASH_ALG_REGISTRY_SHA256 1 +#define IANA_NAMED_INFO_HASH_ALG_REGISTRY_SHA384 7 +#define IANA_NAMED_INFO_HASH_ALG_REGISTRY_SHA512 8 +#define PUB_KEY_MAX_SIZE 626 +#define RAW_QUOTE_MAX_SIZE 8192 +#define CBOR_QUOTE_MAX_SIZE ((RAW_QUOTE_MAX_SIZE)*2) +#define QUOTE_MIN_SIZE 1020 typedef struct _sgx_cert { @@ -90,8 +107,12 @@ typedef struct _sgx_cert_config unsigned char* date_not_valid_after; uint8_t* quote_buf; size_t quote_buf_size; + uint8_t* evidence_buf; + size_t evidence_size; char* ext_oid; size_t ext_oid_size; + char* ext_tcg_tagged_oid; + size_t ext_tcg_tagged_oid_size; } sgx_cert_config_t; /* includes all the headers from version number to subject unique identifier of @@ -107,6 +128,8 @@ typedef struct _sgx_cert_config sgx_status_t generate_x509_self_signed_certificate( const unsigned char* oid, size_t oid_size, + const unsigned char* tcg_tagged_oid, + size_t tcg_tagged_oid_size, const unsigned char *subject_name, const uint8_t *p_prv_key, size_t prv_key_size, @@ -114,9 +137,18 @@ sgx_status_t generate_x509_self_signed_certificate( size_t pub_key_size, const uint8_t* p_quote_buf, size_t quote_size, + const uint8_t* p_evidence, + size_t evidence_size, uint8_t **output_cert, size_t *output_cert_size); + +int PEM2DER_PublicKey_converter( + const uint8_t* pem_pub, + size_t pem_len, + uint8_t *der, + size_t *der_len); + sgx_status_t sgx_read_cert_in_der( sgx_cert_t* cert, const void* der_data, @@ -139,4 +171,17 @@ sgx_status_t sgx_get_pubkey_from_cert( uint8_t* pem_data, size_t* pem_size); +sgx_status_t extract_cbor_evidence_and_compare_hash( + const uint8_t* cbor_evidence_buf, + size_t evidence_buf_size, + uint8_t* pem_pub_key, + size_t pem_pub_key_len, + uint8_t* out_quote, + uint32_t* quote_size); + +sgx_status_t sgx_tls_compare_quote_hash( + uint8_t* p_quote, + uint8_t* in_buf, + size_t in_buf_len); + #endif diff --git a/sdk/ttls/cert_verifier.cpp b/sdk/ttls/cert_verifier.cpp index 0eb934e75..2889bfaf7 100644 --- a/sdk/ttls/cert_verifier.cpp +++ b/sdk/ttls/cert_verifier.cpp @@ -34,6 +34,10 @@ #include #include #include "cert_header.h" +#include +#include "cbor.h" +#include "sgx_quote_4.h" +#include "sgx_quote_5.h" typedef struct _cert { @@ -337,78 +341,264 @@ sgx_status_t sgx_cert_verify( return result; } -sgx_status_t sgx_cert_find_extension( - const sgx_cert_t* cert, - const char* oid, - uint8_t* data, - uint32_t* size) +static sgx_status_t compare_cert_pubkey_against_cbor_claim_hash( + const uint8_t* pem_pub_key, + size_t pem_pub_key_len, + cbor_item_t* cbor_hash_entry) { - sgx_status_t result = SGX_ERROR_UNEXPECTED; - const cert_t* impl = (const cert_t*)cert; - const STACK_OF(X509_EXTENSION) * extensions; - int num_extensions; + uint8_t pk_der[PUB_KEY_MAX_SIZE] = {0}; + size_t pk_der_size = 0; + unsigned char *p_sha = NULL; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + cbor_item_t* cbor_hash_alg_id = NULL; + cbor_item_t* cbor_hash_value = NULL; + + if (PEM2DER_PublicKey_converter(pem_pub_key, pem_pub_key_len, pk_der, &pk_der_size)) + goto out; + + if (!cbor_isa_array(cbor_hash_entry) || !cbor_array_is_definite(cbor_hash_entry) + || cbor_array_size(cbor_hash_entry) != 2) { + return SGX_ERROR_TLS_X509_INVALID_EXTENSION; + } - /* Reject invalid parameters */ - if (!_cert_is_valid(impl) || !oid || !size) { - result = SGX_ERROR_INVALID_PARAMETER; - goto done; + cbor_hash_alg_id = cbor_array_get(cbor_hash_entry, /*index=*/0); + if (!cbor_hash_alg_id || !cbor_isa_uint(cbor_hash_alg_id)) { + ret = SGX_ERROR_TLS_X509_INVALID_EXTENSION; + goto out; } - /* Set a pointer to the stack of extensions (possibly NULL) */ - if (!(extensions = X509_get0_extensions(impl->x509))) - goto done; + cbor_hash_value = cbor_array_get(cbor_hash_entry, /*index=*/1); + if (!cbor_hash_value || !cbor_isa_bytestring(cbor_hash_value) + || !cbor_bytestring_is_definite(cbor_hash_value)) { + ret = SGX_ERROR_TLS_X509_INVALID_EXTENSION; + goto out; + } - /* Get the number of extensions (possibly zero) */ - num_extensions = sk_X509_EXTENSION_num(extensions); + uint8_t sha[SHA512_DIGEST_LENGTH]; /* enough to hold SHA-256, -384, or -512 */ + size_t sha_size; + size_t temp_size; + + uint64_t hash_alg_id; + switch (cbor_int_get_width(cbor_hash_alg_id)) { + case CBOR_INT_8: hash_alg_id = cbor_get_uint8(cbor_hash_alg_id); break; + case CBOR_INT_16: hash_alg_id = cbor_get_uint16(cbor_hash_alg_id); break; + case CBOR_INT_32: hash_alg_id = cbor_get_uint32(cbor_hash_alg_id); break; + case CBOR_INT_64: hash_alg_id = cbor_get_uint64(cbor_hash_alg_id); break; + default: ret = SGX_ERROR_TLS_X509_INVALID_EXTENSION; goto out; + } - /* Find the certificate with this OID */ - for (int i = 0; i < num_extensions; i++) + switch (hash_alg_id) { + case IANA_NAMED_INFO_HASH_ALG_REGISTRY_SHA256: + sha_size = SHA256_DIGEST_LENGTH; + break; + case IANA_NAMED_INFO_HASH_ALG_REGISTRY_SHA384: + sha_size = SHA384_DIGEST_LENGTH; + break; + case IANA_NAMED_INFO_HASH_ALG_REGISTRY_SHA512: + sha_size = SHA512_DIGEST_LENGTH; + break; + default: + ret = SGX_ERROR_TLS_X509_INVALID_EXTENSION; + goto out; + } + + temp_size = cbor_bytestring_length(cbor_hash_value); + if (temp_size != sha_size) { + ret = SGX_ERROR_TLS_X509_INVALID_EXTENSION; + goto out; + } + + switch (hash_alg_id) { + case IANA_NAMED_INFO_HASH_ALG_REGISTRY_RESERVED: + case IANA_NAMED_INFO_HASH_ALG_REGISTRY_SHA256: + p_sha = SHA256(pk_der, pk_der_size, sha); + break; + case IANA_NAMED_INFO_HASH_ALG_REGISTRY_SHA384: + p_sha = SHA384(pk_der, pk_der_size, sha); + break; + case IANA_NAMED_INFO_HASH_ALG_REGISTRY_SHA512: + p_sha = SHA512(pk_der, pk_der_size, sha); + break; + } + + if (p_sha == NULL) { - X509_EXTENSION* ext; - ASN1_OBJECT* obj; - sgx_oid_string_t ext_oid; + ret = SGX_ERROR_UNEXPECTED; + goto out; + } - /* Get the i-th extension from the stack */ - if (!(ext = sk_X509_EXTENSION_value(extensions, i))) - goto done; + if (memcmp(cbor_bytestring_handle(cbor_hash_value), sha, sha_size)) { + ret = SGX_ERROR_INVALID_SIGNATURE; + goto out; + } - /* Get the OID */ - if (!(obj = X509_EXTENSION_get_object(ext))) - goto done; + ret = SGX_SUCCESS; +out: + if (cbor_hash_alg_id) cbor_decref(&cbor_hash_alg_id); + if (cbor_hash_value) cbor_decref(&cbor_hash_value); + return ret; +} - /* Get the string name of the OID */ - if (!OBJ_obj2txt(ext_oid.buf, sizeof(ext_oid.buf), obj, 1)) - goto done; - /* If found then get the data */ - if (strcmp(ext_oid.buf, oid) == 0) - { - ASN1_OCTET_STRING* str; +sgx_status_t extract_cbor_evidence_and_compare_hash( + const uint8_t* cbor_evidence_buf, + size_t evidence_buf_size, + uint8_t* pem_pub_key, + size_t pem_pub_key_len, + uint8_t* out_quote, + uint32_t* out_quote_size) +{ + /* for description of evidence format, see ttls.c:generate_cbor_evidence() */ + cbor_item_t* cbor_tagged_evidence = NULL; + cbor_item_t* cbor_evidence = NULL; + cbor_item_t* cbor_quote = NULL; + cbor_item_t* cbor_claims = NULL; /* serialized CBOR map of claims (as bytestring) */ + cbor_item_t* cbor_claims_map = NULL; + cbor_item_t* cbor_hash_entry = NULL; + uint8_t* quote = NULL; + sgx_status_t ret = SGX_SUCCESS; + + struct cbor_pair* claims_pairs = NULL; + uint8_t* claims_buf = NULL; + size_t claims_buf_size = 0; + size_t quote_size = 0; + + if (evidence_buf_size == 0) return SGX_ERROR_UNEXPECTED; + + struct cbor_load_result cbor_result; + cbor_tagged_evidence = cbor_load(cbor_evidence_buf, evidence_buf_size, &cbor_result); + if (cbor_result.error.code != CBOR_ERR_NONE) { + ret = (cbor_result.error.code == CBOR_ERR_MEMERROR) ? + SGX_ERROR_OUT_OF_MEMORY : SGX_ERROR_UNEXPECTED; + goto out; + } + if (!cbor_isa_tag(cbor_tagged_evidence) + || cbor_tag_value(cbor_tagged_evidence) != TCG_DICE_TAGGED_EVIDENCE_TEE_QUOTE_CBOR_TAG) + { + ret = SGX_ERROR_TLS_X509_INVALID_EXTENSION; + goto out; + } - /* Get the data from the extension */ - if (!(str = X509_EXTENSION_get_data(ext))) - goto done; + cbor_evidence = cbor_tag_item(cbor_tagged_evidence); + if (!cbor_evidence || !cbor_isa_array(cbor_evidence) + || !cbor_array_is_definite(cbor_evidence)) { + ret = SGX_ERROR_TLS_X509_INVALID_EXTENSION; + goto out; + } - /* If the caller's buffer is too small, raise error */ - if ((size_t)str->length > *size) - { - *size = (size_t)str->length; - result = SGX_ERROR_INVALID_PARAMETER; - goto done; + if (cbor_array_size(cbor_evidence) != 2) { + ret = SGX_ERROR_TLS_X509_INVALID_EXTENSION; + goto out; + } + + cbor_quote = cbor_array_get(cbor_evidence, /*index=*/0); + if (!cbor_quote || !cbor_isa_bytestring(cbor_quote) || !cbor_bytestring_is_definite(cbor_quote) + || cbor_bytestring_length(cbor_quote) == 0) { + ret = SGX_ERROR_TLS_X509_INVALID_EXTENSION; + goto out; + } + + quote_size = cbor_bytestring_length(cbor_quote); + if (quote_size < QUOTE_MIN_SIZE) { + ret = SGX_ERROR_TLS_X509_INVALID_EXTENSION; + goto out; + } + quote = (uint8_t*)malloc(quote_size); + if (!quote) { + ret = SGX_ERROR_OUT_OF_MEMORY; + goto out; + } + memcpy(quote, cbor_bytestring_handle(cbor_quote), quote_size); + + cbor_claims = cbor_array_get(cbor_evidence, /*index=*/1); + if (!cbor_claims || !cbor_isa_bytestring(cbor_claims) + || !cbor_bytestring_is_definite(cbor_claims) + || cbor_bytestring_length(cbor_claims) == 0) { + ret = SGX_ERROR_TLS_X509_INVALID_EXTENSION; + goto out; + } + + /* claims object is borrowed, no need to free separately */ + claims_buf = cbor_bytestring_handle(cbor_claims); + claims_buf_size = cbor_bytestring_length(cbor_claims); + assert(claims_buf && claims_buf_size); + + /* verify that TEE quote corresponds to the attached serialized claims */ + ret = sgx_tls_compare_quote_hash(quote, claims_buf, claims_buf_size); + if (ret != SGX_SUCCESS) + { + goto out; + } + /* parse and verify CBOR claims */ + cbor_claims_map = cbor_load(claims_buf, claims_buf_size, &cbor_result); + if (cbor_result.error.code != CBOR_ERR_NONE) { + ret = (cbor_result.error.code == CBOR_ERR_MEMERROR) ? + SGX_ERROR_OUT_OF_MEMORY : SGX_ERROR_TLS_X509_INVALID_EXTENSION; + goto out; + } + + if (!cbor_isa_map(cbor_claims_map) || !cbor_map_is_definite(cbor_claims_map) + || cbor_map_size(cbor_claims_map) < 1) { + ret = SGX_ERROR_TLS_X509_INVALID_EXTENSION; + goto out; + } + + claims_pairs = cbor_map_handle(cbor_claims_map); + for (size_t i = 0; i < cbor_map_size(cbor_claims_map); i++) { + if (!claims_pairs[i].key || !cbor_isa_string(claims_pairs[i].key) + || !cbor_string_is_definite(claims_pairs[i].key) + || cbor_string_length(claims_pairs[i].key) == 0) { + ret = SGX_ERROR_TLS_X509_INVALID_EXTENSION; + goto out; + } + + if (strncmp((char*)cbor_string_handle(claims_pairs[i].key), "pubkey-hash", + cbor_string_length(claims_pairs[i].key)) == 0) { + /* claim { "pubkey-hash" : serialized CBOR array hash-entry (as CBOR bstr) } */ + if (!claims_pairs[i].value || !cbor_isa_bytestring(claims_pairs[i].value) + || !cbor_bytestring_is_definite(claims_pairs[i].value) + || cbor_bytestring_length(claims_pairs[i].value) == 0) { + ret = SGX_ERROR_TLS_X509_INVALID_EXTENSION; + goto out; } - if (data) + uint8_t* hash_entry_buf = cbor_bytestring_handle(claims_pairs[i].value); + size_t hash_entry_buf_size = cbor_bytestring_length(claims_pairs[i].value); + + cbor_hash_entry = cbor_load(hash_entry_buf, hash_entry_buf_size, &cbor_result); + if (cbor_result.error.code != CBOR_ERR_NONE) { + ret = (cbor_result.error.code == CBOR_ERR_MEMERROR) ? SGX_ERROR_OUT_OF_EPC + : SGX_ERROR_TLS_X509_INVALID_EXTENSION; + goto out; + } + + ret = compare_cert_pubkey_against_cbor_claim_hash(pem_pub_key, pem_pub_key_len, cbor_hash_entry); + if (ret != SGX_SUCCESS) { - memcpy(data, str->data, (size_t)str->length); - *size = (size_t)str->length; - result = SGX_SUCCESS; - goto done; + goto out; } } } -done: - return result; + memcpy(out_quote, quote, quote_size); + *out_quote_size = (uint32_t)quote_size; + ret = SGX_SUCCESS; + +out: + SGX_TLS_SAFE_FREE(quote); + if (cbor_hash_entry) + cbor_decref(&cbor_hash_entry); + if (cbor_claims_map) + cbor_decref(&cbor_claims_map); + if (cbor_claims) + cbor_decref(&cbor_claims); + if (cbor_quote) + cbor_decref(&cbor_quote); + if (cbor_evidence) + cbor_decref(&cbor_evidence); + if (cbor_tagged_evidence) + cbor_decref(&cbor_tagged_evidence); + return ret; } sgx_status_t sgx_cert_get_public_key( @@ -515,6 +705,72 @@ sgx_status_t sgx_public_key_write_pem( } +sgx_status_t sgx_cert_find_extension( + const sgx_cert_t* cert, + const char* oid, + uint8_t* data, + uint32_t* size) +{ + sgx_status_t result = SGX_ERROR_UNEXPECTED; + const cert_t* impl = (const cert_t*)cert; + const STACK_OF(X509_EXTENSION) * extensions; + int num_extensions; + + /* Reject invalid parameters */ + if (!_cert_is_valid(impl) || !oid || !size) { + result = SGX_ERROR_INVALID_PARAMETER; + goto done; + } + + /* Set a pointer to the stack of extensions (possibly NULL) */ + if (!(extensions = X509_get0_extensions(impl->x509))) + goto done; + + /* Get the number of extensions (possibly zero) */ + num_extensions = sk_X509_EXTENSION_num(extensions); + + /* Find the certificate with this OID */ + for (int i = 0; i < num_extensions; i++) + { + X509_EXTENSION* ext; + ASN1_OBJECT* obj; + sgx_oid_string_t ext_oid; + + /* Get the i-th extension from the stack */ + if (!(ext = sk_X509_EXTENSION_value(extensions, i))) + goto done; + + /* Get the OID */ + if (!(obj = X509_EXTENSION_get_object(ext))) + goto done; + + /* Get the string name of the OID */ + if (!OBJ_obj2txt(ext_oid.buf, sizeof(ext_oid.buf), obj, 1)) + goto done; + + /* If found then get the data */ + if (strcmp(ext_oid.buf, oid) == 0) + { + ASN1_OCTET_STRING* str; + + /* Get the data from the extension */ + if (!(str = X509_EXTENSION_get_data(ext))) + goto done; + + if (data) + { + memcpy(data, str->data, (size_t)str->length); + *size = (size_t)str->length; + result = SGX_SUCCESS; + goto done; + } + } + } + +done: + return result; +} + sgx_status_t sgx_get_pubkey_from_cert( const sgx_cert_t* cert, uint8_t* pem_data, @@ -542,3 +798,229 @@ sgx_status_t sgx_get_pubkey_from_cert( return result; } + +/* a common function to compare hash from target_buf with quote */ +/* possible in_buf could be public_key for legacy or claims buf for interoperable ra-tls*/ +sgx_status_t sgx_tls_compare_quote_hash(uint8_t *p_quote, + uint8_t* in_buf, size_t in_buf_len) +{ + size_t report_data_size = 0; + uint32_t quote_type = 0; + uint8_t *p_report_data = NULL; + uint8_t *hash_in_buf = NULL; // buf to store hash by target_buf + unsigned char *p_sha = NULL; + sgx_status_t ret = SGX_SUCCESS; + + if (p_quote == NULL) return SGX_ERROR_UNEXPECTED; + + quote_type = *(uint32_t *)(p_quote + 4 * sizeof(uint8_t)); + + // get hash of cert pub key + report_data_size = (quote_type == 0x81) ? SGX_REPORT2_DATA_SIZE : SGX_REPORT_DATA_SIZE; + hash_in_buf = (uint8_t*)malloc(report_data_size); + if (!hash_in_buf) { + ret = SGX_ERROR_OUT_OF_MEMORY; + goto done; + } + if (quote_type == 0x81) { + uint16_t _version = 0; + memcpy((void*)&_version, p_quote, sizeof(_version)); + + if (_version == 5) + { + p_report_data = (uint8_t*)&(((sgx_report2_body_v1_5_t*)&(((sgx_quote5_t*)p_quote)->body))->report_data); + } else + { + p_report_data = (uint8_t*)(&((sgx_quote4_t *)p_quote)->report_body.report_data); + } + + p_sha = SHA384(in_buf, in_buf_len, + reinterpret_cast(hash_in_buf)); + if (p_sha == NULL || + memcmp(p_sha, hash_in_buf, SHA384_DIGEST_LENGTH) != 0) { + ret = SGX_ERROR_UNEXPECTED; + goto done; + } + if (memcmp(p_report_data, hash_in_buf, SHA384_DIGEST_LENGTH) != 0) { + ret = SGX_ERROR_INVALID_SIGNATURE; + goto done; + } + } else if (quote_type == 0x00) + { + p_report_data = (uint8_t*)(&((sgx_quote3_t *)p_quote)->report_body.report_data); + p_sha = SHA256(in_buf, in_buf_len, reinterpret_cast(hash_in_buf)); + if (p_sha == NULL || + memcmp(p_sha, hash_in_buf, SHA256_DIGEST_LENGTH) != 0) { + ret = SGX_ERROR_UNEXPECTED; + goto done; + } + // compare hash, only compare the first 32 bytes + if (memcmp(p_report_data, hash_in_buf, SHA256_DIGEST_LENGTH) != 0) { + ret = SGX_ERROR_INVALID_SIGNATURE; + goto done; + } + } + else { + ret = SGX_ERROR_UNEXPECTED; + goto done; + } + +done: + SGX_TLS_SAFE_FREE(hash_in_buf); + return ret; +} + +// support functions +static char b64revtb[256] = { + -3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*0-15*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16-31*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /*32-47*/ + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, /*48-63*/ + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /*64-79*/ + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /*80-95*/ + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /*96-111*/ + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /*112-127*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128-143*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*144-159*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*160-175*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*176-191*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*192-207*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*208-223*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*224-239*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /*240-255*/ +}; + +static unsigned int raw_base64_decode(uint8_t *in, + uint8_t* out, int strict, int *err) { + unsigned int result = 0; + int x = 0; + unsigned char buf[3] = {0, 0, 0}; + unsigned char *p = in, pad = 0; + + *err = 0; + while (!pad) { + switch ((x = b64revtb[*p++])) { + case -3: /* NULL TERMINATOR */ + if (((p - 1) - in) % 4) *err = 1; + return result; + case -2: /* PADDING CHARACTER. INVALID HERE */ + if (((p - 1) - in) % 4 < 2) { + *err = 1; + return result; + } else if (((p - 1) - in) % 4 == 2) { + /* Make sure there's appropriate padding */ + if (*p != '=') { + *err = 1; + return result; + } + buf[2] = 0; + pad = 2; + result++; + break; + } else { + pad = 1; + result += 2; + break; + } + return result; + case -1: + if (strict) { + *err = 2; + return result; + } + break; + default: + switch (((p - 1) - in) % 4) { + case 0: + buf[0] = (unsigned char)(x << 2); + break; + case 1: + buf[0] |= (unsigned char)(x >> 4); + buf[1] = (unsigned char)(x << 4); + break; + case 2: + buf[1] |= (unsigned char)(x >> 2); + buf[2] = (unsigned char)(x << 6); + break; + case 3: + buf[2] |= (unsigned char)x; + result += 3; + for (x = 0; x < 3 - pad; x++) *out++ = buf[x]; + break; + } + break; + } + } + for (x = 0; x < 3 - pad; x++) *out++ = buf[x]; + return result; +} + +void PEM_strip_header_and_footer( + uint8_t *pem, + size_t pem_len, + uint8_t *stripped_pem, + size_t *real_pem_len + ) +{ + int i = 0; + int j = 0; + int real_begin = 0; + int real_end = 0; + for (i = 0; i < (int)pem_len; i++) + { + if (pem[i] == '\n' || pem[i] == '\r') break; + } + real_begin = i+1; // the character right after \n + + // do not search \n from the exact end, + // which may contain one '\n' that we don't want + // to strip the footer "---- END Public Key -----" + for (i = (int)pem_len - 5; i >= 0; i--) + { + if (pem[i] == '\n' || pem[i] == '\r') break; + } + + real_end = i; + + // remove carriage return if any + for (i = real_begin, j = 0; i < real_end; i++) + { + if (pem[i] != '\n' && pem[i] != '\r') + { + stripped_pem[j] = pem[i]; + j++; + } + } + *real_pem_len = j; +} + +int PEM2DER_PublicKey_converter(const uint8_t *pem_pub, size_t pem_len, uint8_t *der, size_t *der_len) +{ + uint8_t *stripped_pk_pem = NULL; + size_t stripped_len = 0; + + int temp_len = 0; + int errorcode = 0; + + if (pem_pub == NULL || pem_len == 0) + return 1; + + stripped_pk_pem = (uint8_t*)malloc(pem_len); + if (stripped_pk_pem == NULL) return 1; + memset(stripped_pk_pem, 0x00, pem_len); + PEM_strip_header_and_footer((uint8_t*)pem_pub, pem_len, stripped_pk_pem, &stripped_len); + + if (stripped_len <= 0 || stripped_len > pem_len) + { + free(stripped_pk_pem); + return 1; + } + temp_len = raw_base64_decode(stripped_pk_pem, der, 0, &errorcode); + free(stripped_pk_pem); + if (!errorcode) + { + *der_len = temp_len; + } + + return errorcode; +} diff --git a/sdk/ttls/ttls.cpp b/sdk/ttls/ttls.cpp index cf345725e..013017ea5 100644 --- a/sdk/ttls/ttls.cpp +++ b/sdk/ttls/ttls.cpp @@ -41,6 +41,10 @@ #include "sgx_ttls_t.h" +#include "cbor.h" +#include + + #ifdef TDX_ENV #include #include "tdx_attest.h" @@ -64,6 +68,241 @@ quote3_error_t tdx_attest_to_sgx_ql_error(tdx_attest_error_t err) { } #endif +sgx_status_t cbor_bstr_from_pk_sha(const uint8_t *pub_key, size_t key_len, cbor_item_t** hash) +{ + uint8_t pk_sha[SHA512_DIGEST_LENGTH] = {0}; // big enough to hold hash for different algo + uint8_t pk_der[PUB_KEY_MAX_SIZE] = {0}; + size_t pk_der_size_byte = 0; + uint8_t *temp_sha = NULL; + size_t sha_len = 0; + uint8_t *ret_sha = NULL; + + memset(pk_der, 0x00, PUB_KEY_MAX_SIZE); + if (PEM2DER_PublicKey_converter(pub_key, key_len, pk_der, &pk_der_size_byte)) + return SGX_ERROR_UNEXPECTED; +#ifndef TDX_ENV + ret_sha = SHA256(pk_der, pk_der_size_byte, pk_sha); + sha_len = SHA256_DIGEST_LENGTH; + + if (ret_sha == NULL || memcmp(ret_sha, pk_sha, SHA256_DIGEST_LENGTH)!=0) + return SGX_ERROR_UNEXPECTED; + +#else // for TDX, need to use sha384 + ret_sha = SHA384(pk_der, pk_der_size_byte, pk_sha); + sha_len = SHA384_DIGEST_LENGTH; + + if (ret_sha == NULL || memcmp(ret_sha, pk_sha, SHA384_DIGEST_LENGTH)!=0) + return SGX_ERROR_UNEXPECTED; +#endif + + temp_sha = (uint8_t*)malloc(sha_len); + if (temp_sha == NULL) return SGX_ERROR_OUT_OF_MEMORY; + + memcpy(temp_sha, pk_sha, sha_len); + cbor_item_t* cbor_bstr = cbor_build_bytestring(temp_sha, sha_len); + + free(temp_sha); + if (!cbor_bstr) + return SGX_ERROR_OUT_OF_MEMORY; + + *hash = cbor_bstr; + return SGX_SUCCESS; +} + +sgx_status_t generate_cbor_pkhash_entry(const uint8_t *p_pub_key, size_t key_size, + uint8_t **out_hash_entry_buf, + size_t *out_hash_entry_buf_size) +{ + cbor_item_t* cbor_hash_entry = cbor_new_definite_array(2); + if (!cbor_hash_entry) + return SGX_ERROR_OUT_OF_MEMORY; + +#ifndef TDX_ENV + /* SGX : RA-TLS always generates SHA256 hash over pubkey */ + cbor_item_t* cbor_hash_alg_id = cbor_build_uint8(IANA_NAMED_INFO_HASH_ALG_REGISTRY_SHA256); + if (!cbor_hash_alg_id) { + cbor_decref(&cbor_hash_entry); + return SGX_ERROR_OUT_OF_MEMORY; + } +#else + /* TDX : for RA-TLS always generates SHA384 hash over pubkey */ + cbor_item_t* cbor_hash_alg_id = cbor_build_uint8(IANA_NAMED_INFO_HASH_ALG_REGISTRY_SHA384); + if (!cbor_hash_alg_id) { + cbor_decref(&cbor_hash_entry); + return SGX_ERROR_OUT_OF_MEMORY; + } +#endif + cbor_item_t* cbor_hash_value; + sgx_status_t ret = cbor_bstr_from_pk_sha(p_pub_key, key_size, &cbor_hash_value); + if (ret < 0) { + cbor_decref(&cbor_hash_alg_id); + cbor_decref(&cbor_hash_entry); + return ret; + } + + int bool_ret = cbor_array_push(cbor_hash_entry, cbor_hash_alg_id); + if (!bool_ret) { + cbor_decref(&cbor_hash_value); + cbor_decref(&cbor_hash_alg_id); + cbor_decref(&cbor_hash_entry); + return SGX_ERROR_OUT_OF_MEMORY; + } + + bool_ret = cbor_array_push(cbor_hash_entry, cbor_hash_value); + if (!bool_ret) { + cbor_decref(&cbor_hash_value); + cbor_decref(&cbor_hash_alg_id); + cbor_decref(&cbor_hash_entry); + return SGX_ERROR_OUT_OF_MEMORY; + } + + /* cbor_hash_entry took ownership of hash_alg_id and hash_value cbor items */ + cbor_decref(&cbor_hash_alg_id); + cbor_decref(&cbor_hash_value); + + uint8_t* hash_entry_buf; + size_t hash_entry_buf_size; + /* for the serialize_alloced buf, we need to free it seperately, as the pointer */ + /* passed to outside invoker, free it in outside invoker */ + cbor_serialize_alloc(cbor_hash_entry, &hash_entry_buf, &hash_entry_buf_size); + + cbor_decref(&cbor_hash_entry); + + if (!hash_entry_buf) + return SGX_ERROR_OUT_OF_MEMORY; + + *out_hash_entry_buf = hash_entry_buf; + *out_hash_entry_buf_size = hash_entry_buf_size; + return SGX_SUCCESS; +} + +sgx_status_t generate_cbor_claims(const uint8_t *p_pub_key, + size_t pub_key_size, + uint8_t **out_claims_buf, + size_t *out_claims_buf_size) +{ + /* currentl implement only claim "pubkey-hash", but there may be more "e.g. nonce" */ + cbor_item_t* cbor_claims = cbor_new_definite_map(1); + if (!cbor_claims) + return SGX_ERROR_OUT_OF_MEMORY; + + cbor_item_t* cbor_pubkey_hash_key = cbor_build_string("pubkey-hash"); + if (!cbor_pubkey_hash_key) { + cbor_decref(&cbor_claims); + return SGX_ERROR_OUT_OF_MEMORY; + } + + uint8_t* hash_entry_buf; + size_t hash_entry_buf_size; + int ret = generate_cbor_pkhash_entry(p_pub_key, pub_key_size, &hash_entry_buf, &hash_entry_buf_size); + if (ret < 0) { + cbor_decref(&cbor_pubkey_hash_key); + cbor_decref(&cbor_claims); + return SGX_ERROR_UNEXPECTED; + } + + cbor_item_t* cbor_pubkey_hash_val = cbor_build_bytestring(hash_entry_buf, hash_entry_buf_size); + + free(hash_entry_buf); + + if (!cbor_pubkey_hash_val) { + cbor_decref(&cbor_pubkey_hash_key); + cbor_decref(&cbor_claims); + return SGX_ERROR_OUT_OF_MEMORY; + } + + struct cbor_pair cbor_pubkey_hash_pair = { .key = cbor_pubkey_hash_key, + .value = cbor_pubkey_hash_val }; + bool bool_ret = cbor_map_add(cbor_claims, cbor_pubkey_hash_pair); + if (!bool_ret) { + cbor_decref(&cbor_pubkey_hash_val); + cbor_decref(&cbor_pubkey_hash_key); + cbor_decref(&cbor_claims); + return SGX_ERROR_OUT_OF_MEMORY; + } + + /* for the serialize_alloced buf, we need to free it seperately, as the pointer */ + /* passed to outside invoker, free it in outside invoker */ + uint8_t* claims_buf; + size_t claims_buf_size; + cbor_serialize_alloc(cbor_claims, &claims_buf, &claims_buf_size); + + cbor_decref(&cbor_pubkey_hash_val); + cbor_decref(&cbor_pubkey_hash_key); + cbor_decref(&cbor_claims); + + if (!claims_buf) + return SGX_ERROR_OUT_OF_MEMORY; + + *out_claims_buf = claims_buf; + *out_claims_buf_size = claims_buf_size; + return SGX_SUCCESS; +} + +sgx_status_t generate_cbor_evidence(uint8_t *quote, size_t quote_size, + uint8_t *claim, size_t claim_size, + uint8_t **out_evidence, size_t *evidence_size) +{ + cbor_item_t* cbor_evidence = cbor_new_definite_array(2); + if (!cbor_evidence) + return SGX_ERROR_OUT_OF_MEMORY; + + cbor_item_t* cbor_quote = cbor_build_bytestring(quote, quote_size); + if (!cbor_quote) { + cbor_decref(&cbor_evidence); + return SGX_ERROR_OUT_OF_MEMORY; + } + + cbor_item_t* cbor_claims = cbor_build_bytestring(claim, claim_size); + if (!cbor_claims) { + cbor_decref(&cbor_quote); + cbor_decref(&cbor_evidence); + return SGX_ERROR_OUT_OF_MEMORY; + } + + int bool_ret = cbor_array_push(cbor_evidence, cbor_quote); + if (!bool_ret) { + cbor_decref(&cbor_claims); + cbor_decref(&cbor_quote); + cbor_decref(&cbor_evidence); + return SGX_ERROR_OUT_OF_MEMORY; + } + + bool_ret = cbor_array_push(cbor_evidence, cbor_claims); + if (!bool_ret) { + cbor_decref(&cbor_claims); + cbor_decref(&cbor_quote); + cbor_decref(&cbor_evidence); + return SGX_ERROR_OUT_OF_MEMORY; + } + + /* cbor_evidence took ownership of quote and claims cbor bstrs */ + cbor_decref(&cbor_claims); + cbor_decref(&cbor_quote); + + cbor_item_t* cbor_tagged_evidence = cbor_new_tag(TCG_DICE_TAGGED_EVIDENCE_TEE_QUOTE_CBOR_TAG); + if (!cbor_tagged_evidence) { + cbor_decref(&cbor_evidence); + return SGX_ERROR_OUT_OF_MEMORY; + } + + cbor_tag_set_item(cbor_tagged_evidence, cbor_evidence); + + uint8_t* evidence_buf; + size_t evidence_buf_size; + cbor_serialize_alloc(cbor_tagged_evidence, &evidence_buf, &evidence_buf_size); + + cbor_decref(&cbor_evidence); + cbor_decref(&cbor_tagged_evidence); + + if (!evidence_buf) + return SGX_ERROR_OUT_OF_MEMORY; + + *out_evidence = evidence_buf; + *evidence_size = evidence_buf_size; + return SGX_SUCCESS; +} + extern "C" quote3_error_t tee_get_certificate_with_evidence( const unsigned char *p_subject_name, const uint8_t *p_prv_key, @@ -76,13 +315,18 @@ extern "C" quote3_error_t tee_get_certificate_with_evidence( #ifndef TDX_ENV sgx_report_t app_report; sgx_target_info_t target_info; - sgx_sha_state_handle_t sha_handle = NULL; sgx_report_data_t report_data = { 0 }; #else tdx_attest_error_t tdx_ret = TDX_ATTEST_ERROR_UNEXPECTED; tdx_uuid_t selected_att_key_id = { 0 }; tdx_report_data_t report_data = { 0 }; #endif + uint8_t* claims = NULL; + size_t claims_size; + + uint8_t* p_evidence = NULL; + size_t evidence_size; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; quote3_error_t func_ret = SGX_QL_ERROR_UNEXPECTED; uint8_t *p_quote = NULL; @@ -100,37 +344,29 @@ extern "C" quote3_error_t tee_get_certificate_with_evidence( return SGX_QL_ERROR_INVALID_PARAMETER; do { -#ifndef TDX_ENV - //OCALL to get target info of QE - ret = sgx_tls_get_qe_target_info_ocall(&func_ret, &target_info, sizeof(sgx_target_info_t)); + // first need to get cbor claims through pub_key + ret = generate_cbor_claims(p_pub_key, public_key_size, &claims, &claims_size); if (ret != SGX_SUCCESS) { func_ret = SGX_QL_ERROR_UNEXPECTED; break; } - if (func_ret != SGX_QL_SUCCESS) - break; - //Use user provided input as report data - //report data = sha256(public key) || 0s - ret = sgx_sha256_init(&sha_handle); - if (ret != SGX_SUCCESS) { +#ifndef TDX_ENV + if (!SHA256(claims, claims_size, reinterpret_cast(&report_data))) + { func_ret = SGX_QL_ERROR_UNEXPECTED; break; } - ret = sgx_sha256_update(p_pub_key, (uint32_t)public_key_size, sha_handle); + //OCALL to get target info of QE + ret = sgx_tls_get_qe_target_info_ocall(&func_ret, &target_info, sizeof(sgx_target_info_t)); if (ret != SGX_SUCCESS) { func_ret = SGX_QL_ERROR_UNEXPECTED; break; } - - ret = sgx_sha256_get_hash(sha_handle, reinterpret_cast(&report_data)); - if (ret != SGX_SUCCESS) { - func_ret = SGX_QL_ERROR_UNEXPECTED; + if (func_ret != SGX_QL_SUCCESS) break; - } - //generate report with returned QE target info ret = sgx_create_report(&target_info, &report_data, &app_report); if (ret != SGX_SUCCESS) { func_ret = SGX_QL_ERROR_UNEXPECTED; @@ -161,8 +397,11 @@ extern "C" quote3_error_t tee_get_certificate_with_evidence( } if (func_ret != SGX_QL_SUCCESS) break; + + #else - if (!SHA256(p_pub_key, public_key_size, reinterpret_cast(&report_data))) { + if (!SHA384(claims, claims_size, reinterpret_cast(&report_data))) + { func_ret = SGX_QL_ERROR_UNEXPECTED; break; } @@ -173,12 +412,22 @@ extern "C" quote3_error_t tee_get_certificate_with_evidence( break; } #endif - - //Generate self-signed X.509 certiciate - //Make SGX quote as an extension + // after generating quote, generating cbor evidence + ret = generate_cbor_evidence(p_quote, quote_size, claims, claims_size, &p_evidence, + &evidence_size); + if (ret != SGX_SUCCESS) { + func_ret = SGX_QL_ERROR_UNEXPECTED; + break; + } + + // generate self-signed X.509 certificate + // Make SGX quote as an extension + // Make cbor formalized quote as an extension ret = generate_x509_self_signed_certificate( (const unsigned char*) oid_sgx_quote, strlen(oid_sgx_quote), + (const unsigned char*) g_evidence_oid, + (size_t)strlen((const char*)g_evidence_oid), p_subject_name, p_prv_key, private_key_size, @@ -186,8 +435,11 @@ extern "C" quote3_error_t tee_get_certificate_with_evidence( public_key_size, p_quote, quote_size, + p_evidence, + evidence_size, pp_output_cert, p_output_cert_size); + if (ret != SGX_SUCCESS) { func_ret = SGX_QL_ERROR_UNEXPECTED; break; @@ -198,11 +450,12 @@ extern "C" quote3_error_t tee_get_certificate_with_evidence( } while (0); SGX_TLS_SAFE_FREE(p_quote); - -#ifndef TDX_ENV - if (sha_handle) - sgx_sha256_close(sha_handle); -#endif + + /* claims and p_evidece are allocated by cbor_serialize_alloc function */ + /* its default alloc mechanism is by standard lib malloc, realloc, free*/ + /* so do not forget to free them here */ + SGX_TLS_SAFE_FREE(claims); + SGX_TLS_SAFE_FREE(p_evidence); return func_ret; } @@ -226,17 +479,13 @@ extern "C" quote3_error_t tee_verify_certificate_with_evidence( quote3_error_t func_ret = SGX_QL_ERROR_UNEXPECTED; uint8_t *p_quote = NULL; uint32_t quote_size = 0; + uint8_t *p_cbor_evidence = NULL; + uint32_t cbor_evidence_size = 0; sgx_ql_qe_report_info_t qve_report_info; uint32_t collateral_expiration_status = 0; - sgx_cert_t cert = {0}; uint8_t *pub_key_buff = NULL; size_t pub_key_buff_size = KEY_BUFF_SIZE; - uint32_t quote_type = 0; - uint8_t *p_report_data = NULL; - uint8_t *p_cert_pub_hash = NULL; - size_t report_data_size = 0; - sgx_sha_state_handle_t sha_handle = NULL; if (p_cert_in_der == NULL || p_qv_result == NULL || @@ -244,7 +493,6 @@ extern "C" quote3_error_t tee_verify_certificate_with_evidence( p_supplemental_data_size == NULL) return SGX_QL_ERROR_INVALID_PARAMETER; - do { //verify X.509 certificate pub_key_buff = (uint8_t*)malloc(KEY_BUFF_SIZE); @@ -264,31 +512,68 @@ extern "C" quote3_error_t tee_verify_certificate_with_evidence( if (ret != SGX_SUCCESS) break; - // try to get quote from cert extension + ret = sgx_get_pubkey_from_cert(&cert, pub_key_buff, &pub_key_buff_size); + if (ret != SGX_SUCCESS) { + func_ret = SGX_QL_ERROR_UNEXPECTED; + break; + } + p_quote = (uint8_t*)malloc(RAW_QUOTE_MAX_SIZE); + if (!p_quote) { + func_ret = SGX_QL_ERROR_OUT_OF_MEMORY; + break; + } + p_cbor_evidence = (uint8_t*)malloc(CBOR_QUOTE_MAX_SIZE); + if (!p_cbor_evidence) { + func_ret = SGX_QL_ERROR_OUT_OF_MEMORY; + break; + } + + // first find cbor evidence here if (sgx_cert_find_extension( &cert, - oid_sgx_quote, - NULL, - "e_size) == SGX_ERROR_INVALID_PARAMETER) + g_evidence_oid, + p_cbor_evidence, + &cbor_evidence_size) == SGX_SUCCESS) { - p_quote = (uint8_t*)malloc(quote_size); - if (!p_quote) { - func_ret = SGX_QL_OUT_OF_EPC; + if (cbor_evidence_size > CBOR_QUOTE_MAX_SIZE) + { + func_ret = SGX_QL_ERROR_UNEXPECTED; + break; + } + ret = extract_cbor_evidence_and_compare_hash(p_cbor_evidence, cbor_evidence_size, + pub_key_buff, pub_key_buff_size, p_quote, "e_size); + if (ret != SGX_SUCCESS) + { + func_ret = SGX_QL_ERROR_UNEXPECTED; break; } } - - if (sgx_cert_find_extension( - &cert, - oid_sgx_quote, - p_quote, - "e_size) != SGX_SUCCESS) + // otherwise, try to find legacy sgx oid + else if (sgx_cert_find_extension( + &cert, + oid_sgx_quote, + p_quote, + "e_size) == SGX_SUCCESS) + { + if (quote_size > RAW_QUOTE_MAX_SIZE) + { + func_ret = SGX_QL_ERROR_UNEXPECTED; + break; + } + ret = sgx_tls_compare_quote_hash(p_quote, + pub_key_buff, pub_key_buff_size); + if (ret != SGX_SUCCESS) + { + func_ret = SGX_QL_ERROR_UNEXPECTED; + break; + } + } + else { func_ret = SGX_QL_ERROR_UNEXPECTED; break; } } - catch (...) { func_ret = SGX_QL_ERROR_UNEXPECTED; break; @@ -355,73 +640,14 @@ extern "C" quote3_error_t tee_verify_certificate_with_evidence( if (func_ret != SGX_QL_SUCCESS) break; - // identify quote type from quote header - quote_type = *(uint32_t *)(p_quote + 4 * sizeof(uint8_t)); - - // extract public key from cert - ret = sgx_get_pubkey_from_cert(&cert, pub_key_buff, &pub_key_buff_size); - if (ret != SGX_SUCCESS) { - func_ret = SGX_QL_ERROR_UNEXPECTED; - break; - } - - // get hash of cert pub key - report_data_size = (quote_type == 0x81) ? SGX_REPORT2_DATA_SIZE : SGX_REPORT_DATA_SIZE; - p_cert_pub_hash = (uint8_t*)malloc(report_data_size); - if (!p_cert_pub_hash) { - func_ret = SGX_QL_OUT_OF_EPC; - break; - } - - ret = sgx_sha256_init(&sha_handle); - if (ret != SGX_SUCCESS) { - func_ret = SGX_QL_ERROR_UNEXPECTED; - break; - } - - // public key - ret = sgx_sha256_update(pub_key_buff, (uint32_t)pub_key_buff_size, sha_handle); - if (ret != SGX_SUCCESS) { - func_ret = SGX_QL_ERROR_UNEXPECTED; - break; - } - - ret = sgx_sha256_get_hash(sha_handle, reinterpret_cast(p_cert_pub_hash)); - if (ret != SGX_SUCCESS) { - func_ret = SGX_QL_ERROR_UNEXPECTED; - break; - } - - // extract report data from quote - if (quote_type == 0) { - p_report_data = (uint8_t *)(&((sgx_quote3_t *)p_quote)->report_body.report_data); - } - else if (quote_type == 0x81) { - p_report_data = (uint8_t *)(&((sgx_quote4_t *)p_quote)->report_body.report_data); - } - else { - func_ret = SGX_QL_ERROR_UNEXPECTED; - break; - } - - // compare hash, only compare the first 32 bytes - if (memcmp(p_report_data, p_cert_pub_hash, SGX_HASH_SIZE) != 0) { - func_ret = SGX_QL_ERROR_PUB_KEY_ID_MISMATCH; - break; - } - } while(0); SGX_TLS_SAFE_FREE(pub_key_buff); SGX_TLS_SAFE_FREE(p_quote); - SGX_TLS_SAFE_FREE(p_cert_pub_hash); - + SGX_TLS_SAFE_FREE(p_cbor_evidence); if (func_ret != SGX_QL_SUCCESS) SGX_TLS_SAFE_FREE(*pp_supplemental_data); - if (sha_handle) - sgx_sha256_close(sha_handle); - return func_ret; } diff --git a/sdk/utls/Makefile b/sdk/utls/Makefile index 9c1d2e68a..530a47408 100644 --- a/sdk/utls/Makefile +++ b/sdk/utls/Makefile @@ -35,13 +35,15 @@ include $(TOP_DIR)/buildenv.mk CERT_UTIL_DIR := ../ttls SGX_QV_PATH ?= ../../external/dcap_source/QuoteVerification PREBUILD_OPENSSL_PATH ?= $(SGX_QV_PATH)/../prebuilt/openssl - +CBOR_PATH ?= $(LINUX_EXTERNAL_DIR)/cbor +LIBCBOR_PATH ?= $(CBOR_PATH)/untrusted/lib INCLUDE += -I. INCLUDE += -I$(COMMON_DIR) \ -I$(COMMON_DIR)/inc \ -I$(COMMON_DIR)/inc/internal \ -I$(PREBUILD_OPENSSL_PATH)/inc \ + -I$(CBOR_PATH)/untrusted/include \ -I$(CERT_UTIL_DIR) \ -I$(SGX_QV_PATH)/QvE/Include \ -I$(SGX_QV_PATH)/dcap_quoteverify/inc \ @@ -57,6 +59,8 @@ vpath %.cpp .. $(COMMON_DIR)/src $(CERT_UTIL_DIR) SRC := utls.cpp +LIBCBOR := libcbor.a + HOST_CERT_SRC := cert_verifier.cpp OBJ := $(SRC:.cpp=.o) @@ -69,19 +73,27 @@ LIBNAME = libsgx_utls.a all: $(LIBNAME) | $(BUILD_DIR) $(CP) $(LIBNAME) $| -$(OBJ): $(SRC) - $(CXX) $(CXXFLAGS) -Wno-deprecated-declarations $(INCLUDE) -c $< -o $@ +$(LIBNAME): $(OBJ) $(CERT_OBJ) + $(AR) rs $@ $(OBJ) $(CERT_OBJ) + $(MKDIR) $(BUILD_DIR)/.libcbor + $(RM) $(BUILD_DIR)/.libcbor/* && cd $(BUILD_DIR)/.libcbor && $(AR) x $(LIBCBOR_PATH)/$(LIBCBOR) + $(AR) rs $@ $(BUILD_DIR)/.libcbor/*.o + @$(RM) -r $(BUILD_DIR)/.libcbor + +$(OBJ): $(LIBCBOR) $(SRC) + $(CXX) $(CXXFLAGS) -Wno-deprecated-declarations $(INCLUDE) -c $(SRC) -o $@ $(CERT_OBJ): $(HOST_CERT_SRC) $(CXX) $(CXXFLAGS) -Wno-deprecated-declarations $(INCLUDE) -c $< -o $@ -$(LIBNAME): $(OBJ) $(CERT_OBJ) - $(AR) rs $@ $(OBJ) $(CERT_OBJ) +$(LIBCBOR): + @test -f $(LIBCBOR_PATH)/$(LIBCBOR) || $(MAKE) -C $(CBOR_PATH) cbor_untrusted .PHONY: clean clean: @$(RM) $(OBJ) $(CERT_OBJ) @$(RM) $(LIBNAME) $(BUILD_DIR)/$(LIBNAME) + $(MAKE) -C $(CBOR_PATH) clean .PHONY: rebuild rebuild: diff --git a/sdk/utls/utls.cpp b/sdk/utls/utls.cpp index 9ec3a6943..3132de647 100644 --- a/sdk/utls/utls.cpp +++ b/sdk/utls/utls.cpp @@ -142,15 +142,11 @@ extern "C" quote3_error_t tee_verify_certificate_with_evidence_host( quote3_error_t func_ret = SGX_QL_ERROR_UNEXPECTED; uint8_t *p_quote = NULL; uint32_t quote_size = 0; - + uint8_t *p_cbor_evidence = NULL; + uint32_t cbor_evidence_size = 0; sgx_cert_t cert = {0}; uint8_t *pub_key_buff = NULL; size_t pub_key_buff_size = KEY_BUFF_SIZE; - uint32_t quote_type = 0; - uint8_t *p_report_data = NULL; - uint8_t *p_cert_pub_hash = NULL; - size_t report_data_size = 0; - SHA256_CTX sha_handle; if (p_cert_in_der == NULL || p_qv_result == NULL || @@ -158,7 +154,6 @@ extern "C" quote3_error_t tee_verify_certificate_with_evidence_host( p_supplemental_data_size == NULL) return SGX_QL_ERROR_INVALID_PARAMETER; - do { //verify X.509 certificate pub_key_buff = (uint8_t*)malloc(KEY_BUFF_SIZE); @@ -178,36 +173,78 @@ extern "C" quote3_error_t tee_verify_certificate_with_evidence_host( if (ret != SGX_SUCCESS) break; - // try to get quote from cert extension + ret = sgx_get_pubkey_from_cert(&cert, pub_key_buff, &pub_key_buff_size); + if (ret != SGX_SUCCESS) { + func_ret = SGX_QL_ERROR_UNEXPECTED; + break; + } + + p_quote = (uint8_t*)malloc(RAW_QUOTE_MAX_SIZE); + if (!p_quote) { + func_ret = SGX_QL_ERROR_OUT_OF_MEMORY; + break; + } + + p_cbor_evidence = (uint8_t*)malloc(CBOR_QUOTE_MAX_SIZE); + if (!p_cbor_evidence) { + func_ret = SGX_QL_ERROR_OUT_OF_MEMORY; + break; + } + if (sgx_cert_find_extension( &cert, - oid_sgx_quote, - NULL, - "e_size) == SGX_ERROR_INVALID_PARAMETER) + g_evidence_oid, + p_cbor_evidence, + &cbor_evidence_size) == SGX_SUCCESS) { - p_quote = (uint8_t*)malloc(quote_size); - if (!p_quote) { - func_ret = SGX_QL_ERROR_OUT_OF_MEMORY; + if (cbor_evidence_size > CBOR_QUOTE_MAX_SIZE) + { + // buffer overflow, return error + func_ret = SGX_QL_ERROR_UNEXPECTED; + break; + } + // if tcg tagged evidence oid found, extract it here + ret = extract_cbor_evidence_and_compare_hash(p_cbor_evidence, cbor_evidence_size, + pub_key_buff, pub_key_buff_size, + p_quote, "e_size); + if (ret != SGX_SUCCESS) + { + func_ret = SGX_QL_ERROR_UNEXPECTED; break; } } - - if (sgx_cert_find_extension( - &cert, - oid_sgx_quote, - p_quote, - "e_size) != SGX_SUCCESS) + else if (sgx_cert_find_extension( + &cert, + oid_sgx_quote, + p_quote, + "e_size) == SGX_SUCCESS) + { + // if no tcg tagged evidence oid found, try to find the legacy + // oid + if (quote_size > RAW_QUOTE_MAX_SIZE) + { + func_ret = SGX_QL_ERROR_UNEXPECTED; + break; + } + ret = sgx_tls_compare_quote_hash(p_quote, + pub_key_buff, pub_key_buff_size); + if (ret != SGX_SUCCESS){ + func_ret = SGX_QL_ERROR_UNEXPECTED; + break; + } + } + else { func_ret = SGX_QL_ERROR_UNEXPECTED; break; } } - catch (...) { func_ret = SGX_QL_ERROR_UNEXPECTED; break; } + // check supplemental data func_ret = sgx_tls_get_supplemental_data_size_ocall(p_supplemental_data_size); if (func_ret != SGX_QL_SUCCESS) { break; @@ -230,65 +267,11 @@ extern "C" quote3_error_t tee_verify_certificate_with_evidence_host( if (func_ret != SGX_QL_SUCCESS) break; - - // identify quote type from quote header - quote_type = *(uint32_t *)(p_quote + 4 * sizeof(uint8_t)); - - // extract public key from cert - ret = sgx_get_pubkey_from_cert(&cert, pub_key_buff, &pub_key_buff_size); - if (ret != SGX_SUCCESS) { - func_ret = SGX_QL_ERROR_UNEXPECTED; - break; - } - - // get hash of cert pub key - report_data_size = (quote_type == 0x81) ? SGX_REPORT2_DATA_SIZE : SGX_REPORT_DATA_SIZE; - p_cert_pub_hash = (uint8_t*)malloc(report_data_size); - if (!p_cert_pub_hash) { - func_ret = SGX_QL_OUT_OF_EPC; - break; - } - - if (!SHA256_Init(&sha_handle)) { - func_ret = SGX_QL_ERROR_UNEXPECTED; - break; - } - - // public key - if (!SHA256_Update(&sha_handle, pub_key_buff, pub_key_buff_size)) { - func_ret = SGX_QL_ERROR_UNEXPECTED; - break; - } - - if (!SHA256_Final(reinterpret_cast(p_cert_pub_hash), &sha_handle)) { - func_ret = SGX_QL_ERROR_UNEXPECTED; - break; - } - - // extract report data from quote - if (quote_type == 0) { - p_report_data = (uint8_t *)(&((sgx_quote3_t *)p_quote)->report_body.report_data); - } - else if (quote_type == 0x81) { - p_report_data = (uint8_t *)(&((sgx_quote4_t *)p_quote)->report_body.report_data); - } - else { - func_ret = SGX_QL_ERROR_UNEXPECTED; - break; - } - - // compare hash, only compare the first 32 bytes - if (memcmp(p_report_data, p_cert_pub_hash, SGX_HASH_SIZE) != 0) { - func_ret = SGX_QL_ERROR_PUB_KEY_ID_MISMATCH; - break; - } - - } while(0); SGX_TLS_SAFE_FREE(pub_key_buff); SGX_TLS_SAFE_FREE(p_quote); - SGX_TLS_SAFE_FREE(p_cert_pub_hash); + SGX_TLS_SAFE_FREE(p_cbor_evidence); if (func_ret != SGX_QL_SUCCESS) SGX_TLS_SAFE_FREE(*pp_supplemental_data);