diff --git a/QuoteGeneration/Makefile b/QuoteGeneration/Makefile index c55c3619..4c725b54 100644 --- a/QuoteGeneration/Makefile +++ b/QuoteGeneration/Makefile @@ -48,11 +48,11 @@ DISTR_VER := $(call get_distr_info, '^VERSION_ID=') # DCAP requires prebuilt enclaves. CHECK_OPT := -ifeq ("$(wildcard psw/ae/data/prebuilt)", "") +ifeq ("$(wildcard psw/ae/data/prebuilt/*.signed.so)", "") CHECK_OPT := opt_check_failed endif -dcap: tdx_logic tdx_qgs tdx_attest $(CHECK_OPT) pce_logic qe3_logic qcnl_wrapper qpl_wrapper qve_wrapper tdx_qe id_enclave +dcap: tdx_logic tdx_qgs tdx_attest $(CHECK_OPT) pce_logic qe3_logic qcnl_wrapper qpl_wrapper qve_wrapper opt_check_failed: @echo "Please run download_prebuilt.sh before compiling" @@ -61,8 +61,6 @@ opt_check_failed: pce_logic: $(MAKE) -C pce_wrapper/linux -id_enclave: - $(MAKE) -C quote_wrapper/quote/id_enclave/linux qe3_logic: pce_logic $(MAKE) -C quote_wrapper/ql/linux @@ -110,7 +108,7 @@ deb_sgx_ae_qve_pkg: $(CHECK_OPT) .PHONY: deb_sgx_ae_tdqe_pkg deb_sgx_tdx_logic_pkg deb_sgx_tdx_qgs_pkg deb_sgx_tdx_attest_pkg ifeq ($(DISTR_ID)$(DISTR_VER),ubuntu18.04) -tdx_qe deb_sgx_ae_tdqe_pkg: +deb_sgx_ae_tdqe_pkg: echo "Skip tdqe in ubuntu 18.04" tdx_logic deb_sgx_tdx_logic_pkg: echo "Skip tdx_logic in ubuntu 18.04" @@ -119,8 +117,6 @@ tdx_qgs deb_sgx_tdx_qgs_pkg: tdx_attest deb_sgx_tdx_attest_pkg: echo "Skip tdx_attest in ubuntu 18.04" else -tdx_qe: - $(MAKE) -C quote_wrapper/tdx_quote/enclave/linux tdx_logic: pce_logic $(MAKE) -C quote_wrapper/tdx_quote/linux tdx_qgs: tdx_logic @@ -184,25 +180,29 @@ rpm_sgx_ae_qe3_pkg: $(CHECK_OPT) .PHONY: rpm_sgx_ae_tdqe_pkg rpm_sgx_ae_tdqe_pkg: $(CHECK_OPT) ./installer/linux/rpm/libsgx-ae-tdqe/build.sh + .PHONY: rpm_sgx_ae_id_enclave_pkg rpm_sgx_ae_id_enclave_pkg: $(CHECK_OPT) ./installer/linux/rpm/libsgx-ae-id-enclave/build.sh .PHONY: rpm_sgx_ae_qve_pkg -rpm_sgx_ae_qve_pkg: $(CHECK_OPT) qve_wrapper +rpm_sgx_ae_qve_pkg: $(CHECK_OPT) ./installer/linux/rpm/libsgx-ae-qve/build.sh + .PHONY: rpm_sgx_tdx_logic_pkg rpm_sgx_tdx_logic_pkg: tdx_logic ./installer/linux/rpm/libsgx-tdx-logic/build.sh + .PHONY: rpm_sgx_tdx_qgs_pkg rpm_sgx_tdx_qgs_pkg: tdx_qgs ./installer/linux/rpm/tdx-qgs/build.sh + .PHONY: rpm_sgx_tdx_attest_pkg rpm_sgx_tdx_attest_pkg: tdx_attest ./installer/linux/rpm/libtdx-attest/build.sh .PHONY: rpm_sgx_dcap_quote_verify_pkg -rpm_sgx_dcap_quote_verify_pkg: $(CHECK_OPT) qve_wrapper +rpm_sgx_dcap_quote_verify_pkg: qve_wrapper ./installer/linux/rpm/libsgx-dcap-quote-verify/build.sh .PHONY: rpm_sgx_qe3_logic_pkg diff --git a/QuoteGeneration/README.md b/QuoteGeneration/README.md index 94e0a7c7..5be32059 100644 --- a/QuoteGeneration/README.md +++ b/QuoteGeneration/README.md @@ -37,7 +37,7 @@ For Windows* OS **NOTE**:`sgx_dcap_dev.inf` is for Windows* Server 2016 LTSC and `sgx_dcap.inf` is for Windows* Server 2019 LTSC. ## How to install - Refer to the *"Installation Instructions"* section in the [Intel(R) Software Guard Extensions: Data Center Attestation Primitives Installation Guide For Windows* OS](https://download.01.org/intel-sgx/sgx-dcap/1.14/windows/docs/Intel_SGX_DCAP_Windows_SW_Installation_Guide.pdf) to install the right packages on your platform. + Refer to the *"Installation Instructions"* section in the [Intel(R) Software Guard Extensions: Data Center Attestation Primitives Installation Guide For Windows* OS](https://download.01.org/intel-sgx/sgx-dcap/1.15/windows/docs/Intel_SGX_DCAP_Windows_SW_Installation_Guide.pdf) to install the right packages on your platform. For Linux* OS @@ -60,7 +60,7 @@ For Linux* OS ``` * On Ubuntu 20.04 ``` - $ sudo apt-get install build-essential wget python-is-python3 debhelper zip libcurl4-openssl-dev pkgconf libboost-dev libboost-system-dev protobuf-c-compiler libprotobuf-c-dev protobuf-compiler + $ sudo apt-get install build-essential wget python-is-python3 debhelper zip libcurl4-openssl-dev pkgconf libboost-dev libboost-system-dev libboost-thread-dev protobuf-c-compiler libprotobuf-c-dev protobuf-compiler ``` * On Red Hat Enterprise Linux 8.5 ``` @@ -193,4 +193,4 @@ A `README.md` is provided in the Intel(R) SGX driver package for Intel(R) SGX DC $ sudo rpm -ivh libsgx-dcap-default-qpl-debuginfo*.rpm ``` ## TDX Attestation Support -- From version 1.14, TDX attestation feature is added into DCAP. Corresponding packages will be built along with the DCAP Quote Generation Library adn DCAP Quote Verification Library. Currently, TDX attestation support has been verified on Red Hat Enterprise Linux 8.5 and CentOS Stream 8 only. +- From version 1.14, TDX attestation feature is added into DCAP. Corresponding packages will be built along with the DCAP Quote Generation Library and DCAP Quote Verification Library. Currently, TDX attestation support has been verified on Red Hat Enterprise Linux 8.5 and CentOS Stream 8 only. diff --git a/QuoteGeneration/common/inc/internal/se_version.h b/QuoteGeneration/common/inc/internal/se_version.h index 9f8a558e..a2812cc6 100644 --- a/QuoteGeneration/common/inc/internal/se_version.h +++ b/QuoteGeneration/common/inc/internal/se_version.h @@ -28,21 +28,21 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -#define STRFILEVER "1.14.100.3" +#define STRFILEVER "1.15.100.3" #define COPYRIGHT "Copyright (C) 2022 Intel Corporation" -#define FILEVER 1,14,100,3 -#define PRODUCTVER 1,14,100,3 -#define STRPRODUCTVER "1.14.100.3" +#define FILEVER 1,15,100,3 +#define PRODUCTVER 1,15,100,3 +#define STRPRODUCTVER "1.15.100.3" #define COMPANYNAME "Intel Corporation" #define PRODUCTNAME "IntelĀ® Software Guard Extensions" -#define DEFAULT_QPL_VERSION "1.13.100.3" -#define QUOTE_VERIFIER_VERSION "1.12.100.3" -#define QUOTE_LOADER_VERSION "1.11.103.3" -#define TDQE_WRAPPER_VERSION "1.14.100.3" -#define PCE_WRAPPER_VERSION "1.14.100.3" +#define DEFAULT_QPL_VERSION "1.13.102.3" +#define QUOTE_VERIFIER_VERSION "1.12.102.3" +#define QUOTE_LOADER_VERSION "1.11.105.3" +#define TDQE_WRAPPER_VERSION "1.14.102.3" +#define PCE_WRAPPER_VERSION "1.14.102.3" -#define QE3_VERSION "1.14.100.2" -#define QVE_VERSION "1.14.100.2" +#define QE3_VERSION "1.15.100.1" +#define QVE_VERSION "1.15.100.1" #define IDE_VERSION "1.14.100.2" #define TDQE_VERSION "1.14.100.2" diff --git a/QuoteGeneration/download_prebuilt.bat b/QuoteGeneration/download_prebuilt.bat index 9d4ebaf2..ca6ef00b 100644 --- a/QuoteGeneration/download_prebuilt.bat +++ b/QuoteGeneration/download_prebuilt.bat @@ -29,9 +29,9 @@ @echo off -set ae_file_name=prebuilt_windows_dcap_1.14.zip -set checksum_file=SHA256SUM_prebuilt_windows_dcap_1.14.cfg -set server_url_path=https://download.01.org/intel-sgx/sgx-dcap/1.14/windows/ +set ae_file_name=prebuilt_windows_dcap_1.15.zip +set checksum_file=SHA256SUM_prebuilt_windows_dcap_1.15.cfg +set server_url_path=https://download.01.org/intel-sgx/sgx-dcap/1.15/windows/ set server_ae_url=%server_url_path%/%ae_file_name% set server_checksum_url=%server_url_path%/%checksum_file% diff --git a/QuoteGeneration/download_prebuilt.sh b/QuoteGeneration/download_prebuilt.sh index 00c21227..ac547d65 100755 --- a/QuoteGeneration/download_prebuilt.sh +++ b/QuoteGeneration/download_prebuilt.sh @@ -32,9 +32,9 @@ top_dir=`dirname $0` out_dir=$top_dir -ae_file_name=prebuilt_dcap_1.14.tar.gz -checksum_file=SHA256SUM_prebuilt_dcap_1.14.cfg -server_url_path=https://download.01.org/intel-sgx/sgx-dcap/1.14/linux +ae_file_name=prebuilt_dcap_1.15.tar.gz +checksum_file=SHA256SUM_prebuilt_dcap_1.15.cfg +server_url_path=https://download.01.org/intel-sgx/sgx-dcap/1.15/linux/ server_ae_url=$server_url_path/$ae_file_name server_checksum_url=$server_url_path/$checksum_file diff --git a/QuoteGeneration/installer/linux/common/libsgx-dcap-default-qpl/BOMs/libsgx-dcap-default-qpl-dev.txt b/QuoteGeneration/installer/linux/common/libsgx-dcap-default-qpl/BOMs/libsgx-dcap-default-qpl-dev.txt new file mode 100644 index 00000000..5b5ca463 --- /dev/null +++ b/QuoteGeneration/installer/linux/common/libsgx-dcap-default-qpl/BOMs/libsgx-dcap-default-qpl-dev.txt @@ -0,0 +1,2 @@ +DeliveryName InstallName FileCheckSum FileFeature FileOwner +/qpl/inc/sgx_default_quote_provider.h /include/sgx_default_quote_provider.h 0 main STP diff --git a/QuoteGeneration/installer/linux/common/libsgx-dcap-default-qpl/Makefile b/QuoteGeneration/installer/linux/common/libsgx-dcap-default-qpl/Makefile index c7ba2475..6cc855c2 100644 --- a/QuoteGeneration/installer/linux/common/libsgx-dcap-default-qpl/Makefile +++ b/QuoteGeneration/installer/linux/common/libsgx-dcap-default-qpl/Makefile @@ -35,6 +35,7 @@ PACKAGE_ROOT_FOLDER=pkgroot PACKAGES=$(notdir $(wildcard $(PACKAGE_ROOT_FOLDER)/*)) USR_LIB_PATH=/usr/$(notdir $(shell gcc -print-multi-os-directory))/$(shell dpkg-architecture -qDEB_HOST_MULTIARCH 2> /dev/null) +USR_INC_PATH=/usr/$(INC_DIR) USR_LIB_VER=1.0.0 SPLIT_VERSION=$(word $2,$(subst ., ,$1)) @@ -60,4 +61,6 @@ $(PACKAGES): $(if $(wildcard $(PACKAGE_ROOT_FOLDER)/$@/$(ETC_DIR)/.*), \ install -d $(shell readlink -m $(DESTDIR)/$@/$(ETC_DIR)) && \ mv $(PACKAGE_ROOT_FOLDER)/$@/$(ETC_DIR)/* $(DESTDIR)/$@/$(ETC_DIR)) - + $(if $(wildcard $(PACKAGE_ROOT_FOLDER)/$@/$(INC_DIR)/.*), \ + install -d $(shell readlink -m $(DESTDIR)/$@/$(USR_INC_PATH)) && \ + mv $(PACKAGE_ROOT_FOLDER)/$@/$(INC_DIR)/* $(DESTDIR)/$@/$(USR_INC_PATH)) diff --git a/QuoteGeneration/installer/linux/common/libsgx-dcap-default-qpl/createTarball.sh b/QuoteGeneration/installer/linux/common/libsgx-dcap-default-qpl/createTarball.sh index 8538ae1a..ad7de915 100755 --- a/QuoteGeneration/installer/linux/common/libsgx-dcap-default-qpl/createTarball.sh +++ b/QuoteGeneration/installer/linux/common/libsgx-dcap-default-qpl/createTarball.sh @@ -51,6 +51,7 @@ cp ${LINUX_INSTALLER_COMMON_DIR}/gen_source/gen_source.py ${SCRIPT_DIR} # Copy the files according to the BOM python ${SCRIPT_DIR}/gen_source.py --bom=BOMs/libsgx-dcap-default-qpl.txt --installdir=pkgroot/libsgx-dcap-default-qpl +python ${SCRIPT_DIR}/gen_source.py --bom=BOMs/libsgx-dcap-default-qpl-dev.txt --cleanup=false --installdir=pkgroot/libsgx-dcap-default-qpl-dev python ${SCRIPT_DIR}/gen_source.py --bom=BOMs/libsgx-dcap-default-qpl-package.txt --cleanup=false python ${SCRIPT_DIR}/gen_source.py --bom=../licenses/BOM_license.txt --cleanup=false diff --git a/QuoteGeneration/installer/linux/common/libsgx-dcap-default-qpl/installConfig b/QuoteGeneration/installer/linux/common/libsgx-dcap-default-qpl/installConfig index d5f3d75a..73e1e329 100644 --- a/QuoteGeneration/installer/linux/common/libsgx-dcap-default-qpl/installConfig +++ b/QuoteGeneration/installer/linux/common/libsgx-dcap-default-qpl/installConfig @@ -6,3 +6,4 @@ DCAP_QPL_DEV_PACKAGE_NAME=libsgx-dcap-default-qpl-dev LIB_DIR=lib ETC_DIR=etc +INC_DIR=include diff --git a/QuoteGeneration/installer/linux/common/libsgx-tdx-logic/BOMs/libsgx-tdx-logic-dev.txt b/QuoteGeneration/installer/linux/common/libsgx-tdx-logic/BOMs/libsgx-tdx-logic-dev.txt index d2966f42..f42724fb 100644 --- a/QuoteGeneration/installer/linux/common/libsgx-tdx-logic/BOMs/libsgx-tdx-logic-dev.txt +++ b/QuoteGeneration/installer/linux/common/libsgx-tdx-logic/BOMs/libsgx-tdx-logic-dev.txt @@ -1,2 +1,2 @@ DeliveryName InstallName FileCheckSum FileFeature FileOwner -/quote_wrapper/tdx_quote/td_ql_logic.h /include/td_ql_logic.h 0 main STP +/quote_wrapper/tdx_quote/inc/td_ql_wrapper.h /include/td_ql_wrapper.h 0 main STP diff --git a/QuoteGeneration/installer/linux/common/libtdx-attest/Makefile b/QuoteGeneration/installer/linux/common/libtdx-attest/Makefile index aa7768b3..8007c84d 100644 --- a/QuoteGeneration/installer/linux/common/libtdx-attest/Makefile +++ b/QuoteGeneration/installer/linux/common/libtdx-attest/Makefile @@ -46,7 +46,9 @@ default: install: $(PACKAGES) cd $(shell readlink -m $(DESTDIR)/$(TDX_ATTEST_PACKAGE_NAME)/$(USR_LIB_PATH)) && \ mv libtdx_attest.so libtdx_attest.so.$(USR_LIB_VER) && \ - ln -fs libtdx_attest.so.$(USR_LIB_VER) libtdx_attest.so.$(call SPLIT_VERSION,$(USR_LIB_VER),1) + ln -fs libtdx_attest.so.$(USR_LIB_VER) libtdx_attest.so.$(call SPLIT_VERSION,$(USR_LIB_VER),1) && \ + cd $(shell readlink -m $(DESTDIR)/$(TDX_ATTEST_DEV_PACKAGE_NAME)/$(USR_LIB_PATH)) && \ + ln -fs libtdx_attest.so.$(call SPLIT_VERSION,$(USR_LIB_VER),1) libtdx_attest.so $(PACKAGES): install -d $(shell readlink -m $(DESTDIR)/$@) diff --git a/QuoteGeneration/installer/linux/deb/libsgx-dcap-ql/libsgx-dcap-ql-1.0/debian/control b/QuoteGeneration/installer/linux/deb/libsgx-dcap-ql/libsgx-dcap-ql-1.0/debian/control index 91ae8f13..0ed7758c 100644 --- a/QuoteGeneration/installer/linux/deb/libsgx-dcap-ql/libsgx-dcap-ql-1.0/debian/control +++ b/QuoteGeneration/installer/linux/deb/libsgx-dcap-ql/libsgx-dcap-ql-1.0/debian/control @@ -9,11 +9,11 @@ Homepage: https://github.com/intel/SGXDataCenterAttestationPrimitives Package: libsgx-dcap-ql Architecture: amd64 Depends: libsgx-qe3-logic(>= @dep_version@), libsgx-pce-logic(>= @dep_version@), ${shlibs:Depends}, ${misc:Depends} -Recommends: libsgx-dcap-quote-verify(>= @dep_version@), libsgx-quote-ex(>= 2.17) +Recommends: libsgx-dcap-quote-verify(>= @dep_version@), libsgx-quote-ex(>= 2.18) Description: Intel(R) Software Guard Extensions Data Center Attestation Primitives Package: libsgx-dcap-ql-dev Section: devel Architecture: amd64 -Depends: libsgx-dcap-ql (= @dep_version@), libsgx-headers (>= 2.17) +Depends: libsgx-dcap-ql (= @dep_version@), libsgx-headers (>= 2.18) Description: Intel(R) Software Guard Extensions Data Center Attestation Primitives For Developers diff --git a/QuoteGeneration/installer/linux/deb/libsgx-dcap-quote-verify/libsgx-dcap-quote-verify-1.0/debian/control b/QuoteGeneration/installer/linux/deb/libsgx-dcap-quote-verify/libsgx-dcap-quote-verify-1.0/debian/control index d64ae373..2e92777d 100644 --- a/QuoteGeneration/installer/linux/deb/libsgx-dcap-quote-verify/libsgx-dcap-quote-verify-1.0/debian/control +++ b/QuoteGeneration/installer/linux/deb/libsgx-dcap-quote-verify/libsgx-dcap-quote-verify-1.0/debian/control @@ -9,11 +9,11 @@ Homepage: https://github.com/intel/SGXDataCenterAttestationPrimitives Package: libsgx-dcap-quote-verify Architecture: amd64 Depends: ${shlibs:Depends}, ${misc:Depends} -Recommends: libsgx-ae-qve (>= @dep_version@), libsgx-urts (>= @dep_version@) +Recommends: libsgx-ae-qve (>= @dep_version@), libsgx-urts (>= 2.18) Description: Intel(R) Software Guard Extensions Data Center Attestation Primitives Package: libsgx-dcap-quote-verify-dev Section: devel Architecture: amd64 -Depends: libsgx-dcap-quote-verify (= @dep_version@), libsgx-headers (>= 2.17) +Depends: libsgx-dcap-quote-verify (= @dep_version@), libsgx-headers (>= 2.18) Description: Intel(R) Software Guard Extensions Data Center Attestation Primitives For Developers diff --git a/QuoteGeneration/installer/linux/deb/libsgx-pce-logic/build.sh b/QuoteGeneration/installer/linux/deb/libsgx-pce-logic/build.sh index 1e7ac1ea..4118897d 100755 --- a/QuoteGeneration/installer/linux/deb/libsgx-pce-logic/build.sh +++ b/QuoteGeneration/installer/linux/deb/libsgx-pce-logic/build.sh @@ -35,6 +35,7 @@ set -e SCRIPT_DIR=$(dirname "$0") ROOT_DIR="${SCRIPT_DIR}/../../../../" +LINUX_BUILD_DIR=$(readlink -m "${SGX_SDK}/lib64") LINUX_INSTALLER_DIR="${ROOT_DIR}/installer/linux" LINUX_INSTALLER_COMMON_DIR="${LINUX_INSTALLER_DIR}/common" LINUX_INSTALLER_COMMON_PCE_LOGIC_DIR="${LINUX_INSTALLER_COMMON_DIR}/libsgx-pce-logic" @@ -110,7 +111,7 @@ rename_tarball() { build_deb_package() { pushd ${SCRIPT_DIR}/${DEB_BUILD_FOLDER} - SOURCE_DATE_EPOCH="$(date +%s)" dpkg-buildpackage -us -uc + SOURCE_DATE_EPOCH="$(date +%s)" LINUX_BUILD_DIR="${LINUX_BUILD_DIR}" dpkg-buildpackage -us -uc popd } diff --git a/QuoteGeneration/installer/linux/deb/libsgx-pce-logic/libsgx-pce-logic-1.0/debian/control b/QuoteGeneration/installer/linux/deb/libsgx-pce-logic/libsgx-pce-logic-1.0/debian/control index be6a5ecd..149999f0 100644 --- a/QuoteGeneration/installer/linux/deb/libsgx-pce-logic/libsgx-pce-logic-1.0/debian/control +++ b/QuoteGeneration/installer/linux/deb/libsgx-pce-logic/libsgx-pce-logic-1.0/debian/control @@ -8,5 +8,5 @@ Homepage: https://github.com/intel/SGXDataCenterAttestationPrimitives Package: libsgx-pce-logic Architecture: amd64 -Depends: libsgx-urts (>= 2.17), libsgx-ae-pce(>= 2.17), ${shlibs:Depends}, ${misc:Depends} +Depends: libsgx-urts (>= 2.18), libsgx-ae-pce(>= 2.18), ${shlibs:Depends}, ${misc:Depends} Description: Intel(R) Software Guard Extensions Data Center Attestation Primitives diff --git a/QuoteGeneration/installer/linux/deb/libsgx-pce-logic/libsgx-pce-logic-1.0/debian/rules b/QuoteGeneration/installer/linux/deb/libsgx-pce-logic/libsgx-pce-logic-1.0/debian/rules index ecf4506c..208b0b31 100755 --- a/QuoteGeneration/installer/linux/deb/libsgx-pce-logic/libsgx-pce-logic-1.0/debian/rules +++ b/QuoteGeneration/installer/linux/deb/libsgx-pce-logic/libsgx-pce-logic-1.0/debian/rules @@ -6,3 +6,6 @@ export DH_VERBOSE=1 %: dh $@ + +override_dh_shlibdeps: + dh_shlibdeps -l $(LINUX_BUILD_DIR) --dpkg-shlibdeps-params=--ignore-missing-info diff --git a/QuoteGeneration/installer/linux/deb/libsgx-qe3-logic/build.sh b/QuoteGeneration/installer/linux/deb/libsgx-qe3-logic/build.sh index 41e70c54..84c2d1d0 100755 --- a/QuoteGeneration/installer/linux/deb/libsgx-qe3-logic/build.sh +++ b/QuoteGeneration/installer/linux/deb/libsgx-qe3-logic/build.sh @@ -35,6 +35,7 @@ set -e SCRIPT_DIR=$(dirname "$0") ROOT_DIR="${SCRIPT_DIR}/../../../../" +LINUX_BUILD_DIR=$(readlink -m "${SGX_SDK}/lib64") LINUX_INSTALLER_DIR="${ROOT_DIR}/installer/linux" LINUX_INSTALLER_COMMON_DIR="${LINUX_INSTALLER_DIR}/common" LINUX_INSTALLER_COMMON_QE3_LOGIC_DIR="${LINUX_INSTALLER_COMMON_DIR}/libsgx-qe3-logic" @@ -111,7 +112,7 @@ rename_tarball() { build_deb_package() { pushd ${SCRIPT_DIR}/${DEB_BUILD_FOLDER} - SOURCE_DATE_EPOCH="$(date +%s)" dpkg-buildpackage -us -uc + SOURCE_DATE_EPOCH="$(date +%s)" LINUX_BUILD_DIR="${LINUX_BUILD_DIR}" dpkg-buildpackage -us -uc popd } diff --git a/QuoteGeneration/installer/linux/deb/libsgx-qe3-logic/libsgx-qe3-logic-1.0/debian/control b/QuoteGeneration/installer/linux/deb/libsgx-qe3-logic/libsgx-qe3-logic-1.0/debian/control index accd0c1f..70c4a03e 100644 --- a/QuoteGeneration/installer/linux/deb/libsgx-qe3-logic/libsgx-qe3-logic-1.0/debian/control +++ b/QuoteGeneration/installer/linux/deb/libsgx-qe3-logic/libsgx-qe3-logic-1.0/debian/control @@ -8,5 +8,5 @@ Homepage: https://github.com/intel/SGXDataCenterAttestationPrimitives Package: libsgx-qe3-logic Architecture: amd64 -Depends: libsgx-urts (>= 2.17), libsgx-ae-qe3(>= @dep_version@), libsgx-ae-id-enclave(>= @dep_version@), ${shlibs:Depends}, ${misc:Depends} +Depends: libsgx-urts (>= 2.18), libsgx-ae-qe3(>= @dep_version@), libsgx-ae-id-enclave(>= @dep_version@), ${shlibs:Depends}, ${misc:Depends} Description: Intel(R) Software Guard Extensions Data Center Attestation Primitives diff --git a/QuoteGeneration/installer/linux/deb/libsgx-qe3-logic/libsgx-qe3-logic-1.0/debian/rules b/QuoteGeneration/installer/linux/deb/libsgx-qe3-logic/libsgx-qe3-logic-1.0/debian/rules index ecf4506c..208b0b31 100755 --- a/QuoteGeneration/installer/linux/deb/libsgx-qe3-logic/libsgx-qe3-logic-1.0/debian/rules +++ b/QuoteGeneration/installer/linux/deb/libsgx-qe3-logic/libsgx-qe3-logic-1.0/debian/rules @@ -6,3 +6,6 @@ export DH_VERBOSE=1 %: dh $@ + +override_dh_shlibdeps: + dh_shlibdeps -l $(LINUX_BUILD_DIR) --dpkg-shlibdeps-params=--ignore-missing-info diff --git a/QuoteGeneration/installer/linux/deb/libsgx-tdx-logic/build.sh b/QuoteGeneration/installer/linux/deb/libsgx-tdx-logic/build.sh index c6ba7fd3..262afb20 100755 --- a/QuoteGeneration/installer/linux/deb/libsgx-tdx-logic/build.sh +++ b/QuoteGeneration/installer/linux/deb/libsgx-tdx-logic/build.sh @@ -35,7 +35,8 @@ set -e SCRIPT_DIR=$(dirname "$0") ROOT_DIR="${SCRIPT_DIR}/../../../../" -LINUX_BUILD_DIR=$(readlink -m "${ROOT_DIR}/build/linux") +LINUX_BUILD_DIR=$(readlink -m "${SGX_SDK}/lib64") +DCAP_BUILD_DIR=$(readlink -m "${ROOT_DIR}/build/linux") LINUX_INSTALLER_DIR="${ROOT_DIR}/installer/linux" LINUX_INSTALLER_COMMON_DIR="${LINUX_INSTALLER_DIR}/common" LINUX_INSTALLER_COMMON_TDX_LOGIC_DIR="${LINUX_INSTALLER_COMMON_DIR}/libsgx-tdx-logic" @@ -118,7 +119,7 @@ rename_tarball() { build_deb_package() { pushd ${SCRIPT_DIR}/${DEB_BUILD_FOLDER} - SOURCE_DATE_EPOCH="$(date +%s)" LINUX_BUILD_DIR="${LINUX_BUILD_DIR}" dpkg-buildpackage -us -uc + SOURCE_DATE_EPOCH="$(date +%s)" ALL_BUILD_DIR=${LINUX_BUILD_DIR}:${DCAP_BUILD_DIR} dpkg-buildpackage -us -uc popd } diff --git a/QuoteGeneration/installer/linux/deb/libsgx-tdx-logic/libsgx-tdx-logic-1.0/debian/control b/QuoteGeneration/installer/linux/deb/libsgx-tdx-logic/libsgx-tdx-logic-1.0/debian/control index 0b965bc6..78b29d33 100644 --- a/QuoteGeneration/installer/linux/deb/libsgx-tdx-logic/libsgx-tdx-logic-1.0/debian/control +++ b/QuoteGeneration/installer/linux/deb/libsgx-tdx-logic/libsgx-tdx-logic-1.0/debian/control @@ -8,7 +8,7 @@ Homepage: https://github.com/intel/SGXDataCenterAttestationPrimitives Package: libsgx-tdx-logic Architecture: amd64 -Depends: libsgx-urts (>= 2.17), libsgx-pce-logic(>= @dep_version@), libsgx-ae-tdqe(>= @dep_version@), libsgx-ae-id-enclave(>= @dep_version@), ${shlibs:Depends}, ${misc:Depends} +Depends: libsgx-urts (>= 2.18), libsgx-pce-logic(>= @dep_version@), libsgx-ae-tdqe(>= @dep_version@), libsgx-ae-id-enclave(>= @dep_version@), ${shlibs:Depends}, ${misc:Depends} Description: Intel(R) Trust Domain Extensions QE logic library Package: libsgx-tdx-logic-dev diff --git a/QuoteGeneration/installer/linux/deb/libsgx-tdx-logic/libsgx-tdx-logic-1.0/debian/rules b/QuoteGeneration/installer/linux/deb/libsgx-tdx-logic/libsgx-tdx-logic-1.0/debian/rules index 208b0b31..d545caab 100755 --- a/QuoteGeneration/installer/linux/deb/libsgx-tdx-logic/libsgx-tdx-logic-1.0/debian/rules +++ b/QuoteGeneration/installer/linux/deb/libsgx-tdx-logic/libsgx-tdx-logic-1.0/debian/rules @@ -8,4 +8,4 @@ export DH_VERBOSE=1 dh $@ override_dh_shlibdeps: - dh_shlibdeps -l $(LINUX_BUILD_DIR) --dpkg-shlibdeps-params=--ignore-missing-info + dh_shlibdeps -l $(ALL_BUILD_DIR) --dpkg-shlibdeps-params=--ignore-missing-info diff --git a/QuoteGeneration/installer/linux/deb/tdx-qgs/build.sh b/QuoteGeneration/installer/linux/deb/tdx-qgs/build.sh index f4e2f71a..2de561d0 100755 --- a/QuoteGeneration/installer/linux/deb/tdx-qgs/build.sh +++ b/QuoteGeneration/installer/linux/deb/tdx-qgs/build.sh @@ -35,7 +35,8 @@ set -e SCRIPT_DIR=$(dirname "$0") ROOT_DIR="${SCRIPT_DIR}/../../../../" -LINUX_BUILD_DIR=$(readlink -m "${ROOT_DIR}/build/linux") +LINUX_BUILD_DIR=$(readlink -m "${SGX_SDK}/lib64") +DCAP_BUILD_DIR=$(readlink -m "${ROOT_DIR}/build/linux") LINUX_INSTALLER_DIR="${ROOT_DIR}/installer/linux" LINUX_INSTALLER_COMMON_DIR="${LINUX_INSTALLER_DIR}/common" LINUX_INSTALLER_COMMON_TDX_QGS_DIR="${LINUX_INSTALLER_COMMON_DIR}/tdx-qgs" @@ -122,7 +123,7 @@ rename_tarball() { build_deb_package() { pushd ${SCRIPT_DIR}/${DEB_BUILD_FOLDER} - SOURCE_DATE_EPOCH="$(date +%s)" LINUX_BUILD_DIR="${LINUX_BUILD_DIR}" dpkg-buildpackage -us -uc + SOURCE_DATE_EPOCH="$(date +%s)" ALL_BUILD_DIR=${LINUX_BUILD_DIR}:${DCAP_BUILD_DIR} dpkg-buildpackage -us -uc popd } diff --git a/QuoteGeneration/installer/linux/deb/tdx-qgs/tdx-qgs-1.0/debian/rules b/QuoteGeneration/installer/linux/deb/tdx-qgs/tdx-qgs-1.0/debian/rules index 7770058a..d6ca4a64 100755 --- a/QuoteGeneration/installer/linux/deb/tdx-qgs/tdx-qgs-1.0/debian/rules +++ b/QuoteGeneration/installer/linux/deb/tdx-qgs/tdx-qgs-1.0/debian/rules @@ -8,4 +8,4 @@ dh $@ override_dh_shlibdeps: - dh_shlibdeps -l $(LINUX_BUILD_DIR) --dpkg-shlibdeps-params=--ignore-missing-info + dh_shlibdeps -l $(ALL_BUILD_DIR) --dpkg-shlibdeps-params=--ignore-missing-info diff --git a/QuoteGeneration/installer/linux/rpm/libsgx-dcap-ql/libsgx-dcap-ql.spec b/QuoteGeneration/installer/linux/rpm/libsgx-dcap-ql/libsgx-dcap-ql.spec index 222c8a70..e6a23036 100644 --- a/QuoteGeneration/installer/linux/rpm/libsgx-dcap-ql/libsgx-dcap-ql.spec +++ b/QuoteGeneration/installer/linux/rpm/libsgx-dcap-ql/libsgx-dcap-ql.spec @@ -37,7 +37,7 @@ Release: 1%{?dist} Summary: Intel(R) Software Guard Extensions Data Center Attestation Primitives Group: Development/Libraries Requires: libsgx-qe3-logic >= %{version}-%{release} libsgx-pce-logic >= %{version}-%{release} -Recommends: libsgx-dcap-quote-verify >= %{version}-%{release} libsgx-quote-ex >= 2.17 +Recommends: libsgx-dcap-quote-verify >= %{version}-%{release} libsgx-quote-ex >= 2.18 License: BSD License URL: https://github.com/intel/SGXDataCenterAttestationPrimitives @@ -49,7 +49,7 @@ Intel(R) Software Guard Extensions Data Center Attestation Primitives %package devel Summary: Intel(R) Software Guard Extensions Data Center Attestation Primitives for Developers Group: Development/Libraries -Requires: %{name} = %{version}-%{release} libsgx-headers >= 2.17 +Requires: %{name} = %{version}-%{release} libsgx-headers >= 2.18 %description devel Intel(R) Software Guard Extensions Data Center Attestation Primitives for Developers diff --git a/QuoteGeneration/installer/linux/rpm/libsgx-dcap-quote-verify/libsgx-dcap-quote-verify.spec b/QuoteGeneration/installer/linux/rpm/libsgx-dcap-quote-verify/libsgx-dcap-quote-verify.spec index 9d8db4cf..a89d4e07 100644 --- a/QuoteGeneration/installer/linux/rpm/libsgx-dcap-quote-verify/libsgx-dcap-quote-verify.spec +++ b/QuoteGeneration/installer/linux/rpm/libsgx-dcap-quote-verify/libsgx-dcap-quote-verify.spec @@ -36,7 +36,7 @@ Version: @version@ Release: 1%{?dist} Summary: Intel(R) Software Guard Extensions Data Center Attestation Primitives Group: Development/Libraries -Recommends: libsgx-ae-qve >= %{version}-%{release} libsgx-urts >= 2.17 +Recommends: libsgx-ae-qve >= %{version}-%{release} libsgx-urts >= 2.18 License: BSD License URL: https://github.com/intel/SGXDataCenterAttestationPrimitives @@ -48,7 +48,7 @@ Intel(R) Software Guard Extensions Data Center Attestation Primitives %package devel Summary: Intel(R) Software Guard Extensions Data Center Attestation Primitives for Developers Group: Development/Libraries -Requires: %{name} = %{version}-%{release} libsgx-headers >= 2.17 +Requires: %{name} = %{version}-%{release} libsgx-headers >= 2.18 %description devel Intel(R) Software Guard Extensions Data Center Attestation Primitives for Developers diff --git a/QuoteGeneration/installer/linux/rpm/libsgx-pce-logic/libsgx-pce-logic.spec b/QuoteGeneration/installer/linux/rpm/libsgx-pce-logic/libsgx-pce-logic.spec index b3bf250e..91a29eac 100644 --- a/QuoteGeneration/installer/linux/rpm/libsgx-pce-logic/libsgx-pce-logic.spec +++ b/QuoteGeneration/installer/linux/rpm/libsgx-pce-logic/libsgx-pce-logic.spec @@ -36,7 +36,7 @@ Version: @version@ Release: 1%{?dist} Summary: Intel(R) Software Guard Extensions PCE logic Group: Development/Libraries -Requires: libsgx-urts >= 2.17 libsgx-ae-pce >= 2.17 +Requires: libsgx-urts >= 2.18 libsgx-ae-pce >= 2.18 License: BSD License URL: https://github.com/intel/SGXDataCenterAttestationPrimitives diff --git a/QuoteGeneration/installer/linux/rpm/libsgx-qe3-logic/libsgx-qe3-logic.spec b/QuoteGeneration/installer/linux/rpm/libsgx-qe3-logic/libsgx-qe3-logic.spec index 3aeeaefc..993e5e96 100644 --- a/QuoteGeneration/installer/linux/rpm/libsgx-qe3-logic/libsgx-qe3-logic.spec +++ b/QuoteGeneration/installer/linux/rpm/libsgx-qe3-logic/libsgx-qe3-logic.spec @@ -36,7 +36,7 @@ Version: @version@ Release: 1%{?dist} Summary: Intel(R) Software Guard Extensions QE3 logic Group: Development/Libraries -Requires: libsgx-urts >= 2.17 libsgx-ae-qe3 >= %{version}-%{release} libsgx-ae-id-enclave >= %{version}-%{release} +Requires: libsgx-urts >= 2.18 libsgx-ae-qe3 >= %{version}-%{release} libsgx-ae-id-enclave >= %{version}-%{release} License: BSD License URL: https://github.com/intel/SGXDataCenterAttestationPrimitives diff --git a/QuoteGeneration/installer/linux/rpm/libsgx-tdx-logic/libsgx-tdx-logic.spec b/QuoteGeneration/installer/linux/rpm/libsgx-tdx-logic/libsgx-tdx-logic.spec index 2f8a0a6a..93d79c36 100644 --- a/QuoteGeneration/installer/linux/rpm/libsgx-tdx-logic/libsgx-tdx-logic.spec +++ b/QuoteGeneration/installer/linux/rpm/libsgx-tdx-logic/libsgx-tdx-logic.spec @@ -36,7 +36,7 @@ Version: @version@ Release: 1%{?dist} Summary: Intel(R) Trust Domain Extensions QE logic library Group: Development/Libraries -Requires: libsgx-urts >= 2.17 libsgx-ae-tdqe >= %{version}-%{release} libsgx-ae-id-enclave >= %{version}-%{release} libsgx-pce-logic >= %{version}-%{release} +Requires: libsgx-urts >= 2.18 libsgx-ae-tdqe >= %{version}-%{release} libsgx-ae-id-enclave >= %{version}-%{release} libsgx-pce-logic >= %{version}-%{release} License: BSD License URL: https://github.com/intel/SGXDataCenterAttestationPrimitives diff --git a/QuoteGeneration/installer/win/DCAP_Components/DCAP_Components.nuspec b/QuoteGeneration/installer/win/DCAP_Components/DCAP_Components.nuspec index f9b3dd28..ed4ad2d5 100644 --- a/QuoteGeneration/installer/win/DCAP_Components/DCAP_Components.nuspec +++ b/QuoteGeneration/installer/win/DCAP_Components/DCAP_Components.nuspec @@ -2,7 +2,7 @@ DCAP_Components - 1.14.100.3 + 1.15.100.3 DCAP Components Intel(R) SGX Intel @@ -10,7 +10,7 @@ DCAP Components Copyright (C) 2022 Intel Corporation - + diff --git a/QuoteGeneration/installer/win/Tools/Installer_VersionSync.py b/QuoteGeneration/installer/win/Tools/Installer_VersionSync.py index 093d9a21..657292b4 100644 --- a/QuoteGeneration/installer/win/Tools/Installer_VersionSync.py +++ b/QuoteGeneration/installer/win/Tools/Installer_VersionSync.py @@ -89,8 +89,8 @@ def Main(argv): Identity = Metadata[0].getElementsByTagName("version") Identity[0].firstChild.replaceWholeText(version) - print vsixmanifest.toxml() - f = open(xmlFile, "wb") + print(vsixmanifest.toxml()) + f = open(xmlFile, "w") vsixmanifest.writexml(f) f.close() diff --git a/QuoteGeneration/pccs/README.md b/QuoteGeneration/pccs/README.md index 2a4bf0f6..7f581f74 100644 --- a/QuoteGeneration/pccs/README.md +++ b/QuoteGeneration/pccs/README.md @@ -6,7 +6,7 @@ This is a lightweight Provisioning Certificate Caching Service implemented in no - **Prerequisites** - Install node.js (Version 12.22 or later) + Install node.js (Version 14.20 or later) - For Debian and Ubuntu based distributions, you can use the following command:
$ curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
@@ -78,7 +78,7 @@ This is a lightweight Provisioning Certificate Caching Service implemented in no - **HTTPS_PORT** - The port you want the PCCS to listen on. The default listening port is 8081. - **hosts** - The hosts that will be accepted for connections. Default is localhost only. To accept all connections use 0.0.0.0 -- **uri** - The URL of Intel Provisioning Certificate Service. The default URL is https://api.trustedservices.intel.com/sgx/certification/v3/ +- **uri** - The URL of Intel Provisioning Certificate Service. The default URL is https://api.trustedservices.intel.com/sgx/certification/v4/ - **ApiKey** - The PCCS uses this API key to request collaterals from Intel's Provisioning Certificate Service. User needs to subscribe first to obtain an API key. For how to subscribe to Intel Provisioning Certificate Service and receive an API key, goto https://api.portal.trustedservices.intel.com/provisioning-certification and click on 'Subscribe'. - **proxy** - Specify the proxy server for internet connection, for example, "http://192.168.1.1:80". Leave blank for no proxy or system proxy. - **RefreshSchedule** - cron-style refresh schedule for the PCCS to refresh cached artifacts including CRL/TCB Info/QE Identity/QVE Identity. @@ -135,7 +135,7 @@ In /etc/sgx_default_qcnl.conf, set "use_secure_cert": true (For Windows see ../q $ sudo systemctl start/stop/restart pccs - If PCCS was installed manually by current user, you can start it with the following command
- $ node -r esm pccs_server.js + $ node pccs_server.js ##

Uninstall

diff --git a/QuoteGeneration/pccs/config/default.json b/QuoteGeneration/pccs/config/default.json index 98c43768..77b05f99 100644 --- a/QuoteGeneration/pccs/config/default.json +++ b/QuoteGeneration/pccs/config/default.json @@ -1,7 +1,7 @@ { "HTTPS_PORT" : 8081, "hosts" : "127.0.0.1", - "uri": "https://api.trustedservices.intel.com/sgx/certification/v3/", + "uri": "https://api.trustedservices.intel.com/sgx/certification/v4/", "ApiKey": "", "proxy" : "", "RefreshSchedule": "0 0 1 * * *", diff --git a/QuoteGeneration/pccs/config/test_offline.json b/QuoteGeneration/pccs/config/test_offline.json new file mode 100644 index 00000000..8e60b380 --- /dev/null +++ b/QuoteGeneration/pccs/config/test_offline.json @@ -0,0 +1,52 @@ +{ + "HTTPS_PORT" : 8083, + "hosts" : "0.0.0.0", + "uri": "https://sbx.api.trustedservices.intel.com/sgx/certification/v4/", + "ApiKey": "", + "proxy": "", + "RefreshSchedule": "0 0 1 * * *", + "UserTokenHash" : "", + "AdminTokenHash" : "", + "CachingFillMode" : "OFFLINE", + "LogLevel" : "debug", + "DB_CONFIG" : "sqlite", + "sqlite" : { + "database" : "database", + "username" : "username", + "password" : "password", + "options" : { + "host": "localhost", + "dialect": "sqlite", + "pool": { + "max": 5, + "min": 0, + "acquire": 30000, + "idle": 10000 + }, + "define": { + "freezeTableName": true + }, + "logging" : false, + "storage": "test_offline.db" + } + }, + "mysql" : { + "database" : "pckcache", + "username" : "root", + "password" : "mypass", + "options" : { + "host": "localhost", + "dialect": "mysql", + "pool": { + "max": 5, + "min": 0, + "acquire": 30000, + "idle": 10000 + }, + "define": { + "freezeTableName": true + }, + "logging" : false + } + } +} diff --git a/QuoteGeneration/pccs/container/Dockerfile b/QuoteGeneration/pccs/container/Dockerfile index 1e96caa5..463e5e84 100644 --- a/QuoteGeneration/pccs/container/Dockerfile +++ b/QuoteGeneration/pccs/container/Dockerfile @@ -1,7 +1,7 @@ FROM ubuntu:20.04 AS builder # DCAP version (github repo branch, tag or commit hash) -ARG DCAP_VERSION=DCAP_1.14 +ARG DCAP_VERSION=DCAP_1.15 # update and install packages RUN DEBIAN_FRONTEND=noninteractive \ @@ -58,4 +58,4 @@ WORKDIR /opt/intel/pccs/ USER ${USER} # entrypoint to start pccs -ENTRYPOINT ["/usr/bin/node", "-r", "esm", "pccs_server.js"] +ENTRYPOINT ["/usr/bin/node", "pccs_server.js"] diff --git a/QuoteGeneration/pccs/controllers/crlController.js b/QuoteGeneration/pccs/controllers/crlController.js index 292e30b3..b234d713 100644 --- a/QuoteGeneration/pccs/controllers/crlController.js +++ b/QuoteGeneration/pccs/controllers/crlController.js @@ -31,6 +31,7 @@ import { crlService } from '../services/index.js'; import PccsStatus from '../constants/pccs_status_code.js'; +import PccsError from '../utils/PccsError.js'; export async function getCrl(req, res, next) { const MAX_URL_LENGTH = 2048; diff --git a/QuoteGeneration/pccs/dao/models/pcs_certificates.js b/QuoteGeneration/pccs/dao/models/pcs_certificates.js index 080ef634..ec3f5215 100644 --- a/QuoteGeneration/pccs/dao/models/pcs_certificates.js +++ b/QuoteGeneration/pccs/dao/models/pcs_certificates.js @@ -35,6 +35,7 @@ export default class PcsCertificates extends Sequelize.Model { static init(sequelize) { super.init( { + id: { type: Sequelize.DataTypes.INTEGER, primaryKey: true }, cert: { type: Sequelize.DataTypes.BLOB }, crl: { type: Sequelize.DataTypes.BLOB }, }, diff --git a/QuoteGeneration/pccs/dao/models/platforms.js b/QuoteGeneration/pccs/dao/models/platforms.js index 670dbffd..baae1ef9 100644 --- a/QuoteGeneration/pccs/dao/models/platforms.js +++ b/QuoteGeneration/pccs/dao/models/platforms.js @@ -40,10 +40,13 @@ export default class Platforms extends Sequelize.Model { type: Sequelize.DataTypes.BLOB, // store binary data in DB get() { - return (this.getDataValue('platform_manifest') || '').toString('hex'); + return (this.getDataValue('platform_manifest') || '').toString( + 'hex' + ); }, set(value) { - this.setDataValue('platform_manifest', Buffer.from(value, 'hex')); + if (value) + this.setDataValue('platform_manifest', Buffer.from(value, 'hex')); }, }, enc_ppid: { @@ -53,7 +56,7 @@ export default class Platforms extends Sequelize.Model { return (this.getDataValue('enc_ppid') || '').toString('hex'); }, set(value) { - this.setDataValue('enc_ppid', Buffer.from(value, 'hex')); + if (value) this.setDataValue('enc_ppid', Buffer.from(value, 'hex')); }, }, fmspc: { type: Sequelize.DataTypes.STRING }, diff --git a/QuoteGeneration/pccs/dao/models/platforms_registered.js b/QuoteGeneration/pccs/dao/models/platforms_registered.js index be30dd6f..34b0e68f 100644 --- a/QuoteGeneration/pccs/dao/models/platforms_registered.js +++ b/QuoteGeneration/pccs/dao/models/platforms_registered.js @@ -44,16 +44,19 @@ export default class PlatformsRegistered extends Sequelize.Model { return (this.getDataValue('enc_ppid') || '').toString('hex'); }, set(value) { - this.setDataValue('enc_ppid', Buffer.from(value, 'hex')); + if (value) this.setDataValue('enc_ppid', Buffer.from(value, 'hex')); }, }, platform_manifest: { type: Sequelize.DataTypes.BLOB, get() { - return (this.getDataValue('platform_manifest') || '').toString('hex'); + return (this.getDataValue('platform_manifest') || '').toString( + 'hex' + ); }, set(value) { - this.setDataValue('platform_manifest', Buffer.from(value, 'hex')); + if (value) + this.setDataValue('platform_manifest', Buffer.from(value, 'hex')); }, }, state: { type: Sequelize.DataTypes.INTEGER }, diff --git a/QuoteGeneration/pccs/install.bat b/QuoteGeneration/pccs/install.bat index 215ebd29..933c21eb 100644 --- a/QuoteGeneration/pccs/install.bat +++ b/QuoteGeneration/pccs/install.bat @@ -10,4 +10,4 @@ call npm install node-windows@1.0.0-beta.6 -g call npm link node-windows -call node pccs.service.win +call node pccs.winsvc.inst.cjs diff --git a/QuoteGeneration/pccs/install.sh b/QuoteGeneration/pccs/install.sh index 71569027..0146bde7 100755 --- a/QuoteGeneration/pccs/install.sh +++ b/QuoteGeneration/pccs/install.sh @@ -14,7 +14,7 @@ function version_gt() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$ # check nodejs version function checkDependencies() { echo "Checking nodejs version ..." - expected_node_v="v10.20.0" + expected_node_v="v14.20.0" if which node > /dev/null then cur_node_v=$(node -v) diff --git a/QuoteGeneration/pccs/package.json b/QuoteGeneration/pccs/package.json index 23a29a26..cb01581b 100644 --- a/QuoteGeneration/pccs/package.json +++ b/QuoteGeneration/pccs/package.json @@ -1,7 +1,8 @@ { "name": "PCCS", "description": "Provisioning Certificate Caching Service", - "version": "1.14.0", + "version": "1.15.0", + "type": "module", "dependencies": { "@fidm/x509": "^1.2.1", "ajv": "^6.12.4", @@ -9,7 +10,6 @@ "caw": "^2.0.1", "cls-hooked": "^4.2.2", "config": "^3.3.7", - "esm": "^3.2.25", "express": "^4.17.1", "ffi-napi": "^4.0.3", "got": "^11.6.0", @@ -18,16 +18,18 @@ "node-schedule": "^2.1.0", "ref-array-di": "^1.2.2", "ref-napi": "^3.0.3", - "sequelize": "^6.19.0", + "sequelize": "^6.21.4", "sqlite3": "^5.0.6", "umzug": "^2.3.0", "winston": "^3.3.3" }, "engines": { - "node": ">= 12.22.0" + "node": ">= 14.20.0" }, "scripts": { - "start": "set NODE_ENV=dev && node -r esm pccs_server.js", - "test": "NODE_ENV=test mocha -r esm ../../../unittests/psw/pccs_ut/test.js --timeout 120000 --exit" + "start": "node pccs_server.js", + "test": "NODE_ENV=test mocha ../../../unittests/psw/pccs_ut/test.js --timeout 120000 --exit", + "offline": "NODE_ENV=test_offline mocha ../../../unittests/psw/pccs_ut/test_offline.js --timeout 120000 --exit", + "req": "NODE_ENV=test_req mocha ../../../unittests/psw/pccs_ut/test_req.js --timeout 120000 --exit" } } diff --git a/QuoteGeneration/pccs/pccs.service b/QuoteGeneration/pccs/pccs.service index ec7bde9d..9f6cfcc8 100644 --- a/QuoteGeneration/pccs/pccs.service +++ b/QuoteGeneration/pccs/pccs.service @@ -8,7 +8,7 @@ Type=simple User=pccs WorkingDirectory=/opt/intel/sgx-dcap-pccs/ EnvironmentFile=/etc/environment -ExecStart=/usr/bin/node -r esm /opt/intel/sgx-dcap-pccs/pccs_server.js +ExecStart=/usr/bin/node /opt/intel/sgx-dcap-pccs/pccs_server.js Restart=on-failure RestartSec=15s diff --git a/QuoteGeneration/pccs/pccs.service.win b/QuoteGeneration/pccs/pccs.winsvc.inst.cjs similarity index 97% rename from QuoteGeneration/pccs/pccs.service.win rename to QuoteGeneration/pccs/pccs.winsvc.inst.cjs index e7c432ec..af3e52f9 100644 --- a/QuoteGeneration/pccs/pccs.service.win +++ b/QuoteGeneration/pccs/pccs.winsvc.inst.cjs @@ -6,8 +6,6 @@ var svc = new Service({ description: 'PCK Certificate Caching Service for Intel SGX DCAP', script: require('path').join(__dirname,'pccs_server.js'), nodeOptions: [ - '-r', - 'esm' ] //,workingDirectory: '...' //, allowServiceLogon: true diff --git a/QuoteGeneration/pccs/pccs.service.win-un b/QuoteGeneration/pccs/pccs.winsvc.uninst.cjs similarity index 100% rename from QuoteGeneration/pccs/pccs.service.win-un rename to QuoteGeneration/pccs/pccs.winsvc.uninst.cjs diff --git a/QuoteGeneration/pccs/pccs_server.js b/QuoteGeneration/pccs/pccs_server.js index 83e436cc..b279efaa 100644 --- a/QuoteGeneration/pccs/pccs_server.js +++ b/QuoteGeneration/pccs/pccs_server.js @@ -44,7 +44,7 @@ import * as error from './middleware/error.js'; import addRequestId from './middleware/addRequestId.js'; import * as refreshService from './services/refreshService.js'; import * as appUtil from './utils/apputil.js'; -import { cachingModeManager } from './services/caching_modes/cachingModeManager'; +import { cachingModeManager } from './services/caching_modes/cachingModeManager.js'; import { LazyCachingMode, ReqCachingMode, @@ -64,8 +64,8 @@ const app = express(); const { urlencoded, json } = body_parser; const { scheduleJob } = node_schedule; - // Get PCS API version from the config file - global.PCS_VERSION = appUtil.get_api_version_from_url(Config.get('uri')); +// Get PCS API version from the config file +global.PCS_VERSION = appUtil.get_api_version_from_url(Config.get('uri')); // startup check if (!appUtil.startup_check()) { @@ -138,8 +138,23 @@ appUtil.database_check().then((db_init_ok) => { logger.error('The private key or certificate for HTTPS server is missing.'); logger.endAndExitProcess(); } - const credentials = { key: privateKey, cert: certificate }; - const httpsServer = https.createServer(credentials, app); + const secure_sigalgs = [ + 'ecdsa_secp256r1_sha256', + 'ecdsa_secp384r1_sha384', + 'ecdsa_secp521r1_sha512', + 'rsa_pss_rsae_sha256', + 'rsa_pss_rsae_sha384', + 'rsa_pss_rsae_sha512', + 'rsa_pkcs1_sha256', + 'rsa_pkcs1_sha384', + 'rsa_pkcs1_sha512', + ]; + const options = { + key: privateKey, + cert: certificate, + sigalgs: secure_sigalgs.join(':'), + }; + const httpsServer = https.createServer(options, app); httpsServer.listen( Config.get('HTTPS_PORT'), Config.get('hosts'), diff --git a/QuoteGeneration/pccs/pcs_client/pcs_client.js b/QuoteGeneration/pccs/pcs_client/pcs_client.js index 5a2e8a1a..8be7fe95 100644 --- a/QuoteGeneration/pccs/pcs_client/pcs_client.js +++ b/QuoteGeneration/pccs/pcs_client/pcs_client.js @@ -87,7 +87,7 @@ async function do_request(url, options) { return response; } catch (err) { - logger.error(err); + logger.error(err); if (err.response && err.response.headers) { logger.info('Request-ID is : ' + err.response.headers['request-id']); } @@ -99,6 +99,7 @@ function getTdxUrl(url) { return url.replace('/sgx/', '/tdx/'); } +/* export async function getCert(enc_ppid, cpusvn, pcesvn, pceid) { const options = { searchParams: { @@ -113,6 +114,7 @@ export async function getCert(enc_ppid, cpusvn, pcesvn, pceid) { return do_request(Config.get('uri') + 'pckcert', options); } +*/ export async function getCerts(enc_ppid, pceid) { const options = { diff --git a/QuoteGeneration/pccs/services/crlService.js b/QuoteGeneration/pccs/services/crlService.js index 301b8dd3..25829528 100644 --- a/QuoteGeneration/pccs/services/crlService.js +++ b/QuoteGeneration/pccs/services/crlService.js @@ -28,7 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -import * as crlCacheDao from '../dao/crlCacheDao'; +import * as crlCacheDao from '../dao/crlCacheDao.js'; import { cachingModeManager } from './caching_modes/cachingModeManager.js'; export async function getCrl(uri) { diff --git a/QuoteGeneration/pccs/services/pccs_schemas.js b/QuoteGeneration/pccs/services/pccs_schemas.js index 57955af1..44c8cfa5 100644 --- a/QuoteGeneration/pccs/services/pccs_schemas.js +++ b/QuoteGeneration/pccs/services/pccs_schemas.js @@ -484,6 +484,9 @@ export const PLATFORM_COLLATERAL_SCHEMA_V4 = { collaterals: { type: 'object', properties: { + version:{ + "const": 4, + }, pck_certs: { type: 'array', items: { @@ -871,11 +874,14 @@ export const PLATFORM_COLLATERAL_SCHEMA_V4 = { }, required: ['SGX-PCK-Certificate-Issuer-Chain'], }, + rootcacrl_cdp: { + type: 'string', + }, rootcacrl: { type: 'string', }, }, - required: ['pck_certs', 'tcbinfos', 'certificates'], + required: ['version','pck_certs', 'tcbinfos', 'certificates'], }, }, required: ['platforms', 'collaterals'], diff --git a/QuoteGeneration/pccs/services/pckcrlService.js b/QuoteGeneration/pccs/services/pckcrlService.js index c410c261..badfd5f3 100644 --- a/QuoteGeneration/pccs/services/pckcrlService.js +++ b/QuoteGeneration/pccs/services/pckcrlService.js @@ -30,7 +30,7 @@ */ import Constants from '../constants/index.js'; import * as pckcrlDao from '../dao/pckcrlDao.js'; -import { cachingModeManager } from './caching_modes/cachingModeManager'; +import { cachingModeManager } from './caching_modes/cachingModeManager.js'; export async function getPckCrl(ca, encoding) { // query pck crl from local database first diff --git a/QuoteGeneration/pccs/services/platformCollateralService.js b/QuoteGeneration/pccs/services/platformCollateralService.js index dd74a9c0..d9936ba3 100644 --- a/QuoteGeneration/pccs/services/platformCollateralService.js +++ b/QuoteGeneration/pccs/services/platformCollateralService.js @@ -42,9 +42,13 @@ import * as pckcrlDao from '../dao/pckcrlDao.js'; import * as enclaveIdentityDao from '../dao/enclaveIdentityDao.js'; import * as pckCertchainDao from '../dao/pckCertchainDao.js'; import * as pcsCertificatesDao from '../dao/pcsCertificatesDao.js'; +import * as crlCacheDao from '../dao/crlCacheDao.js'; import * as pckLibWrapper from '../lib_wrapper/pcklib_wrapper.js'; import * as appUtil from '../utils/apputil.js'; -import { PLATFORM_COLLATERAL_SCHEMA_V3, PLATFORM_COLLATERAL_SCHEMA_V4 } from './pccs_schemas.js'; +import { + PLATFORM_COLLATERAL_SCHEMA_V3, + PLATFORM_COLLATERAL_SCHEMA_V4, +} from './pccs_schemas.js'; import { sequelize } from '../dao/models/index.js'; const ajv = new Ajv(); @@ -332,6 +336,9 @@ export async function addPlatformCollateral(collateralJson, version) { await pcsCertificatesDao.upsertRootCACrl( Buffer.from(collaterals.rootcacrl, 'hex') ); + if (collaterals.rootcacrl_cdp) { + await crlCacheDao.upsertCrl(collaterals.rootcacrl_cdp, Buffer.from(collaterals.rootcacrl, 'hex')); + } } }); } diff --git a/QuoteGeneration/pccs/uninstall.bat b/QuoteGeneration/pccs/uninstall.bat index aca36c27..8a059191 100644 --- a/QuoteGeneration/pccs/uninstall.bat +++ b/QuoteGeneration/pccs/uninstall.bat @@ -2,7 +2,7 @@ echo Uninstall npm packages ...... -call node pccs.service.win-un +call node pccs.winsvc.uninst.cjs @ call rd /s /q node_modules diff --git a/QuoteGeneration/pccs/utils/apputil.js b/QuoteGeneration/pccs/utils/apputil.js index 3da918db..e2e4ed81 100644 --- a/QuoteGeneration/pccs/utils/apputil.js +++ b/QuoteGeneration/pccs/utils/apputil.js @@ -34,6 +34,7 @@ import Constants from '../constants/index.js'; import { sequelize, PcsVersion } from '../dao/models/index.js'; import Umzug from 'umzug'; import * as fs from 'fs'; +import url from 'url'; export function get_api_version_from_url(url) { if (!url) return 0; @@ -110,7 +111,7 @@ async function db_migration() { } return Promise.all(queries); } else { - const migration = await import(path); + const migration = await import(url.pathToFileURL(path)); return migration.default.up(sequelize); } }, @@ -126,7 +127,7 @@ async function db_migration() { return Promise.all(queries); } } else { - const migration = await import(path); + const migration = await import(url.pathToFileURL(path)); return migration.default.down(sequelize); } }, diff --git a/QuoteGeneration/psw/ae/data/prebuilt/README.md b/QuoteGeneration/psw/ae/data/prebuilt/README.md index 3ed56647..e2ed3547 100644 --- a/QuoteGeneration/psw/ae/data/prebuilt/README.md +++ b/QuoteGeneration/psw/ae/data/prebuilt/README.md @@ -2,10 +2,10 @@ 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.17_reproducible](https://github.com/intel/linux-sgx/tree/sgx_2.17_reproducible) and signed by Intel. # QE3 source code -The QE3 is part of [Intel(R) Software Guard Extensions Data Center Attestation Primitives](https://github.com/intel/SGXDataCenterAttestationPrimitives/) Github repository. The libsgx_qe3.signed.so in prebuilt package is built by [qe3](https://github.com/intel/SGXDataCenterAttestationPrimitives/tree/master/QuoteGeneration/quote_wrapper/quote/enclave) with branch [sgx_2.17_reproducible](https://github.com/intel/linux-sgx/tree/sgx_2.17_reproducible) and signed by Intel. +The QE3 is part of [Intel(R) Software Guard Extensions Data Center Attestation Primitives](https://github.com/intel/SGXDataCenterAttestationPrimitives/) Github repository. The libsgx_qe3.signed.so in prebuilt package is built by [qe3](https://github.com/intel/SGXDataCenterAttestationPrimitives/tree/master/QuoteGeneration/quote_wrapper/quote/enclave) with branch [sgx_2.18_reproducible](https://github.com/intel/linux-sgx/tree/sgx_2.18_reproducible) and signed by Intel. # QVE source code -The QVE is part of [Intel(R) Software Guard Extensions Data Center Attestation Primitives](https://github.com/intel/SGXDataCenterAttestationPrimitives/) Github repository. The libsgx_qve.signed.so in prebuilt package is built by [qve](https://github.com/intel/SGXDataCenterAttestationPrimitives/tree/master/QuoteVerification/QvE/Enclave) with branch [sgx_2.17_reproducible](https://github.com/intel/linux-sgx/tree/sgx_2.17_reproducible)and signed by Intel. +The QVE is part of [Intel(R) Software Guard Extensions Data Center Attestation Primitives](https://github.com/intel/SGXDataCenterAttestationPrimitives/) Github repository. The libsgx_qve.signed.so in prebuilt package is built by [qve](https://github.com/intel/SGXDataCenterAttestationPrimitives/tree/master/QuoteVerification/QvE/Enclave) with branch [sgx_2.18_reproducible](https://github.com/intel/linux-sgx/tree/sgx_2.18_reproducible)and signed by Intel. # IDE source code The IDE is part of [Intel(R) Software Guard Extensions Data Center Attestation Primitives](https://github.com/intel/SGXDataCenterAttestationPrimitives/) Github repository. The libsgx_id_enclave.signed.so in prebuilt package is built by [id_enclave](https://github.com/intel/SGXDataCenterAttestationPrimitives/tree/master/QuoteGeneration/quote_wrapper/quote/id_enclave) with branch [sgx_2.17_reproducible](https://github.com/intel/linux-sgx/tree/sgx_2.17_reproducible) and signed by Intel. diff --git a/QuoteGeneration/qcnl/certification_provider.cpp b/QuoteGeneration/qcnl/certification_provider.cpp new file mode 100644 index 00000000..6a23c67a --- /dev/null +++ b/QuoteGeneration/qcnl/certification_provider.cpp @@ -0,0 +1,202 @@ +/* + * 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. + * + */ +/** + * File: certification_provider.cpp + * + * Description: CertificationProvider class implementation + * + */ +#include "certification_provider.h" +#include "local_cache.h" +#include "qcnl_util.h" +#include + +// calculate sha256 hash +string sha256_hash(const void *data, size_t data_size) { + string hash = sha256(data, data_size); + if (hash.empty()) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] sha256 error. \n"); + } + return hash; +} + +////////////////////// CertificationProvider class /////////////////////////////////////// +CertificationProvider::CertificationProvider(const string &base_url) { + this->base_url_ = base_url; +} + +CertificationProvider::~CertificationProvider() { +} + +sgx_qcnl_error_t CertificationProvider::get_certification(http_header_map &header_map, + const string &query_string, + PccsResponseObject *pccs_resp_obj) { + + if (this->base_url_.empty()) { + return SGX_QCNL_INVALID_CONFIG; + } + + sgx_qcnl_error_t ret = SGX_QCNL_UNEXPECTED_ERROR; + char *resp_msg = NULL; + uint32_t resp_size = 0; + char *resp_header = NULL; + uint32_t header_size = 0; + string url = this->base_url_ + query_string; + + ret = qcnl_https_request(url.c_str(), header_map, NULL, 0, NULL, 0, &resp_msg, resp_size, &resp_header, header_size); + if (ret != SGX_QCNL_SUCCESS) { + return ret; + } else if (!resp_msg || resp_size == 0) { + return SGX_QCNL_UNEXPECTED_ERROR; + } + + pccs_resp_obj->set_raw_header(resp_header, header_size).set_raw_body(resp_msg, resp_size); + + if (resp_msg) { + free(resp_msg); + resp_msg = NULL; + } + if (resp_header) { + free(resp_header); + resp_header = NULL; + } + + return ret; +} + +////////////////////// CacheProvider class /////////////////////////////////////// +CacheProvider::CacheProvider(const string &base_url) { + this->base_url_ = base_url; +} + +CacheProvider::~CacheProvider() { +} + +sgx_qcnl_error_t CacheProvider::get_certification(const string &query_string, + PccsResponseObject *pccs_resp_obj) { + string url = this->base_url_ + query_string; + string cache_key = sha256_hash(url.data(), url.size()); + sgx_qcnl_error_t ret = SGX_QCNL_UNEXPECTED_ERROR; + + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Fetching from the local cache for: '%s' \n", url.c_str()); + + vector value; + if (!LocalCache::Instance().get_data(cache_key, value)) { + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Cache missed. \n"); + return SGX_QCNL_CACHE_MISSING; + } + + do { + if (value.size() < sizeof(CacheItemHeader) || + value.size() > UINT32_MAX) { + break; + } + + // Check expiry + CacheItemHeader cache_header = {0}; + if (memcpy_s(&cache_header, sizeof(CacheItemHeader), value.data(), sizeof(CacheItemHeader)) != 0) + break; + if (is_cache_item_expired(cache_header.expiry)) { + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Cache expired. \n"); + ret = SGX_QCNL_CACHE_EXPIRED; + break; + } + + // Parse header + uint8_t *p_data = value.data() + sizeof(CacheItemHeader); + uint32_t header_size = *reinterpret_cast(p_data); + if (header_size > value.size() - sizeof(CacheItemHeader) - 2 * sizeof(uint32_t)) + break; + p_data += sizeof(uint32_t); + pccs_resp_obj->set_raw_header((const char *)p_data, header_size); + + // Parse body + p_data += header_size; + uint32_t body_size = *reinterpret_cast(p_data); + if (body_size != value.size() - sizeof(CacheItemHeader) - 2 * sizeof(uint32_t) - header_size) + break; + p_data += sizeof(uint32_t); + pccs_resp_obj->set_raw_body((const char *)p_data, body_size); + + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Fetched from the local cache successfully. \n"); + + ret = SGX_QCNL_SUCCESS; + } while (false); + + if (ret != SGX_QCNL_SUCCESS) { + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Cache item expired or corrupted. \n"); + LocalCache::Instance().remove_data(cache_key); + } + + return ret; +} + +sgx_qcnl_error_t CacheProvider::set_certification(uint32_t default_expiry_seconds, + const string &query_string, + PccsResponseObject *pccs_resp_obj) { + // Cache-Control:max-age has higher priority over config file + uint32_t cache_max_age = pccs_resp_obj->get_cache_max_age(); + uint32_t expiry_seconds = (cache_max_age > 0) ? cache_max_age : default_expiry_seconds; + + if (expiry_seconds > 0) { + string url = this->base_url_ + query_string; + string cache_key = sha256_hash(url.data(), url.size()); + if (cache_key.empty()) { + return SGX_QCNL_UNEXPECTED_ERROR; + } + + vector value; + + time_t current_time = time(NULL); + CacheItemHeader cache_header = {0}; + cache_header.expiry = current_time + expiry_seconds; + + // Append cache header + uint8_t *p_data = reinterpret_cast(&cache_header); + value.insert(value.end(), p_data, p_data + sizeof(cache_header)); + + // Append repsonse header and body + string header = pccs_resp_obj->get_raw_header(); + size_t header_size = header.size(); + string body = pccs_resp_obj->get_raw_body(); + size_t body_size = body.size(); + value.insert(value.end(), (uint8_t *)&header_size, (uint8_t *)&header_size + 4); + value.insert(value.end(), header.data(), header.data() + header_size); + value.insert(value.end(), (uint8_t *)&body_size, (uint8_t *)&body_size + 4); + value.insert(value.end(), body.data(), body.data() + body_size); + + LocalCache::Instance().set_data(cache_key, value); + + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Caching collateral '%s' for %d seconds. \n", url.c_str(), expiry_seconds); + } + + return SGX_QCNL_SUCCESS; +} \ No newline at end of file diff --git a/QuoteGeneration/qcnl/certification_service.cpp b/QuoteGeneration/qcnl/certification_service.cpp new file mode 100644 index 00000000..29d1991f --- /dev/null +++ b/QuoteGeneration/qcnl/certification_service.cpp @@ -0,0 +1,792 @@ +/* + * 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. + * + */ +/** + * File: certification_service.cpp + * + * Description: CertificationService class + * + */ +#include "certification_service.h" +#include "qcnl_config.h" +#include "qcnl_util.h" +#include "se_memcpy.h" +#include "sgx_ql_lib_common.h" +#include + +CertificationService::CertificationService() { +} + +CertificationService::CertificationService(const char *custom_param) { + if (custom_param) + custom_param_ = custom_param; +} + +CertificationService::~CertificationService() { +} + +string CertificationService::get_custom_param_string() { + if (custom_param_.empty()) + return ""; + + // custom_param_ is BASE64 encoded string, so we need to escape '+','/','=' + string s = custom_param_; + s = regex_replace(s, regex("\\+"), "%2B"); + s = regex_replace(s, regex("\\/"), "%2F"); + s = regex_replace(s, regex("\\="), "%3D"); + return "customParameter=" + s; +} + +sgx_qcnl_error_t CertificationService::build_pckcert_options(const sgx_ql_pck_cert_id_t *p_pck_cert_id, + http_header_map &header_map, + string &query_string) { + sgx_qcnl_error_t ret = SGX_QCNL_UNEXPECTED_ERROR; + + // Append QE ID + query_string.append("pckcert?qeid="); + if (!concat_string_with_hex_buf(query_string, p_pck_cert_id->p_qe3_id, p_pck_cert_id->qe3_id_size)) { + return ret; + } + + // Append encrypted PPID + query_string.append("&encrypted_ppid="); + if (p_pck_cert_id->p_encrypted_ppid == NULL) { + uint8_t enc_ppid_unused[consts::ENC_PPID_SIZE] = {0}; + if (!concat_string_with_hex_buf(query_string, (const uint8_t *)&enc_ppid_unused, sizeof(enc_ppid_unused))) { + return ret; + } + } else { + if (!concat_string_with_hex_buf(query_string, p_pck_cert_id->p_encrypted_ppid, p_pck_cert_id->encrypted_ppid_size)) { + return ret; + } + } + + // Append cpusvn + query_string.append("&cpusvn="); + if (!concat_string_with_hex_buf(query_string, reinterpret_cast(p_pck_cert_id->p_platform_cpu_svn), sizeof(sgx_cpu_svn_t))) { + return ret; + } + + // Append pcesvn + query_string.append("&pcesvn="); + if (!concat_string_with_hex_buf(query_string, reinterpret_cast(p_pck_cert_id->p_platform_pce_isv_svn), sizeof(sgx_isv_svn_t))) { + return ret; + } + + // Append pceid + query_string.append("&pceid="); + if (!concat_string_with_hex_buf(query_string, reinterpret_cast(&p_pck_cert_id->pce_id), sizeof(p_pck_cert_id->pce_id))) { + return ret; + } + + // Custom request options + Document &custom_options = QcnlConfig::Instance()->getCustomRequestOptions(); + if (!custom_options.IsNull() && custom_options.HasMember("get_cert") && custom_options["get_cert"].IsObject()) { + // Custom parameters in JSON config + if (custom_options["get_cert"].HasMember("params")) { + Value ¶ms = custom_options["get_cert"]["params"]; + if (params.IsObject()) { + Value::ConstMemberIterator it = params.MemberBegin(); + while (it != params.MemberEnd()) { + if (it->value.IsString()) { + string key = it->name.GetString(); + string value = it->value.GetString(); + query_string.append("&").append(key).append("=").append(value); + } + it++; + } + } + } + // Custom headers in JSON config + if (custom_options["get_cert"].HasMember("headers")) { + Value &headers = custom_options["get_cert"]["headers"]; + if (headers.IsObject()) { + Value::ConstMemberIterator it = headers.MemberBegin(); + while (it != headers.MemberEnd()) { + if (it->value.IsString()) { + string key = it->name.GetString(); + string value = it->value.GetString(); + header_map.insert(pair(key, value)); + } + it++; + } + } + } + } + + return SGX_QCNL_SUCCESS; +} + +sgx_qcnl_error_t CertificationService::build_pckcrl_options(const char *ca, + uint16_t ca_size, + http_header_map &header_map, + string &query_string) { + (void)header_map; // currently no custom headers for fetching pck crl + (void)ca_size; + + // Append ca and encoding + query_string.append("pckcrl?ca=").append(ca); + if (is_collateral_service_pcs() || QcnlConfig::Instance()->getCollateralVersion() == "3.1") { + query_string.append("&encoding=der"); + } + if (!custom_param_.empty()) { + query_string.append("&").append(get_custom_param_string()); + } + + return SGX_QCNL_SUCCESS; +} + +sgx_qcnl_error_t CertificationService::build_tcbinfo_options(const char *fmspc, + uint16_t fmspc_size, + http_header_map &header_map, + string &query_string) { + (void)header_map; + + // Append fmspc + query_string.append("tcb?fmspc="); + if (!concat_string_with_hex_buf(query_string, reinterpret_cast(fmspc), fmspc_size)) { + return SGX_QCNL_UNEXPECTED_ERROR; + } + if (!custom_param_.empty()) { + query_string.append("&").append(get_custom_param_string()); + } + + return SGX_QCNL_SUCCESS; +} + +sgx_qcnl_error_t CertificationService::build_qeidentity_options(http_header_map &header_map, string &query_string) { + (void)header_map; + + query_string.append("qe/identity"); + if (!custom_param_.empty()) { + query_string.append("?").append(get_custom_param_string()); + } + + return SGX_QCNL_SUCCESS; +} + +sgx_qcnl_error_t CertificationService::build_qveidentity_options(http_header_map &header_map, string &query_string) { + (void)header_map; + + query_string.append("qve/identity"); + if (!custom_param_.empty()) { + query_string.append("?").append(get_custom_param_string()); + } + + return SGX_QCNL_SUCCESS; +} + +sgx_qcnl_error_t CertificationService::build_root_ca_crl_options(const char *root_ca_cdp_url, http_header_map &header_map, string &query_string) { + (void)header_map; + + if (!is_collateral_service_pcs()) { + if (QcnlConfig::Instance()->getCollateralVersion() == "3.0") { + // For PCCS API version 3.0, will call API /rootcacrl, and it will return HEX encoded CRL + query_string.append("rootcacrl"); + if (!custom_param_.empty()) { + query_string.append("?").append(get_custom_param_string()); + } + } else if (QcnlConfig::Instance()->getCollateralVersion() == "3.1") { + // For PCCS API version 3.0, will call API /crl, and it will return raw DER buffer + query_string.append("crl?uri=").append(root_ca_cdp_url); + if (!custom_param_.empty()) { + query_string.append("&").append(get_custom_param_string()); + } + } else { + return SGX_QCNL_INVALID_CONFIG; + } + } + + return SGX_QCNL_SUCCESS; +} + +sgx_qcnl_error_t CertificationService::resp_obj_to_pck_certchain(PccsResponseObject *pccs_resp_obj, + sgx_ql_config_t **pp_quote_config) { + sgx_qcnl_error_t ret = SGX_QCNL_UNEXPECTED_ERROR; + + PckCertResponseObject *pckcert_resp_obj = (PckCertResponseObject *)pccs_resp_obj; + + do { + // Get TCBm , Issuer Chain, PCK certificate from response + string tcbm = pckcert_resp_obj->get_tcbm(); + string certchain = pckcert_resp_obj->get_pckcert_issuer_chain(); + string pck_cert = pckcert_resp_obj->get_pckcert(); + if (tcbm.size() != (consts::CPUSVN_SIZE + consts::PCESVN_SIZE) * 2 || certchain.empty() || pck_cert.empty()) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Response message error. \n"); + ret = SGX_QCNL_MSG_ERROR; + break; + } + + certchain = unescape(certchain); + + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] sgx-Tcbm: %s \n", tcbm.c_str()); + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] pckCert: %s \n", pck_cert.c_str()); + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] sgx-Pck-Certificate-Issuer-Chain: %s \n", certchain.c_str()); + + // allocate output buffer + *pp_quote_config = (sgx_ql_config_t *)malloc(sizeof(sgx_ql_config_t)); + if (*pp_quote_config == NULL) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Out of memory. \n"); + ret = SGX_QCNL_OUT_OF_MEMORY; + break; + } + memset(*pp_quote_config, 0, sizeof(sgx_ql_config_t)); + + // set version + (*pp_quote_config)->version = SGX_QL_CONFIG_VERSION_1; + + // set tcbm + if (!hex_string_to_byte_array(reinterpret_cast(tcbm.data()), + consts::CPUSVN_SIZE * 2, + reinterpret_cast(&(*pp_quote_config)->cert_cpu_svn), + sizeof(sgx_cpu_svn_t))) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Failed to parse cpu svn. \n"); + ret = SGX_QCNL_MSG_ERROR; + break; + } + if (!hex_string_to_byte_array(reinterpret_cast(tcbm.data() + consts::CPUSVN_SIZE * 2), + consts::PCESVN_SIZE * 2, + reinterpret_cast(&(*pp_quote_config)->cert_pce_isv_svn), + sizeof(sgx_isv_svn_t))) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Failed to parse pce svn. \n"); + ret = SGX_QCNL_MSG_ERROR; + break; + } + + // set certchain (leaf cert || intermediateCA || root CA || '\0') + (*pp_quote_config)->cert_data_size = (uint32_t)(certchain.size() + pck_cert.size() + 1); + (*pp_quote_config)->p_cert_data = (uint8_t *)malloc((*pp_quote_config)->cert_data_size); + if (!(*pp_quote_config)->p_cert_data) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Out of memory. \n"); + ret = SGX_QCNL_OUT_OF_MEMORY; + break; + } + if (memcpy_s((*pp_quote_config)->p_cert_data, (*pp_quote_config)->cert_data_size, pck_cert.data(), pck_cert.size()) != 0) { + ret = SGX_QCNL_UNEXPECTED_ERROR; + break; + } + if (memcpy_s((*pp_quote_config)->p_cert_data + pck_cert.size(), certchain.size(), certchain.data(), certchain.size()) != 0) { + ret = SGX_QCNL_UNEXPECTED_ERROR; + break; + } + (*pp_quote_config)->p_cert_data[(*pp_quote_config)->cert_data_size - 1] = 0; // NULL terminator + + ret = SGX_QCNL_SUCCESS; + } while (0); + + if (ret != SGX_QCNL_SUCCESS) { + sgx_qcnl_free_pck_cert_chain(*pp_quote_config); + } + + return ret; +} +sgx_qcnl_error_t CertificationService::resp_obj_to_pck_crl(PccsResponseObject *pccs_resp_obj, + uint8_t **pp_crl_chain, + uint16_t *p_crl_chain_size) { + sgx_qcnl_error_t ret = SGX_QCNL_UNEXPECTED_ERROR; + PckCrlResponseObject *pckcrl_resp_obj = (PckCrlResponseObject *)pccs_resp_obj; + + do { + string certchain = pckcrl_resp_obj->get_pckcrl_issuer_chain(); + string crl = pckcrl_resp_obj->get_pckcrl(); + if (certchain.empty() || crl.empty()) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Response message error. \n"); + ret = SGX_QCNL_MSG_ERROR; + break; + } + + certchain = unescape(certchain); + + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] sgx-pck-crl-issuer-chain: %s \n", certchain.c_str()); + + // Always append a NULL terminator to CRL and certchain + *p_crl_chain_size = (uint16_t)(certchain.size() + crl.size() + 2); + *pp_crl_chain = (uint8_t *)malloc(*p_crl_chain_size); + if (*pp_crl_chain == NULL) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Out of memory. \n"); + ret = SGX_QCNL_OUT_OF_MEMORY; + break; + } + + // set certchain (crl || ('\0) || intermediateCA || root CA || '\0') + uint8_t *ptr = *pp_crl_chain; + if (memcpy_s(ptr, crl.size(), crl.data(), crl.size()) != 0) { + ret = SGX_QCNL_UNEXPECTED_ERROR; + break; + } + ptr += crl.size(); + *ptr++ = '\0'; // add NULL terminator + + if (memcpy_s(ptr, certchain.size(), certchain.data(), certchain.size()) != 0) { + ret = SGX_QCNL_UNEXPECTED_ERROR; + break; + } + ptr += certchain.size(); + *ptr = '\0'; // add NULL terminator + + ret = SGX_QCNL_SUCCESS; + } while (0); + + if (ret != SGX_QCNL_SUCCESS) { + sgx_qcnl_free_pck_crl_chain(*pp_crl_chain); + } + + return ret; +} + +sgx_qcnl_error_t CertificationService::resp_obj_to_tcbinfo(PccsResponseObject *pccs_resp_obj, + uint8_t **pp_tcbinfo, + uint16_t *p_tcbinfo_size) { + sgx_qcnl_error_t ret = SGX_QCNL_UNEXPECTED_ERROR; + TcbInfoResponseObject *tcbinfo_resp_obj = (TcbInfoResponseObject *)pccs_resp_obj; + + do { + string certchain = tcbinfo_resp_obj->get_tcbinfo_issuer_chain(); + string tcbinfo = tcbinfo_resp_obj->get_tcbinfo(); + if (certchain.empty() || tcbinfo.empty()) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Response message error. \n"); + ret = SGX_QCNL_MSG_ERROR; + break; + } + + certchain = unescape(certchain); + + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] tcbinfo: %s \n", tcbinfo.c_str()); + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] tcb-info-issuer-chain: %s \n", tcbinfo.c_str()); + + *p_tcbinfo_size = (uint16_t)(certchain.size() + tcbinfo.size() + 2); + *pp_tcbinfo = (uint8_t *)malloc(*p_tcbinfo_size); + if (*pp_tcbinfo == NULL) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Out of memory. \n"); + ret = SGX_QCNL_OUT_OF_MEMORY; + break; + } + + // set certchain (tcbinfo || '\0' || signingCA || root CA || '\0') + if (memcpy_s(*pp_tcbinfo, *p_tcbinfo_size, tcbinfo.data(), tcbinfo.size()) != 0) { + ret = SGX_QCNL_UNEXPECTED_ERROR; + break; + } + (*pp_tcbinfo)[tcbinfo.size()] = '\0'; // add NULL terminator + if (memcpy_s(*pp_tcbinfo + tcbinfo.size() + 1, certchain.size(), certchain.data(), certchain.size()) != 0) { + ret = SGX_QCNL_UNEXPECTED_ERROR; + break; + } + (*pp_tcbinfo)[*p_tcbinfo_size - 1] = '\0'; // add NULL terminator + + ret = SGX_QCNL_SUCCESS; + } while (0); + + if (ret != SGX_QCNL_SUCCESS) { + sgx_qcnl_free_tcbinfo(*pp_tcbinfo); + } + + return ret; +} + +sgx_qcnl_error_t CertificationService::resp_obj_to_qe_identity(PccsResponseObject *pccs_resp_obj, + uint8_t **pp_qe_identity, + uint16_t *p_qe_identity_size) { + sgx_qcnl_error_t ret = SGX_QCNL_UNEXPECTED_ERROR; + QeIdentityResponseObject *qe_identity_resp_obj = (QeIdentityResponseObject *)pccs_resp_obj; + + do { + string certchain = qe_identity_resp_obj->get_enclave_id_issuer_chain(); + string qeidentity = qe_identity_resp_obj->get_qeidentity(); + if (certchain.empty() || qeidentity.empty()) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Response message error. \n"); + ret = SGX_QCNL_MSG_ERROR; + break; + } + + certchain = unescape(certchain); + + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] qe identity: %s \n", qeidentity.c_str()); + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] sgx-enclave-identity-issuer-chain: %s \n", certchain.c_str()); + + *p_qe_identity_size = (uint16_t)(certchain.size() + qeidentity.size() + 2); + *pp_qe_identity = (uint8_t *)malloc(*p_qe_identity_size); + if (*pp_qe_identity == NULL) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Out of memory. \n"); + ret = SGX_QCNL_OUT_OF_MEMORY; + break; + } + + // set certchain (QE identity || '\0' || signingCA || root CA || '\0') + if (memcpy_s(*pp_qe_identity, *p_qe_identity_size, qeidentity.data(), qeidentity.size()) != 0) { + ret = SGX_QCNL_UNEXPECTED_ERROR; + break; + } + (*pp_qe_identity)[qeidentity.size()] = '\0'; // add NULL terminator + if (memcpy_s(*pp_qe_identity + qeidentity.size() + 1, certchain.size(), certchain.data(), certchain.size()) != 0) { + ret = SGX_QCNL_UNEXPECTED_ERROR; + break; + } + (*pp_qe_identity)[*p_qe_identity_size - 1] = '\0'; // add NULL terminator + + ret = SGX_QCNL_SUCCESS; + } while (0); + + if (ret != SGX_QCNL_SUCCESS) { + sgx_qcnl_free_qe_identity(*pp_qe_identity); + } + + return ret; +} + +sgx_qcnl_error_t CertificationService::resp_obj_to_qve_identity(PccsResponseObject *pccs_resp_obj, + char **pp_qve_identity, + uint32_t *p_qve_identity_size, + char **pp_qve_identity_issuer_chain, + uint32_t *p_qve_identity_issuer_chain_size) { + sgx_qcnl_error_t ret = SGX_QCNL_UNEXPECTED_ERROR; + QveIdentityResponseObject *qve_identity_resp_obj = (QveIdentityResponseObject *)pccs_resp_obj; + + do { + string certchain = qve_identity_resp_obj->get_enclave_id_issuer_chain(); + string qveidentity = qve_identity_resp_obj->get_qveidentity(); + if (certchain.empty() || qveidentity.empty()) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Response message error. \n"); + ret = SGX_QCNL_MSG_ERROR; + break; + } + + certchain = unescape(certchain); + + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] qve identity: %s \n", qveidentity.c_str()); + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] sgx-enclave-identity-issuer-chain: %s \n", certchain.c_str()); + + // allocate buffers + *p_qve_identity_size = (uint32_t)qveidentity.size() + 1; + *pp_qve_identity = (char *)malloc(*p_qve_identity_size); + if (*pp_qve_identity == NULL) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Out of memory. \n"); + ret = SGX_QCNL_OUT_OF_MEMORY; + break; + } + *p_qve_identity_issuer_chain_size = (uint32_t)(certchain.size() + 1); + *pp_qve_identity_issuer_chain = (char *)malloc(*p_qve_identity_issuer_chain_size); + if (*pp_qve_identity_issuer_chain == NULL) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Out of memory. \n"); + ret = SGX_QCNL_OUT_OF_MEMORY; + break; + } + + // set QvE identity + if (memcpy_s(*pp_qve_identity, *p_qve_identity_size, qveidentity.data(), qveidentity.size()) != 0) { + ret = SGX_QCNL_UNEXPECTED_ERROR; + break; + } + (*pp_qve_identity)[*p_qve_identity_size - 1] = '\0'; // add NULL terminator + + // set certchain (signingCA || root CA) + if (memcpy_s(*pp_qve_identity_issuer_chain, *p_qve_identity_issuer_chain_size, certchain.data(), certchain.size()) != 0) { + ret = SGX_QCNL_UNEXPECTED_ERROR; + break; + } + (*pp_qve_identity_issuer_chain)[*p_qve_identity_issuer_chain_size - 1] = '\0'; // add NULL terminator + + ret = SGX_QCNL_SUCCESS; + } while (0); + + if (ret != SGX_QCNL_SUCCESS) { + sgx_qcnl_free_qve_identity(*pp_qve_identity, *pp_qve_identity_issuer_chain); + } + + return ret; +} + +sgx_qcnl_error_t CertificationService::resp_obj_to_root_ca_crl(PccsResponseObject *pccs_resp_obj, + uint8_t **pp_root_ca_crl, + uint16_t *p_root_ca_crl_size) { + sgx_qcnl_error_t ret = SGX_QCNL_UNEXPECTED_ERROR; + + do { + string root_ca_crl = pccs_resp_obj->get_raw_body(); + + *p_root_ca_crl_size = (uint16_t)(root_ca_crl.size() + 1); + *pp_root_ca_crl = (uint8_t *)malloc(*p_root_ca_crl_size); + if (*pp_root_ca_crl == NULL) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Out of memory. \n"); + ret = SGX_QCNL_OUT_OF_MEMORY; + break; + } + + // set Root CA CRL + if (memcpy_s(*pp_root_ca_crl, *p_root_ca_crl_size, root_ca_crl.data(), root_ca_crl.size()) != 0) { + ret = SGX_QCNL_UNEXPECTED_ERROR; + break; + } + // Add NULL terminator + (*pp_root_ca_crl)[(*p_root_ca_crl_size) - 1] = 0; + + ret = SGX_QCNL_SUCCESS; + } while (0); + + if (ret != SGX_QCNL_SUCCESS) { + sgx_qcnl_free_root_ca_crl(*pp_root_ca_crl); + } + + return ret; +} + +sgx_qcnl_error_t CertificationService::get_pck_cert_chain(const sgx_ql_pck_cert_id_t *p_pck_cert_id, + sgx_ql_config_t **pp_quote_config) { + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Getting pck certificate and chain. \n"); + + sgx_qcnl_error_t ret = SGX_QCNL_SUCCESS; + http_header_map header_map; + string query_string; + PccsResponseObject pccs_resp_obj; + + // build query options for getting pck certificate + if ((ret = build_pckcert_options(p_pck_cert_id, header_map, query_string)) != SGX_QCNL_SUCCESS) { + return ret; + } + + // First try local service + CertificationProvider localProvider(QcnlConfig::Instance()->getLocalPckUrl()); + if ((ret = localProvider.get_certification(header_map, query_string, &pccs_resp_obj)) == SGX_QCNL_SUCCESS) { + qcnl_log(SGX_QL_LOG_INFO, + "[QCNL] Successfully fetched certificate from primary URL: '%s'. \n", + QcnlConfig::Instance()->getLocalPckUrl().c_str()); + return resp_obj_to_pck_certchain(&pccs_resp_obj, pp_quote_config); + } + + // then try the cache. encrypted_ppid shouldn't be part of cache key because the caller will send + // all 0 encrypted ppid sometimes + string qs_without_ppid = regex_replace(query_string, regex("&encrypted_ppid=[0-9a-zA-Z]+&"), "&"); + CacheProvider cacheProvider(QcnlConfig::Instance()->getServerUrl()); + if ((ret = cacheProvider.get_certification(qs_without_ppid, &pccs_resp_obj)) == SGX_QCNL_SUCCESS) { + return resp_obj_to_pck_certchain(&pccs_resp_obj, pp_quote_config); + } + + // try the remote service at last + qcnl_log(SGX_QL_LOG_INFO, + "[QCNL] Certificate not found in local cache. Trying to fetch response from remote URL: '%s'. \n", + QcnlConfig::Instance()->getServerUrl().c_str()); + CertificationProvider remoteProvider(QcnlConfig::Instance()->getServerUrl()); + if ((ret = remoteProvider.get_certification(header_map, query_string, &pccs_resp_obj)) == SGX_QCNL_SUCCESS) { + qcnl_log(SGX_QL_LOG_INFO, + "[QCNL] Successfully fetched certificate from remote URL: '%s'. \n", + QcnlConfig::Instance()->getServerUrl().c_str()); + if ((ret = resp_obj_to_pck_certchain(&pccs_resp_obj, pp_quote_config)) == SGX_QCNL_SUCCESS) { + // update cache + ret = cacheProvider.set_certification((uint32_t)(QcnlConfig::Instance()->getCacheExpireHour() * 3600), + qs_without_ppid, &pccs_resp_obj); + } + } + return ret; +} + +sgx_qcnl_error_t CertificationService::get_pck_crl_chain(const char *ca, + uint16_t ca_size, + uint8_t **pp_crl_chain, + uint16_t *p_crl_chain_size) { + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Getting pck crl. \n"); + + sgx_qcnl_error_t ret = SGX_QCNL_SUCCESS; + http_header_map header_map; + string query_string; + PccsResponseObject pccs_resp_obj; + + // build query options for getting pck crl + if ((ret = build_pckcrl_options(ca, ca_size, header_map, query_string)) != SGX_QCNL_SUCCESS) { + return ret; + } + + // First try local cache + CacheProvider cacheProvider(QcnlConfig::Instance()->getCollateralServiceUrl()); + if ((ret = cacheProvider.get_certification(query_string, &pccs_resp_obj)) == SGX_QCNL_SUCCESS) { + return resp_obj_to_pck_crl(&pccs_resp_obj, pp_crl_chain, p_crl_chain_size); + } + + // Then try remote service + CertificationProvider remoteProvider(QcnlConfig::Instance()->getCollateralServiceUrl()); + if ((ret = remoteProvider.get_certification(header_map, query_string, &pccs_resp_obj)) == SGX_QCNL_SUCCESS) { + if ((ret = resp_obj_to_pck_crl(&pccs_resp_obj, pp_crl_chain, p_crl_chain_size)) == SGX_QCNL_SUCCESS) { + // update cache + ret = cacheProvider.set_certification((uint32_t)(QcnlConfig::Instance()->getVerifyCollateralExpireHour() * 3600), + query_string, &pccs_resp_obj); + } + } + return ret; +} + +sgx_qcnl_error_t CertificationService::get_tcbinfo(sgx_prod_type_t prod_type, + const char *fmspc, + uint16_t fmspc_size, + uint8_t **pp_tcbinfo, + uint16_t *p_tcbinfo_size) { + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Getting tcb info. \n"); + + sgx_qcnl_error_t ret = SGX_QCNL_SUCCESS; + http_header_map header_map; + string query_string; + PccsResponseObject pccs_resp_obj; + + string base_url = QcnlConfig::Instance()->getCollateralServiceUrl(); + if (prod_type == SGX_PROD_TYPE_TDX) { + auto found = base_url.find("/sgx/"); + if (found != std::string::npos) { + base_url = base_url.replace(found, 5, "/tdx/"); + } else { + return SGX_QCNL_UNEXPECTED_ERROR; + } + } + + // build query options for getting tcbinfo + if ((ret = build_tcbinfo_options(fmspc, fmspc_size, header_map, query_string)) != SGX_QCNL_SUCCESS) { + return ret; + } + + CacheProvider cacheProvider(base_url); + if ((ret = cacheProvider.get_certification(query_string, &pccs_resp_obj)) == SGX_QCNL_SUCCESS) { + return resp_obj_to_tcbinfo(&pccs_resp_obj, pp_tcbinfo, p_tcbinfo_size); + } + + CertificationProvider remoteProvider(base_url); + if ((ret = remoteProvider.get_certification(header_map, query_string, &pccs_resp_obj)) == SGX_QCNL_SUCCESS) { + if ((ret = resp_obj_to_tcbinfo(&pccs_resp_obj, pp_tcbinfo, p_tcbinfo_size)) == SGX_QCNL_SUCCESS) { + ret = cacheProvider.set_certification((uint32_t)(QcnlConfig::Instance()->getVerifyCollateralExpireHour() * 3600), + query_string, &pccs_resp_obj); + } + } + return ret; +} + +sgx_qcnl_error_t CertificationService::get_qe_identity(sgx_qe_type_t qe_type, + uint8_t **pp_qe_identity, + uint16_t *p_qe_identity_size) { + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Getting quote enclave identity. \n"); + + sgx_qcnl_error_t ret = SGX_QCNL_SUCCESS; + http_header_map header_map; + string query_string; + PccsResponseObject pccs_resp_obj; + + string base_url = QcnlConfig::Instance()->getCollateralServiceUrl(); + + if (qe_type == SGX_QE_TYPE_TD) { + auto found = base_url.find("/sgx/"); + if (found != std::string::npos) { + base_url = base_url.replace(found, 5, "/tdx/"); + } else { + return SGX_QCNL_UNEXPECTED_ERROR; + } + } + + if ((ret = build_qeidentity_options(header_map, query_string)) != SGX_QCNL_SUCCESS) { + return ret; + } + + CacheProvider cacheProvider(base_url); + if ((ret = cacheProvider.get_certification(query_string, &pccs_resp_obj)) == SGX_QCNL_SUCCESS) { + return resp_obj_to_qe_identity(&pccs_resp_obj, pp_qe_identity, p_qe_identity_size); + } + + CertificationProvider remoteProvider(base_url); + if ((ret = remoteProvider.get_certification(header_map, query_string, &pccs_resp_obj)) == SGX_QCNL_SUCCESS) { + if ((ret = resp_obj_to_qe_identity(&pccs_resp_obj, pp_qe_identity, p_qe_identity_size)) == SGX_QCNL_SUCCESS) { + ret = cacheProvider.set_certification((uint32_t)(QcnlConfig::Instance()->getVerifyCollateralExpireHour() * 3600), + query_string, &pccs_resp_obj); + } + } + return ret; +} + +sgx_qcnl_error_t CertificationService::get_qve_identity(char **pp_qve_identity, + uint32_t *p_qve_identity_size, + char **pp_qve_identity_issuer_chain, + uint32_t *p_qve_identity_issuer_chain_size) { + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Getting quote verification enclave identity. \n"); + + sgx_qcnl_error_t ret = SGX_QCNL_SUCCESS; + http_header_map header_map; + string query_string; + PccsResponseObject pccs_resp_obj; + + string base_url = QcnlConfig::Instance()->getCollateralServiceUrl(); + + if ((ret = build_qveidentity_options(header_map, query_string)) != SGX_QCNL_SUCCESS) { + return ret; + } + + CacheProvider cacheProvider(base_url); + if ((ret = cacheProvider.get_certification(query_string, &pccs_resp_obj)) == SGX_QCNL_SUCCESS) { + return resp_obj_to_qve_identity(&pccs_resp_obj, pp_qve_identity, p_qve_identity_size, + pp_qve_identity_issuer_chain, p_qve_identity_issuer_chain_size); + } + + CertificationProvider remoteProvider(base_url); + if ((ret = remoteProvider.get_certification(header_map, query_string, &pccs_resp_obj)) == SGX_QCNL_SUCCESS) { + if ((ret = resp_obj_to_qve_identity(&pccs_resp_obj, pp_qve_identity, p_qve_identity_size, + pp_qve_identity_issuer_chain, p_qve_identity_issuer_chain_size)) == SGX_QCNL_SUCCESS) { + ret = cacheProvider.set_certification((uint32_t)(QcnlConfig::Instance()->getVerifyCollateralExpireHour() * 3600), + query_string, &pccs_resp_obj); + } + } + return ret; +} + +sgx_qcnl_error_t CertificationService::get_root_ca_crl(const char *root_ca_cdp_url, + uint8_t **pp_root_ca_crl, + uint16_t *p_root_ca_crl_size) { + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Getting root ca crl. \n"); + + sgx_qcnl_error_t ret = SGX_QCNL_SUCCESS; + http_header_map header_map; + string query_string; + PccsResponseObject pccs_resp_obj; + + string base_url = QcnlConfig::Instance()->getCollateralServiceUrl(); + if (is_collateral_service_pcs()) { + base_url = root_ca_cdp_url; + } else { + ret = build_root_ca_crl_options(root_ca_cdp_url, header_map, query_string); + if (ret != SGX_QCNL_SUCCESS) { + return ret; + } + } + + CacheProvider cacheProvider(base_url); + if ((ret = cacheProvider.get_certification(query_string, &pccs_resp_obj)) == SGX_QCNL_SUCCESS) { + return resp_obj_to_root_ca_crl(&pccs_resp_obj, pp_root_ca_crl, p_root_ca_crl_size); + } + + CertificationProvider remoteProvider(base_url); + if ((ret = remoteProvider.get_certification(header_map, query_string, &pccs_resp_obj)) == SGX_QCNL_SUCCESS) { + if ((ret = resp_obj_to_root_ca_crl(&pccs_resp_obj, pp_root_ca_crl, p_root_ca_crl_size)) == SGX_QCNL_SUCCESS) { + ret = cacheProvider.set_certification((uint32_t)(QcnlConfig::Instance()->getVerifyCollateralExpireHour() * 3600), + query_string, &pccs_resp_obj); + } + } + return ret; +} diff --git a/QuoteGeneration/qcnl/inc/certification_provider.h b/QuoteGeneration/qcnl/inc/certification_provider.h new file mode 100644 index 00000000..76b28e67 --- /dev/null +++ b/QuoteGeneration/qcnl/inc/certification_provider.h @@ -0,0 +1,91 @@ +/* + * 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. + * + */ +/** File: certification_provider.h + * + * Description: Header file of CertificationProvider class + * + */ +#ifndef CERTIFICATIONPROVIDER_H_ +#define CERTIFICATIONPROVIDER_H_ +#pragma once + +#include "network_wrapper.h" +#include "pccs_response_object.h" +#include "qcnl_config.h" +#include "sgx_default_qcnl_wrapper.h" +#include + +#ifdef _MSC_VER +#include +#endif + +using namespace std; + +class CertificationProvider { +private: +protected: + string base_url_; + +public: + CertificationProvider(const string &base_url); + ~CertificationProvider(); + + sgx_qcnl_error_t get_certification(http_header_map &header_map, + const string &query_string, + PccsResponseObject *pccs_resp_obj); +}; + +class CacheProvider { +private: + bool is_cache_item_expired(time_t expiry) { + time_t current_time = time(NULL); + + if (current_time == ((time_t)-1) || current_time >= expiry) + return true; + + return false; + } + +protected: + string base_url_; + +public: + CacheProvider(const string &base_url); + ~CacheProvider(); + + sgx_qcnl_error_t get_certification(const string &query_string, + PccsResponseObject *pccs_resp_obj); + sgx_qcnl_error_t set_certification(uint32_t default_expiry_seconds, + const string &query_string, + PccsResponseObject *pccs_resp_obj); +}; + +#endif // CERTIFICATIONPROVIDER_H_ \ No newline at end of file diff --git a/QuoteGeneration/qcnl/inc/certification_service.h b/QuoteGeneration/qcnl/inc/certification_service.h new file mode 100644 index 00000000..47be9f41 --- /dev/null +++ b/QuoteGeneration/qcnl/inc/certification_service.h @@ -0,0 +1,115 @@ +/* + * 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. + * + */ +/** File: certification_service.h + * + * Description: Header file of CertificationService class + * + */ +#ifndef CERTIFICATIONSERVICE_H_ +#define CERTIFICATIONSERVICE_H_ +#pragma once + +#include "certification_provider.h" +#include "network_wrapper.h" +#include "sgx_default_qcnl_wrapper.h" +#include +#include + +using namespace std; + +class CertificationService { +private: + string custom_param_; + +protected: + string get_custom_param_string(); + sgx_qcnl_error_t build_pckcert_options(const sgx_ql_pck_cert_id_t *p_pck_cert_id, + http_header_map &header_map, + string &query_string); + sgx_qcnl_error_t build_pckcrl_options(const char *ca, + uint16_t ca_size, + http_header_map &header_map, + string &query_string); + sgx_qcnl_error_t build_tcbinfo_options(const char *fmspc, + uint16_t fmspc_size, + http_header_map &header_map, + string &query_string); + sgx_qcnl_error_t build_qeidentity_options(http_header_map &header_map, string &query_string); + sgx_qcnl_error_t build_qveidentity_options(http_header_map &header_map, string &query_string); + sgx_qcnl_error_t build_root_ca_crl_options(const char *root_ca_cdp_url, http_header_map &header_map, string &query_string); + sgx_qcnl_error_t resp_obj_to_pck_certchain(PccsResponseObject *pccs_resp_obj, + sgx_ql_config_t **pp_quote_config); + sgx_qcnl_error_t resp_obj_to_pck_crl(PccsResponseObject *pccs_resp_obj, + uint8_t **pp_crl_chain, + uint16_t *p_crl_chain_size); + sgx_qcnl_error_t resp_obj_to_tcbinfo(PccsResponseObject *pccs_resp_obj, + uint8_t **pp_tcbinfo, + uint16_t *p_tcbinfo_size); + sgx_qcnl_error_t resp_obj_to_qe_identity(PccsResponseObject *pccs_resp_obj, + uint8_t **pp_qe_identity, + uint16_t *p_qe_identity_size); + sgx_qcnl_error_t resp_obj_to_qve_identity(PccsResponseObject *pccs_resp_obj, + char **pp_qve_identity, + uint32_t *p_qve_identity_size, + char **pp_qve_identity_issuer_chain, + uint32_t *p_qve_identity_issuer_chain_size); + sgx_qcnl_error_t resp_obj_to_root_ca_crl(PccsResponseObject *pccs_resp_obj, + uint8_t **pp_root_ca_crl, + uint16_t *p_root_ca_crl_size); + +public: + CertificationService(); + CertificationService(const char *custom_param); + ~CertificationService(); + + sgx_qcnl_error_t get_pck_cert_chain(const sgx_ql_pck_cert_id_t *p_pck_cert_id, + sgx_ql_config_t **pp_quote_config); + sgx_qcnl_error_t get_pck_crl_chain(const char *ca, + uint16_t ca_size, + uint8_t **pp_crl_chain, + uint16_t *p_crl_chain_size); + sgx_qcnl_error_t get_tcbinfo(sgx_prod_type_t prod_type, + const char *fmspc, + uint16_t fmspc_size, + uint8_t **pp_tcbinfo, + uint16_t *p_tcbinfo_size); + sgx_qcnl_error_t get_qe_identity(sgx_qe_type_t qe_type, + uint8_t **pp_qe_identity, + uint16_t *p_qe_identity_size); + sgx_qcnl_error_t get_qve_identity(char **pp_qve_identity, + uint32_t *p_qve_identity_size, + char **pp_qve_identity_issuer_chain, + uint32_t *p_qve_identity_issuer_chain_size); + sgx_qcnl_error_t get_root_ca_crl(const char *root_ca_cdp_url, + uint8_t **pp_root_ca_crl, + uint16_t *p_root_ca_crl_size); +}; +#endif // CERTIFICATIONSERVICE_H_ diff --git a/QuoteGeneration/qcnl/inc/local_cache.h b/QuoteGeneration/qcnl/inc/local_cache.h index acbf3111..56e1a523 100644 --- a/QuoteGeneration/qcnl/inc/local_cache.h +++ b/QuoteGeneration/qcnl/inc/local_cache.h @@ -28,9 +28,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -/** File: local_cache.h - * - * Description: Implementation of local cache for PCK certificate chain +/** File: local_cache.h + * + * Description: Implementation of local cache for PCK certificate chain & collaterals * */ #ifndef LOCALCACHE_H_ @@ -38,15 +38,24 @@ #pragma once #include "qcnl_config.h" -#include "se_memcpy.h" #include "qcnl_util.h" +#include "se_memcpy.h" +#include #include +#include #include #include #include +#ifdef _MSC_VER +#else +#include +#endif + using namespace std; +static std::mutex mutex_cache_lock; + template class MemoryCache { private: @@ -55,9 +64,8 @@ class MemoryCache { size_t size_; public: - // Set default cache size to 5. In fact 1 is enough for PCK certchain. - // We set 5 here tentatively for future expansion - MemoryCache() : size_(5) {} + // Set default cache size to 20 + MemoryCache() : size_(20) {} void set(const Key key, const Value value) { auto pos = map_.find(key); @@ -85,6 +93,14 @@ class MemoryCache { value = pos->second.first; return true; } + + void remove(const Key key) { + auto pos = map_.find(key); + if (pos != map_.end()) { + keys_.erase(pos->second.second); + map_.erase(key); + } + } }; struct CacheItemHeader { @@ -92,147 +108,188 @@ struct CacheItemHeader { }; // (key, value) pair, where -// Cache Key = QE_ID || CPU_SVN || PCE_SVN || PCE_ID -// Cache value = CacheItemHeader || sgx_ql_config_t -class LocalMemCache { +// Cache Key = sha256(URL) +// Cache value = CacheItemHeader || HTTP RESPONSE(HEADER SIZE || HEADER || BODY SIZE || BODY) +class LocalCache { private: // - MemoryCache> m_cache; + MemoryCache> mem_cache_; +#ifdef _MSC_VER + wstring cache_dir_; +#else + string cache_dir_; +#endif - // - string pck_cert_id_to_key(const sgx_ql_pck_cert_id_t *p_pck_cert_id) { - string key = ""; +public: + static LocalCache &Instance() { + static LocalCache myInstance; + return myInstance; + } - if (!p_pck_cert_id) { - return ""; + LocalCache(LocalCache const &) = delete; + LocalCache(LocalCache &&) = delete; + LocalCache &operator=(LocalCache const &) = delete; + LocalCache &operator=(LocalCache &&) = delete; + + bool get_data(const string &key, vector &value) { + // Lock the cache mutex + std::lock_guard lock(mutex_cache_lock); + + bool cache_hit = false; + if (!mem_cache_.get(key, value)) { + // If memory cache missed, turn to file cache + if (!cache_dir_.empty()) { +#ifdef _MSC_VER + wstring wskey(key.begin(), key.end()); + const auto file_name = cache_dir_ + L"\\" + wskey; +#else + const auto file_name = cache_dir_ + "/" + key; +#endif + ifstream ifs(file_name, std::ios::in | std::ios::binary); + if (ifs.is_open()) { + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Cache hit in folder '%s'. \n", cache_dir_.c_str()); + value.assign(std::istreambuf_iterator(ifs), std::istreambuf_iterator()); + // Need to update memory cache if file cache is hit + mem_cache_.set(key, value); + cache_hit = true; + } + ifs.close(); + } + } else { + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Cache hit in memory. \n"); + cache_hit = true; } - if (!concat_string_with_hex_buf(key, p_pck_cert_id->p_qe3_id, p_pck_cert_id->qe3_id_size)) - return ""; - - if (!concat_string_with_hex_buf(key, reinterpret_cast(p_pck_cert_id->p_platform_cpu_svn), sizeof(sgx_cpu_svn_t))) - return ""; - - if (!concat_string_with_hex_buf(key, reinterpret_cast(p_pck_cert_id->p_platform_pce_isv_svn), sizeof(sgx_isv_svn_t))) - return ""; - - if (!concat_string_with_hex_buf(key, reinterpret_cast(&p_pck_cert_id->pce_id), sizeof(p_pck_cert_id->pce_id))) - return ""; - - return key; + return cache_hit; } - bool is_cache_item_expired(time_t expiry) { - time_t current_time = time(NULL); - - if (current_time == ((time_t)-1) || current_time >= expiry) - return true; + void set_data(const string &key, vector &value) { + // Lock the cache mutex + std::lock_guard lock(mutex_cache_lock); + + // Update memory cache + mem_cache_.set(key, value); + + if (!cache_dir_.empty()) { + // Update file cache +#ifdef _MSC_VER + wstring wskey(key.begin(), key.end()); + const auto file_name = cache_dir_ + L"\\" + wskey; +#else + const auto file_name = cache_dir_ + "/" + key; +#endif + ofstream ofs(file_name, ios::out | ios::binary); + if (!ofs.is_open()) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Failed to write cache file '%s'. \n", file_name.c_str()); + } + ofs.write(reinterpret_cast(&value[0]), value.size()); + ofs.close(); - return false; + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Updated file cache successfully. \n"); + } } -public: - static LocalMemCache &Instance() { - static LocalMemCache myInstance; - return myInstance; + void remove_data(const string &key) { + // Lock the cache mutex + std::lock_guard lock(mutex_cache_lock); + + // Remove memory cache entry + mem_cache_.remove(key); + + if (!cache_dir_.empty()) { + // Remove file cache +#ifdef _MSC_VER + wstring wskey(key.begin(), key.end()); + const auto file_name = cache_dir_ + L"\\" + wskey; + ::DeleteFile(file_name.c_str()); +#else + const auto file_name = cache_dir_ + "/" + key; + std::remove(file_name.c_str()); +#endif + } } - LocalMemCache(LocalMemCache const &) = delete; - LocalMemCache(LocalMemCache &&) = delete; - LocalMemCache &operator=(LocalMemCache const &) = delete; - LocalMemCache &operator=(LocalMemCache &&) = delete; - - bool get_pck_cert_chain(const sgx_ql_pck_cert_id_t *p_pck_cert_id, - sgx_ql_config_t **pp_quote_config) { - if (!p_pck_cert_id) - return false; - - string cache_key = pck_cert_id_to_key(p_pck_cert_id); - if (cache_key.empty()) - return false; - - vector value; - bool ret = false; - const uint32_t ql_config_header_size = sizeof(sgx_ql_config_t) - sizeof(uint8_t *); - - do { - if (!m_cache.get(cache_key, value)) - break; - - if (value.size() < sizeof(CacheItemHeader) + ql_config_header_size) - break; - - // Check expiry - CacheItemHeader cache_header = {0}; - if (memcpy_s(&cache_header, sizeof(CacheItemHeader), value.data(), sizeof(CacheItemHeader)) != 0) - break; - if (is_cache_item_expired(cache_header.expiry)) - break; +protected: + LocalCache() { + init_cache_directory(); + } + ~LocalCache() {} - const uint8_t *p_ql_config_cache = value.data() + sizeof(CacheItemHeader); +#ifdef _MSC_VER + void init_cache_directory() { + const DWORD buffSize = MAX_PATH; - *pp_quote_config = (sgx_ql_config_t *)malloc(sizeof(sgx_ql_config_t)); - if (*pp_quote_config == NULL) - break; + auto env_home = std::make_unique(buffSize); + memset(env_home.get(), 0, buffSize); + GetEnvironmentVariable(L"LOCALAPPDATA", env_home.get(), buffSize); + std::wstring wenv_home(env_home.get()); - if (memcpy_s(*pp_quote_config, ql_config_header_size, p_ql_config_cache, ql_config_header_size) != 0) - break; + auto env_azdcap_cache = std::make_unique(buffSize); + memset(env_azdcap_cache.get(), 0, buffSize); + GetEnvironmentVariable(L"AZDCAP_CACHE", env_azdcap_cache.get(), buffSize); + std::wstring wenv_azdcap_cache(env_azdcap_cache.get()); - if ((*pp_quote_config)->cert_data_size != value.size() - sizeof(CacheItemHeader) - ql_config_header_size) - break; + const std::wstring application_name(L"\\.dcap-qcnl"); + std::wstring dirname; - (*pp_quote_config)->p_cert_data = (uint8_t *)malloc((*pp_quote_config)->cert_data_size); - if (!(*pp_quote_config)->p_cert_data) - break; + if (wenv_azdcap_cache != L"" && wenv_azdcap_cache[0] != 0) { + dirname = wenv_azdcap_cache; + } else if (wenv_home != L"" && wenv_home[0] != 0) { + dirname = wenv_home.append(L"..\\..\\LocalLow"); + } - if (memcpy_s((*pp_quote_config)->p_cert_data, (*pp_quote_config)->cert_data_size, - p_ql_config_cache + ql_config_header_size, (*pp_quote_config)->cert_data_size) != 0) - break; + dirname += application_name; + make_dir(dirname); + cache_dir_ = dirname; + } - ret = true; - } while (0); + bool make_dir(const std::wstring &dirname) { + CreateDirectory(dirname.c_str(), NULL); + if (GetLastError() == ERROR_PATH_NOT_FOUND && GetLastError() != ERROR_ALREADY_EXISTS) + return false; + return true; + } +#else + void init_cache_directory() { + const char *cache_locations[5]; + cache_locations[0] = ::getenv("AZDCAP_CACHE"); + cache_locations[1] = ::getenv("XDG_CACHE_HOME"); + cache_locations[2] = ::getenv("HOME"); + cache_locations[3] = ::getenv("TMPDIR"); + cache_locations[4] = "/tmp/"; + + string application_name("/.dcap-qcnl/"); + for (auto &cache_location : cache_locations) { + if (cache_location != 0 && strcmp(cache_location, "") != 0) { + string dirname = cache_location + application_name; + if (make_dir(dirname)) + cache_dir_ = dirname; + return; + } + } + } - if (!ret) { - sgx_qcnl_free_pck_cert_chain(*pp_quote_config); + bool make_dir(const std::string &dirname) { + struct stat buf {}; + int rc = stat(dirname.c_str(), &buf); + if (rc == 0) { + if (S_ISDIR(buf.st_mode)) { + return true; + } else { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] '%s' already exists, and is not a directory. \n", dirname.c_str()); + return false; + } } - return ret; - } + rc = mkdir(dirname.c_str(), 0777); + if (rc != 0) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Error creating directory '%s'. \n", dirname.c_str()); + return false; + } - void set_pck_cert_chain(const sgx_ql_pck_cert_id_t *p_pck_cert_id, - sgx_ql_config_t **pp_quote_config) { - if (!p_pck_cert_id) - return; - - string cache_key = pck_cert_id_to_key(p_pck_cert_id); - if (cache_key.empty()) - return; - - time_t current_time = time(NULL); - if (current_time == ((time_t)-1)) - return; - CacheItemHeader cache_header = {0}; - cache_header.expiry = current_time + QcnlConfig::Instance()->getCacheExpireHour() * 3600; - - vector value; - // Append cache header - uint8_t *p_data = reinterpret_cast(&cache_header); - value.insert(value.end(), p_data, p_data + sizeof(cache_header)); - - // Append sgx_ql_config_t strcture header - p_data = reinterpret_cast(*pp_quote_config); - const uint32_t ql_config_header_size = sizeof(sgx_ql_config_t) - sizeof(uint8_t *); - value.insert(value.end(), p_data, p_data + ql_config_header_size); - - // Append certificate data - value.insert(value.end(), (*pp_quote_config)->p_cert_data, (*pp_quote_config)->p_cert_data + (*pp_quote_config)->cert_data_size); - - m_cache.set(cache_key, value); + return true; } - -protected: - LocalMemCache() {} - ~LocalMemCache() {} +#endif }; #endif // LOCALCACHE_H_ \ No newline at end of file diff --git a/QuoteGeneration/qcnl/inc/network_wrapper.h b/QuoteGeneration/qcnl/inc/network_wrapper.h index ca07c046..31794174 100644 --- a/QuoteGeneration/qcnl/inc/network_wrapper.h +++ b/QuoteGeneration/qcnl/inc/network_wrapper.h @@ -28,8 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -/** File: network_wrapper.h - * +/** File: network_wrapper.h + * * Description: Definitions of network access interfaces * */ diff --git a/QuoteGeneration/qcnl/inc/pccs_response_object.h b/QuoteGeneration/qcnl/inc/pccs_response_object.h index e36d19ac..f1f545f0 100644 --- a/QuoteGeneration/qcnl/inc/pccs_response_object.h +++ b/QuoteGeneration/qcnl/inc/pccs_response_object.h @@ -28,8 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -/** File: pccs_response_object.h - * +/** File: pccs_response_object.h + * * Description: Header file of PccsResponseObject class and its sub-classes * */ @@ -39,6 +39,7 @@ #include "document.h" #include "qcnl_def.h" +#include #include #include @@ -53,10 +54,12 @@ class PccsResponseObject { PccsResponseObject &set_raw_header(const char *header, uint32_t header_size); PccsResponseObject &set_raw_body(const char *body, uint32_t body_size); + string &get_raw_header(); string &get_raw_body(); string get_header_key_value(const char *key); string get_body_key_value(const char *key); string get_real_response_body(const char *key); + uint32_t get_cache_max_age(); protected: string header_raw_; @@ -90,12 +93,9 @@ class PckCrlResponseObject : public PccsResponseObject { PckCrlResponseObject() {} ~PckCrlResponseObject() {} string get_pckcrl_issuer_chain() { - // string chain = this->get_header_key_value(intelpcs::CRL_ISSUER_CHAIN); - // return chain.empty() ? this->get_body_key_value(azurepccs::CRL_ISSUER_CHAIN) : chain; return this->get_header_key_value(intelpcs::CRL_ISSUER_CHAIN); } string get_pckcrl() { - //return this->get_real_response_body(); return this->body_raw_; } }; @@ -114,16 +114,10 @@ class TcbInfoResponseObject : public PccsResponseObject { if (!chain.empty()) return chain; - // chain = this->get_body_key_value(azurepccs::SGX_TCB_INFO_ISSUER_CHAIN); - // if (!chain.empty()) - // return chain; - - // return this->get_body_key_value(azurepccs::TCB_INFO_ISSUER_CHAIN); - return ""; } string get_tcbinfo() { - //return this->get_real_response_body(); + // return this->get_real_response_body(); return body_raw_; } }; @@ -134,12 +128,9 @@ class QeIdentityResponseObject : public PccsResponseObject { QeIdentityResponseObject() {} ~QeIdentityResponseObject() {} string get_enclave_id_issuer_chain() { - // string chain = this->get_header_key_value(intelpcs::ENCLAVE_ID_ISSUER_CHAIN); - // return chain.empty() ? this->get_body_key_value(azurepccs::ENCLAVE_ID_ISSUER_CHAIN) : chain; return this->get_header_key_value(intelpcs::ENCLAVE_ID_ISSUER_CHAIN); } string get_qeidentity() { - //return this->get_real_response_body(); return body_raw_; } }; @@ -150,12 +141,9 @@ class QveIdentityResponseObject : public PccsResponseObject { QveIdentityResponseObject() {} ~QveIdentityResponseObject() {} string get_enclave_id_issuer_chain() { - // string chain = this->get_header_key_value(intelpcs::ENCLAVE_ID_ISSUER_CHAIN); - // return chain.empty() ? this->get_body_key_value(azurepccs::ENCLAVE_ID_ISSUER_CHAIN) : chain; return this->get_header_key_value(intelpcs::ENCLAVE_ID_ISSUER_CHAIN); } string get_qveidentity() { - // return this->get_real_response_body(); return body_raw_; } }; diff --git a/QuoteGeneration/qcnl/inc/qcnl_config.h b/QuoteGeneration/qcnl/inc/qcnl_config.h index fcc3c629..cbef60b9 100644 --- a/QuoteGeneration/qcnl/inc/qcnl_config.h +++ b/QuoteGeneration/qcnl/inc/qcnl_config.h @@ -28,8 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -/** File: qcnl_config.h - * +/** File: qcnl_config.h + * * Description: Configurations for QCNL library * */ @@ -38,8 +38,8 @@ #pragma once #include "document.h" -#include #include +#include using namespace std; using namespace rapidjson; @@ -52,7 +52,7 @@ using namespace rapidjson; #include #endif -#define CACHE_MAX_EXPIRY_HOURS 2160 +#define CACHE_MAX_EXPIRY_HOURS 2160 // 90 days class QcnlConfig { protected: @@ -71,21 +71,22 @@ class QcnlConfig { // Local URL address string local_pck_url_; // Cache expire hours - uint32_t cache_expire_hour_; + double pck_cache_expire_hours_; + // Collateral expire hours + double verify_collateral_expire_hours_; // custom request options for Azure Document custom_request_options_; - QcnlConfig() : server_url_("https://localhost:8081/sgx/certification/v3/"), + QcnlConfig() : server_url_("https://localhost:8081/sgx/certification/v4/"), use_secure_cert_(true), collateral_service_url_(server_url_), collateral_version_("3.0"), retry_times_(0), retry_delay_(0), local_pck_url_(""), - cache_expire_hour_(0) {} - // To define the virtual destructor outside the class: - virtual ~QcnlConfig() { - }; + pck_cache_expire_hours_(0), + verify_collateral_expire_hours_(0) {} + virtual ~QcnlConfig(){}; public: QcnlConfig(QcnlConfig const &) = delete; @@ -124,8 +125,12 @@ class QcnlConfig { return local_pck_url_; } - uint32_t getCacheExpireHour() { - return cache_expire_hour_; + double getCacheExpireHour() { + return pck_cache_expire_hours_; + } + + double getVerifyCollateralExpireHour() { + return verify_collateral_expire_hours_; } Document &getCustomRequestOptions() { @@ -153,4 +158,4 @@ class QcnlConfigJson : public QcnlConfig { bool load_config(); }; -#endif //QCNLCONFIG_H_ \ No newline at end of file +#endif // QCNLCONFIG_H_ diff --git a/QuoteGeneration/qcnl/inc/qcnl_def.h b/QuoteGeneration/qcnl/inc/qcnl_def.h index 1f12093b..293adad5 100644 --- a/QuoteGeneration/qcnl/inc/qcnl_def.h +++ b/QuoteGeneration/qcnl/inc/qcnl_def.h @@ -53,6 +53,7 @@ constexpr char TCB_INFO_ISSUER_CHAIN[] = "tcb-info-issuer-chain"; constexpr char SGX_TCBM[] = "sgx-tcbm"; constexpr char ENCLAVE_ID_ISSUER_CHAIN[] = "sgx-enclave-identity-issuer-chain"; constexpr char REQUEST_ID[] = "request-id"; +constexpr char CACHE_CONTROL[] = "Cache-Control"; } // namespace intelpcs // Azure returns the headers in JSON format inside body, so they are case sensitive @@ -60,10 +61,6 @@ namespace azurepccs { constexpr char PCK_CERT[] = "pckCert"; constexpr char PCK_CERT_ISSUER_CHAIN[] = "sgx-Pck-Certificate-Issuer-Chain"; constexpr char SGX_TCBM[] = "sgx-Tcbm"; -// constexpr char CRL_ISSUER_CHAIN[] = "SGX-PCK-CRL-Issuer-Chain"; -// constexpr char SGX_TCB_INFO_ISSUER_CHAIN[] = "SGX-TCB-Info-Issuer-Chain"; -// constexpr char TCB_INFO_ISSUER_CHAIN[] = "TCB-Info-Issuer-Chain"; -// constexpr char ENCLAVE_ID_ISSUER_CHAIN[] = "SGX-Enclave-Identity-Issuer-Chain"; } // namespace azurepccs #endif \ No newline at end of file diff --git a/QuoteGeneration/qcnl/inc/qcnl_util.h b/QuoteGeneration/qcnl/inc/qcnl_util.h index c8d06f4e..26f7fb15 100644 --- a/QuoteGeneration/qcnl/inc/qcnl_util.h +++ b/QuoteGeneration/qcnl/inc/qcnl_util.h @@ -28,8 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -/** File: qcnl_util.h - * +/** File: qcnl_util.h + * * Description: Utility functions for QCNL * */ @@ -51,5 +51,6 @@ bool concat_string_with_hex_buf(string &url, const uint8_t *ba, const uint32_t b bool req_body_append_para(string &req_body, const string ¶_name, const uint8_t *para, const uint32_t para_size); void http_header_to_map(const char *resp_header, uint32_t header_size, unordered_map &header_map); bool is_collateral_service_pcs(); +string sha256(const void *data, size_t data_size); #endif \ No newline at end of file diff --git a/QuoteGeneration/qcnl/inc/qv_collateral_provider.h b/QuoteGeneration/qcnl/inc/qv_collateral_provider.h deleted file mode 100644 index ae381aea..00000000 --- a/QuoteGeneration/qcnl/inc/qv_collateral_provider.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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. - * - */ -/** File: qv_collateral_provider.h - * - * Description: Header file of QvCollateralProvider class - * - */ -#ifndef QVCOLLATERALPROVIDER_H_ -#define QVCOLLATERALPROVIDER_H_ -#pragma once - -#include "sgx_default_qcnl_wrapper.h" -#include -#include - -using namespace std; - -class QvCollateralProvider { -private: - string custom_param_; - - string get_custom_param_string(); - sgx_qcnl_error_t build_pck_crl_url(const char *ca, - string &url); - sgx_qcnl_error_t build_tcbinfo_url(sgx_prod_type_t prod_type, - const char *fmspc, - uint16_t fmspc_size, - string &url); - sgx_qcnl_error_t build_qeidentity_url(sgx_qe_type_t qe_type, string &url); - sgx_qcnl_error_t build_qveidentity_url(string &url); - sgx_qcnl_error_t build_root_ca_crl_url(const char *root_ca_cdp_url, string &url); -public: - QvCollateralProvider(); - QvCollateralProvider(const char* custom_param); - ~QvCollateralProvider(); - - sgx_qcnl_error_t get_pck_crl_chain(const char *ca, - uint16_t ca_size, - uint8_t **p_crl_chain, - uint16_t *p_crl_chain_size); - sgx_qcnl_error_t get_tcbinfo(sgx_prod_type_t prod_type, - const char *fmspc, - uint16_t fmspc_size, - uint8_t **p_tcbinfo, - uint16_t *p_tcbinfo_size); - sgx_qcnl_error_t get_qe_identity(sgx_qe_type_t qe_type, - uint8_t **p_qe_identity, - uint16_t *p_qe_identity_size); - sgx_qcnl_error_t get_qve_identity(char **pp_qve_identity, - uint32_t *p_qve_identity_size, - char **pp_qve_identity_issuer_chain, - uint32_t *p_qve_identity_issuer_chain_size); - sgx_qcnl_error_t get_root_ca_crl(const char *root_ca_cdp_url, - uint8_t **p_root_ca_crl, - uint16_t *p_root_ca_crl_size); -}; -#endif diff --git a/QuoteGeneration/qcnl/inc/sgx_default_qcnl_wrapper.h b/QuoteGeneration/qcnl/inc/sgx_default_qcnl_wrapper.h index f049d9c7..a4303cdf 100644 --- a/QuoteGeneration/qcnl/inc/sgx_default_qcnl_wrapper.h +++ b/QuoteGeneration/qcnl/inc/sgx_default_qcnl_wrapper.h @@ -28,8 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -/** File: sgx_default_qcnl_wrapper.h - * +/** File: sgx_default_qcnl_wrapper.h + * * Description: Definitions and prototypes for the PCK Collateral Network Library APIs * */ @@ -63,6 +63,9 @@ typedef enum _sgx_qcnl_error_t { SGX_QCNL_ERROR_STATUS_CERTS_UNAVAILABLE = SGX_QCNL_MK_ERROR(0x0012), ///< Certs not available SGX_QCNL_ERROR_STATUS_SERVICE_UNAVAILABLE = SGX_QCNL_MK_ERROR(0x0013), ///< Service is currently not available SGX_QCNL_INVALID_CONFIG = SGX_QCNL_MK_ERROR(0x0030), ///< Error in configuration file + SGX_QCNL_CACHE_MISSING = SGX_QCNL_MK_ERROR(0x0031), ///< Cache missing + SGX_QCNL_CACHE_EXPIRED = SGX_QCNL_MK_ERROR(0x0032), ///< Cache expired + SGX_QCNL_ROOT_CA_UNTRUSTED = SGX_QCNL_MK_ERROR(0x0033), ///< The certificate used to establish SSL session is untrusted } sgx_qcnl_error_t; typedef enum _sgx_qe_type_t { @@ -81,7 +84,7 @@ void sgx_qcnl_free_pck_cert_chain(sgx_ql_config_t *p_quote_config); sgx_qcnl_error_t sgx_qcnl_get_pck_crl_chain(const char *ca, uint16_t ca_size, - const char* custom_param_b64_string, + const char *custom_param_b64_string, uint8_t **p_crl_chain, uint16_t *p_crl_chain_size); @@ -89,7 +92,7 @@ void sgx_qcnl_free_pck_crl_chain(uint8_t *p_crl_chain); sgx_qcnl_error_t sgx_qcnl_get_tcbinfo(const char *fmspc, uint16_t fmspc_size, - const char* custom_param_b64_string, + const char *custom_param_b64_string, uint8_t **p_tcbinfo, uint16_t *p_tcbinfo_size); @@ -97,20 +100,20 @@ void sgx_qcnl_free_tcbinfo(uint8_t *p_tcbinfo); sgx_qcnl_error_t tdx_qcnl_get_tcbinfo(const char *fmspc, uint16_t fmspc_size, - const char* custom_param_b64_string, + const char *custom_param_b64_string, uint8_t **p_tcbinfo, uint16_t *p_tcbinfo_size); void tdx_qcnl_free_tcbinfo(uint8_t *p_tcbinfo); sgx_qcnl_error_t sgx_qcnl_get_qe_identity(sgx_qe_type_t qe_type, - const char* custom_param_b64_string, + const char *custom_param_b64_string, uint8_t **p_qe_identity, uint16_t *p_qe_identity_size); void sgx_qcnl_free_qe_identity(uint8_t *p_qe_identity); -sgx_qcnl_error_t sgx_qcnl_get_qve_identity(const char* custom_param_b64_string, +sgx_qcnl_error_t sgx_qcnl_get_qve_identity(const char *custom_param_b64_string, char **pp_qve_identity, uint32_t *p_qve_identity_size, char **pp_qve_identity_issuer_chain, @@ -119,7 +122,7 @@ sgx_qcnl_error_t sgx_qcnl_get_qve_identity(const char* custom_param_b64_string, void sgx_qcnl_free_qve_identity(char *p_qve_identity, char *p_qve_identity_issuer_chain); sgx_qcnl_error_t sgx_qcnl_get_root_ca_crl(const char *root_ca_cdp_url, - const char* custom_param_b64_string, + const char *custom_param_b64_string, uint8_t **p_root_ca_crl, uint16_t *p_root_ca_crl_size); @@ -127,7 +130,7 @@ void sgx_qcnl_free_root_ca_crl(uint8_t *p_root_ca_crl); bool sgx_qcnl_get_api_version(uint16_t *p_major_ver, uint16_t *p_minor_ver); -sgx_qcnl_error_t sgx_qcnl_set_logging_callback(sgx_ql_logging_callback_t logger); +sgx_qcnl_error_t sgx_qcnl_set_logging_callback(sgx_ql_logging_callback_t logger, sgx_ql_log_level_t loglevel = SGX_QL_LOG_ERROR); void qcnl_log(sgx_ql_log_level_t level, const char *fmt, ...); diff --git a/QuoteGeneration/qcnl/linux/Makefile b/QuoteGeneration/qcnl/linux/Makefile index cb81e23d..3f8df1a8 100644 --- a/QuoteGeneration/qcnl/linux/Makefile +++ b/QuoteGeneration/qcnl/linux/Makefile @@ -32,6 +32,7 @@ ######## SGX SDK Settings ######## TOP_DIR = ../.. include $(TOP_DIR)/buildenv.mk +PREBUILD_OPENSSL_PATH = ../../../prebuilt/openssl ######## SGX CNL Library Settings ######## @@ -42,7 +43,8 @@ CNL_Lib_Include_Paths := -I../../quote_wrapper/common/inc \ -I../inc -I$(SGX_SDK)/include \ -I../../common/inc/internal \ -I../../pce_wrapper/inc \ - -I../../../QuoteVerification/QVL/Src/ThirdParty/rapidjson/include/rapidjson + -I../../../QuoteVerification/QVL/Src/ThirdParty/rapidjson/include/rapidjson \ + -I$(PREBUILD_OPENSSL_PATH)/inc CNL_Lib_C_Flags := $(COMMON_FLAGS) -g -fPIC -Wno-attributes $(CNL_Lib_Include_Paths) @@ -55,7 +57,8 @@ ifdef SELF_SIGNED_CERT CNL_Lib_Cpp_Flags+= -DSELF_SIGNED_CERT endif -CNL_Lib_Link_Flags := $(SGX_COMMON_FLAGS) -g -L$(TOP_DIR)/build/linux -L$(SGX_SDK)/lib64 -lpthread -ldl -lcurl +CNL_Lib_Link_Flags := $(SGX_COMMON_FLAGS) -g -L$(TOP_DIR)/build/linux -L$(SGX_SDK)/lib64 -L$(PREBUILD_OPENSSL_PATH)/lib/linux64 \ + -lpthread -ldl -lcurl ifndef DEBUG CNL_Lib_Cpp_Flags += -DDISABLE_TRACE diff --git a/QuoteGeneration/qcnl/linux/network_wrapper.cpp b/QuoteGeneration/qcnl/linux/network_wrapper.cpp index 5c8ea1f7..0b1ca990 100644 --- a/QuoteGeneration/qcnl/linux/network_wrapper.cpp +++ b/QuoteGeneration/qcnl/linux/network_wrapper.cpp @@ -97,12 +97,22 @@ static sgx_qcnl_error_t curl_error_to_qcnl_error(CURLcode curl_error) { case CURLE_UNKNOWN_OPTION: return SGX_QCNL_NETWORK_UNKNOWN_OPTION; case CURLE_PEER_FAILED_VERIFICATION: - return SGX_QCNL_NETWORK_HTTPS_ERROR; + return SGX_QCNL_ROOT_CA_UNTRUSTED; default: return SGX_QCNL_NETWORK_ERROR; } } +template +static CURLcode curl_set_opt_with_log(CURL *handle, CURLoption option, T param) { + CURLcode result = curl_easy_setopt(handle, option, param); + if (result != CURLE_OK) { + auto optionStr = std::to_string(option); + qcnl_log(SGX_QL_LOG_ERROR, "curl_easy_setopt(%s) returned %d.", optionStr.c_str(), result); + } + return result; +} + /** * This method converts PCCS HTTP status codes to QCNL error codes * @@ -161,12 +171,14 @@ sgx_qcnl_error_t qcnl_https_request(const char *url, network_malloc_info_t res_body = {0, 0}; struct curl_slist *headers = NULL; + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Request URL %s \n", url); + do { curl = curl_easy_init(); if (!curl) break; - if (curl_easy_setopt(curl, CURLOPT_URL, url) != CURLE_OK) + if (curl_set_opt_with_log(curl, CURLOPT_URL, url) != CURLE_OK) break; // append user token @@ -191,42 +203,42 @@ sgx_qcnl_error_t qcnl_https_request(const char *url, } // set header - if (curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers) != CURLE_OK) + if (curl_set_opt_with_log(curl, CURLOPT_HTTPHEADER, headers) != CURLE_OK) break; if (req_body && req_body_size > 0) { // using CURLOPT_POSTFIELDS implies setting CURLOPT_POST to 1. - if (curl_easy_setopt(curl, CURLOPT_POST, 1) != CURLE_OK) + if (curl_set_opt_with_log(curl, CURLOPT_POST, 1) != CURLE_OK) break; // size of the POST data - if (curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)req_body_size) != CURLE_OK) + if (curl_set_opt_with_log(curl, CURLOPT_POSTFIELDSIZE, (long)req_body_size) != CURLE_OK) break; // pass in a pointer to the data - libcurl will not copy - if (curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req_body) != CURLE_OK) + if (curl_set_opt_with_log(curl, CURLOPT_POSTFIELDS, req_body) != CURLE_OK) break; } if (!QcnlConfig::Instance()->is_server_secure()) { // if not set this option, the below error code will be returned for self signed cert // CURLE_SSL_CACERT (60) Peer certificate cannot be authenticated with known CA certificates. - if (curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L) != CURLE_OK) + if (curl_set_opt_with_log(curl, CURLOPT_SSL_VERIFYPEER, 0L) != CURLE_OK) break; // if not set this option, the below error code will be returned for self signed cert // // CURLE_PEER_FAILED_VERIFICATION (51) The remote server's SSL certificate or SSH md5 fingerprint was deemed not OK. - if (curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L) != CURLE_OK) + if (curl_set_opt_with_log(curl, CURLOPT_SSL_VERIFYHOST, 0L) != CURLE_OK) break; } // Set write callback functions - if (curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback) != CURLE_OK) + if (curl_set_opt_with_log(curl, CURLOPT_WRITEFUNCTION, write_callback) != CURLE_OK) break; - if (curl_easy_setopt(curl, CURLOPT_WRITEDATA, reinterpret_cast(&res_body)) != CURLE_OK) + if (curl_set_opt_with_log(curl, CURLOPT_WRITEDATA, reinterpret_cast(&res_body)) != CURLE_OK) break; // Set header callback functions - if (curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_callback) != CURLE_OK) + if (curl_set_opt_with_log(curl, CURLOPT_HEADERFUNCTION, write_callback) != CURLE_OK) break; - if (curl_easy_setopt(curl, CURLOPT_HEADERDATA, reinterpret_cast(&res_header)) != CURLE_OK) + if (curl_set_opt_with_log(curl, CURLOPT_HEADERDATA, reinterpret_cast(&res_header)) != CURLE_OK) break; uint32_t retry_times = QcnlConfig::Instance()->getRetryTimes() + 1; @@ -260,9 +272,11 @@ sgx_qcnl_error_t qcnl_https_request(const char *url, } continue; } else { - if (curl_ret != CURLE_OK) + if (curl_ret != CURLE_OK) { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Encountered CURL error: (%d) %s \n", + curl_ret, curl_easy_strerror(curl_ret)); ret = curl_error_to_qcnl_error(curl_ret); - else + } else ret = pccs_status_to_qcnl_error(http_code); goto cleanup; } diff --git a/QuoteGeneration/qcnl/linux/qcnl_config_impl.cpp b/QuoteGeneration/qcnl/linux/qcnl_config_impl.cpp index 60949252..61e6a74f 100644 --- a/QuoteGeneration/qcnl/linux/qcnl_config_impl.cpp +++ b/QuoteGeneration/qcnl/linux/qcnl_config_impl.cpp @@ -29,8 +29,8 @@ * */ /** - * File: qcnl_config.cpp - * + * File: qcnl_config_impl.cpp + * * Description: Read configuration data * */ @@ -43,6 +43,7 @@ static struct init_solib { init_solib() { + // put global initialization logic here curl_global_init(CURL_GLOBAL_DEFAULT); } } _init_solib; @@ -90,9 +91,18 @@ bool QcnlConfigLegacy::load_config() { } else if (name.compare("PCK_CACHE_EXPIRE_HOURS") == 0) { try { string::size_type sz; - cache_expire_hour_ = stoi(value, &sz); - if (cache_expire_hour_ > CACHE_MAX_EXPIRY_HOURS) - cache_expire_hour_ = CACHE_MAX_EXPIRY_HOURS; + pck_cache_expire_hours_ = (double)stoi(value, &sz); + if (pck_cache_expire_hours_ > CACHE_MAX_EXPIRY_HOURS) + pck_cache_expire_hours_ = CACHE_MAX_EXPIRY_HOURS; + } catch (const invalid_argument &) { + continue; + } + } else if (name.compare("VERIFY_COLLATERAL_CACHE_EXPIRE_HOURS") == 0) { + try { + string::size_type sz; + verify_collateral_expire_hours_ = (double)stoi(value, &sz); + if (verify_collateral_expire_hours_ > CACHE_MAX_EXPIRY_HOURS) + verify_collateral_expire_hours_ = CACHE_MAX_EXPIRY_HOURS; } catch (const invalid_argument &) { continue; } diff --git a/QuoteGeneration/qcnl/linux/sgx_default_qcnl.conf b/QuoteGeneration/qcnl/linux/sgx_default_qcnl.conf index c8a494ac..72b2f62e 100644 --- a/QuoteGeneration/qcnl/linux/sgx_default_qcnl.conf +++ b/QuoteGeneration/qcnl/linux/sgx_default_qcnl.conf @@ -2,7 +2,7 @@ // *** ATTENTION : This file is in JSON format so the keys are case sensitive. Don't change them. //PCCS server address - "pccs_url": "https://localhost:8081/sgx/certification/v3/", + "pccs_url": "https://localhost:8081/sgx/certification/v4/", // To accept insecure HTTPS certificate, set this option to false "use_secure_cert": true, @@ -10,7 +10,7 @@ // You can use the Intel PCS or another PCCS to get quote verification collateral. Retrieval of PCK // Certificates will always use the PCCS described in PCCS_URL. When COLLATERAL_SERVICE is not defined, both // PCK Certs and verification collateral will be retrieved using PCCS_URL - //"collateral_service": "https://api.trustedservices.intel.com/sgx/certification/v3/", + //"collateral_service": "https://api.trustedservices.intel.com/sgx/certification/v4/", // If you use a PCCS service to get the quote verification collateral, you can specify which PCCS API version is to be used. // The legacy 3.0 API will return CRLs in HEX encoded DER format and the sgx_ql_qve_collateral_t.version will be set to 3.0, while @@ -30,11 +30,14 @@ // If LOCAL_PCK_URL is defined, the QCNL will try to retrieve PCK cert chain from LOCAL_PCK_URL first, // and failover to PCCS_URL as in legacy mode. - //"local_pck_url": "http://localhost:8081/sgx/certification/v3/", + //"local_pck_url": "http://localhost:8081/sgx/certification/v4/", // If LOCAL_PCK_URL is not defined, the QCNL will cache PCK certificates in memory by default. // The cached PCK certificates will expire after PCK_CACHE_EXPIRE_HOURS hours. - "pck_cache_expire_hours": 168 + "pck_cache_expire_hours": 168, + + // To set cache expire time for quote verification collateral in hours + "verify_collateral_cache_expire_hours": 168 // You can add custom request headers and parameters to the get certificate API. // But the default PCCS implementation just ignores them. diff --git a/QuoteGeneration/qcnl/linux/sgx_default_qcnl_azure.conf b/QuoteGeneration/qcnl/linux/sgx_default_qcnl_azure.conf index e7bcb4db..0babd705 100644 --- a/QuoteGeneration/qcnl/linux/sgx_default_qcnl_azure.conf +++ b/QuoteGeneration/qcnl/linux/sgx_default_qcnl_azure.conf @@ -3,11 +3,11 @@ // This is a typical config file when used in Microsoft Azure environment - "pccs_url": " https://global.acccache.azure.net/sgx/certification/v3/", + "pccs_url": "https://global.acccache.azure.net/sgx/certification/v4/", "use_secure_cert": true, - "collateral_service": https://api.trustedservices.intel.com/sgx/certification/v3/, + "collateral_service": "https://api.trustedservices.intel.com/sgx/certification/v4/", "pccs_api_version": "3.1", @@ -15,10 +15,12 @@ "retry_delay": 5, - "local_pck_url": http://169.254.169.254/metadata/THIM/sgx/certification/v3/, + "local_pck_url": "http://10.0.0.100/metadata/THIM/sgx/certification/v4/", "pck_cache_expire_hours": 48, + "verify_collateral_cache_expire_hours": 48, + "custom_request_options" : { "get_cert" : { "headers": { diff --git a/QuoteGeneration/qcnl/linux/sgx_default_qcnl_dev.conf b/QuoteGeneration/qcnl/linux/sgx_default_qcnl_dev.conf index 7ee019ff..08ee41ce 100644 --- a/QuoteGeneration/qcnl/linux/sgx_default_qcnl_dev.conf +++ b/QuoteGeneration/qcnl/linux/sgx_default_qcnl_dev.conf @@ -8,7 +8,7 @@ // It is recommended to use "3.1" for DCAP 1.12 release and later //PCCS server address - "pccs_url": "https://localhost:8081/sgx/certification/v3/", + "pccs_url": "https://localhost:8081/sgx/certification/v4/", // To accept insecure HTTPS certificate, set this option to false "use_secure_cert": false, diff --git a/QuoteGeneration/qcnl/linux/sgx_default_qcnl_intelpcs.conf b/QuoteGeneration/qcnl/linux/sgx_default_qcnl_intelpcs.conf index c093f7f8..ec170e7f 100644 --- a/QuoteGeneration/qcnl/linux/sgx_default_qcnl_intelpcs.conf +++ b/QuoteGeneration/qcnl/linux/sgx_default_qcnl_intelpcs.conf @@ -5,12 +5,12 @@ // but retrieves quote verificay collateral from Intel PCS //PCCS server address - "pccs_url": "https://192.168.1.100:8081/sgx/certification/v3/", + "pccs_url": "https://192.168.1.100:8081/sgx/certification/v4/", // To accept insecure HTTPS certificate, set this option to false "use_secure_cert": true, - "collateral_service": "https://api.trustedservices.intel.com/sgx/certification/v3/" + "collateral_service": "https://api.trustedservices.intel.com/sgx/certification/v4/" "retry_times": 6, diff --git a/QuoteGeneration/qcnl/pccs_response_object.cpp b/QuoteGeneration/qcnl/pccs_response_object.cpp index 054aedb4..c0ab9518 100644 --- a/QuoteGeneration/qcnl/pccs_response_object.cpp +++ b/QuoteGeneration/qcnl/pccs_response_object.cpp @@ -29,14 +29,15 @@ * */ /** - * File: pccs_response_object.cpp - * + * File: pccs_response_object.cpp + * * Description: Object class to save PCCS/PCS response message * */ #include "pccs_response_object.h" #include "qcnl_def.h" #include "qcnl_util.h" +#include "sgx_default_qcnl_wrapper.h" PccsResponseObject::PccsResponseObject() : is_body_json_(false) { } @@ -68,8 +69,12 @@ PccsResponseObject &PccsResponseObject::set_raw_body(const char *body, uint32_t return *this; } +string &PccsResponseObject::get_raw_header() { + return this->header_raw_; +} + string &PccsResponseObject::get_raw_body() { - return body_raw_; + return this->body_raw_; } string PccsResponseObject::get_header_key_value(const char *key) { @@ -78,6 +83,7 @@ string PccsResponseObject::get_header_key_value(const char *key) { if (it != header_map_.end()) { return it->second; } else { + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Header '%s' not found. \n", key); return ""; } } @@ -88,6 +94,7 @@ string PccsResponseObject::get_body_key_value(const char *key) { if (val.IsString()) { return val.GetString(); } else { + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Body '%s' is not string. \n", key); return ""; } @@ -100,5 +107,27 @@ string PccsResponseObject::get_real_response_body(const char *key) { string body = get_body_key_value(key); if (body.empty()) return body_raw_; - else return body; + else + return body; +} + +uint32_t PccsResponseObject::get_cache_max_age() { + stringstream ss(this->get_header_key_value(intelpcs::CACHE_CONTROL)); + string directive; + while (std::getline(ss, directive, ',')) { + std::size_t pos = directive.find("max-age="); + if (pos != std::string::npos) { + string value = directive.substr(pos + 8); + try { + string::size_type sz; + return stoi(value, &sz); + } catch (const invalid_argument &) { + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Failed to parse Cache-Control: max-age. \n"); + return 0; + } + } else { + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Cache-Control: max-age not found in header. \n"); + } + } + return 0; } diff --git a/QuoteGeneration/qcnl/pckcert_provider.cpp b/QuoteGeneration/qcnl/pckcert_provider.cpp deleted file mode 100644 index 3aad4693..00000000 --- a/QuoteGeneration/qcnl/pckcert_provider.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - * 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. - * - */ -/** - * File: pckcert_provider.cpp - * - * Description: PCK certificates provider - * - */ -#include "pckcert_provider.h" -#include "local_cache.h" -#include "network_wrapper.h" -#include "pccs_response_object.h" - -PckCertProvider::PckCertProvider() { -} - -PckCertProvider::~PckCertProvider() { -} - -sgx_qcnl_error_t PckCertProvider::build_pckcert_url(const string &base_url, - const sgx_ql_pck_cert_id_t *p_pck_cert_id, - string &url) { - sgx_qcnl_error_t ret = SGX_QCNL_UNEXPECTED_ERROR; - - url = base_url; - - // Append QE ID - url.append("pckcert?qeid="); - if (!concat_string_with_hex_buf(url, p_pck_cert_id->p_qe3_id, p_pck_cert_id->qe3_id_size)) { - return ret; - } - - // Append encrypted PPID - url.append("&encrypted_ppid="); - if (p_pck_cert_id->p_encrypted_ppid == NULL) { - uint8_t enc_ppid_unused[consts::ENC_PPID_SIZE] = {0}; - if (!concat_string_with_hex_buf(url, (const uint8_t *)&enc_ppid_unused, sizeof(enc_ppid_unused))) { - return ret; - } - } else { - if (!concat_string_with_hex_buf(url, p_pck_cert_id->p_encrypted_ppid, p_pck_cert_id->encrypted_ppid_size)) { - return ret; - } - } - - // Append cpusvn - url.append("&cpusvn="); - if (!concat_string_with_hex_buf(url, reinterpret_cast(p_pck_cert_id->p_platform_cpu_svn), sizeof(sgx_cpu_svn_t))) { - return ret; - } - - // Append pcesvn - url.append("&pcesvn="); - if (!concat_string_with_hex_buf(url, reinterpret_cast(p_pck_cert_id->p_platform_pce_isv_svn), sizeof(sgx_isv_svn_t))) { - return ret; - } - - // Append pceid - url.append("&pceid="); - if (!concat_string_with_hex_buf(url, reinterpret_cast(&p_pck_cert_id->pce_id), sizeof(p_pck_cert_id->pce_id))) { - return ret; - } - - // Custom request parameters - Document &custom_options = QcnlConfig::Instance()->getCustomRequestOptions(); - if (!custom_options.IsNull() && custom_options.HasMember("get_cert") && custom_options["get_cert"].IsObject()) { - if (custom_options["get_cert"].HasMember("params")) { - Value ¶ms = custom_options["get_cert"]["params"]; - if (params.IsObject()) { - Value::ConstMemberIterator it = params.MemberBegin(); - while (it != params.MemberEnd()) { - if (it->value.IsString()) { - string key = it->name.GetString(); - string value = it->value.GetString(); - url.append("&").append(key).append("=").append(value); - } - it++; - } - } - } - } - - qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Request URL %s \n", url.c_str()); - - return SGX_QCNL_SUCCESS; -} - -sgx_qcnl_error_t PckCertProvider::get_pck_cert_chain_from_url(const string &pck_url, - const sgx_ql_pck_cert_id_t *p_pck_cert_id, - sgx_ql_config_t **pp_quote_config) { - string url(""); - char *resp_msg = NULL; - uint32_t resp_size = 0; - char *resp_header = NULL; - uint32_t header_size = 0; - sgx_qcnl_error_t ret = SGX_QCNL_UNEXPECTED_ERROR; - map header_map; - - // initialize https request url - ret = build_pckcert_url(pck_url, p_pck_cert_id, url); - if (ret != SGX_QCNL_SUCCESS) { - return ret; - } - - // Custom request headers - Document &custom_options = QcnlConfig::Instance()->getCustomRequestOptions(); - if (!custom_options.IsNull() && custom_options.HasMember("get_cert") && custom_options["get_cert"].IsObject()) { - if (custom_options["get_cert"].HasMember("headers")) { - Value &headers = custom_options["get_cert"]["headers"]; - if (headers.IsObject()) { - Value::ConstMemberIterator it = headers.MemberBegin(); - while (it != headers.MemberEnd()) { - if (it->value.IsString()) { - string key = it->name.GetString(); - string value = it->value.GetString(); - header_map.insert(pair(key, value)); - } - it++; - } - } - } - } - - ret = qcnl_https_request(url.c_str(), header_map, NULL, 0, NULL, 0, &resp_msg, resp_size, &resp_header, header_size); - if (ret != SGX_QCNL_SUCCESS) { - return ret; - } - - PckCertResponseObject pckcert_resp_obj; - pckcert_resp_obj.set_raw_header(resp_header, header_size).set_raw_body(resp_msg, resp_size); - - do { - // Get TCBm , Issuer Chain, PCK certificate from response - string tcbm = pckcert_resp_obj.get_tcbm(); - string certchain = pckcert_resp_obj.get_pckcert_issuer_chain(); - string pck_cert = pckcert_resp_obj.get_pckcert(); - if (tcbm.size() != (consts::CPUSVN_SIZE + consts::PCESVN_SIZE) * 2 || certchain.empty() || pck_cert.empty()) { - ret = SGX_QCNL_MSG_ERROR; - break; - } - - certchain = unescape(certchain); - - // allocate output buffer - *pp_quote_config = (sgx_ql_config_t *)malloc(sizeof(sgx_ql_config_t)); - if (*pp_quote_config == NULL) { - ret = SGX_QCNL_OUT_OF_MEMORY; - break; - } - memset(*pp_quote_config, 0, sizeof(sgx_ql_config_t)); - - // set version - (*pp_quote_config)->version = SGX_QL_CONFIG_VERSION_1; - - // set tcbm - if (!hex_string_to_byte_array(reinterpret_cast(tcbm.data()), - consts::CPUSVN_SIZE * 2, - reinterpret_cast(&(*pp_quote_config)->cert_cpu_svn), - sizeof(sgx_cpu_svn_t))) { - ret = SGX_QCNL_MSG_ERROR; - break; - } - if (!hex_string_to_byte_array(reinterpret_cast(tcbm.data() + consts::CPUSVN_SIZE * 2), - consts::PCESVN_SIZE * 2, - reinterpret_cast(&(*pp_quote_config)->cert_pce_isv_svn), - sizeof(sgx_isv_svn_t))) { - ret = SGX_QCNL_MSG_ERROR; - break; - } - - // set certchain (leaf cert || intermediateCA || root CA) - (*pp_quote_config)->cert_data_size = (uint32_t)(certchain.size() + pck_cert.size()); - (*pp_quote_config)->p_cert_data = (uint8_t *)malloc((*pp_quote_config)->cert_data_size); - if (!(*pp_quote_config)->p_cert_data) { - ret = SGX_QCNL_OUT_OF_MEMORY; - break; - } - if (memcpy_s((*pp_quote_config)->p_cert_data, (*pp_quote_config)->cert_data_size, pck_cert.data(), pck_cert.size()) != 0) { - ret = SGX_QCNL_UNEXPECTED_ERROR; - break; - } - if (memcpy_s((*pp_quote_config)->p_cert_data + pck_cert.size(), certchain.size(), certchain.data(), certchain.size()) != 0) { - ret = SGX_QCNL_UNEXPECTED_ERROR; - break; - } - - ret = SGX_QCNL_SUCCESS; - } while (0); - - if (ret != SGX_QCNL_SUCCESS) { - sgx_qcnl_free_pck_cert_chain(*pp_quote_config); - } - if (resp_msg) { - free(resp_msg); - resp_msg = NULL; - } - if (resp_header) { - free(resp_header); - resp_header = NULL; - } - - return ret; -} - -sgx_qcnl_error_t PckCertProvider::get_pck_cert_chain(const sgx_ql_pck_cert_id_t *p_pck_cert_id, - sgx_ql_config_t **pp_quote_config) { - sgx_qcnl_error_t ret = SGX_QCNL_ERROR_STATUS_UNEXPECTED; - - if (!QcnlConfig::Instance()->getLocalPckUrl().empty()) { - qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Try local service... \n"); - // Will get PCK certificates from LOCAL_PCK_URL - ret = this->get_pck_cert_chain_from_url(QcnlConfig::Instance()->getLocalPckUrl(), - p_pck_cert_id, pp_quote_config); - if (ret == SGX_QCNL_SUCCESS) - return ret; - - qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Failed to retrieve PCK certchain from local PCK service. \n"); - } - - // try memory cache next - if (QcnlConfig::Instance()->getCacheExpireHour() > 0) { - qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Try memory cache... \n"); - if (LocalMemCache::Instance().get_pck_cert_chain(p_pck_cert_id, pp_quote_config)) { - qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Retrieved PCK certchain from memory cache successfully. \n"); - return SGX_QCNL_SUCCESS; - } - } - - // Failover to remote service - if (!QcnlConfig::Instance()->getServerUrl().empty()) { - qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Try remote service... \n"); - // Try to fetch PCK certificates from PCCS - ret = this->get_pck_cert_chain_from_url(QcnlConfig::Instance()->getServerUrl(), - p_pck_cert_id, pp_quote_config); - if (ret == SGX_QCNL_SUCCESS && QcnlConfig::Instance()->getCacheExpireHour() > 0) { - // Update local cache - LocalMemCache::Instance().set_pck_cert_chain(p_pck_cert_id, pp_quote_config); - } - } - - return ret; -} diff --git a/QuoteGeneration/qcnl/qcnl_config.cpp b/QuoteGeneration/qcnl/qcnl_config.cpp index ee2a055b..501d6b7c 100644 --- a/QuoteGeneration/qcnl/qcnl_config.cpp +++ b/QuoteGeneration/qcnl/qcnl_config.cpp @@ -29,22 +29,29 @@ * */ /** - * File: qcnl_config.cpp - * + * File: qcnl_config.cpp + * * Description: Read configuration data * */ #include "qcnl_config.h" +#include "error/en.h" +#include "error/error.h" #include "sgx_default_qcnl_wrapper.h" #include #include +#include using namespace std; std::shared_ptr QcnlConfig::myInstance; +static std::mutex mutex_config_lock; std::shared_ptr QcnlConfig::Instance() { + // Lock the mutex + std::lock_guard lock(mutex_config_lock); + if (!myInstance) { QcnlConfigJson *pConfigJson = new QcnlConfigJson(); if (pConfigJson->load_config()) { @@ -69,11 +76,18 @@ bool QcnlConfig::load_config_json(const TCHAR *json_file) { ParseResult ok = config.ParseStream(isw); if (!ok) { - qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Failed to load config file in JSON. Either the legacy format config file is used, \n"); - qcnl_log(SGX_QL_LOG_INFO, " or there is something wrong with it (should be JSON format). \n"); + // If the config file starts with '{', it's likely JSON format + char first_byte = 0; + ifs.clear(); + ifs.seekg(0, ifs.beg); + if (ifs.get(first_byte) && first_byte == '{') { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Load JSON config error: %s (offset %u).\n", + GetParseError_En(ok.Code()), ok.Offset()); + } else { + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Failed to load config file in JSON format. \n"); + } return false; - } - else { + } else { qcnl_log(SGX_QL_LOG_INFO, "[QCNL] JSON config file %s is loaded successfully. \n", json_file); } @@ -129,10 +143,19 @@ bool QcnlConfig::load_config_json(const TCHAR *json_file) { if (config.HasMember("pck_cache_expire_hours")) { Value &val = config["pck_cache_expire_hours"]; - if (val.IsInt()) { - this->cache_expire_hour_ = val.GetInt(); - if (this->cache_expire_hour_ > CACHE_MAX_EXPIRY_HOURS) - this->cache_expire_hour_ = CACHE_MAX_EXPIRY_HOURS; + if (val.IsDouble() || val.IsInt()) { + this->pck_cache_expire_hours_ = val.GetDouble(); + if (this->pck_cache_expire_hours_ > CACHE_MAX_EXPIRY_HOURS) + this->pck_cache_expire_hours_ = CACHE_MAX_EXPIRY_HOURS; + } + } + + if (config.HasMember("verify_collateral_cache_expire_hours")) { + Value &val = config["verify_collateral_cache_expire_hours"]; + if (val.IsDouble() || val.IsInt()) { + this->verify_collateral_expire_hours_ = val.GetDouble(); + if (this->verify_collateral_expire_hours_ > CACHE_MAX_EXPIRY_HOURS) + this->verify_collateral_expire_hours_ = CACHE_MAX_EXPIRY_HOURS; } } diff --git a/QuoteGeneration/qcnl/qcnl_util.cpp b/QuoteGeneration/qcnl/qcnl_util.cpp index 43fb8c35..a231973c 100644 --- a/QuoteGeneration/qcnl/qcnl_util.cpp +++ b/QuoteGeneration/qcnl/qcnl_util.cpp @@ -29,7 +29,7 @@ * */ /** File: qcnl_util.cpp - * + * * Description: Utility functions for QCNL * */ @@ -37,20 +37,25 @@ #include "qcnl_util.h" #include "qcnl_config.h" #include - -#ifdef _MSC_VER +#ifndef _MSC_VER +#include +#else +#include +#include #define sscanf sscanf_s +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L) #endif /** -* Method converts char containing ASCII code into its corresponding value, -* e.g. converts '0' to 0x00, 'A' to 0x0A. -* -* @param in char containing ASCII code (allowed values: '0-9', 'a-f', 'A-F') -* @param val output parameter containing converted value, if method succeeds. -* -* @return true if conversion succeeds, false otherwise -*/ + * Method converts char containing ASCII code into its corresponding value, + * e.g. converts '0' to 0x00, 'A' to 0x0A. + * + * @param in char containing ASCII code (allowed values: '0-9', 'a-f', 'A-F') + * @param val output parameter containing converted value, if method succeeds. + * + * @return true if conversion succeeds, false otherwise + */ bool convert_ascii_to_value(uint8_t in, uint8_t &val) { if (in >= '0' && in <= '9') { val = static_cast(in - '0'); @@ -66,14 +71,14 @@ bool convert_ascii_to_value(uint8_t in, uint8_t &val) { } /** -* Method converts byte containing value from 0x00-0x0F into its corresponding ASCII code, -* e.g. converts 0x00 to '0', 0x0A to 'A'. -* Note: This is mainly a helper method for internal use in byte_array_to_hex_string(). -* -* @param in byte to be converted (allowed values: 0x00-0x0F) -* -* @return ASCII code representation of the byte or 0 if method failed (e.g input value was not in provided range). -*/ + * Method converts byte containing value from 0x00-0x0F into its corresponding ASCII code, + * e.g. converts 0x00 to '0', 0x0A to 'A'. + * Note: This is mainly a helper method for internal use in byte_array_to_hex_string(). + * + * @param in byte to be converted (allowed values: 0x00-0x0F) + * + * @return ASCII code representation of the byte or 0 if method failed (e.g input value was not in provided range). + */ uint8_t convert_value_to_ascii(uint8_t in) { if (in <= 0x09) { return (uint8_t)(in + '0'); @@ -84,11 +89,14 @@ uint8_t convert_value_to_ascii(uint8_t in) { return 0; } -//Function to do HEX decoding -//@param in_buf, character strings which are HEX encoding of a byte array -// out_buf, output the decode byte array on success -//@return true on success and false on error -//The in_size must be even number and equals 2*out_size +/** + * Function to do HEX decoding. The in_size must be even number and equals 2*out_size + * @param in_buf character strings which are HEX encoding of a byte array + * @param in_size Size of input buffer + * @param out_buf output the decode byte array on success + * @param out_size Size of output buffer + * @return true on success and false on error + */ bool hex_string_to_byte_array(const uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size) { if (out_size > UINT32_MAX / 2) return false; @@ -106,11 +114,14 @@ bool hex_string_to_byte_array(const uint8_t *in_buf, uint32_t in_size, uint8_t * return true; } -//Function to do HEX encoding of array of bytes -//@param in_buf, bytes array whose length is in_size -// out_buf, output the HEX encoding of in_buf on success. -//@return true on success and false on error -//The out_size must always be 2*in_size since each byte into encoded by 2 characters +/** + * Function to do HEX encoding of array of bytes. The out_size must always be 2*in_size since each byte into encoded by 2 characters + * @param in_buf bytes array whose length is in_size + * @param in_size Size of input buffer + * @param out_buf output the HEX encoding of in_buf on success. + * @param out_size Size of output buffer + * @return true on success and false on error + */ bool byte_array_to_hex_string(const uint8_t *in_buf, uint32_t in_size, uint8_t *out_buf, uint32_t out_size) { if (in_size > UINT32_MAX / 2) return false; @@ -148,14 +159,14 @@ string unescape(string &src) { } /** -* This function appends request parameters of byte array type to the URL in HEX string format -* -* @param url Request URL -* @param ba Request parameter in byte array -* @param ba_size Size of byte array -* -* @return true If the byte array was appended to the URL successfully -*/ + * This function appends request parameters of byte array type to the URL in HEX string format + * + * @param url Request URL + * @param ba Request parameter in byte array + * @param ba_size Size of byte array + * + * @return true If the byte array was appended to the URL successfully + */ bool concat_string_with_hex_buf(string &url, const uint8_t *ba, const uint32_t ba_size) { if (ba_size >= UINT32_MAX / 2) return false; @@ -173,15 +184,15 @@ bool concat_string_with_hex_buf(string &url, const uint8_t *ba, const uint32_t b } /** -* This function appends appends request parameters of byte array type to the JSON request body in HEX string format -* -* @param req_body Request body in JSON string format -* @param para_name The name of the Request parameter as JSON key -* @param para The Request parameter in byte array which will be converted into HEX string as JSON value -* @param para_size Size of para in byte array -* -* @return true If the byte array was appended to the Request body successfully -*/ + * This function appends appends request parameters of byte array type to the JSON request body in HEX string format + * + * @param req_body Request body in JSON string format + * @param para_name The name of the Request parameter as JSON key + * @param para The Request parameter in byte array which will be converted into HEX string as JSON value + * @param para_size Size of para in byte array + * + * @return true If the byte array was appended to the Request body successfully + */ bool req_body_append_para(string &req_body, const string ¶_name, const uint8_t *para, const uint32_t para_size) { if (para_size >= UINT32_MAX / 2) return false; @@ -202,16 +213,19 @@ bool req_body_append_para(string &req_body, const string ¶_name, const uint8 return true; } -// Convert http header string to a map -// HTTP 1.1 header specification -// message-header = field-name ":" [ field-value ] -// field-name = token -// field-value = *( field-content | LWS ) -// field-content = -//@param resp_header, http header string -// header_map, a map that stores fields and values +/** + * Convert http header string to a map + * HTTP 1.1 header specification + * message-header = field-name ":" [ field-value ] + * field-name = token + * field-value = *( field-content | LWS ) + * field-content = + * @param resp_header HTTP response header in string + * @param header_size Size of HTTP response header + * @param header_map a map that stores fields and values + */ void http_header_to_map(const char *resp_header, uint32_t header_size, unordered_map &header_map) { size_t length = header_size; size_t start = 0, end = 0; @@ -241,13 +255,141 @@ void http_header_to_map(const char *resp_header, uint32_t header_size, unordered } /** -* Method to check the collateral service is PCCS or PCS -* -* @return true if the URL contains trustedservices.intel.com, otherwise false. -*/ + * Method to check the collateral service is PCCS or PCS + * + * @return true if the URL contains trustedservices.intel.com, otherwise false. + */ bool is_collateral_service_pcs() { if (QcnlConfig::Instance()->getCollateralServiceUrl().find("trustedservices.intel.com") != string::npos) return true; else return false; } + +#ifndef _MSC_VER +string sha256(const void *data, size_t data_size) { + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256_CTX sha256; + SHA256_Init(&sha256); + SHA256_Update(&sha256, data, data_size); + SHA256_Final(hash, &sha256); + + std::string retval; + retval.reserve(2 * sizeof(hash) + 1); + for (size_t i = 0; i < sizeof(hash); i++) { + char buf[3]; + snprintf(buf, sizeof(buf), "%02x", hash[i]); + retval += buf; + } + + return retval; +} +#else +string sha256(const void *data, size_t data_size) { + BCRYPT_ALG_HANDLE hAlg = NULL; + BCRYPT_HASH_HANDLE hHash = NULL; + NTSTATUS status = STATUS_UNSUCCESSFUL; + DWORD cbData = 0, cbHash = 0, cbHashObject = 0; + PBYTE pbHashObject = NULL; + PBYTE pbHash = NULL; + string retval; + + // open an algorithm handle + if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider( + &hAlg, + BCRYPT_SHA256_ALGORITHM, + NULL, + 0))) { + goto Cleanup; + } + + // calculate the size of the buffer to hold the hash object + if (!NT_SUCCESS(status = BCryptGetProperty( + hAlg, + BCRYPT_OBJECT_LENGTH, + (PBYTE)&cbHashObject, + sizeof(DWORD), + &cbData, + 0))) { + goto Cleanup; + } + + // allocate the hash object on the heap + pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHashObject); + if (NULL == pbHashObject) { + goto Cleanup; + } + + // calculate the length of the hash + if (!NT_SUCCESS(status = BCryptGetProperty( + hAlg, + BCRYPT_HASH_LENGTH, + (PBYTE)&cbHash, + sizeof(DWORD), + &cbData, + 0))) { + goto Cleanup; + } + + // allocate the hash buffer on the heap + pbHash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHash); + if (NULL == pbHash) { + goto Cleanup; + } + + // create a hash + if (!NT_SUCCESS(status = BCryptCreateHash( + hAlg, + &hHash, + pbHashObject, + cbHashObject, + NULL, + 0, + 0))) { + goto Cleanup; + } + + // hash some data + if (!NT_SUCCESS(status = BCryptHashData( + hHash, + (PBYTE)data, + (ULONG)data_size, + 0))) { + goto Cleanup; + } + + // close the hash + if (!NT_SUCCESS(status = BCryptFinishHash( + hHash, + pbHash, + cbHash, + 0))) { + goto Cleanup; + } + + retval.reserve(2 * cbHash + 1); + for (size_t i = 0; i < cbHash; i++) { + char buf[3]; + snprintf(buf, sizeof(buf), "%02x", pbHash[i]); + retval += buf; + } + + return retval; + +Cleanup: + + if (hAlg) + BCryptCloseAlgorithmProvider(hAlg, 0); + + if (hHash) + BCryptDestroyHash(hHash); + + if (pbHashObject) + HeapFree(GetProcessHeap(), 0, pbHashObject); + + if (pbHash) + HeapFree(GetProcessHeap(), 0, pbHash); + + return ""; +} +#endif \ No newline at end of file diff --git a/QuoteGeneration/qcnl/qv_collateral_provider.cpp b/QuoteGeneration/qcnl/qv_collateral_provider.cpp deleted file mode 100644 index d438d27e..00000000 --- a/QuoteGeneration/qcnl/qv_collateral_provider.cpp +++ /dev/null @@ -1,514 +0,0 @@ -/* - * 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. - * - */ -/** - * File: qv_collateral_provider.cpp - * - * Description: Quote verification collateral provider - * - */ -#include "qv_collateral_provider.h" -#include "network_wrapper.h" -#include "pccs_response_object.h" -#include "qcnl_config.h" -#include "se_memcpy.h" -#include "qcnl_util.h" -#include - -#define FREE_RESP_BUFFER(resp_msg, resp_header) \ - if (resp_msg) { \ - free(resp_msg); \ - resp_msg = NULL; \ - } \ - if (resp_header) { \ - free(resp_header); \ - resp_header = NULL; \ - } - -QvCollateralProvider::QvCollateralProvider() { -} - -QvCollateralProvider::QvCollateralProvider(const char *custom_param) { - if (custom_param) - custom_param_ = custom_param; -} - -QvCollateralProvider::~QvCollateralProvider() { -} - -string QvCollateralProvider::get_custom_param_string() { - if (custom_param_.empty()) - return ""; - - // custom_param_ is BASE64 encoded string, so we need to escape '+','/','=' - string s = custom_param_; - s = regex_replace(s, regex("\\+"), "%2B"); - s = regex_replace(s, regex("\\/"), "%2F"); - s = regex_replace(s, regex("\\="), "%3D"); - return "customParameters=" + s; -} - -sgx_qcnl_error_t QvCollateralProvider::build_pck_crl_url(const char *ca, string &url) { - // initialize https request url - url = QcnlConfig::Instance()->getCollateralServiceUrl(); - - // Append ca and encoding - url.append("pckcrl?ca=").append(ca); - if (is_collateral_service_pcs() || QcnlConfig::Instance()->getCollateralVersion() == "3.1") { - url.append("&encoding=der"); - } - if (!custom_param_.empty()) { - url.append("&").append(get_custom_param_string()); - } - - qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Request URL %s \n", url.c_str()); - - return SGX_QCNL_SUCCESS; -} - -sgx_qcnl_error_t QvCollateralProvider::get_pck_crl_chain(const char *ca, - uint16_t ca_size, - uint8_t **p_crl_chain, - uint16_t *p_crl_chain_size) { - (void)ca_size; // UNUSED - // initialize https request url - string url(""); - sgx_qcnl_error_t ret = build_pck_crl_url(ca, url); - if (ret != SGX_QCNL_SUCCESS) { - return ret; - } - - char *resp_msg = NULL, *resp_header = NULL; - uint32_t resp_size = 0, header_size = 0; - map header_map; - - ret = qcnl_https_request(url.c_str(), header_map, NULL, 0, NULL, 0, &resp_msg, resp_size, &resp_header, header_size); - if (ret != SGX_QCNL_SUCCESS) { - return ret; - } else if (!resp_msg || resp_size == 0) { - return SGX_QCNL_UNEXPECTED_ERROR; - } - - PckCrlResponseObject pckcrl_resp_obj; - pckcrl_resp_obj.set_raw_header(resp_header, header_size).set_raw_body(resp_msg, resp_size); - - do { - string certchain = pckcrl_resp_obj.get_pckcrl_issuer_chain(); - string crl = pckcrl_resp_obj.get_pckcrl(); - if (certchain.empty() || crl.empty()) { - ret = SGX_QCNL_MSG_ERROR; - break; - } - - certchain = unescape(certchain); - - // Always append a NULL terminator to CRL and certchain - *p_crl_chain_size = (uint16_t)(certchain.size() + crl.size() + 2); - *p_crl_chain = (uint8_t *)malloc(*p_crl_chain_size); - if (*p_crl_chain == NULL) { - ret = SGX_QCNL_OUT_OF_MEMORY; - break; - } - - // set certchain (crl || ('\0) || intermediateCA || root CA || '\0') - uint8_t *ptr = *p_crl_chain; - if (memcpy_s(ptr, crl.size(), crl.data(), crl.size()) != 0) { - ret = SGX_QCNL_UNEXPECTED_ERROR; - break; - } - ptr += crl.size(); - *ptr++ = '\0'; // add NULL terminator - - if (memcpy_s(ptr, certchain.size(), certchain.data(), certchain.size()) != 0) { - ret = SGX_QCNL_UNEXPECTED_ERROR; - break; - } - ptr += certchain.size(); - *ptr = '\0'; // add NULL terminator - - ret = SGX_QCNL_SUCCESS; - } while (0); - - if (ret != SGX_QCNL_SUCCESS) { - sgx_qcnl_free_pck_crl_chain(*p_crl_chain); - } - - FREE_RESP_BUFFER(resp_msg, resp_header) - - return ret; -} - -sgx_qcnl_error_t QvCollateralProvider::build_tcbinfo_url(sgx_prod_type_t prod_type, - const char *fmspc, - uint16_t fmspc_size, - string &url) { - // initialize https request url - url = QcnlConfig::Instance()->getCollateralServiceUrl(); - - if (prod_type == SGX_PROD_TYPE_TDX) { - auto found = url.find("/sgx/"); - if (found != std::string::npos) { - url = url.replace(found, 5, "/tdx/"); - } else { - return SGX_QCNL_UNEXPECTED_ERROR; - } - } - - // Append fmspc - url.append("tcb?fmspc="); - if (!concat_string_with_hex_buf(url, reinterpret_cast(fmspc), fmspc_size)) { - return SGX_QCNL_UNEXPECTED_ERROR; - } - if (!custom_param_.empty()) { - url.append("&").append(get_custom_param_string()); - } - - qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Request URL %s \n", url.c_str()); - - return SGX_QCNL_SUCCESS; -} - -sgx_qcnl_error_t QvCollateralProvider::get_tcbinfo(sgx_prod_type_t prod_type, - const char *fmspc, - uint16_t fmspc_size, - uint8_t **p_tcbinfo, - uint16_t *p_tcbinfo_size) { - string url(""); - sgx_qcnl_error_t ret = build_tcbinfo_url(prod_type, fmspc, fmspc_size, url); - if (ret != SGX_QCNL_SUCCESS) { - return ret; - } - - char *resp_msg = NULL, *resp_header = NULL; - uint32_t resp_size = 0, header_size = 0; - map header_map; - - ret = qcnl_https_request(url.c_str(), header_map, NULL, 0, NULL, 0, &resp_msg, resp_size, &resp_header, header_size); - if (ret != SGX_QCNL_SUCCESS) { - return ret; - } - - TcbInfoResponseObject tcbinfo_resp_obj; - tcbinfo_resp_obj.set_raw_header(resp_header, header_size).set_raw_body(resp_msg, resp_size); - - do { - string certchain = tcbinfo_resp_obj.get_tcbinfo_issuer_chain(); - string tcbinfo = tcbinfo_resp_obj.get_tcbinfo(); - if (certchain.empty() || tcbinfo.empty()) { - ret = SGX_QCNL_MSG_ERROR; - break; - } - - certchain = unescape(certchain); - - *p_tcbinfo_size = (uint16_t)(certchain.size() + tcbinfo.size() + 2); - *p_tcbinfo = (uint8_t *)malloc(*p_tcbinfo_size); - if (*p_tcbinfo == NULL) { - ret = SGX_QCNL_OUT_OF_MEMORY; - break; - } - - // set certchain (tcbinfo || '\0' || signingCA || root CA || '\0') - if (memcpy_s(*p_tcbinfo, *p_tcbinfo_size, tcbinfo.data(), tcbinfo.size()) != 0) { - ret = SGX_QCNL_UNEXPECTED_ERROR; - break; - } - (*p_tcbinfo)[tcbinfo.size()] = '\0'; // add NULL terminator - if (memcpy_s(*p_tcbinfo + tcbinfo.size() + 1, certchain.size(), certchain.data(), certchain.size()) != 0) { - ret = SGX_QCNL_UNEXPECTED_ERROR; - break; - } - (*p_tcbinfo)[*p_tcbinfo_size - 1] = '\0'; // add NULL terminator - - ret = SGX_QCNL_SUCCESS; - } while (0); - - if (ret != SGX_QCNL_SUCCESS) { - sgx_qcnl_free_tcbinfo(*p_tcbinfo); - } - - FREE_RESP_BUFFER(resp_msg, resp_header) - - return ret; -} - -sgx_qcnl_error_t QvCollateralProvider::build_qeidentity_url(sgx_qe_type_t qe_type, string &url) { - url = QcnlConfig::Instance()->getCollateralServiceUrl(); - - if (qe_type == SGX_QE_TYPE_TD) { - auto found = url.find("/sgx/"); - if (found != std::string::npos) { - url = url.replace(found, 5, "/tdx/"); - } else { - return SGX_QCNL_UNEXPECTED_ERROR; - } - } - - url.append("qe/identity"); - if (!custom_param_.empty()) { - url.append("?").append(get_custom_param_string()); - } - - qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Request URL %s \n", url.c_str()); - - return SGX_QCNL_SUCCESS; -} - -sgx_qcnl_error_t QvCollateralProvider::get_qe_identity(sgx_qe_type_t qe_type, - uint8_t **p_qe_identity, - uint16_t *p_qe_identity_size) { - (void)qe_type; - // initialize https request url - string url(""); - sgx_qcnl_error_t ret = build_qeidentity_url(qe_type, url); - if (ret != SGX_QCNL_SUCCESS) { - return ret; - } - - char *resp_msg = NULL, *resp_header = NULL; - uint32_t resp_size = 0, header_size = 0; - map header_map; - - ret = qcnl_https_request(url.c_str(), header_map, NULL, 0, NULL, 0, &resp_msg, resp_size, &resp_header, header_size); - if (ret != SGX_QCNL_SUCCESS) { - return ret; - } - - QeIdentityResponseObject qe_identity_resp_obj; - qe_identity_resp_obj.set_raw_header(resp_header, header_size).set_raw_body(resp_msg, resp_size); - - do { - string certchain = qe_identity_resp_obj.get_enclave_id_issuer_chain(); - string qeidentity = qe_identity_resp_obj.get_qeidentity(); - if (certchain.empty() || qeidentity.empty()) { - ret = SGX_QCNL_MSG_ERROR; - break; - } - - certchain = unescape(certchain); - - *p_qe_identity_size = (uint16_t)(certchain.size() + qeidentity.size() + 2); - *p_qe_identity = (uint8_t *)malloc(*p_qe_identity_size); - if (*p_qe_identity == NULL) { - ret = SGX_QCNL_OUT_OF_MEMORY; - break; - } - - // set certchain (QE identity || '\0' || signingCA || root CA || '\0') - if (memcpy_s(*p_qe_identity, *p_qe_identity_size, qeidentity.data(), qeidentity.size()) != 0) { - ret = SGX_QCNL_UNEXPECTED_ERROR; - break; - } - (*p_qe_identity)[qeidentity.size()] = '\0'; // add NULL terminator - if (memcpy_s(*p_qe_identity + qeidentity.size() + 1, certchain.size(), certchain.data(), certchain.size()) != 0) { - ret = SGX_QCNL_UNEXPECTED_ERROR; - break; - } - (*p_qe_identity)[*p_qe_identity_size - 1] = '\0'; // add NULL terminator - - ret = SGX_QCNL_SUCCESS; - } while (0); - - if (ret != SGX_QCNL_SUCCESS) { - sgx_qcnl_free_qe_identity(*p_qe_identity); - } - - FREE_RESP_BUFFER(resp_msg, resp_header) - - return ret; -} - -sgx_qcnl_error_t QvCollateralProvider::build_qveidentity_url(string &url) { - url = QcnlConfig::Instance()->getCollateralServiceUrl(); - url.append("qve/identity"); - if (!custom_param_.empty()) { - url.append("?").append(get_custom_param_string()); - } - - qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Request URL %s \n", url.c_str()); - - return SGX_QCNL_SUCCESS; -} - -sgx_qcnl_error_t QvCollateralProvider::get_qve_identity(char **pp_qve_identity, - uint32_t *p_qve_identity_size, - char **pp_qve_identity_issuer_chain, - uint32_t *p_qve_identity_issuer_chain_size) { - string url(""); - sgx_qcnl_error_t ret = build_qveidentity_url(url); - if (ret != SGX_QCNL_SUCCESS) { - return ret; - } - - *pp_qve_identity = NULL; - *pp_qve_identity_issuer_chain = NULL; - - char *resp_msg = NULL, *resp_header = NULL; - uint32_t resp_size = 0, header_size = 0; - map header_map; - - ret = qcnl_https_request(url.c_str(), header_map, NULL, 0, NULL, 0, &resp_msg, resp_size, &resp_header, header_size); - if (ret != SGX_QCNL_SUCCESS) { - return ret; - } - - QveIdentityResponseObject qve_identity_resp_obj; - qve_identity_resp_obj.set_raw_header(resp_header, header_size).set_raw_body(resp_msg, resp_size); - - do { - string certchain = qve_identity_resp_obj.get_enclave_id_issuer_chain(); - string qveidentity = qve_identity_resp_obj.get_qveidentity(); - if (certchain.empty() || qveidentity.empty()) { - ret = SGX_QCNL_MSG_ERROR; - break; - } - - certchain = unescape(certchain); - - // allocate buffers - *p_qve_identity_size = (uint32_t)qveidentity.size() + 1; - *pp_qve_identity = (char *)malloc(*p_qve_identity_size); - if (*pp_qve_identity == NULL) { - ret = SGX_QCNL_OUT_OF_MEMORY; - break; - } - *p_qve_identity_issuer_chain_size = (uint32_t)(certchain.size() + 1); - *pp_qve_identity_issuer_chain = (char *)malloc(*p_qve_identity_issuer_chain_size); - if (*pp_qve_identity_issuer_chain == NULL) { - ret = SGX_QCNL_OUT_OF_MEMORY; - break; - } - - // set QvE identity - if (memcpy_s(*pp_qve_identity, *p_qve_identity_size, qveidentity.data(), qveidentity.size()) != 0) { - ret = SGX_QCNL_UNEXPECTED_ERROR; - break; - } - (*pp_qve_identity)[*p_qve_identity_size - 1] = '\0'; // add NULL terminator - - // set certchain (signingCA || root CA) - if (memcpy_s(*pp_qve_identity_issuer_chain, *p_qve_identity_issuer_chain_size, certchain.data(), certchain.size()) != 0) { - ret = SGX_QCNL_UNEXPECTED_ERROR; - break; - } - (*pp_qve_identity_issuer_chain)[*p_qve_identity_issuer_chain_size - 1] = '\0'; // add NULL terminator - - ret = SGX_QCNL_SUCCESS; - } while (0); - - if (ret != SGX_QCNL_SUCCESS) { - sgx_qcnl_free_qve_identity(*pp_qve_identity, *pp_qve_identity_issuer_chain); - } - - FREE_RESP_BUFFER(resp_msg, resp_header) - - return ret; -} - -sgx_qcnl_error_t QvCollateralProvider::build_root_ca_crl_url(const char *root_ca_cdp_url, string &url) { - url = QcnlConfig::Instance()->getCollateralServiceUrl(); - // Append url - if (!is_collateral_service_pcs()) { - if (QcnlConfig::Instance()->getCollateralVersion() == "3.0") { - // For PCCS API version 3.0, will call API /rootcacrl, and it will return HEX encoded CRL - url.append("rootcacrl"); - if (!custom_param_.empty()) { - url.append("?").append(get_custom_param_string()); - } - } else if (QcnlConfig::Instance()->getCollateralVersion() == "3.1") { - // For PCCS API version 3.0, will call API /crl, and it will return raw DER buffer - url.append("crl?uri=").append(root_ca_cdp_url); - if (!custom_param_.empty()) { - url.append("&").append(get_custom_param_string()); - } - } else { - return SGX_QCNL_INVALID_CONFIG; - } - } - - return SGX_QCNL_SUCCESS; -} - -sgx_qcnl_error_t QvCollateralProvider::get_root_ca_crl(const char *root_ca_cdp_url, - uint8_t **p_root_ca_crl, - uint16_t *p_root_ca_crl_size) { - // initialize https request url - string url(""); - sgx_qcnl_error_t ret = build_root_ca_crl_url(root_ca_cdp_url, url); - if (ret != SGX_QCNL_SUCCESS) { - return ret; - } - - char *resp_msg = NULL, *resp_header = NULL; - uint32_t resp_size = 0, header_size = 0; - map header_map; - - if (is_collateral_service_pcs()) { - qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Request URL %s \n", root_ca_cdp_url); - ret = qcnl_https_request(root_ca_cdp_url, header_map, NULL, 0, NULL, 0, &resp_msg, resp_size, &resp_header, header_size); - } else { - qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Request URL %s \n", url.c_str()); - ret = qcnl_https_request(url.c_str(), header_map, NULL, 0, NULL, 0, &resp_msg, resp_size, &resp_header, header_size); - } - - if (ret != SGX_QCNL_SUCCESS) { - return ret; - } - - PccsResponseObject pccs_resp_obj; - pccs_resp_obj.set_raw_body(resp_msg, resp_size); - - do { - string root_ca_crl = pccs_resp_obj.get_raw_body(); - - *p_root_ca_crl_size = (uint16_t)root_ca_crl.size(); - *p_root_ca_crl = (uint8_t *)malloc(*p_root_ca_crl_size); - if (*p_root_ca_crl == NULL) { - ret = SGX_QCNL_OUT_OF_MEMORY; - break; - } - - // set Root CA CRL - if (memcpy_s(*p_root_ca_crl, *p_root_ca_crl_size, root_ca_crl.data(), root_ca_crl.size()) != 0) { - ret = SGX_QCNL_UNEXPECTED_ERROR; - break; - } - - ret = SGX_QCNL_SUCCESS; - } while (0); - - if (ret != SGX_QCNL_SUCCESS) { - sgx_qcnl_free_root_ca_crl(*p_root_ca_crl); - } - - FREE_RESP_BUFFER(resp_msg, resp_header) - - return ret; -} diff --git a/QuoteGeneration/qcnl/sgx_default_qcnl_wrapper.cpp b/QuoteGeneration/qcnl/sgx_default_qcnl_wrapper.cpp index 595936a1..7acf9f4b 100644 --- a/QuoteGeneration/qcnl/sgx_default_qcnl_wrapper.cpp +++ b/QuoteGeneration/qcnl/sgx_default_qcnl_wrapper.cpp @@ -29,27 +29,27 @@ * */ /** - * File: sgx_default_qcnl_wrapper.cpp - * - * Description: SGX default PCK Collateral Network Library + * File: sgx_default_qcnl_wrapper.cpp + * + * Description: SGX default PCK Collateral Network Library * */ #include "sgx_default_qcnl_wrapper.h" -#include "pckcert_provider.h" +#include "certification_service.h" #include "qcnl_config.h" #include "qcnl_def.h" -#include "qv_collateral_provider.h" -#include "sgx_pce.h" #include "qcnl_util.h" +#include "sgx_pce.h" #include #include static sgx_ql_logging_callback_t logger_callback = nullptr; +static sgx_ql_log_level_t g_loglevel = SGX_QL_LOG_ERROR; void qcnl_log(sgx_ql_log_level_t level, const char *fmt, ...) { - if (logger_callback != nullptr) { - char message[512]; + if (logger_callback != nullptr && level <= g_loglevel) { + char message[2500]; // to make sure the full URL can be logged. va_list args; va_start(args, fmt); vsnprintf(message, sizeof(message), fmt, args); @@ -63,14 +63,14 @@ void qcnl_log(sgx_ql_log_level_t level, const char *fmt, ...) { } /** -* This API gets PCK certificate chain and TCBm from PCCS server based on the information provided(QE_ID, TCBr, EncPPID, PCE_ID) -* The buffer allocated by this function should be freed with sgx_qcnl_free_pck_cert_chain by the caller. -* -* @param p_pck_cert_id PCK cert identity information -* @param pp_quote_config Output buffer for quote configuration data -* -* @return SGX_QCNL_SUCCESS If the PCK certificate chain and TCBm was retrieved from PCCS server successfully. -*/ + * This API gets PCK certificate chain and TCBm from PCCS server based on the information provided(QE_ID, TCBr, EncPPID, PCE_ID) + * The buffer allocated by this function should be freed with sgx_qcnl_free_pck_cert_chain by the caller. + * + * @param p_pck_cert_id PCK cert identity information + * @param pp_quote_config Output buffer for quote configuration data + * + * @return SGX_QCNL_SUCCESS If the PCK certificate chain and TCBm was retrieved from PCCS server successfully. + */ sgx_qcnl_error_t sgx_qcnl_get_pck_cert_chain(const sgx_ql_pck_cert_id_t *p_pck_cert_id, sgx_ql_config_t **pp_quote_config) { @@ -92,13 +92,13 @@ sgx_qcnl_error_t sgx_qcnl_get_pck_cert_chain(const sgx_ql_pck_cert_id_t *p_pck_c return SGX_QCNL_INVALID_PARAMETER; } - PckCertProvider pckCertProvider; - return pckCertProvider.get_pck_cert_chain(p_pck_cert_id, pp_quote_config); + CertificationService certificationService; + return certificationService.get_pck_cert_chain(p_pck_cert_id, pp_quote_config); } /** -* This API frees the buffer allocated by sgx_qcnl_get_pck_cert_chain -*/ + * This API frees the buffer allocated by sgx_qcnl_get_pck_cert_chain + */ void sgx_qcnl_free_pck_cert_chain(sgx_ql_config_t *p_quote_config) { if (p_quote_config) { if (p_quote_config->p_cert_data) { @@ -112,19 +112,19 @@ void sgx_qcnl_free_pck_cert_chain(sgx_ql_config_t *p_quote_config) { } /** -* This API gets CRL certificate chain from PCCS server. The p_crl_chain buffer allocated by this API -* must be freed with sgx_qcnl_free_pck_crl_chain upon success. -* -* @param ca Currently only "platform" or "processor" -* @param ca_size Size of the ca buffer -* @param p_crl_chain Output buffer for CRL certificate chain -* @param p_crl_chain_size Size of CRL certificate chain -* -* @return SGX_QCNL_SUCCESS If the CRL certificate chain was retrieved from PCCS server successfully. -*/ + * This API gets CRL certificate chain from PCCS server. The p_crl_chain buffer allocated by this API + * must be freed with sgx_qcnl_free_pck_crl_chain upon success. + * + * @param ca Currently only "platform" or "processor" + * @param ca_size Size of the ca buffer + * @param p_crl_chain Output buffer for CRL certificate chain + * @param p_crl_chain_size Size of CRL certificate chain + * + * @return SGX_QCNL_SUCCESS If the CRL certificate chain was retrieved from PCCS server successfully. + */ sgx_qcnl_error_t sgx_qcnl_get_pck_crl_chain(const char *ca, uint16_t ca_size, - const char* custom_param_b64_string, + const char *custom_param_b64_string, uint8_t **p_crl_chain, uint16_t *p_crl_chain_size) { // Check input parameters @@ -136,13 +136,13 @@ sgx_qcnl_error_t sgx_qcnl_get_pck_crl_chain(const char *ca, return SGX_QCNL_INVALID_PARAMETER; } - QvCollateralProvider qvCollateralProvider(custom_param_b64_string); - return qvCollateralProvider.get_pck_crl_chain(ca, ca_size, p_crl_chain, p_crl_chain_size); + CertificationService certificationService(custom_param_b64_string); + return certificationService.get_pck_crl_chain(ca, ca_size, p_crl_chain, p_crl_chain_size); } /** -* This API frees the p_crl_chain buffer allocated by sgx_qcnl_get_pck_crl_chain -*/ + * This API frees the p_crl_chain buffer allocated by sgx_qcnl_get_pck_crl_chain + */ void sgx_qcnl_free_pck_crl_chain(uint8_t *p_crl_chain) { if (p_crl_chain) { free(p_crl_chain); @@ -151,21 +151,21 @@ void sgx_qcnl_free_pck_crl_chain(uint8_t *p_crl_chain) { } /** -* This API gets TCB information from PCCS server. The p_tcbinfo buffer allocated by this API -* must be freed with sgx_qcnl_free_tcbinfo upon success. -* -* @param prod_type SGX or TDX -* @param fmspc Family-Model-Stepping value -* @param fmspc_size Size of the fmspc buffer -* @param p_tcbinfo Output buffer for TCB information -* @param p_tcbinfo_size Size of TCB information -* -* @return SGX_QCNL_SUCCESS If the TCB information was retrieved from PCCS server successfully. -*/ + * This API gets TCB information from PCCS server. The p_tcbinfo buffer allocated by this API + * must be freed with sgx_qcnl_free_tcbinfo upon success. + * + * @param prod_type SGX or TDX + * @param fmspc Family-Model-Stepping value + * @param fmspc_size Size of the fmspc buffer + * @param p_tcbinfo Output buffer for TCB information + * @param p_tcbinfo_size Size of TCB information + * + * @return SGX_QCNL_SUCCESS If the TCB information was retrieved from PCCS server successfully. + */ sgx_qcnl_error_t qcnl_get_tcbinfo_internal(sgx_prod_type_t prod_type, const char *fmspc, uint16_t fmspc_size, - const char* custom_param_b64_string, + const char *custom_param_b64_string, uint8_t **p_tcbinfo, uint16_t *p_tcbinfo_size) { // Check input parameters @@ -177,13 +177,13 @@ sgx_qcnl_error_t qcnl_get_tcbinfo_internal(sgx_prod_type_t prod_type, return SGX_QCNL_INVALID_PARAMETER; } - QvCollateralProvider qvCollateralProvider(custom_param_b64_string); - return qvCollateralProvider.get_tcbinfo(prod_type, fmspc, fmspc_size, p_tcbinfo, p_tcbinfo_size); + CertificationService certificationService(custom_param_b64_string); + return certificationService.get_tcbinfo(prod_type, fmspc, fmspc_size, p_tcbinfo, p_tcbinfo_size); } sgx_qcnl_error_t sgx_qcnl_get_tcbinfo(const char *fmspc, uint16_t fmspc_size, - const char* custom_param_b64_string, + const char *custom_param_b64_string, uint8_t **p_tcbinfo, uint16_t *p_tcbinfo_size) { return qcnl_get_tcbinfo_internal(SGX_PROD_TYPE_SGX, @@ -196,7 +196,7 @@ sgx_qcnl_error_t sgx_qcnl_get_tcbinfo(const char *fmspc, sgx_qcnl_error_t tdx_qcnl_get_tcbinfo(const char *fmspc, uint16_t fmspc_size, - const char* custom_param_b64_string, + const char *custom_param_b64_string, uint8_t **p_tcbinfo, uint16_t *p_tcbinfo_size) { return qcnl_get_tcbinfo_internal(SGX_PROD_TYPE_TDX, @@ -208,8 +208,8 @@ sgx_qcnl_error_t tdx_qcnl_get_tcbinfo(const char *fmspc, } /** -* This API frees the p_tcbinfo buffer allocated by sgx_qcnl_get_tcbinfo -*/ + * This API frees the p_tcbinfo buffer allocated by sgx_qcnl_get_tcbinfo + */ void sgx_qcnl_free_tcbinfo(uint8_t *p_tcbinfo) { if (p_tcbinfo) { free(p_tcbinfo); @@ -218,8 +218,8 @@ void sgx_qcnl_free_tcbinfo(uint8_t *p_tcbinfo) { } /** -* This API frees the p_tcbinfo buffer allocated by tdx_qcnl_get_tcbinfo -*/ + * This API frees the p_tcbinfo buffer allocated by tdx_qcnl_get_tcbinfo + */ void tdx_qcnl_free_tcbinfo(uint8_t *p_tcbinfo) { if (p_tcbinfo) { free(p_tcbinfo); @@ -227,31 +227,31 @@ void tdx_qcnl_free_tcbinfo(uint8_t *p_tcbinfo) { } /** -* This API gets QE identity from PCCS server. The p_qe_identity buffer allocated by this API -* must be freed with sgx_qcnl_free_qe_identity upon success. -* -* @param qe_type Type of QE -* @param p_qe_identity Output buffer for QE identity -* @param p_qe_identity_size Size of QE identity -* -* @return SGX_QCNL_SUCCESS If the QE identity was retrieved from PCCS server successfully. -*/ + * This API gets QE identity from PCCS server. The p_qe_identity buffer allocated by this API + * must be freed with sgx_qcnl_free_qe_identity upon success. + * + * @param qe_type Type of QE + * @param p_qe_identity Output buffer for QE identity + * @param p_qe_identity_size Size of QE identity + * + * @return SGX_QCNL_SUCCESS If the QE identity was retrieved from PCCS server successfully. + */ sgx_qcnl_error_t sgx_qcnl_get_qe_identity(sgx_qe_type_t qe_type, - const char* custom_param_b64_string, + const char *custom_param_b64_string, uint8_t **p_qe_identity, uint16_t *p_qe_identity_size) { // Check input parameters - if (p_qe_identity == NULL || p_qe_identity_size == NULL ) { + if (p_qe_identity == NULL || p_qe_identity_size == NULL) { return SGX_QCNL_INVALID_PARAMETER; } - QvCollateralProvider qvCollateralProvider(custom_param_b64_string); - return qvCollateralProvider.get_qe_identity(qe_type, p_qe_identity, p_qe_identity_size); + CertificationService certificationService(custom_param_b64_string); + return certificationService.get_qe_identity(qe_type, p_qe_identity, p_qe_identity_size); } /** -* This API frees the p_qe_identity buffer allocated by sgx_qcnl_get_qe_identity -*/ + * This API frees the p_qe_identity buffer allocated by sgx_qcnl_get_qe_identity + */ void sgx_qcnl_free_qe_identity(uint8_t *p_qe_identity) { if (p_qe_identity) { free(p_qe_identity); @@ -260,17 +260,17 @@ void sgx_qcnl_free_qe_identity(uint8_t *p_qe_identity) { } /** -* This API gets QvE identity from PCCS server. The pp_qve_identity and pp_qve_identity_issuer_chain buffer allocated by this API -* must be freed with sgx_qcnl_free_qve_identity upon success. -* -* @param pp_qve_identity Output buffer for QvE identity -* @param p_qve_identity_size Size of QvE identity -* @param pp_qve_identity_issuer_chain Output buffer for QvE identity certificate chain -* @param p_qve_identity_issuer_chain_size Size of QvE identity certificate chain -* -* @return SGX_QCNL_SUCCESS If the QvE identity was retrieved from PCCS server successfully. -*/ -sgx_qcnl_error_t sgx_qcnl_get_qve_identity(const char* custom_param_b64_string, + * This API gets QvE identity from PCCS server. The pp_qve_identity and pp_qve_identity_issuer_chain buffer allocated by this API + * must be freed with sgx_qcnl_free_qve_identity upon success. + * + * @param pp_qve_identity Output buffer for QvE identity + * @param p_qve_identity_size Size of QvE identity + * @param pp_qve_identity_issuer_chain Output buffer for QvE identity certificate chain + * @param p_qve_identity_issuer_chain_size Size of QvE identity certificate chain + * + * @return SGX_QCNL_SUCCESS If the QvE identity was retrieved from PCCS server successfully. + */ +sgx_qcnl_error_t sgx_qcnl_get_qve_identity(const char *custom_param_b64_string, char **pp_qve_identity, uint32_t *p_qve_identity_size, char **pp_qve_identity_issuer_chain, @@ -280,13 +280,13 @@ sgx_qcnl_error_t sgx_qcnl_get_qve_identity(const char* custom_param_b64_string, return SGX_QCNL_INVALID_PARAMETER; } - QvCollateralProvider qvCollateralProvider(custom_param_b64_string); - return qvCollateralProvider.get_qve_identity(pp_qve_identity, p_qve_identity_size, pp_qve_identity_issuer_chain, p_qve_identity_issuer_chain_size); + CertificationService certificationService(custom_param_b64_string); + return certificationService.get_qve_identity(pp_qve_identity, p_qve_identity_size, pp_qve_identity_issuer_chain, p_qve_identity_issuer_chain_size); } /** -* This API frees the p_qve_identity and p_qve_identity_issuer_chain buffer allocated by sgx_qcnl_get_qve_identity -*/ + * This API frees the p_qve_identity and p_qve_identity_issuer_chain buffer allocated by sgx_qcnl_get_qve_identity + */ void sgx_qcnl_free_qve_identity(char *p_qve_identity, char *p_qve_identity_issuer_chain) { if (p_qve_identity) { free(p_qve_identity); @@ -299,17 +299,17 @@ void sgx_qcnl_free_qve_identity(char *p_qve_identity, char *p_qve_identity_issue } /** -* This API gets Root CA CRL from PCCS server. The p_root_ca_crl buffer allocated by this API -* must be freed with sgx_qcnl_free_root_ca_crl upon success. -* -* @param root_ca_cdp_url The url of root CA CRL -* @param p_root_ca_crl Output buffer for Root CA CRL -* @param p_root_ca_cal_size Size of Root CA CRL -* -* @return SGX_QCNL_SUCCESS If the Root CA CRL was retrieved from PCCS server successfully. -*/ + * This API gets Root CA CRL from PCCS server. The p_root_ca_crl buffer allocated by this API + * must be freed with sgx_qcnl_free_root_ca_crl upon success. + * + * @param root_ca_cdp_url The url of root CA CRL + * @param p_root_ca_crl Output buffer for Root CA CRL + * @param p_root_ca_cal_size Size of Root CA CRL + * + * @return SGX_QCNL_SUCCESS If the Root CA CRL was retrieved from PCCS server successfully. + */ sgx_qcnl_error_t sgx_qcnl_get_root_ca_crl(const char *root_ca_cdp_url, - const char* custom_param_b64_string, + const char *custom_param_b64_string, uint8_t **p_root_ca_crl, uint16_t *p_root_ca_crl_size) { // Check input parameters @@ -317,13 +317,13 @@ sgx_qcnl_error_t sgx_qcnl_get_root_ca_crl(const char *root_ca_cdp_url, return SGX_QCNL_INVALID_PARAMETER; } - QvCollateralProvider qvCollateralProvider(custom_param_b64_string); - return qvCollateralProvider.get_root_ca_crl(root_ca_cdp_url, p_root_ca_crl, p_root_ca_crl_size); + CertificationService certificationService(custom_param_b64_string); + return certificationService.get_root_ca_crl(root_ca_cdp_url, p_root_ca_crl, p_root_ca_crl_size); } /** -* This API frees the p_root_ca_crl buffer allocated by sgx_qcnl_get_root_ca_crl -*/ + * This API frees the p_root_ca_crl buffer allocated by sgx_qcnl_get_root_ca_crl + */ void sgx_qcnl_free_root_ca_crl(uint8_t *p_root_ca_crl) { if (p_root_ca_crl) { free(p_root_ca_crl); @@ -369,7 +369,8 @@ bool sgx_qcnl_get_api_version(uint16_t *p_major_ver, uint16_t *p_minor_ver) { return true; } -sgx_qcnl_error_t sgx_qcnl_set_logging_callback(sgx_ql_logging_callback_t logger) { +sgx_qcnl_error_t sgx_qcnl_set_logging_callback(sgx_ql_logging_callback_t logger, sgx_ql_log_level_t loglevel) { logger_callback = logger; + g_loglevel = loglevel; return SGX_QCNL_SUCCESS; } diff --git a/QuoteGeneration/qcnl/win/network_wrapper.cpp b/QuoteGeneration/qcnl/win/network_wrapper.cpp index e851edb0..4baafe0a 100644 --- a/QuoteGeneration/qcnl/win/network_wrapper.cpp +++ b/QuoteGeneration/qcnl/win/network_wrapper.cpp @@ -48,6 +48,7 @@ extern bool g_isWin81OrLater; static sgx_qcnl_error_t windows_last_error_to_qcnl_error(void) { DWORD ec = GetLastError(); + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Error in WinHttp : %ld. \n", ec); switch (ec) { case ERROR_WINHTTP_CONNECTION_ERROR: case ERROR_WINHTTP_CANNOT_CONNECT: @@ -179,7 +180,7 @@ sgx_qcnl_error_t qcnl_https_request_once(const char *url, hRequest = WinHttpOpenRequest(hConnect, pwszVerb, urlComp.lpszUrlPath, L"HTTP/1.0", WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, - WINHTTP_FLAG_SECURE); + _wcsnicmp(wurl, L"https", 5) == 0 ? WINHTTP_FLAG_SECURE : 0); if (!hRequest) { ret = windows_last_error_to_qcnl_error(); break; @@ -428,6 +429,8 @@ sgx_qcnl_error_t qcnl_https_request(const char *url, uint32_t retry_delay = QcnlConfig::Instance()->getRetryDelay(); uint32_t current_delay_time = 1; // wait 1 second before first retry + qcnl_log(SGX_QL_LOG_INFO, "[QCNL] Request URL %s \n", url); + while (retry_times > 0) { ret = qcnl_https_request_once(url, header_map, req_body, req_body_size, user_token, user_token_size, resp_msg, resp_size, resp_header, header_size); diff --git a/QuoteGeneration/qcnl/win/qcnl_config_impl.cpp b/QuoteGeneration/qcnl/win/qcnl_config_impl.cpp index eee9641f..fa7f1fa6 100644 --- a/QuoteGeneration/qcnl/win/qcnl_config_impl.cpp +++ b/QuoteGeneration/qcnl/win/qcnl_config_impl.cpp @@ -50,6 +50,7 @@ using namespace std; #define REG_VALUE_QCNL_RETRY_DELAY _T("RETRY_DELAY") #define REG_VALUE_QCNL_LOCAL_PCK_URL _T("LOCAL_PCK_URL") #define REG_VALUE_QCNL_CACHE_EXPIRE_HOURS _T("PCK_CACHE_EXPIRE_HOURS") +#define REG_VALUE_QCNL_COLLATERAL_EXPIRE_HOURS _T("VERIFY_COLLATERAL_CACHE_EXPIRE_HOURS") #define REG_VALUE_QCNL_CONFIG_FILE _T("CONFIG_FILE") @@ -153,9 +154,17 @@ bool QcnlConfigLegacy::load_config() { DWORD dwCacheExpireHours = 0; status = RegQueryValueEx(key, REG_VALUE_QCNL_CACHE_EXPIRE_HOURS, NULL, &type, (LPBYTE)&dwCacheExpireHours, &count); if (ERROR_SUCCESS == status && type == REG_DWORD) { - cache_expire_hour_ = (uint32_t)dwCacheExpireHours; - if (cache_expire_hour_ > CACHE_MAX_EXPIRY_HOURS) - cache_expire_hour_ = CACHE_MAX_EXPIRY_HOURS; + pck_cache_expire_hours_ = (double)dwCacheExpireHours; + if (pck_cache_expire_hours_ > CACHE_MAX_EXPIRY_HOURS) + pck_cache_expire_hours_ = CACHE_MAX_EXPIRY_HOURS; + } + + DWORD dwVerifyCollateralExpireHours = 0; + status = RegQueryValueEx(key, REG_VALUE_QCNL_COLLATERAL_EXPIRE_HOURS, NULL, &type, (LPBYTE)&dwVerifyCollateralExpireHours, &count); + if (ERROR_SUCCESS == status && type == REG_DWORD) { + verify_collateral_expire_hours_ = (double)dwVerifyCollateralExpireHours; + if (verify_collateral_expire_hours_ > CACHE_MAX_EXPIRY_HOURS) + verify_collateral_expire_hours_ = CACHE_MAX_EXPIRY_HOURS; } RegCloseKey(key); diff --git a/QuoteGeneration/qcnl/win/qcnl_wrapper.vcxproj b/QuoteGeneration/qcnl/win/qcnl_wrapper.vcxproj index 185a9ec8..d237922e 100644 --- a/QuoteGeneration/qcnl/win/qcnl_wrapper.vcxproj +++ b/QuoteGeneration/qcnl/win/qcnl_wrapper.vcxproj @@ -104,7 +104,7 @@ Windows true - Winhttp.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Bcrypt.lib;Winhttp.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) qcnl_wrapper.def true @@ -127,7 +127,7 @@ Windows true - Winhttp.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Bcrypt.lib;Winhttp.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) qcnl_wrapper.def true @@ -153,7 +153,7 @@ true true true - Winhttp.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Bcrypt.lib;Winhttp.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) qcnl_wrapper.def true @@ -179,7 +179,7 @@ true true true - Winhttp.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Bcrypt.lib;Winhttp.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) qcnl_wrapper.def true @@ -197,10 +197,10 @@ + + - - diff --git a/QuoteGeneration/qcnl/win/qcnl_wrapper.vcxproj.filters b/QuoteGeneration/qcnl/win/qcnl_wrapper.vcxproj.filters index 91c62c47..d30ff72c 100644 --- a/QuoteGeneration/qcnl/win/qcnl_wrapper.vcxproj.filters +++ b/QuoteGeneration/qcnl/win/qcnl_wrapper.vcxproj.filters @@ -62,19 +62,19 @@ Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files diff --git a/QuoteGeneration/qpl/inc/sgx_default_quote_provider.h b/QuoteGeneration/qpl/inc/sgx_default_quote_provider.h index a0599240..1b99d34b 100644 --- a/QuoteGeneration/qpl/inc/sgx_default_quote_provider.h +++ b/QuoteGeneration/qpl/inc/sgx_default_quote_provider.h @@ -29,7 +29,7 @@ * */ /** - * File: sgx_dcap_qpl.h + * File: sgx_default_quote_provider.h * * Description: Definitions and prototypes for the Quote Provider Library * @@ -70,7 +70,7 @@ quote3_error_t sgx_ql_get_qve_identity(char **pp_qve_identity, quote3_error_t sgx_ql_free_qve_identity(char *p_qve_identity, char *p_qve_identity_issuer_chain); quote3_error_t sgx_ql_get_root_ca_crl(uint8_t **pp_root_ca_crl, uint16_t *p_root_ca_crl_size); quote3_error_t sgx_ql_free_root_ca_crl(uint8_t *p_root_ca_crl); -quote3_error_t sgx_ql_set_logging_callback(sgx_ql_logging_callback_t logger); +quote3_error_t sgx_ql_set_logging_callback(sgx_ql_logging_callback_t logger, sgx_ql_log_level_t loglevel = SGX_QL_LOG_ERROR); #if defined(__cplusplus) } diff --git a/QuoteGeneration/qpl/qpl_api.txt b/QuoteGeneration/qpl/qpl_api.txt index 9abd1731..bc356675 100644 --- a/QuoteGeneration/qpl/qpl_api.txt +++ b/QuoteGeneration/qpl/qpl_api.txt @@ -101,7 +101,7 @@ Parameters pck_ca [In] Null terminated string identifier of the PCK Cert CA that issued the PCK Certificates. custom_param [In] - Custom parameter that will be appended to request URL in Base64 format ( ...&customParameters=Base64(custom_param) ) + Custom parameter that will be appended to request URL in Base64 format ( ...&customParameter=Base64(custom_param) ) custom_param_length [In] Length of custom_param. pp_quote_collateral [Out] @@ -149,13 +149,13 @@ Parameters: pp_qve_identity[Out] Pointer to a pointer to the UTF-8 encoded JSON string containing the QVE Identity structure. The provider library will allocate this buffer and it is expected that the caller will free it using - the provider libraryā€™s sgx_ql_free_qve_identity() API. + the provider library's sgx_ql_free_qve_identity() API. p_qve_identity_size[Out] The length of the string in bytes in the buffer pointed by *pp_qve_identity including the terminating null character. pp_qve_identity_issuer_chain[Out] Pointer to a pointer to the QVE identity certificate chain. The provider library will allocate This - buffer and it is expected that the caller will free it using the provider libraryā€™s sgx_ql_free_qve_identity() API. + buffer and it is expected that the caller will free it using the provider library's sgx_ql_free_qve_identity() API. p_qve_identity_issuer_chain_size[Out] The length of the string in bytes in the buffer pointed by *pp_qve_identity_issuer_chain including the terminating null character. @@ -216,8 +216,8 @@ typedef struct _sgx_ql_qve_collateral_t uint32_t version; ///< 'version' is the backward compatible legacy representation struct { ///< For PCS V1 and V2 APIs, the major_version = 1 and minor_version = 0 and uint16_t major_version; ///< the CRLs will be formatted in PEM. For PCS V3 APIs, the major_version = 3 and the - uint16_t minor_version; ///< minor_version can be either 0 or 1. minor_verion of 0 indicates the CRLā€™s are formatted - ///< in Base16 encoded DER. A minor version of 1 indicates the CRLā€™s are formatted in raw binary DER. + uint16_t minor_version; ///< minor_version can be either 0 or 1. minor_verion of 0 indicates the CRLs are formatted + ///< in Base16 encoded DER. A minor version of 1 indicates the CRLs are formatted in raw binary DER. }; }; char *pck_crl_issuer_chain; @@ -236,4 +236,4 @@ typedef struct _sgx_ql_qve_collateral_t uint32_t qe_identity_size; }sgx_ql_qve_collateral_t; -typedef sgx_ql_qve_collateral_t tdx_ql_qve_collateral_t; \ No newline at end of file +typedef sgx_ql_qve_collateral_t tdx_ql_qve_collateral_t; diff --git a/QuoteGeneration/qpl/sgx_default_quote_provider.cpp b/QuoteGeneration/qpl/sgx_default_quote_provider.cpp index a5c7013c..1f1a68ea 100644 --- a/QuoteGeneration/qpl/sgx_default_quote_provider.cpp +++ b/QuoteGeneration/qpl/sgx_default_quote_provider.cpp @@ -52,9 +52,10 @@ using namespace std; static const char *X509_DELIMITER = "-----BEGIN CERTIFICATE-----"; static sgx_ql_logging_callback_t logger_callback = nullptr; +static sgx_ql_log_level_t g_loglevel = SGX_QL_LOG_ERROR; void qpl_log(sgx_ql_log_level_t level, const char *fmt, ...) { - if (logger_callback != nullptr) { + if (logger_callback != nullptr && level <= g_loglevel) { char message[512]; va_list args; va_start(args, fmt); @@ -89,6 +90,8 @@ static quote3_error_t qcnl_error_to_ql_error(sgx_qcnl_error_t ret) { case SGX_QCNL_NETWORK_UNKNOWN_OPTION: case SGX_QCNL_NETWORK_INIT_ERROR: return SGX_QL_NETWORK_ERROR; + case SGX_QCNL_ROOT_CA_UNTRUSTED: + return SGX_QL_ROOT_CA_UNTRUSTED; case SGX_QCNL_MSG_ERROR: return SGX_QL_ERROR_MESSAGE_PARSING_ERROR; case SGX_QCNL_ERROR_STATUS_NO_CACHE_DATA: @@ -243,7 +246,11 @@ quote3_error_t ql_get_quote_verification_collateral_internal(sgx_prod_type_t pro if (qcnl_ret != SGX_QCNL_SUCCESS) { qpl_log(SGX_QL_LOG_ERROR, "[QPL] Failed to get TCBInfo : 0x%04x\n", qcnl_ret); - ret = qcnl_error_to_ql_error(qcnl_ret); + if (qcnl_ret == SGX_QCNL_ERROR_STATUS_NO_CACHE_DATA) { + ret = SGX_QL_TCBINFO_NOT_FOUND; + } else { + ret = qcnl_error_to_ql_error(qcnl_ret); + } break; } @@ -263,7 +270,11 @@ quote3_error_t ql_get_quote_verification_collateral_internal(sgx_prod_type_t pro qcnl_ret = sgx_qcnl_get_qe_identity(qe_type, base64_string, &p_qe_identity, &qe_identity_size); if (qcnl_ret != SGX_QCNL_SUCCESS) { qpl_log(SGX_QL_LOG_ERROR, "[QPL] Failed to get QE identity : 0x%04x\n", qcnl_ret); - ret = qcnl_error_to_ql_error(qcnl_ret); + if (qcnl_ret == SGX_QCNL_ERROR_STATUS_NO_CACHE_DATA) { + ret = SGX_QL_QEIDENTITY_NOT_FOUND; + } else { + ret = qcnl_error_to_ql_error(qcnl_ret); + } break; } @@ -295,15 +306,6 @@ quote3_error_t ql_get_quote_verification_collateral_internal(sgx_prod_type_t pro ret = qcnl_error_to_ql_error(qcnl_ret); break; } - // Add NULL terminator to Root CA CRL - (*pp_quote_collateral)->root_ca_crl_size++; - char *p_root_ca_crl = (char *)realloc((*pp_quote_collateral)->root_ca_crl, (*pp_quote_collateral)->root_ca_crl_size); - if (p_root_ca_crl == NULL) { - ret = SGX_QL_ERROR_OUT_OF_MEMORY; - break; - } - (*pp_quote_collateral)->root_ca_crl = p_root_ca_crl; - (*pp_quote_collateral)->root_ca_crl[(*pp_quote_collateral)->root_ca_crl_size - 1] = 0; ret = SGX_QL_SUCCESS; } while (0); @@ -459,7 +461,12 @@ quote3_error_t sgx_ql_get_root_ca_crl(uint8_t **pp_root_ca_crl, uint16_t *p_root sgx_qcnl_error_t qcnl_ret = sgx_qcnl_get_qe_identity(SGX_QE_TYPE_ECDSA, NULL, &p_qe_identity, &qe_identity_size); if (qcnl_ret != SGX_QCNL_SUCCESS) { qpl_log(SGX_QL_LOG_ERROR, "[QPL] Failed to get QE identity : 0x%04x\n", qcnl_ret); - return qcnl_error_to_ql_error(qcnl_ret); + if (qcnl_ret == SGX_QCNL_ERROR_STATUS_NO_CACHE_DATA) { + ret = SGX_QL_QEIDENTITY_NOT_FOUND; + } else { + ret = qcnl_error_to_ql_error(qcnl_ret); + } + return ret; } do { @@ -505,8 +512,9 @@ quote3_error_t sgx_ql_free_root_ca_crl(uint8_t *p_root_ca_crl) { return SGX_QL_SUCCESS; } -quote3_error_t sgx_ql_set_logging_callback(sgx_ql_logging_callback_t logger) { +quote3_error_t sgx_ql_set_logging_callback(sgx_ql_logging_callback_t logger, sgx_ql_log_level_t loglevel) { logger_callback = logger; - sgx_qcnl_set_logging_callback(logger); + g_loglevel = loglevel; + sgx_qcnl_set_logging_callback(logger, g_loglevel); return SGX_QL_SUCCESS; } diff --git a/QuoteGeneration/quote_wrapper/common/inc/sgx_ql_lib_common.h b/QuoteGeneration/quote_wrapper/common/inc/sgx_ql_lib_common.h index 2bfc091e..011680d1 100644 --- a/QuoteGeneration/quote_wrapper/common/inc/sgx_ql_lib_common.h +++ b/QuoteGeneration/quote_wrapper/common/inc/sgx_ql_lib_common.h @@ -131,6 +131,14 @@ typedef enum _quote3_error_t { SGX_QL_COLLATERAL_VERSION_NOT_SUPPORTED = SGX_QL_MK_ERROR(0x0053), ///< SGX quote verification collateral version not supported by QVL/QvE SGX_QL_TDX_MODULE_MISMATCH = SGX_QL_MK_ERROR(0x0060), ///< TDX SEAM module identity is NOT match to Intel signed TDX SEAM module + SGX_QL_QEIDENTITY_NOT_FOUND = SGX_QL_MK_ERROR(0x0061), ///< QE identity was not found + SGX_QL_TCBINFO_NOT_FOUND = SGX_QL_MK_ERROR(0x0062), ///< TCB Info was not found + SGX_QL_INTERNAL_SERVER_ERROR = SGX_QL_MK_ERROR(0x0063), ///< Internal server error + + SGX_QL_SUPPLEMENTAL_DATA_VERSION_NOT_SUPPORTED = SGX_QL_MK_ERROR(0x0064), ///< The supplemental data version is not supported + + SGX_QL_ROOT_CA_UNTRUSTED = SGX_QL_MK_ERROR(0x0065), ///< The certificate used to establish SSL session is untrusted + SGX_QL_ERROR_MAX = SGX_QL_MK_ERROR(0x00FF), ///< Indicate max error to allow better translation. } quote3_error_t; diff --git a/QuoteGeneration/quote_wrapper/common/inc/sgx_quote_4.h b/QuoteGeneration/quote_wrapper/common/inc/sgx_quote_4.h index 11afbb87..1342821d 100644 --- a/QuoteGeneration/quote_wrapper/common/inc/sgx_quote_4.h +++ b/QuoteGeneration/quote_wrapper/common/inc/sgx_quote_4.h @@ -41,6 +41,7 @@ #include "sgx_quote_3.h" #include "sgx_report2.h" +#include "sgx_quote.h" #pragma pack(push, 1) @@ -151,6 +152,8 @@ typedef struct _sgx_quote4_t { #endif } sgx_quote4_t; +typedef sgx_att_key_id_ext_t tee_att_att_key_id_t; + #pragma pack(pop) #endif //_SGX_QUOTE_4_H_ diff --git a/QuoteGeneration/quote_wrapper/qgs/Makefile b/QuoteGeneration/quote_wrapper/qgs/Makefile index 30faa15c..762f567c 100644 --- a/QuoteGeneration/quote_wrapper/qgs/Makefile +++ b/QuoteGeneration/quote_wrapper/qgs/Makefile @@ -41,7 +41,7 @@ PROTOBUF_CFLAGS = `pkg-config --cflags protobuf-lite` QGS_INC = -I$(SGX_SDK)/include \ -I$(COMMON_DIR)/inc/internal \ -I$(TOP_DIR)/qpl/inc \ - -I$(TOP_DIR)/quote_wrapper/tdx_quote + -I$(TOP_DIR)/quote_wrapper/tdx_quote/inc QGS_CFLAGS = -g -MMD $(CFLAGS) $(QGS_INC) $(PROTOBUF_CFLAGS) QGS_CXXFLAGS = -g -MMD $(CXXFLAGS) $(QGS_INC) $(PROTOBUF_CFLAGS) ifeq ($(CC_NO_LESS_THAN_8), 1) @@ -57,7 +57,7 @@ QGS_LFLAGS = -L$(TOP_DIR)/build/linux -lsgx_tdx_logic -lsgx_pce_logic -ldl \ # add protobuf for link QGS_LFLAGS += `pkg-config --libs protobuf-lite` # add boost_system for link -QGS_LFLAGS += -lboost_system -lpthread +QGS_LFLAGS += -lboost_system -lboost_thread -lpthread vpath %.c $(COMMON_DIR)/src diff --git a/QuoteGeneration/quote_wrapper/qgs/qgs.conf b/QuoteGeneration/quote_wrapper/qgs/qgs.conf index 3d4b74bd..c0aa75d9 100644 --- a/QuoteGeneration/quote_wrapper/qgs/qgs.conf +++ b/QuoteGeneration/quote_wrapper/qgs/qgs.conf @@ -1,2 +1,3 @@ #set port number port = 4050 +number_threads = 4 diff --git a/QuoteGeneration/quote_wrapper/qgs/qgs_server.cpp b/QuoteGeneration/quote_wrapper/qgs/qgs_server.cpp index 5f161f6e..fec30a8d 100644 --- a/QuoteGeneration/quote_wrapper/qgs/qgs_server.cpp +++ b/QuoteGeneration/quote_wrapper/qgs/qgs_server.cpp @@ -29,27 +29,28 @@ * */ -#include "qgs_log.h" #include "qgs_server.h" -#include "qgs_msg_wrapper.h" #include "qgs.message.pb.h" -#include "td_ql_logic.h" +#include "qgs_log.h" +#include "qgs_msg_wrapper.h" #include "se_trace.h" -#include -#include -#include -#include -#include +#include "td_ql_wrapper.h" #include #include -#include -#include -#include -#include #include +#include #include +#include +#include +#include +#include +#include #include -#include +#include +#include +#include +#include +#include using namespace std; using boost::uint8_t; @@ -58,183 +59,219 @@ static const int QGS_TIMEOUT = 30; namespace intel { namespace sgx { namespace dcap { namespace qgs { +void cleanup(tee_att_config_t *p_ctx) { + QGS_LOG_INFO("About to delete ctx in cleanup\n"); + tee_att_free_context(p_ctx); + return; +} +boost::thread_specific_ptr ptr(cleanup); + +class QgsConnection : public boost::enable_shared_from_this { + public: + using Pointer = boost::shared_ptr; + using RequestPointer = boost::shared_ptr; + using ResponsePointer = boost::shared_ptr; + using ConnectionSet = boost::unordered_set; + static Pointer create(boost::mutex &connection_mtx, + ConnectionSet &connections, + asio::thread_pool &pool, + asio::io_service &io_service) { + return Pointer(new QgsConnection(connection_mtx, connections, pool, + io_service)); + } - class QgsConnection : public boost::enable_shared_from_this - { - public: - using Pointer = boost::shared_ptr; - using RequestPointer = boost::shared_ptr; - using ResponsePointer = boost::shared_ptr; - using ConnectionSet = boost::unordered_set; - static Pointer create(boost::mutex& connection_mtx, - ConnectionSet& connections, - asio::thread_pool& pool, - asio::io_service& io_service) { - return Pointer(new QgsConnection(connection_mtx, connections, pool, - io_service)); - } + gs::socket &get_socket() { + return m_socket; + } - gs::socket& get_socket() { - return m_socket; - } + void start() { + m_timer.expires_from_now(timeout); + m_timer.async_wait([this](boost::system::error_code ec) { + if (!ec) { + QGS_LOG_ERROR("timeout\n"); + stop(); + } + }); + start_read_header(); + } - void start() { - m_timer.expires_from_now(timeout); - m_timer.async_wait([this](boost::system::error_code ec) { - if (!ec) { - QGS_LOG_ERROR("timeout\n"); - stop(); - } - }); - start_read_header(); + void stop() { + boost::system::error_code ec; + QGS_LOG_INFO("About to shutdown and close socket\n"); + m_socket.shutdown(asio::socket_base::shutdown_both, ec); + m_socket.close(); + { + boost::lock_guard lock(m_connection_mtx); + m_connections.erase(shared_from_this()); + QGS_LOG_INFO("erased a connection, now [%d]\n", m_connections.size()); } + } - void stop() { - boost::system::error_code ec; - QGS_LOG_INFO("About to shutdown and close socket\n"); - m_socket.shutdown(asio::socket_base::shutdown_both, ec); - m_socket.close(); - { - boost::lock_guard lock(m_connection_mtx); - m_connections.erase(shared_from_this()); - QGS_LOG_INFO("erased a connection, now [%d]\n", m_connections.size()); - } + private: + boost::mutex &m_connection_mtx; + ConnectionSet &m_connections; + asio::thread_pool &m_pool; + gs::socket m_socket; + asio::deadline_timer m_timer; + vector m_readbuf; + QgsMsgWrapper m_packed_request; + + const boost::posix_time::time_duration timeout = + boost::posix_time::seconds(QGS_TIMEOUT); + + QgsConnection(boost::mutex &connection_mtx, + ConnectionSet &connections, + asio::thread_pool &pool, + asio::io_service &io_service) + : m_connection_mtx(connection_mtx), + m_connections(connections), + m_pool(pool), + m_socket(io_service), + m_timer(io_service), + m_packed_request(boost::shared_ptr(new Request())) { + } + + void handle_read_header(const boost::system::error_code &ec) { + std::ostringstream oss; + oss << ec.category().name() << ':' << ec.value(); + QGS_LOG_INFO("handle read header, status [%s]\n", + oss.str().c_str()); + if (!ec) { + QGS_LOG_INFO("Got header!\n"); + unsigned msg_len = m_packed_request.decode_header(m_readbuf); + QGS_LOG_INFO("body should be [%d] bytes!\n", msg_len); + start_read_body(msg_len); } + } - private: - boost::mutex& m_connection_mtx; - ConnectionSet& m_connections; - asio::thread_pool& m_pool; - gs::socket m_socket; - asio::deadline_timer m_timer; - vector m_readbuf; - QgsMsgWrapper m_packed_request; - - const boost::posix_time::time_duration timeout = - boost::posix_time::seconds(QGS_TIMEOUT); - - QgsConnection(boost::mutex &connection_mtx, - ConnectionSet &connections, - asio::thread_pool &pool, - asio::io_service &io_service) - : m_connection_mtx(connection_mtx), - m_connections(connections), - m_pool(pool), - m_socket(io_service), - m_timer(io_service), - m_packed_request(boost::shared_ptr(new Request())) { + void handle_read_body(const boost::system::error_code &ec) { + std::ostringstream oss; + oss << ec.category().name() << ':' << ec.value(); + QGS_LOG_INFO("handle read body status [%s]\n", + oss.str().c_str()); + if (!ec) { + QGS_LOG_INFO("Got body!\n"); + handle_request(); } + } - void handle_read_header(const boost::system::error_code& ec) { + void handle_request() { + if (m_packed_request.unpack(m_readbuf)) { std::ostringstream oss; - oss << ec.category().name() << ':' << ec.value(); - QGS_LOG_INFO("handle read header, status [%s]\n", + oss << boost::this_thread::get_id(); + QGS_LOG_INFO("unpack message successfully in thread [%s]\n", oss.str().c_str()); - if (!ec) { - QGS_LOG_INFO("Got header!\n"); - unsigned msg_len = m_packed_request.decode_header(m_readbuf); - QGS_LOG_INFO("body should be [%d] bytes!\n", msg_len); - start_read_body(msg_len); - } + RequestPointer req = m_packed_request.get_msg(); + asio::post(m_pool, [this, self = shared_from_this(), req] { + boost::system::error_code ec; + ResponsePointer resp = prepare_response(req); + + vector writebuf; + QgsMsgWrapper resp_msg(resp); + resp_msg.pack(writebuf); + std::ostringstream oss1; + oss1 << boost::this_thread::get_id(); + QGS_LOG_INFO("About to write response in thread [%s]\n", + oss1.str().c_str()); + asio::write(m_socket, asio::buffer(writebuf), ec); + m_timer.cancel(); + stop(); + }); } + } - void handle_read_body(const boost::system::error_code& ec) { - std::ostringstream oss; - oss << ec.category().name() << ':' << ec.value(); - QGS_LOG_INFO("handle read body status [%s]\n", - oss.str().c_str()); - if (!ec) { - QGS_LOG_INFO("Got body!\n"); - handle_request(); - } - } + void start_read_header() { + m_readbuf.resize(HEADER_SIZE); + asio::async_read(m_socket, asio::buffer(m_readbuf), + boost::bind(&QgsConnection::handle_read_header, + shared_from_this(), + asio::placeholders::error)); + } - void handle_request() { - if (m_packed_request.unpack(m_readbuf)) { + void start_read_body(unsigned msg_len) { + m_readbuf.resize(HEADER_SIZE + msg_len); + asio::mutable_buffers_1 buf = asio::buffer(&m_readbuf[HEADER_SIZE], + msg_len); + asio::async_read(m_socket, buf, + boost::bind(&QgsConnection::handle_read_body, + shared_from_this(), + asio::placeholders::error)); + } + + ResponsePointer prepare_response(RequestPointer req) { + ResponsePointer resp(new Response); + tee_att_error_t tee_att_ret = TEE_ATT_SUCCESS; + + QGS_LOG_INFO("enter prepare_response\n"); + if (ptr.get() == 0) { + tee_att_error_t ret = TEE_ATT_SUCCESS; + tee_att_config_t *p_ctx = NULL; + QGS_LOG_INFO("call tee_att_create_context\n"); + ret = tee_att_create_context(NULL, NULL, &p_ctx); + if (TEE_ATT_SUCCESS == ret) { std::ostringstream oss; oss << boost::this_thread::get_id(); - QGS_LOG_INFO("unpack message successfully in thread [%s]\n", - oss.str().c_str()); - RequestPointer req = m_packed_request.get_msg(); - asio::post(m_pool, [this, self = shared_from_this(), req] { - boost::system::error_code ec; - ResponsePointer resp = prepare_response(req); - - vector writebuf; - QgsMsgWrapper resp_msg(resp); - resp_msg.pack(writebuf); - std::ostringstream oss1; - oss1 << boost::this_thread::get_id(); - QGS_LOG_INFO("About to write response in thread [%s]\n", - oss1.str().c_str()); - asio::write(m_socket, asio::buffer(writebuf), ec); - m_timer.cancel(); - stop(); - }); + QGS_LOG_INFO("create context in thread[%s]\n", + oss.str().c_str()); + ptr.reset(p_ctx); + } else { + QGS_LOG_ERROR("Cannot create context\n"); } } - void start_read_header() { - m_readbuf.resize(HEADER_SIZE); - asio::async_read(m_socket, asio::buffer(m_readbuf), - boost::bind(&QgsConnection::handle_read_header, - shared_from_this(), - asio::placeholders::error)); - } - - void start_read_body(unsigned msg_len) { - m_readbuf.resize(HEADER_SIZE + msg_len); - asio::mutable_buffers_1 buf = asio::buffer(&m_readbuf[HEADER_SIZE], - msg_len); - asio::async_read(m_socket, buf, - boost::bind(&QgsConnection::handle_read_body, - shared_from_this(), - asio::placeholders::error)); - } - - ResponsePointer prepare_response(RequestPointer req) { - ResponsePointer resp(new Response); - quote3_error_t quote3_ret = SGX_QL_SUCCESS; - - switch (req->type()) { - case Request::MsgCase::kGetQuoteRequest: - { - uint32_t size = 0; - vector quote_buf; - auto get_quote_resp = new Response::GetQuoteResponse(); - resp->set_type(Response::kGetQuoteResponse); - quote3_ret = td_init_quote(PPID_RSA3072_ENCRYPTED, false); - if (SGX_QL_SUCCESS != quote3_ret) { + switch (req->type()) { + case Request::MsgCase::kGetQuoteRequest: { + uint32_t size = 0; + vector quote_buf; + auto get_quote_resp = new Response::GetQuoteResponse(); + resp->set_type(Response::kGetQuoteResponse); + + sgx_target_info_t qe_target_info; + uint8_t hash[32] = {0}; + size_t hash_size = sizeof(hash); + int retry = 1; + + do { + QGS_LOG_INFO("call tee_att_init_quote\n"); + tee_att_ret = tee_att_init_quote(ptr.get(), &qe_target_info, false, + &hash_size, + hash); + if (TEE_ATT_SUCCESS != tee_att_ret) { + get_quote_resp->set_error_code(1); + QGS_LOG_ERROR("tee_att_init_quote return 0x%x\n", tee_att_ret); + } else if (TEE_ATT_SUCCESS != (tee_att_ret = tee_att_get_quote_size(ptr.get(), &size))) { + get_quote_resp->set_error_code(1); + QGS_LOG_ERROR("tee_att_get_quote_size return 0x%x\n", tee_att_ret); + } else { + quote_buf.resize(size); + tee_att_ret = tee_att_get_quote(ptr.get(), + (uint8_t *)req->getquoterequest().report().c_str(), + (uint32_t)req->getquoterequest().report().length(), + NULL, + quote_buf.data(), + size); + if (TEE_ATT_SUCCESS != tee_att_ret) { get_quote_resp->set_error_code(1); - QGS_LOG_ERROR("td_init_quote return 0x%x\n", quote3_ret); - } - else if (SGX_QL_SUCCESS != (quote3_ret = td_get_quote_size(PPID_RSA3072_ENCRYPTED, &size))) { - get_quote_resp->set_error_code(1); - QGS_LOG_ERROR("td_get_quote_size return 0x%x\n", quote3_ret); + QGS_LOG_ERROR("tee_att_get_quote return 0x%x\n", tee_att_ret); } else { - quote_buf.resize(size); - quote3_ret = td_get_quote((sgx_report2_t *)(req->getquoterequest().report().c_str()), - (sgx_quote4_t *)quote_buf.data(), size); - if (SGX_QL_SUCCESS != quote3_ret) { - get_quote_resp->set_error_code(1); - QGS_LOG_ERROR("td_get_quote return 0x%x\n", quote3_ret); - } else { - get_quote_resp->set_error_code(0); - get_quote_resp->set_quote(quote_buf.data(), size); - QGS_LOG_ERROR("td_get_quote return Success\n"); - } + get_quote_resp->set_error_code(0); + get_quote_resp->set_quote(quote_buf.data(), size); + QGS_LOG_INFO("tee_att_get_quote return Success\n"); } - resp->set_allocated_getquoteresponse(get_quote_resp); - QGS_LOG_INFO("byte length is: %d\n", resp->ByteSize()); - break; } - default: - QGS_LOG_ERROR("Whoops, bad request!"); - break; - } - - return resp; + // Only return once when the return code is TEE_ATT_ATT_KEY_NOT_INITIALIZED + } while (TEE_ATT_ATT_KEY_NOT_INITIALIZED == tee_att_ret && retry--); + resp->set_allocated_getquoteresponse(get_quote_resp); + QGS_LOG_INFO("byte length is: %d\n", resp->ByteSize()); + break; } + default: + QGS_LOG_ERROR("Whoops, bad request!"); + break; + } + + return resp; + } }; @@ -244,8 +281,8 @@ namespace intel { namespace sgx { namespace dcap { namespace qgs { boost::mutex connection_mtx; boost::unordered_set> connections; boost::asio::thread_pool pool; - QgsServerImpl(asio::io_service& in_io_service, gs::endpoint& ep) - : pool(4), acceptor(in_io_service, ep), io_service(in_io_service) { + QgsServerImpl(asio::io_service &in_io_service, gs::endpoint &ep, uint8_t num_threads) + : pool(num_threads), acceptor(in_io_service, ep), io_service(in_io_service) { start_accept(); } @@ -297,9 +334,8 @@ namespace intel { namespace sgx { namespace dcap { namespace qgs { asio::io_service& io_service; }; - - QgsServer::QgsServer(asio::io_service& io_service, gs::endpoint& ep) - : d(new QgsServerImpl(io_service, ep)) { + QgsServer::QgsServer(asio::io_service &io_service, gs::endpoint &ep, uint8_t num_threads) + : d(new QgsServerImpl(io_service, ep, num_threads)) { } void QgsServer::shutdown() { diff --git a/QuoteGeneration/quote_wrapper/qgs/qgs_server.h b/QuoteGeneration/quote_wrapper/qgs/qgs_server.h index 83f96b47..3e0d38cb 100644 --- a/QuoteGeneration/quote_wrapper/qgs/qgs_server.h +++ b/QuoteGeneration/quote_wrapper/qgs/qgs_server.h @@ -32,6 +32,7 @@ #ifndef QGS_SERVER_H #define QGS_SERVER_H +#include #include #include @@ -42,9 +43,9 @@ namespace intel { namespace sgx { namespace dcap { namespace qgs { class QgsServer { public: - QgsServer(asio::io_service& io_service, gs::endpoint& ep); - ~QgsServer(); - void shutdown(); + QgsServer(asio::io_service &io_service, gs::endpoint &ep, uint8_t num_threads); + ~QgsServer(); + void shutdown(); private: QgsServer(); @@ -56,4 +57,3 @@ namespace intel { namespace sgx { namespace dcap { namespace qgs { }; }}}} #endif /* QGS_SERVER_H */ - diff --git a/QuoteGeneration/quote_wrapper/qgs/server_main.cpp b/QuoteGeneration/quote_wrapper/qgs/server_main.cpp index 5e498378..ca7c1b1b 100644 --- a/QuoteGeneration/quote_wrapper/qgs/server_main.cpp +++ b/QuoteGeneration/quote_wrapper/qgs/server_main.cpp @@ -37,6 +37,7 @@ #include #define QGS_CONFIG_FILE "/etc/qgs.conf" +#define QGS_UNIX_SOCKET_FILE "/var/run/tdx-qgs/qgs.socket" using namespace std; using namespace intel::sgx::dcap::qgs; @@ -71,9 +72,10 @@ int main(int argc, const char* argv[]) { bool no_daemon = false; unsigned long int port = 0; + unsigned long int num_threads = 0; char *endptr = NULL; - if (argc > 3) { - cout << "Usage: " << argv[0] << "[--no-daemon] [-p=port_number]" + if (argc > 4) { + cout << "Usage: " << argv[0] << "[--no-daemon] [-p=port_number] [-n=number_threads]" << endl; exit(1); } @@ -98,16 +100,30 @@ int main(int argc, const char* argv[]) } cout << "port number [" << port << "] found in cmdline" << endl; continue; + } else if (strncmp(argv[i], "-n=", 3) == 0) { + if (strspn(argv[i] + 3, "0123456789") != strlen(argv[i] + 3)) { + cout << "Please input valid thread number" << endl; + exit(1); + } + errno = 0; + num_threads = strtoul(argv[i] + 3, &endptr, 10); + if (errno || strlen(endptr) || (num_threads > 255)) { + cout << "Please input valid thread number[0, 255]" << endl; + exit(1); + } + cout << "thread number [" << num_threads << "] found in cmdline" << endl; + continue; } else { - cout << "Usage: " << argv[0] << "[--no-daemon] [-p=port_number]" - << endl; + cout << "Usage: " << argv[0] << "[--no-daemon] [-p=port_number] [-n=number_threads]" + << endl; exit(1); } } + // Use the port number in QGS_CONFIG_FILE if no valid port number on // command line - if (port == 0) { + if (port == 0 || num_threads == 0) { ifstream config_file(QGS_CONFIG_FILE); if (config_file.is_open()) { string line; @@ -127,7 +143,7 @@ int main(int argc, const char* argv[]) << endl; exit(1); } - if( name.compare("port") == 0) { + if (!port && name.compare("port") == 0) { errno = 0; endptr = NULL; port = strtoul(line.substr(delimiterPos + 1).c_str(), @@ -137,6 +153,16 @@ int main(int argc, const char* argv[]) << QGS_CONFIG_FILE << endl; exit(1); } + } else if (!num_threads && name.compare("number_threads") == 0) { + errno = 0; + endptr = NULL; + num_threads = strtoul(line.substr(delimiterPos + 1).c_str(), + &endptr, 10); + if (errno || strlen(endptr) || (num_threads > 255)) { + cout << "Please input valid thread number[0, 255] in " + << QGS_CONFIG_FILE << endl; + exit(1); + } } // ignore unrecognized configs. } @@ -146,9 +172,7 @@ int main(int argc, const char* argv[]) } if (port == 0) { - cout << "Please provide valid port number in cmdline or " - << QGS_CONFIG_FILE << endl; - exit(1); + cout << "Use unix socket: " << QGS_UNIX_SOCKET_FILE << endl; } if(!no_daemon && daemon(0, 0) < 0) { @@ -166,14 +190,21 @@ int main(int argc, const char* argv[]) do { reload = false; asio::io_service io_service; - struct sockaddr_vm vm_addr = {}; - vm_addr.svm_family = AF_VSOCK; - vm_addr.svm_reserved1 = 0; - vm_addr.svm_port = port & UINT_MAX; - vm_addr.svm_cid = VMADDR_CID_ANY; - asio::generic::stream_protocol::endpoint ep(&vm_addr, sizeof(vm_addr)); - QGS_LOG_INFO("About to create QgsServer\n"); - server = new QgsServer(io_service, ep); + gs::endpoint ep; + if (port) { + struct sockaddr_vm vm_addr = {}; + vm_addr.svm_family = AF_VSOCK; + vm_addr.svm_reserved1 = 0; + vm_addr.svm_port = port & UINT_MAX; + vm_addr.svm_cid = VMADDR_CID_ANY; + asio::generic::stream_protocol::endpoint vsock_ep(&vm_addr, sizeof(vm_addr)); + ep = vsock_ep; + } else { + asio::local::stream_protocol::endpoint unix_ep(QGS_UNIX_SOCKET_FILE); + ep = unix_ep; + } + QGS_LOG_INFO("About to create QgsServer with num_thread = %d\n", (uint8_t)num_threads); + server = new QgsServer(io_service, ep, (uint8_t)num_threads); QGS_LOG_INFO("About to start main loop\n"); io_service.run(); QGS_LOG_INFO("Quit main loop\n"); diff --git a/QuoteGeneration/quote_wrapper/quote/enclave/linux/config.xml b/QuoteGeneration/quote_wrapper/quote/enclave/linux/config.xml index 87a51d12..b52a8d23 100644 --- a/QuoteGeneration/quote_wrapper/quote/enclave/linux/config.xml +++ b/QuoteGeneration/quote_wrapper/quote/enclave/linux/config.xml @@ -2,7 +2,7 @@ 1 1 0x1 - 8 + 9 1 1 0 diff --git a/QuoteGeneration/quote_wrapper/quote/enclave/quoting_enclave_3.cpp b/QuoteGeneration/quote_wrapper/quote/enclave/quoting_enclave_3.cpp index 33bc9aae..aa36d616 100644 --- a/QuoteGeneration/quote_wrapper/quote/enclave/quoting_enclave_3.cpp +++ b/QuoteGeneration/quote_wrapper/quote/enclave/quoting_enclave_3.cpp @@ -161,6 +161,7 @@ const uint32_t g_sgx_nistp256_r_m1[] = {//hard-coded value for n-1 where n is or #define HASH_DRBG_OUT_LEN 40 //320 bits static const char QE_ID_STRING[] = "QE_ID_DER"; static const char QE_ATT_STRING[] = "QE_ATT_DER"; +static const sgx_key_128bit_t empty_qe_id = {0}; #define MAX_CERT_DATA_SIZE (4098*3) #define MIN_CERT_DATA_SIZE (500) @@ -398,6 +399,92 @@ static qe3_error_t get_att_key_based_from_seal_key(sgx_ec256_private_t *p_att_pr return ret; } +/** + * The QE_ID is a platform ID that is not associated with a particular SVN but is dependent on the Quoting Enclave's + * (QE) MRSIGNER and its Seal Key. The QE_ID is designed to be dependent on the seal key which is dependent on the + * platform's OWNER_EPOCH value. The OWNER_EPOCH value is set by the platform owner in the BIOS configuration. If the + * BIOS's non-volatile memory (FLASH) is wiped, then the QE_ID will change even if generated by the same QE. This + * prevents the QE_ID from being a true HW ID which cannot be modified by the platform owner. + * + * 1) QE_ID-Seed = EGETKEY(KEYNAME=SEAL_KEY, + * KEY_POLICY=MRSIGNER, + * KEY_ID = 0, + * CPUSVN=0, + * ISVSVN = 0) + * 2) QE_ID = AES128-CMAC(QE_ID-Seed, 16 bytes below) + * + * Byte Position | Value + * 0 | 0x00 + * 1-9 | "QE_ID_DER" (ascii encoded) + * 10-13 | 0x00000000 + * 14-15 | 0x0080 (Big Endian) + * + * @param p_qe_id[Out] Pointer to the QE_ID. Must not be NULL. + * + * @return REFQE3_SUCCESS Successfully created the QE_ID. + * @return REFQE3_ERROR_INVALID_PARAMETER The QE_ID pointer is NULL. + * @return REFQE3_ERROR_CRYPTO Error in the crypto library functions ues to generate the key. + * @return REFQE3_ERROR_OUT_OF_MEMORY Heap memory was exhausted. + * + */ +static qe3_error_t get_qe_id_internal(sgx_key_128bit_t *p_qe_id) +{ + sgx_status_t sgx_status = SGX_SUCCESS; + qe3_error_t ret = REFQE3_SUCCESS; + sgx_key_128bit_t key_tmp; + sgx_key_request_t qe_id_key_req; + + // Defense-in-depth. This is only called internally so should never be NULL + if (NULL == p_qe_id) { + return REFQE3_ERROR_INVALID_PARAMETER; + } + + memset(&key_tmp, 0, sizeof(key_tmp)); + + // Set up the key request structure for Seal Key with both CPUSVN and ISVSVN set to 0 and KeyID set to 0 + memset(&qe_id_key_req, 0, sizeof(sgx_key_request_t)); + qe_id_key_req.key_name = SGX_KEYSELECT_SEAL; // Seal key + qe_id_key_req.key_policy = SGX_KEYPOLICY_MRSIGNER; + qe_id_key_req.attribute_mask.xfrm = 0; + qe_id_key_req.misc_mask = 0xFFFFFFFF; + qe_id_key_req.attribute_mask.flags = ~SGX_FLAGS_MODE64BIT; //set all bits except the SGX_FLAGS_MODE64BIT + sgx_status = sgx_get_key(&qe_id_key_req, &key_tmp); + if (SGX_SUCCESS != sgx_status) { + ret = REFQE3_ERROR_CRYPTO; + goto ret_point; + } + + uint8_t content[16]; + memset(&content, 0, sizeof(content)); + //1-10bytes: "QE_ID_DER"(ascii encoded) + memcpy(content + 1, QE_ID_STRING, 9); + //14-15bytes: 0x0080 (Big Endian) + content[14] = 0x00; + content[15] = 0x80; + + // Generate the mac as QE_ID + ref_static_assert(sizeof(sgx_cmac_128bit_key_t) == sizeof(sgx_key_128bit_t)); + ref_static_assert(sizeof(sgx_cmac_128bit_tag_t) == sizeof(*p_qe_id)); + if ((sgx_status = sgx_rijndael128_cmac_msg(reinterpret_cast(&key_tmp), + content, + sizeof(content), + reinterpret_cast(p_qe_id))) != SGX_SUCCESS) { + if (sgx_status == SGX_ERROR_OUT_OF_MEMORY) { + ret = REFQE3_ERROR_OUT_OF_MEMORY; + } + else { + ret = REFQE3_ERROR_CRYPTO; + } + } + else { + ret = REFQE3_SUCCESS; + } + +ret_point: + (void)memset_s(&key_tmp, sizeof(key_tmp), 0, sizeof(key_tmp)); //clear provisioning key in stack + return ret; +} + /** * An internal function used to verify the ECDSA Blob. It will verify the format of the blob and check the * authenticity using the seal key. If the TCB of the platform has increased since the last time the blob was sealed, @@ -1080,6 +1167,11 @@ uint32_t gen_att_key(uint8_t *p_blob, goto ret_point; } + // Add QE_ID to the ECDSA Blob for backward compatible qe_logic to fill pck_cert_id. + ret = get_qe_id_internal(&plaintext_data.qe_id); + if (REFQE3_SUCCESS != ret) { + goto ret_point; + } plaintext_data.seal_blob_type = SGX_QL_SEAL_ECDSA_KEY_BLOB; plaintext_data.ecdsa_key_version = SGX_QL_ECDSA_KEY_BLOB_VERSION_0; // Call sgx_seal_data to generate the ECDSA Blob with the updated information @@ -1328,7 +1420,10 @@ uint32_t store_cert_data(ref_plaintext_ecdsa_data_sdk_t *p_plaintext_data, memcpy_s(&local_plaintext_data.raw_cpu_svn, sizeof(local_plaintext_data.raw_cpu_svn), &p_plaintext_data->raw_cpu_svn, sizeof(p_plaintext_data->raw_cpu_svn)); local_plaintext_data.raw_pce_info.pce_isv_svn = p_plaintext_data->raw_pce_info.pce_isv_svn; local_plaintext_data.raw_pce_info.pce_id = p_plaintext_data->raw_pce_info.pce_id; - memcpy_s(&local_plaintext_data.qe_id, sizeof(local_plaintext_data.qe_id), &p_plaintext_data->qe_id, sizeof(p_plaintext_data->qe_id)); + // Overwrite qe_id if provided in p_plaintext_data + if (memcmp(&p_plaintext_data->qe_id, &empty_qe_id, sizeof(sgx_key_128bit_t))) { + memcpy_s(&local_plaintext_data.qe_id, sizeof(local_plaintext_data.qe_id), &p_plaintext_data->qe_id, sizeof(p_plaintext_data->qe_id)); + } // Call sgx_seal_data to generate the ECDSA Blob with the updated information sgx_status = sgx_seal_data(sizeof(local_plaintext_data), @@ -1448,6 +1543,7 @@ uint32_t gen_quote(uint8_t *p_blob, sgx_ql_ppid_rsa3072_encrypted_cert_info_t *p_cert_encrypted_ppid_info_data; sgx_sha_state_handle_t sha_quote_context = NULL; sgx_report_data_t qe_report_data; + sgx_key_128bit_t qe_id = { 0 }; sgx_ec256_public_t le_att_pub_key; uint8_t verify_result = SGX_EC_INVALID_SIGNATURE; @@ -1596,7 +1692,17 @@ uint32_t gen_quote(uint8_t *p_blob, p_quote->header.att_key_type = SGX_QL_ALG_ECDSA_P256; p_quote->header.pce_svn = pce_isvsvn; // Both are little endian // Sizes of user_data and qe_id were checked above. If here, then sizes are OK without overflow. - memcpy(&p_quote->header.user_data, &plaintext.qe_id, sizeof(plaintext.qe_id)); + // Copy qe_id if provided in plaintext. + if (memcmp(&plaintext.qe_id, &empty_qe_id, sizeof(sgx_key_128bit_t))) { + memcpy(&p_quote->header.user_data, &plaintext.qe_id, sizeof(plaintext.qe_id)); + } + else { + ret = get_qe_id_internal(&qe_id); + if (REFQE3_SUCCESS != ret) { + goto ret_point; + } + memcpy(&p_quote->header.user_data, &qe_id, sizeof(qe_id)); + } // Copy in Intel's Vender ID memcpy(p_quote->header.vendor_id, g_vendor_id, 16); // Copy the incoming report into Quote body. diff --git a/QuoteGeneration/quote_wrapper/quote/enclave/win/config.xml b/QuoteGeneration/quote_wrapper/quote/enclave/win/config.xml index a243d6db..af3c5011 100644 --- a/QuoteGeneration/quote_wrapper/quote/enclave/win/config.xml +++ b/QuoteGeneration/quote_wrapper/quote/enclave/win/config.xml @@ -2,7 +2,7 @@ 1 1 0x1 - 8 + 9 1 1 0 diff --git a/QuoteGeneration/quote_wrapper/tdx-attest-rs/.gitignore b/QuoteGeneration/quote_wrapper/tdx-attest-rs/.gitignore new file mode 100644 index 00000000..07a1e397 --- /dev/null +++ b/QuoteGeneration/quote_wrapper/tdx-attest-rs/.gitignore @@ -0,0 +1,3 @@ +/target +Cargo.lock + diff --git a/QuoteGeneration/quote_wrapper/tdx-attest-rs/Cargo.toml b/QuoteGeneration/quote_wrapper/tdx-attest-rs/Cargo.toml new file mode 100644 index 00000000..2c98ed44 --- /dev/null +++ b/QuoteGeneration/quote_wrapper/tdx-attest-rs/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "tdx-attest-rs" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +tdx-attest-sys = { version = "0.1.0", path = "../tdx-attest-sys" } \ No newline at end of file diff --git a/QuoteGeneration/quote_wrapper/tdx-attest-rs/src/lib.rs b/QuoteGeneration/quote_wrapper/tdx-attest-rs/src/lib.rs new file mode 100644 index 00000000..9d5fb3e2 --- /dev/null +++ b/QuoteGeneration/quote_wrapper/tdx-attest-rs/src/lib.rs @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2011-2022 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. + * + */ + +//! This is the Intel TDX attestation library for Rust. +#![allow(non_camel_case_types)] + +use std::option::Option; +use std::mem; +pub use tdx_attest_sys::tdx_attest_error_t; +pub use tdx_attest_sys::tdx_report_data_t; +pub use tdx_attest_sys::tdx_report_t; +pub use tdx_attest_sys::tdx_rtmr_event_t; +pub use tdx_attest_sys::tdx_uuid_t; + +/// Request a Quote of the calling TD. +/// +/// # Param +/// - **tdx_report_data**\ +/// A set of data that the caller/TD wants to cryptographically bind to the Quote, typically a hash. May be all zeros for the Report data. +/// - **att_key_id_list**\ +/// List (array) of the attestation key IDs supported by the Quote verifier. +/// - **att_key_id**\ +/// The selected attestation key ID when the function returns. +/// - **flags**\ +/// Reserved, must be zero. +/// +/// # Return +/// - ***TDX_ATTEST_SUCCESS***\ +/// Successfully generated the Quote.\ +/// - ***TDX_ATT_ERROR_INVALID_PARAMETER***\ +/// The parameter is incorrect.\ +/// - ***TDX_ATTEST_ERROR_DEVICE_FAILURE***\ +/// Failed to acess tdx attest device.\ +/// - ***TDX_ATTEST_ERROR_VSOCK_FAILURE***\ +/// vsock related failure.\ +/// - ***TDX_ATTEST_ERROR_OUT_OF_MEMORY***\ +/// Heap memory allocation error in library or enclave.\ +/// - ***TDX_ATT_ERROR_UNEXPECTED***\ +/// An unexpected internal error occurred.\ +/// +/// # Examples +/// ``` +/// use tdx_attest_rs::*; +/// +/// let tdx_report_data = tdx_report_data_t{ +/// d: [0; 64usize], +/// }; +/// let att_key_id_list = [tdx_uuid_t{ +/// d: [0; 16usize], +/// }; 2usize]; +/// let list_size = 1024; +/// let mut att_key_id = tdx_uuid_t{ +/// d: [0; 16usize], +/// }; +/// let result = tdx_att_get_quote(Some(&tdx_report_data), Some(&att_key_id_list), Some(&mut att_key_id), 0); +/// ``` +pub fn tdx_att_get_quote( + tdx_report_data: Option<&tdx_report_data_t>, + att_key_id_list: Option<&[tdx_uuid_t]>, + att_key_id: Option<&mut tdx_uuid_t>, + flags: u32, +) -> (tdx_attest_error_t, Option>) { + let p_tdx_report_data = match tdx_report_data { + Some(p) => p as *const tdx_report_data_t, + None => std::ptr::null_mut(), + }; + let (p_att_key_id_list, att_key_id_list_size) = match att_key_id_list { + Some(p) => { + (p.as_ptr() as *const tdx_uuid_t, p.len() as u32) + }, + None => (std::ptr::null(), 0u32), + }; + let p_att_key_id = match att_key_id { + Some(p) => p as *mut tdx_uuid_t, + None => std::ptr::null_mut(), + }; + let mut buf = std::ptr::null_mut(); + let mut buf_len = 0; + unsafe { + let result = tdx_attest_sys::tdx_att_get_quote(p_tdx_report_data, p_att_key_id_list, att_key_id_list_size, p_att_key_id, + &mut buf, &mut buf_len, flags); + match result { + tdx_attest_error_t::TDX_ATTEST_SUCCESS => { + assert!(!buf.is_null()); + assert!(buf_len > 0); + let quote = std::slice::from_raw_parts(buf, buf_len as usize).to_vec(); + tdx_attest_sys::tdx_att_free_quote(buf); + return (result, Some(quote)) + }, + _ => return (result, None), + } + } +} + +/// Request a TDX Report of the calling TD. +/// +/// # Param +/// - **tdx_report_data**\ +/// A set of data that the caller/TD wants to cryptographically bind to the Quote, typically a hash. May be all zeros for the Report data. +/// - **tdx_report**\ +/// the generated TDX Report. +/// +/// # Return +/// - ***TDX_ATTEST_SUCCESS***\ +/// Successfully generate report.\ +/// - ***TDX_ATTEST_ERROR_INVALID_PARAMETER***\ +/// The parameter is incorrect. +/// - ***TDX_ATTEST_ERROR_DEVICE_FAILURE***\ +/// Failed to acess tdx attest device.\ +/// - ***TDX_ATTEST_ERROR_REPORT_FAILURE***\ +/// Failed to get the TD Report.\ +/// - ***TDX_ATT_ERROR_UNEXPECTED***\ +/// An unexpected internal error occurred.\ +/// +/// # Examples +/// ``` +/// use tdx_attest_rs::*; +/// +/// let tdx_report_data = tdx_report_data_t{ +/// d: [0; 64usize], +/// }; +/// let mut tdx_report =tdx_report_t{ +/// d: [0; 1024usize], +/// }; +/// let result = tdx_att_get_report(Some(&tdx_report_data), &mut tdx_report); +/// ``` +pub fn tdx_att_get_report( + tdx_report_data: Option<&tdx_report_data_t>, + tdx_report: &mut tdx_report_t, +) -> tdx_attest_error_t { + let p_tdx_report_data = match tdx_report_data { + Some(p) => p as *const tdx_report_data_t, + None => std::ptr::null_mut(), + }; + unsafe { + tdx_attest_sys::tdx_att_get_report(p_tdx_report_data, tdx_report) + } +} + +/// Extend one of the TDX runtime measurement registers (RTMRs). +/// +/// # Param +/// - **rtmr_event**\ +/// A set of data that contains the index of the RTMR to extend, the data with which to extend it and a description of the data. +/// +/// # Return +/// - ***TDX_ATTEST_SUCCESS***\ +/// Successfully extended the RTMR.\ +/// - ***TDX_ATTEST_ERROR_INVALID_PARAMETER***\ +/// The parameter is incorrect. +/// - ***TDX_ATTEST_ERROR_DEVICE_FAILURE***\ +/// Failed to acess tdx attest device.\ +/// - ***TDX_ATTEST_ERROR_EXTEND_FAILURE***\ +/// Failed to extend data.\ +/// - ***TDX_ATTEST_ERROR_NOT_SUPPORTED***\ +/// rtmr_event.event_data_size != 0.\ +/// - ***TDX_ATT_ERROR_UNEXPECTED***\ +/// An unexpected internal error occurred.\ +/// +/// # Examples +/// ``` +/// use tdx_attest_rs::*; +/// +/// let rtmr_event = [0u8; 68usize]; +/// let result = tdx_att_extend(&rtmr_event); +/// ``` + +pub fn tdx_att_extend( + rtmr_event: &[u8], +) -> tdx_attest_error_t { + if rtmr_event.len() < mem::size_of::() { + return tdx_attest_error_t::TDX_ATTEST_ERROR_INVALID_PARAMETER; + } + unsafe { + let s: tdx_rtmr_event_t = std::ptr::read(rtmr_event.as_ptr() as *const _); + if rtmr_event.len() - mem::size_of::() != s.event_data_size as usize { + return tdx_attest_error_t::TDX_ATTEST_ERROR_INVALID_PARAMETER; + } + tdx_attest_sys::tdx_att_extend(rtmr_event.as_ptr() as *const tdx_rtmr_event_t) + } +} + +/// Retrieve the list of attestation key IDs supported by the platform. +/// +/// # Param +/// +/// # Return +/// - ***TDX_ATTEST_SUCCESS***\ +/// Successfully populated the att_key_id_list.\ +/// - ***TDX_ATT_ERROR_UNEXPECTED***\ +/// An unexpected internal error occurred.\ +/// +/// # Examples +/// ``` +/// use tdx_attest_rs::*; +/// let (result, att_key_id_list) = tdx_att_get_supported_att_key_ids(); +/// ``` +pub fn tdx_att_get_supported_att_key_ids( +) -> (tdx_attest_error_t, Option>){ + const MAX_ATT_KEY_ID_COUNT: usize = 20; + let mut list_count = 0; + unsafe { + let result = tdx_attest_sys::tdx_att_get_supported_att_key_ids(std::ptr::null_mut() as *mut tdx_uuid_t, &mut list_count); + match result { + tdx_attest_error_t::TDX_ATTEST_SUCCESS => { + if list_count > MAX_ATT_KEY_ID_COUNT as u32 { + return (tdx_attest_error_t::TDX_ATTEST_ERROR_UNEXPECTED, None); + } + let box_buf: Box<[tdx_uuid_t; MAX_ATT_KEY_ID_COUNT]> = Box::new([tdx_uuid_t{d: [0; 16usize],}; MAX_ATT_KEY_ID_COUNT]); + let p_buf = Box::into_raw(box_buf); + let result = tdx_attest_sys::tdx_att_get_supported_att_key_ids(p_buf as *mut tdx_uuid_t, &mut list_count); + let att_key_id_list = Box::from_raw(p_buf)[..list_count as usize].to_vec(); + match result { + tdx_attest_error_t::TDX_ATTEST_SUCCESS => { + return (result, Some(att_key_id_list)) + }, + _ => return (result, None), + } + }, + _ => return (result, None), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_tdx_att_get_report() { + let tdx_report_data = tdx_report_data_t{ + d: [0; 64usize], + }; + let mut tdx_report = tdx_report_t{ + d: [0; 1024usize], + + }; + let result = tdx_att_get_report(Some(&tdx_report_data), &mut tdx_report); + assert_eq!(result, tdx_attest_error_t::TDX_ATTEST_ERROR_DEVICE_FAILURE); + } + + #[test] + fn test_tdx_att_get_quote() { + let tdx_report_data = tdx_report_data_t{ + d: [0; 64usize], + }; + let mut att_key_id = tdx_uuid_t{ + d: [0; 16usize], + }; + let (result, quote) = tdx_att_get_quote(Some(&tdx_report_data), None, Some(&mut att_key_id), 0); + println!("att_key_id {:?}", att_key_id.d); + match quote { + q => println!("quote {:?}", q), + } + assert_eq!(result,tdx_attest_error_t::TDX_ATTEST_ERROR_DEVICE_FAILURE); + } + + #[test] + fn test_tdx_att_extend() { + let mut rtmr_event = [0u8; mem::size_of::()]; + rtmr_event[0] = 1; + let result = tdx_att_extend(&rtmr_event); + assert_eq!(result,tdx_attest_error_t::TDX_ATTEST_ERROR_DEVICE_FAILURE); + } + + #[test] + fn test_tdx_att_get_supported_att_key_ids() { + let (result, att_key_ids) = tdx_att_get_supported_att_key_ids(); + let ids = att_key_ids.unwrap(); + println!("att_key_id size {:?}", ids.len()); + for id in ids { + println!("att_key_id {:?}", id.d); + } + assert_eq!(result,tdx_attest_error_t::TDX_ATTEST_SUCCESS); + } +} diff --git a/QuoteGeneration/quote_wrapper/tdx-attest-sys/.gitignore b/QuoteGeneration/quote_wrapper/tdx-attest-sys/.gitignore new file mode 100644 index 00000000..96ef6c0b --- /dev/null +++ b/QuoteGeneration/quote_wrapper/tdx-attest-sys/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/QuoteGeneration/quote_wrapper/tdx-attest-sys/Cargo.toml b/QuoteGeneration/quote_wrapper/tdx-attest-sys/Cargo.toml new file mode 100644 index 00000000..ad0106e0 --- /dev/null +++ b/QuoteGeneration/quote_wrapper/tdx-attest-sys/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "tdx-attest-sys" +version = "0.1.0" +edition = "2018" +links = "tdx_attest" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] + +[build-dependencies] +bindgen = "0.59.1" diff --git a/SampleCode/TDQuoteVerificationSample/Enclave/Enclave.cpp b/QuoteGeneration/quote_wrapper/tdx-attest-sys/bindings.h similarity index 86% rename from SampleCode/TDQuoteVerificationSample/Enclave/Enclave.cpp rename to QuoteGeneration/quote_wrapper/tdx-attest-sys/bindings.h index 29fad8d4..91431c03 100644 --- a/SampleCode/TDQuoteVerificationSample/Enclave/Enclave.cpp +++ b/QuoteGeneration/quote_wrapper/tdx-attest-sys/bindings.h @@ -29,13 +29,4 @@ * */ -#include "Enclave_t.h" /* print_string */ -#include -#include /* vsnprintf */ -#include -#include "sgx_utils.h" - - -sgx_status_t ecall_get_target_info(sgx_target_info_t* target_info) { - return sgx_self_target(target_info); -} +#include "tdx_attest.h" diff --git a/QuoteGeneration/quote_wrapper/tdx-attest-sys/build.rs b/QuoteGeneration/quote_wrapper/tdx-attest-sys/build.rs new file mode 100644 index 00000000..7423559e --- /dev/null +++ b/QuoteGeneration/quote_wrapper/tdx-attest-sys/build.rs @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2011-2022 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. + * + */ + +extern crate bindgen; + +use std::env; +use std::path::PathBuf; + +fn main() { + // Tell cargo to tell rustc to link the system tdx_attest + // shared library. + println!("cargo:rustc-link-lib=tdx_attest"); + + // Tell cargo to invalidate the built crate whenever the wrapper changes + println!("cargo:rerun-if-changed=bingings.h"); + + // Set sdk to search path if SGX_SDK is in environment variable + let mut sdk_inc = String::from("-I"); + match env::var("SGX_SDK") { + Ok(val) => { + sdk_inc.push_str(&val); + sdk_inc.push_str("/include/"); + }, + _ => (), + } + + // The bindgen::Builder is the main entry point + // to bindgen, and lets you build up options for + // the resulting bindings. + let bindings = bindgen::Builder::default() + // The input header we would like to generate + // bindings for. + .header("bindings.h") + // Include search path + .clang_arg(sdk_inc) + // Convert C enum to Rust enum + .rustified_enum("_tdx_attest_error_t") + // Disable debug trait for packed C structures + .no_debug("_tdx_uuid_t") + .no_debug("_tdx_report_data_t") + .no_debug("_tdx_report_t") + .no_debug("_tdx_rtmr_event_t") + + // Tell cargo to invalidate the built crate whenever any of the + // included header files changed. + .parse_callbacks(Box::new(bindgen::CargoCallbacks)) + // Finish the builder and generate the bindings. + .generate() + // Unwrap the Result and panic on failure. + .expect("Unable to generate bindings"); + + // Write the bindings to the $OUT_DIR/bindings.rs file. + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); +} diff --git a/QuoteGeneration/quote_wrapper/tdx-attest-sys/src/lib.rs b/QuoteGeneration/quote_wrapper/tdx-attest-sys/src/lib.rs new file mode 100644 index 00000000..0004d995 --- /dev/null +++ b/QuoteGeneration/quote_wrapper/tdx-attest-sys/src/lib.rs @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2011-2022 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. + * + */ +//! Intel(R) Software Guard Extensions Data Center Attestation Primitives (Intel(R) SGX DCAP) +//! Rust raw FFI bindings for TDX Attestation Library +//! ================================================ +//! +//! Please install the following prerequisite: +//! * Intel(R) SGX DCAP Driver +//! * Intel(R) SGX SDK +//! * Intel(R) SGX DCAP Packages +//! * Intel(R) SGX DCAP PCCS (Provisioning Certificate Caching Service) +//! +//! *Please refer to [SGX DCAP Linux installation guide]( +//! https://download.01.org/intel-sgx/sgx-dcap/#version#/linux/docs/Intel_SGX_SW_Installation_Guide_for_Linux.pdf) +//! to install above dependencies.* +//! +//! *Note that you need to change **\#version\#** to actual version number in URL, such as 1.4.*\ +//! *Note that you need to install **libtdx-attest-dev** and **clang** for this package.* + +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/QuoteGeneration/quote_wrapper/tdx_attest/tdx_attest.c b/QuoteGeneration/quote_wrapper/tdx_attest/tdx_attest.c index 24183b55..7c0565ff 100644 --- a/QuoteGeneration/quote_wrapper/tdx_attest/tdx_attest.c +++ b/QuoteGeneration/quote_wrapper/tdx_attest/tdx_attest.c @@ -196,7 +196,7 @@ tdx_attest_error_t tdx_att_get_quote( get_quote_blob_t *p_get_quote_blob = NULL; tdx_report_t tdx_report; uint32_t msg_size = 0; - Qgs__Message__Response *resp; + Qgs__Message__Response *resp = NULL; Qgs__Message__Request request = QGS__MESSAGE__REQUEST__INIT; Qgs__Message__Request__GetQuoteRequest get_quote_request = QGS__MESSAGE__REQUEST__GET_QUOTE_REQUEST__INIT; @@ -406,6 +406,7 @@ tdx_attest_error_t tdx_att_get_quote( if (-1 != devfd) { close(devfd); } + protobuf_c_message_free_unpacked((ProtobufCMessage *)resp, NULL); free(p_get_quote_blob); return ret; diff --git a/QuoteGeneration/quote_wrapper/tdx_attest/tdx_attest.h b/QuoteGeneration/quote_wrapper/tdx_attest/tdx_attest.h index 0c79cc67..f4126c33 100644 --- a/QuoteGeneration/quote_wrapper/tdx_attest/tdx_attest.h +++ b/QuoteGeneration/quote_wrapper/tdx_attest/tdx_attest.h @@ -62,7 +62,7 @@ typedef enum _tdx_attest_error_t { #pragma pack(push, 1) #define TDX_UUID_SIZE 16 -typedef struct tdx_uuid_t +typedef struct _tdx_uuid_t { uint8_t d[TDX_UUID_SIZE]; } tdx_uuid_t; @@ -149,6 +149,7 @@ extern "C" { * @return TDX_ATTEST_SUCCESS: Successfully generated the Quote. * @return TDX_ATTEST_ERROR_UNEXPECTED: An unexpected internal error occurred. * @return TDX_ATTEST_ERROR_INVALID_PARAMETER: The parameter is incorrect + * @return TDX_ATTEST_ERROR_DEVICE_FAILURE: Failed to acess tdx attest device. * @return TDX_ATTEST_ERROR_REPORT_FAILURE: Failed to get TD report. * @return TDX_ATTEST_ERROR_VSOCK_FAILURE: Failed read/write in vsock mode * @return TDX_ATTEST_ERROR_QUOTE_FAILURE: Failed to get quote from QGS @@ -191,6 +192,7 @@ tdx_attest_error_t tdx_att_free_quote( * generated TDX Report. Must not be NULL. * @return TDX_ATTEST_SUCCESS: Successfully generated the Report. * @return TDX_ATTEST_ERROR_INVALID_PARAMETER: p_tdx_report == NULL + * @return TDX_ATTEST_ERROR_DEVICE_FAILURE: Failed to acess tdx attest device. * @return TDX_ATTEST_ERROR_REPORT_FAILURE: Failed to get TD report. */ tdx_attest_error_t tdx_att_get_report( @@ -217,6 +219,7 @@ tdx_attest_error_t tdx_att_get_report( * @return TDX_ATTEST_SUCCESS: Successfully extended the RTMR. * @return TDX_ATTEST_ERROR_INVALID_PARAMETER: p_rtmr_event == NULL * @return TDX_ATTEST_ERROR_UNEXPECTED: An unexpected internal error occurred. + * @return TDX_ATTEST_ERROR_DEVICE_FAILURE: Failed to acess tdx attest device. * @return TDX_ATTEST_ERROR_EXTEND_FAILURE: Failed to extend data. * @return TDX_ATTEST_ERROR_NOT_SUPPORTED: p_rtmr_event->event_data_size != 0 */ diff --git a/QuoteGeneration/quote_wrapper/tdx_quote/inc/td_ql_wrapper.h b/QuoteGeneration/quote_wrapper/tdx_quote/inc/td_ql_wrapper.h new file mode 100644 index 00000000..dd7d3a48 --- /dev/null +++ b/QuoteGeneration/quote_wrapper/tdx_quote/inc/td_ql_wrapper.h @@ -0,0 +1,365 @@ +/* + * 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. + * + */ +/** + * File: td_ql_wrapper.h + * + * Description: API definitions for TD quote library + * + */ +#ifndef _TD_QL_WRAPPER_H_ +#define _TD_QL_WRAPPER_H_ +#include "sgx_quote_4.h" + +#define TEE_ATT_MK_ERROR(x) (0x00011000|(x)) + +/** Possible errors generated by the quote interface. */ +typedef enum _tee_att_error_t { + TEE_ATT_SUCCESS = 0x0000, ///< Success + TEE_ATT_ERROR_MIN = TEE_ATT_MK_ERROR(0x0001), ///< Indicate min error to allow better translation. + TEE_ATT_ERROR_UNEXPECTED = TEE_ATT_MK_ERROR(0x0001), ///< Unexpected error + TEE_ATT_ERROR_INVALID_PARAMETER = TEE_ATT_MK_ERROR(0x0002), ///< The parameter is incorrect + TEE_ATT_ERROR_OUT_OF_MEMORY = TEE_ATT_MK_ERROR(0x0003), ///< Not enough memory is available to complete this operation + TEE_ATT_ERROR_ECDSA_ID_MISMATCH = TEE_ATT_MK_ERROR(0x0004), ///< Expected ECDSA_ID does not match the value stored in the ECDSA Blob + TEE_ATT_PATHNAME_BUFFER_OVERFLOW_ERROR = TEE_ATT_MK_ERROR(0x0005), ///< The ECDSA blob pathname is too large + TEE_ATT_FILE_ACCESS_ERROR = TEE_ATT_MK_ERROR(0x0006), ///< Error accessing ECDSA blob + TEE_ATT_ERROR_STORED_KEY = TEE_ATT_MK_ERROR(0x0007), ///< Cached ECDSA key is invalid + TEE_ATT_ERROR_PUB_KEY_ID_MISMATCH = TEE_ATT_MK_ERROR(0x0008), ///< Cached ECDSA key does not match requested key + TEE_ATT_ERROR_INVALID_PCE_SIG_SCHEME = TEE_ATT_MK_ERROR(0x0009), ///< PCE use the incorrect signature scheme + TEE_ATT_ATT_KEY_BLOB_ERROR = TEE_ATT_MK_ERROR(0x000a), ///< There is a problem with the attestation key blob. + TEE_ATT_UNSUPPORTED_ATT_KEY_ID = TEE_ATT_MK_ERROR(0x000b), ///< Unsupported attestation key ID. + TEE_ATT_UNSUPPORTED_LOADING_POLICY = TEE_ATT_MK_ERROR(0x000c), ///< Unsupported enclave loading policy. + TEE_ATT_INTERFACE_UNAVAILABLE = TEE_ATT_MK_ERROR(0x000d), ///< Unable to load the QE enclave + TEE_ATT_PLATFORM_LIB_UNAVAILABLE = TEE_ATT_MK_ERROR(0x000e), ///< Unable to find the platform library with the dependent APIs. Not fatal. + TEE_ATT_ATT_KEY_NOT_INITIALIZED = TEE_ATT_MK_ERROR(0x000f), ///< The attestation key doesn't exist or has not been certified. + TEE_ATT_ATT_KEY_CERT_DATA_INVALID = TEE_ATT_MK_ERROR(0x0010), ///< The certification data retrieved from the platform library is invalid. + TEE_ATT_NO_PLATFORM_CERT_DATA = TEE_ATT_MK_ERROR(0x0011), ///< The platform library doesn't have any platfrom cert data. + TEE_ATT_OUT_OF_EPC = TEE_ATT_MK_ERROR(0x0012), ///< Not enough memory in the EPC to load the enclave. + TEE_ATT_ERROR_REPORT = TEE_ATT_MK_ERROR(0x0013), ///< There was a problem verifying an SGX REPORT. + TEE_ATT_ENCLAVE_LOST = TEE_ATT_MK_ERROR(0x0014), ///< Interfacing to the enclave failed due to a power transition. + TEE_ATT_INVALID_REPORT = TEE_ATT_MK_ERROR(0x0015), ///< Error verifying the application enclave's report. + TEE_ATT_ENCLAVE_LOAD_ERROR = TEE_ATT_MK_ERROR(0x0016), ///< Unable to load the enclaves. Could be due to file I/O error, loading infrastructure error, or non-SGX capable system + TEE_ATT_UNABLE_TO_GENERATE_QE_REPORT = TEE_ATT_MK_ERROR(0x0017), ///< The QE was unable to generate its own report targeting the application enclave either + ///< because the QE doesn't support this feature there is an enclave compatibility issue. + ///< Please call again with the p_qe_report_info to NULL. + TEE_ATT_KEY_CERTIFCATION_ERROR = TEE_ATT_MK_ERROR(0x0018), ///< Caused when the provider library returns an invalid TCB (too high). + TEE_ATT_NETWORK_ERROR = TEE_ATT_MK_ERROR(0x0019), ///< Network error when retrieving PCK certs + TEE_ATT_MESSAGE_ERROR = TEE_ATT_MK_ERROR(0x001a), ///< Message error when retrieving PCK certs + TEE_ATT_NO_QUOTE_COLLATERAL_DATA = TEE_ATT_MK_ERROR(0x001b), ///< The platform does not have the quote verification collateral data available. + TEE_ATT_QUOTE_CERTIFICATION_DATA_UNSUPPORTED = TEE_ATT_MK_ERROR(0x001c), + TEE_ATT_QUOTE_FORMAT_UNSUPPORTED = TEE_ATT_MK_ERROR(0x001d), + TEE_ATT_UNABLE_TO_GENERATE_REPORT = TEE_ATT_MK_ERROR(0x001e), + TEE_ATT_QE_REPORT_INVALID_SIGNATURE = TEE_ATT_MK_ERROR(0x001f), + TEE_ATT_QE_REPORT_UNSUPPORTED_FORMAT = TEE_ATT_MK_ERROR(0x0020), + TEE_ATT_PCK_CERT_UNSUPPORTED_FORMAT = TEE_ATT_MK_ERROR(0x0021), + TEE_ATT_PCK_CERT_CHAIN_ERROR = TEE_ATT_MK_ERROR(0x0022), + TEE_ATT_TCBINFO_UNSUPPORTED_FORMAT = TEE_ATT_MK_ERROR(0x0023), + TEE_ATT_TCBINFO_MISMATCH = TEE_ATT_MK_ERROR(0x0024), + TEE_ATT_QEIDENTITY_UNSUPPORTED_FORMAT = TEE_ATT_MK_ERROR(0x0025), + TEE_ATT_QEIDENTITY_MISMATCH = TEE_ATT_MK_ERROR(0x0026), + TEE_ATT_TCB_OUT_OF_DATE = TEE_ATT_MK_ERROR(0x0027), + TEE_ATT_TCB_OUT_OF_DATE_CONFIGURATION_NEEDED = TEE_ATT_MK_ERROR(0x0028), ///< TCB out of date and Configuration needed + TEE_ATT_SGX_ENCLAVE_IDENTITY_OUT_OF_DATE = TEE_ATT_MK_ERROR(0x0029), + TEE_ATT_SGX_ENCLAVE_REPORT_ISVSVN_OUT_OF_DATE = TEE_ATT_MK_ERROR(0x002a), + TEE_ATT_QE_IDENTITY_OUT_OF_DATE = TEE_ATT_MK_ERROR(0x002b), + TEE_ATT_SGX_TCB_INFO_EXPIRED = TEE_ATT_MK_ERROR(0x002c), + TEE_ATT_SGX_PCK_CERT_CHAIN_EXPIRED = TEE_ATT_MK_ERROR(0x002d), + TEE_ATT_SGX_CRL_EXPIRED = TEE_ATT_MK_ERROR(0x002e), + TEE_ATT_SGX_SIGNING_CERT_CHAIN_EXPIRED = TEE_ATT_MK_ERROR(0x002f), + TEE_ATT_SGX_ENCLAVE_IDENTITY_EXPIRED = TEE_ATT_MK_ERROR(0x0030), + TEE_ATT_PCK_REVOKED = TEE_ATT_MK_ERROR(0x0031), + TEE_ATT_TCB_REVOKED = TEE_ATT_MK_ERROR(0x0032), + TEE_ATT_TCB_CONFIGURATION_NEEDED = TEE_ATT_MK_ERROR(0x0033), + TEE_ATT_UNABLE_TO_GET_COLLATERAL = TEE_ATT_MK_ERROR(0x0034), + TEE_ATT_ERROR_INVALID_PRIVILEGE = TEE_ATT_MK_ERROR(0x0035), ///< No enough privilege to perform the operation + TEE_ATT_NO_QVE_IDENTITY_DATA = TEE_ATT_MK_ERROR(0x0037), ///< The platform does not have the QVE identity data available. + TEE_ATT_CRL_UNSUPPORTED_FORMAT = TEE_ATT_MK_ERROR(0x0038), + TEE_ATT_QEIDENTITY_CHAIN_ERROR = TEE_ATT_MK_ERROR(0x0039), + TEE_ATT_TCBINFO_CHAIN_ERROR = TEE_ATT_MK_ERROR(0x003a), + TEE_ATT_ERROR_QVL_QVE_MISMATCH = TEE_ATT_MK_ERROR(0x003b), ///< QvE returned supplemental data version mismatched between QVL and QvE + TEE_ATT_TCB_SW_HARDENING_NEEDED = TEE_ATT_MK_ERROR(0x003c), ///< TCB up to date but SW Hardening needed + TEE_ATT_TCB_CONFIGURATION_AND_SW_HARDENING_NEEDED = TEE_ATT_MK_ERROR(0x003d), ///< TCB up to date but Configuration and SW Hardening needed + + TEE_ATT_UNSUPPORTED_MODE = TEE_ATT_MK_ERROR(0x003e), + + TEE_ATT_NO_DEVICE = TEE_ATT_MK_ERROR(0x003f), + TEE_ATT_SERVICE_UNAVAILABLE = TEE_ATT_MK_ERROR(0x0040), + TEE_ATT_NETWORK_FAILURE = TEE_ATT_MK_ERROR(0x0041), + TEE_ATT_SERVICE_TIMEOUT = TEE_ATT_MK_ERROR(0x0042), + TEE_ATT_ERROR_BUSY = TEE_ATT_MK_ERROR(0x0043), + + TEE_ATT_UNKNOWN_MESSAGE_RESPONSE = TEE_ATT_MK_ERROR(0x0044), /// Unexpected error from the cache service + TEE_ATT_PERSISTENT_STORAGE_ERROR = TEE_ATT_MK_ERROR(0x0045), /// Error storing the retrieved cached data in persistent memory + TEE_ATT_ERROR_MESSAGE_PARSING_ERROR = TEE_ATT_MK_ERROR(0x0046), /// Message parsing error + TEE_ATT_PLATFORM_UNKNOWN = TEE_ATT_MK_ERROR(0x0047), /// Platform was not found in the cache + TEE_ATT_UNKNOWN_API_VERSION = TEE_ATT_MK_ERROR(0x0048), /// The current PCS API version configured is unknown + TEE_ATT_CERTS_UNAVAILABLE = TEE_ATT_MK_ERROR(0x0049), /// Certificates are not available for this platform + + TEE_ATT_QVEIDENTITY_MISMATCH = TEE_ATT_MK_ERROR(0x0050), ///< QvE Identity is NOT match to Intel signed QvE identity + TEE_ATT_QVE_OUT_OF_DATE = TEE_ATT_MK_ERROR(0x0051), ///< QvE ISVSVN is smaller then the ISVSVN threshold + TEE_ATT_PSW_NOT_AVAILABLE = TEE_ATT_MK_ERROR(0x0052), ///< SGX PSW library cannot be loaded, could be due to file I/O error + TEE_ATT_COLLATERAL_VERSION_NOT_SUPPORTED = TEE_ATT_MK_ERROR(0x0053), ///< SGX quote verification collateral version not supported by QVL/QvE + TEE_ATT_TDX_MODULE_MISMATCH = TEE_ATT_MK_ERROR(0x0060), ///< TDX SEAM module identity is NOT match to Intel signed TDX SEAM module + + TEE_ATT_ERROR_MAX = TEE_ATT_MK_ERROR(0x00FF), ///< Indicate max error to allow better translation. + +} tee_att_error_t; + +struct tee_att_config_t; + +typedef enum +{ + TEE_ATT_TDQE, + TEE_ATT_PCE, + TEE_ATT_QPL, + TEE_ATT_IDE, +} tee_att_ae_type_t; + + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * The application calls this API to selected a platform's attestation key id and alloc a context to be used + * during quote generation flow. The application need to call tee_att_free_context to release the context after + * it is not used anymore. + * + * @param p_att_key_id The selected att_key_id from the quote verifier's list. It includes the QE identity as + * well as the attestation key's algorithm type. It can be NULL to use default list. + * @param p_path A full path of TDQE. It can be NULL to use default path. + * @param pp_context Allocated context that contains information during quote generation flow. It cannot be NULL. + * @return TEE_ATT_SUCCESS Successfully created the context using the attestation key. + * @return TEE_ATT_UNSUPPORTED_ATT_KEY_ID p_att_key_id is not valid. + * @return TEE_ATT_ERROR_INVALID_PARAMETER pp_context is NULL. Or p_qe_path is not valid. + * + */ +tee_att_error_t tee_att_create_context(const tee_att_att_key_id_t* p_att_key_id, + const char* p_qe_path, + tee_att_config_t** pp_context); + +/** + * The application calls this API to release the context. + * + * @param p_context The context that contains information during quote generation flow. + * @return TEE_ATT_SUCCESS Successfully released the context. + * @return TEE_ATT_ERROR_INVALID_PARAMETER p_context is NULL. + * + */ +tee_att_error_t tee_att_free_context(tee_att_config_t* p_context); + +/** + * The application calls this API to request the selected platform's attestation key owner to generate or obtain + * the attestation key. Once called, the QE that owns the attestation key described by the inputted attestation + * key id will do what is required to get this platform's attestation including getting any certification data + * required from the PCE. Depending on the type of attestation key and the attestation key owner, this API will + * return the same attestation key public ID or generate a new one. The caller can request that the attestation + * key owner "refresh" the key. This will cause the owner to either re-get the key or generate a new one. The + * platform's attestation key owner is expected to store the key in persistent memory and use it in the + * subsequent quote generation APIs described below. + * + * In an environment where attestation key provisioning and certification needs to take place during a platform + * deployment phase, an application can generate the attestation key, certify it with the PCK Cert and register + * it with the attestation owners cloud infrastructure. That way, the key is available during the run time + * phase to generate code without requiring re-certification. + * + * The QE's target info is also returned by this API that will allow the application's enclave to generate a + * REPORT that the attestation key owner's QE can verify using local REPORT-based attestation when generating a + * quote. + * + * In order to allow the application to allocate the public key id buffer first, the application can call this + * function with the p_pub_key_id set to NULL and the p_pub_key_id_size to a valid size_t pointer. In this + * case, the function will return the required buffer size to contain the p_pub_key_id_size and ignore the other + * parameters. The application can then call this API again with the correct p_pub_key_size and the pointer to + * the allocated buffer in p_pub_key_id. + * + * @param p_context The context that contains information during quote generation flow. + * @param p_qe_target_info Pointer to QE's target info required by the application to generate an enclave REPORT + * targeting the selected QE. Must not be NULL when p_pub_key_id is not NULL. + * @param refresh_att_key A flag indicating the attestation key owner should re-generated and certify or + * otherwise attempt to re-provision the attestation key. For example, for ECDSDA, the + * platform will generate a new key and request the PCE to recertify it. For EPID, the + * platform will attempt to re-provision the EPID key. The behavior is dependent on the + * key type and the key owner, but it should make an attempt to refresh the key typically + * to update the key to the current platform's TCB. + * @param p_pub_key_id_size This parameter can be used in 2 ways. When p_pub_key_id is NULL, the API will + * return the buffer size required to hold the attestation's public key ID. The + * application can then allocate the buffer and call it again with p_pub_key_id not set + * to NULL and the other parameters valid. If p_pub_key_id is not NULL, p_pub_key_size + * must be large enough to hold the return attestation's public key ID. Must not be + * NULL. + * @param p_pub_key_id This parameter can be used in 2 ways. When it is passed in as NULL and p_pub_key_id_size + * is not NULL, the API will return the buffer size required to hold the attestation's + * public key ID. The other parameters will be ignored. When it is not NULL, it must point + * to a buffer which is at least a long as the value passed in by p_pub_key_id. Can either + * be NULL or point to the correct buffer.his will point to the buffer that will contain the + * attestation key's public identifier. If first called with a NULL pointer, the API will + * return the required length of the buffer in p_pub_key_id_size. + * @return TEE_ATT_SUCCESS Successfully selected an attestation key. Either returns the required attestation's + * public key ID size in p_pub_key_id_size when p_pub_key_id is passed in as NULL. When + * p_pub_key_id is not NULL, p_qe_target_info will contain the attestation key's QE + * target info for REPORT generation and p_pub_key_id will contain the attestation's + * public key ID. + * @return TEE_ATT_ERROR_INVALID_PARAMETER Invalid parameter if p_pub_key_id_size is NULL. If p_pub_key_size is + * not NULL, the other parameters must be valid. + * @return TEE_ATT_ERROR_OUT_OF_MEMORY There is not enough EPC memory to load one of the Architecture Enclaves + * needed to complete this operation. + * @return TEE_ATT_ENCLAVE_LOST Enclave lost after power transition or used in child process created by + * linux:fork(). + * @return TEE_ATT_ENCLAVE_LOAD_ERROR Unable to load the enclaves required to initialize the attestation key. + * Could be due to file I/O error, loading infrastructure error or insufficient + * enclave memory. + * @return TEE_ATT_ERROR_INVALID_PRIVILEGE No enough privilege to perform the operation. + * @return TEE_ATT_ERROR_UNEXPECTED Unexpected internal error. + * + */ +tee_att_error_t tee_att_init_quote(const tee_att_config_t* p_context, + sgx_target_info_t* p_qe_target_info, + bool refresh_att_key, + size_t* p_pub_key_id_size, + uint8_t* p_pub_key_id); + + +/** + * The application needs to call this function before generating a quote. The quote size is variable + * depending on the type of attestation key selected and other platform or key data required to generate the + * quote. Once the application calls this API, it will use the returned p_quote_size to allocate the buffer + * required to hold the generated quote. A pointer to this buffer is provided to the tee_att_get_quote() API. + * + * If the key is not available, this API may return an error (TEE_ATT_ATT_KEY_NOT_INITIALIZED) depending on + * the algorithm. In this case, the caller must call sgx_ql_init_quote() to re-generate and certify the + * attestation key. + * + * @param p_context The context that contains information during quote generation flow. + * @param p_quote_size Pointer to the location where the required quote buffer size will be returned. Must + * not be NULL. + * @return TEE_ATT_SUCCESS Successfully calculated the required quote size. The required size in bytes is + * returned in the memory pointed to by p_quote_size. + * @return TEE_ATT_ATT_KEY_NOT_INITIALIZED The Attestaion key has not been generated, certified or requires + * recertification yet. Need to call InitQuote first/again to get attestaion + * key regenerated/receritifed. + * @return TEE_ATT_ATT_KEY_CERT_DATA_INVALID Quote certification data from the platform library is invalid. + * @return TEE_ATT_ERROR_INVALID_PARAMETER Invalid parameter if p_quote_size is NULL. Or p_context is not valid. + * @return TEE_ATT_ERROR_OUT_OF_MEMORY There is not enough EPC memory to load one of the Architecture Enclaves + * needed to complete this operation. + * @return TEE_ATT_ENCLAVE_LOST Enclave lost after power transition or used in child process created by + * linux:fork(). + * @return TEE_ATT_ENCLAVE_LOAD_ERROR Unable to load the enclaves required to initialize the attestation key. + * Could be due to file I/O error, loading infrastructure error or insufficient + * enclave memory. + * @return TEE_ATT_ERROR_INVALID_PRIVILEGE No enough privilege to perform the operation. + * @return TEE_ATT_ERROR_UNEXPECTED Unexpected internal error. + */ +tee_att_error_t tee_att_get_quote_size(const tee_att_config_t* p_context, + uint32_t* p_quote_size); + + +/** + * The function will take the application enclave's REPORT that will be converted into a quote after the QE verifies + * the REPORT. Once verified it will sign it with platform's attestation key matching the selected attestation key + * ID. If the key is not available, this API may return an error (TEE_ATT_ATT_KEY_NOT_INITIALIZED) depending on the + * algorithm. In this case, the caller must call tee_att_init_quote() to get the library to + * re-generate/re-certify the attestation key. + * + * @param p_context The context that contains information during quote generation flow. + * @param p_report Pointer to the application enclave's REPORT that needs the quote. The report needs to be generated + * using the QE's target info reurned by the tee_att_init_quote() API. Must not be NULL. + * @param report_size size of the application enclave's REPORT. + * @param p_qe_report_info Pointer to a data structure that will contain the information required for the QE to generate + * a REPORT that can be verified by the application enclave. The inputted data structure + * contains the application's TARGET_INFO, a nonce and a buffer to hold the generated report. + * The QE Report will be generated using the target information and the QE's REPORT.ReportData = + * SHA256(*p_nonce||*p_quote)||32-0x00's. This parameter is used when the application wants to + * verify the QE's REPORT to provide earlier detection that the QE is not being spoofed by + * untrusted code. A spoofed QE will ultimately be rejected by the remote verifier. This + * parameter is optional and will be ignored when NULL. + * @param quote_size Size of the buffer pointed to by p_quote (in bytes). + * @param p_quote Pointer to the buffer that will contain the generated quote. Must not be NULL. + * @return TEE_ATT_SUCCESS Successfully created the quote. + * @return TEE_ATT_ERROR_INVALID_PARAMETER One of the parameters is not valid. + * @return TEE_ATT_ATT_KEY_NOT_INITIALIZED The Attestaion key has not been generated, certified or requires + * recertification yet. Need to call InitQuote first/again to get attestaion + * key regenerated/receritifed. + * @return TEE_ATT_ATT_KEY_CERT_DATA_INVALID Quote certification data from the platform library is invalid. + * @return TEE_ATT_ERROR_OUT_OF_MEMORY There is not enough EPC memory to load one of the Architecture Enclaves + * needed to complete this operation. + * @return TEE_ATT_ENCLAVE_LOST Enclave lost after power transition or used in child process created by + * linux:fork(). + * @return TEE_ATT_ENCLAVE_LOAD_ERROR Unable to load the enclaves required to initialize the attestation key. + * Could be due to file I/O error, loading infrastructure error or insufficient + * enclave memory. + * @return TEE_ATT_ERROR_INVALID_PRIVILEGE No enough privilege to perform the operation. + * @return TEE_ATT_ERROR_UNEXPECTED Unexpected internal error. + */ +tee_att_error_t tee_att_get_quote(const tee_att_config_t* p_context, + const uint8_t* p_report, + uint32_t report_size, + sgx_qe_report_info_t* p_qe_report_info, + uint8_t* p_quote, + uint32_t quote_size); + +/** + * The application can call this function to get the selected att_key_id. + * + * @param p_context The context that contains information during quote generation flow. + * @param p_att_key_id The selected att_key_id from the quote verifier's list. It cannot be NULL. + * @return TEE_ATT_SUCCESS Successfully created the quote. + * @return TEE_ATT_ERROR_INVALID_PARAMETER One of the parameters is not valid. + * @return TEE_ATT_ERROR_UNEXPECTED Unexpected internal error. + */ +tee_att_error_t tee_att_get_keyid(const tee_att_config_t* p_context, + tee_att_att_key_id_t* p_att_key_id); + +#ifndef _MSC_VER +/** + * This API can be used to set the full path of TDQE, IDE, PCE and QPL library. + * + * The function takes the enum and the corresponding full path. + * + * @param p_context The context that contains information during quote generation flow. + * @param type Specify the full path of which binary is going to be changed. + * @param p_path It should be a valid path. + * @return TEE_ATT_SUCCESS Successfully set the full path. + * @return TEE_ATT_UNSUPPORTED_MODE This function is called on Windows. + * @return TEE_ATT_ERROR_INVALID_PARAMETER p_path is not a valid full path or the path is too long. + * @return TEE_ATT_ERROR_UNEXPECTED An unexpected internal error occurred. + * + */ +tee_att_error_t tee_att_set_path(const tee_att_config_t* p_context, + tee_att_ae_type_t type, + const char* p_path); +#endif +#if defined(__cplusplus) +} +#endif + + +#endif + diff --git a/QuoteGeneration/quote_wrapper/tdx_quote/linux/Makefile b/QuoteGeneration/quote_wrapper/tdx_quote/linux/Makefile index 722c7b8b..0d36a4d2 100644 --- a/QuoteGeneration/quote_wrapper/tdx_quote/linux/Makefile +++ b/QuoteGeneration/quote_wrapper/tdx_quote/linux/Makefile @@ -52,7 +52,7 @@ vpath %.c $(COMMON_DIR)/src Quote_C_Files := tdqe_u.c id_enclave_u.c se_thread.c se_trace.c Quote_Cpp_Files := $(wildcard ../*.cpp) -Quote_Include_Paths := -I$(SGX_SDK)/include -I../../common/inc -I./ \ +Quote_Include_Paths := -I$(SGX_SDK)/include -I../inc -I../../common/inc -I./ \ -I../enclave -I$(TOP_DIR)/pce_wrapper/inc \ -I$(COMMON_DIR)/inc/internal \ -I$(COMMON_DIR)/inc/internal/linux diff --git a/QuoteGeneration/quote_wrapper/tdx_quote/linux/td_ql_logic.lds b/QuoteGeneration/quote_wrapper/tdx_quote/linux/td_ql_logic.lds index 294285cd..7ef0ca80 100644 --- a/QuoteGeneration/quote_wrapper/tdx_quote/linux/td_ql_logic.lds +++ b/QuoteGeneration/quote_wrapper/tdx_quote/linux/td_ql_logic.lds @@ -1,12 +1,12 @@ { global: - td_set_enclave_load_policy; - td_set_qe_path; - td_set_qpl_path; - td_init_quote; - td_get_quote_size; - td_get_quote; - get_qpl_handle; + tee_att_create_context; + tee_att_free_context; + tee_att_init_quote; + tee_att_get_quote_size; + tee_att_get_quote; + tee_att_get_keyid; + tee_att_set_path; local: *; }; diff --git a/QuoteGeneration/quote_wrapper/tdx_quote/td_ql_logic.cpp b/QuoteGeneration/quote_wrapper/tdx_quote/td_ql_logic.cpp index f03f1246..6d758817 100644 --- a/QuoteGeneration/quote_wrapper/tdx_quote/td_ql_logic.cpp +++ b/QuoteGeneration/quote_wrapper/tdx_quote/td_ql_logic.cpp @@ -37,60 +37,45 @@ * call the trusted functions in the ECDSA-P256 quoting enclave. * */ -#include #include #include -#ifndef _MSC_VER - #include - #include -#else -#include -#include -#endif #include "sgx_urts.h" #include "td_ql_logic.h" #include "user_types.h" #include "tdqe_u.h" #include "id_enclave_u.h" -#include "ecdsa_quote.h" -#include "se_thread.h" -#include "quoting_enclave_tdqe.h" #ifndef _MSC_VER #define TDQE_ENCLAVE_NAME "libsgx_tdqe.signed.so.1" #define ID_ENCLAVE_NAME "libsgx_id_enclave.signed.so.1" - #define SGX_QL_QUOTE_CONFIG_LIB_FILE_NAME "libdcap_quoteprov.so.1" - #define SGX_QL_QUOTE_CONFIG_LIB_FILE_NAME_LEGACY "libdcap_quoteprov.so" - #define TCHAR char - #define _T(x) (x) + #define TEE_ATT_QUOTE_CONFIG_LIB_FILE_NAME "libdcap_quoteprov.so.1" #else #define TDQE_ENCLAVE_NAME _T("tdqe.signed.dll") #define ID_ENCLAVE_NAME _T("id_enclave.signed.dll") - #define SGX_QL_QUOTE_CONFIG_LIB_FILE_NAME "dcap_quoteprov.dll" + #define TEE_ATT_QUOTE_CONFIG_LIB_FILE_NAME _T("dcap_quoteprov.dll") #endif #define ECDSA_BLOB_LABEL "tdqe_data.blob" -#define MAX_PATH 260 #define MAX_CERT_DATA_SIZE (4098*3) #define MIN_CERT_DATA_SIZE (500) // Chosen to be large enough to contain the native cert data types. -typedef quote3_error_t (*sgx_get_quote_config_func_t)(const sgx_ql_pck_cert_id_t *p_pck_cert_id, +typedef tee_att_error_t (*sgx_get_quote_config_func_t)(const sgx_ql_pck_cert_id_t *p_pck_cert_id, sgx_ql_config_t **pp_quote_config); -typedef quote3_error_t (*sgx_free_quote_config_func_t)(sgx_ql_config_t *p_quote_config); +typedef tee_att_error_t (*sgx_free_quote_config_func_t)(sgx_ql_config_t *p_quote_config); -typedef quote3_error_t (*sgx_write_persistent_data_func_t)(const uint8_t *p_buf, - uint32_t buf_size, +typedef tee_att_error_t (*sgx_write_persistent_data_func_t)(const uint8_t *p_buf, + uint32_t buf_size, const char *p_label); -typedef quote3_error_t (*sgx_read_persistent_data_func_t)(const uint8_t *p_buf, - uint32_t *p_buf_size, +typedef tee_att_error_t (*sgx_read_persistent_data_func_t)(const uint8_t *p_buf, + uint32_t *p_buf_size, const char *p_label); #ifndef _MSC_VER -static inline errno_t memcpy_s(void *dest, size_t numberOfElements, const void *src, size_t count) +inline errno_t memcpy_s(void *dest, size_t numberOfElements, const void *src, size_t count) { if(0 == count) return -1; @@ -114,154 +99,89 @@ static inline errno_t memcpy_s(void *dest, size_t numberOfElements, const void * * * @param pce_error Error return by the pce library API. * - * @return SGX_QL_SUCCESS - * @return SGX_QL_OUT_OF_EPC - * @return SGX_QL_INTERFACE_UNAVAILABLE - * @return SGX_QL_ERROR_UNEXPECTED - * @return SGX_QL_KEY_CERTIFCATION_ERROR + * @return TEE_ATT_SUCCESS + * @return TEE_ATT_OUT_OF_EPC + * @return TEE_ATT_INTERFACE_UNAVAILABLE + * @return TEE_ATT_ERROR_UNEXPECTED + * @return TEE_ATT_KEY_CERTIFCATION_ERROR * */ -static quote3_error_t translate_pce_errors(sgx_pce_error_t pce_error) +static tee_att_error_t translate_pce_errors(sgx_pce_error_t pce_error) { - quote3_error_t ret_val = SGX_QL_ERROR_UNEXPECTED; + tee_att_error_t ret_val = TEE_ATT_ERROR_UNEXPECTED; switch(pce_error) { case SGX_PCE_SUCCESS: - ret_val = SGX_QL_SUCCESS; + ret_val = TEE_ATT_SUCCESS; break; case SGX_PCE_OUT_OF_EPC: - ret_val = SGX_QL_OUT_OF_EPC; + ret_val = TEE_ATT_OUT_OF_EPC; break; case SGX_PCE_INTERFACE_UNAVAILABLE: - ret_val = SGX_QL_INTERFACE_UNAVAILABLE; + ret_val = TEE_ATT_INTERFACE_UNAVAILABLE; break; case SGX_PCE_INVALID_TCB: - ret_val = SGX_QL_KEY_CERTIFCATION_ERROR; + ret_val = TEE_ATT_KEY_CERTIFCATION_ERROR; break; case SGX_PCE_INVALID_PRIVILEGE: // Indicates that the QE does not have the prov key bit set. Unexpected for a production release. - ret_val = SGX_QL_ERROR_INVALID_PRIVILEGE; + ret_val = TEE_ATT_ERROR_INVALID_PRIVILEGE; break; case SGX_PCE_UNEXPECTED: case SGX_PCE_INVALID_PARAMETER: // Inputs to the PCE are generated by the QE library. Don't expect input errors. case SGX_PCE_INVALID_REPORT: // Indicates that the QE.REPORT is invalid. This unexpected. case SGX_PCE_CRYPTO_ERROR: // Indicates that the QE.REPORT.ReportData is invalid. This unexpected. - ret_val = SGX_QL_ERROR_UNEXPECTED; + ret_val = TEE_ATT_ERROR_UNEXPECTED; break; default: - ret_val = SGX_QL_ERROR_UNEXPECTED; + ret_val = TEE_ATT_ERROR_UNEXPECTED; break; } return(ret_val); } -/** - * Used to keep track of the TDQE's load status. Allows for - * thread safe updating of the load policy and the storage of - * target information of the QE when the policy is - * persistent mode. Also contains the global ecdsa_blob and - * provides thread safe access to the blob. - */ -struct ql_global_data{ - se_mutex_t m_enclave_load_mutex; - se_mutex_t m_ecdsa_blob_mutex; - - sgx_ql_request_policy_t m_load_policy; - sgx_enclave_id_t m_eid; - sgx_misc_attribute_t m_attributes; - sgx_launch_token_t m_launch_token; - uint8_t m_ecdsa_blob[SGX_QL_TRUSTED_ECDSA_BLOB_SIZE_SDK]; - uint8_t *m_pencryptedppid; - sgx_pce_info_t m_pce_info; - sgx_key_128bit_t* m_qe_id; - void *m_qpl_handle; - char tdqe_path[MAX_PATH]; - char qpl_path[MAX_PATH]; - - ql_global_data(): - m_load_policy(SGX_QL_DEFAULT), - m_eid(0), - m_pencryptedppid(NULL), - m_qe_id(NULL), - m_qpl_handle(NULL) - { - se_mutex_init(&m_enclave_load_mutex); - se_mutex_init(&m_ecdsa_blob_mutex); - memset(&m_attributes, 0, sizeof(m_attributes)); - memset(&m_launch_token, 0, sizeof(m_launch_token)); - memset(m_ecdsa_blob, 0, sizeof(m_ecdsa_blob)); - memset(&m_pce_info, 0, sizeof(m_pce_info)); - memset(tdqe_path, 0, sizeof(tdqe_path)); - memset(qpl_path, 0, sizeof(qpl_path)); - } - ql_global_data(const ql_global_data&); - ql_global_data& operator=(const ql_global_data&); - ~ql_global_data(){ - if (m_eid!=0) sgx_destroy_enclave(m_eid); - se_mutex_destroy(&m_enclave_load_mutex); - se_mutex_destroy(&m_ecdsa_blob_mutex); - if (m_pencryptedppid) - { - free(m_pencryptedppid); - m_pencryptedppid = NULL; - } - if (m_qe_id) - { - free(m_qe_id); - m_qe_id = NULL; - } #ifndef _MSC_VER - if (m_qpl_handle) - { - dlclose(m_qpl_handle); - m_qpl_handle = NULL; - } +void * +#else +HMODULE #endif - } -}; - -static ql_global_data g_ql_global_data; - -#ifndef _MSC_VER -void * get_qpl_handle() +tee_att_config_t::get_qpl_handle() { - if (!g_ql_global_data.m_qpl_handle) { - void * handle = NULL; - if (g_ql_global_data.qpl_path[0]) { - handle = dlopen(g_ql_global_data.qpl_path, RTLD_LAZY); - if (NULL == handle) { - SE_PROD_LOG("Cannot open Quote Provider Library %s\n", g_ql_global_data.qpl_path); - } - } - else { - handle = dlopen(SGX_QL_QUOTE_CONFIG_LIB_FILE_NAME, RTLD_LAZY); - if (NULL == handle) - { - ///TODO: - // This is a temporary solution to make sure the legacy library without a version suffix can be loaded. - // We shall remove this when we have a major version change later and drop the backward compatible - // support for old lib name. - handle = dlopen(SGX_QL_QUOTE_CONFIG_LIB_FILE_NAME_LEGACY, RTLD_LAZY); - if (NULL == handle) { - SE_PROD_LOG("Cannot open Quote Provider Library %s and %s\n", SGX_QL_QUOTE_CONFIG_LIB_FILE_NAME, - SGX_QL_QUOTE_CONFIG_LIB_FILE_NAME_LEGACY); - } + if (m_qpl_handle) + return m_qpl_handle; +#ifndef _MSC_VER + if (qpl_path[0]) { + m_qpl_handle = dlopen(qpl_path, RTLD_LAZY); + if (NULL == m_qpl_handle) { + SE_PROD_LOG("Cannot open Quote Provider Library %s\n", qpl_path); } + return m_qpl_handle; + } + else { + m_qpl_handle = dlopen(TEE_ATT_QUOTE_CONFIG_LIB_FILE_NAME, RTLD_LAZY); + if (NULL == m_qpl_handle) { + SE_PROD_LOG("Cannot open Quote Provider Library %s\n", TEE_ATT_QUOTE_CONFIG_LIB_FILE_NAME); } - g_ql_global_data.m_qpl_handle = handle; } - return g_ql_global_data.m_qpl_handle; + return m_qpl_handle; +} +#else + m_qpl_handle = LoadLibrary(TEE_ATT_QUOTE_CONFIG_LIB_FILE_NAME); + if (m_qpl_handle == NULL) { + SE_PROD_LOG("Couldn't find the platform library. %d\n", GetLastError()); + return NULL; + } + return m_qpl_handle; } #endif - /** * Wrapper function for retrieving the PCK Certificate data from the platform's Quote Provider Library. * @@ -275,18 +195,18 @@ void * get_qpl_handle() * @param p_cert_data Pointer ot the buffer to containt the cert data. Can be NULL. If NULL, the required buffer size * will be returned in p_cert_data_size. * - * @return SGX_QL_SUCCESS - * @return SGX_QL_ERROR_INVALID_PARAMETER - * @return SGX_QL_PLATFORM_LIB_UNAVAILABLE - * @return SGX_QL_NO_PLATFORM_CERT_DATA + * @return TEE_ATT_SUCCESS + * @return TEE_ATT_ERROR_INVALID_PARAMETER + * @return TEE_ATT_PLATFORM_LIB_UNAVAILABLE + * @return TEE_ATT_NO_PLATFORM_CERT_DATA */ -static quote3_error_t get_platform_quote_cert_data(sgx_ql_pck_cert_id_t *p_pck_cert_id, +tee_att_error_t tee_att_config_t::get_platform_quote_cert_data(sgx_ql_pck_cert_id_t *p_pck_cert_id, sgx_cpu_svn_t *p_cert_cpu_svn, sgx_isv_svn_t *p_cert_pce_isv_svn, uint32_t *p_cert_data_size, uint8_t *p_cert_data) { - quote3_error_t ret_val = SGX_QL_PLATFORM_LIB_UNAVAILABLE; + tee_att_error_t ret_val = TEE_ATT_PLATFORM_LIB_UNAVAILABLE; sgx_get_quote_config_func_t p_sgx_get_quote_config = NULL; sgx_free_quote_config_func_t p_sgx_free_quote_config = NULL; sgx_ql_config_t *p_pck_cert_config = NULL; @@ -299,168 +219,112 @@ static quote3_error_t get_platform_quote_cert_data(sgx_ql_pck_cert_id_t *p_pck_c HINSTANCE handle; #endif - if((NULL == p_pck_cert_id) || - (NULL == p_cert_cpu_svn) || - (NULL == p_cert_pce_isv_svn) || - (NULL == p_cert_data_size)) { - return SGX_QL_ERROR_INVALID_PARAMETER; + if ((NULL == p_pck_cert_id) || + (NULL == p_cert_cpu_svn) || + (NULL == p_cert_pce_isv_svn) || + (NULL == p_cert_data_size)) { + return TEE_ATT_ERROR_INVALID_PARAMETER; } - if((NULL != p_cert_data) && (0 == *p_cert_data_size)) { - return SGX_QL_ERROR_INVALID_PARAMETER; + if ((NULL != p_cert_data) && (0 == *p_cert_data_size)) { + return TEE_ATT_ERROR_INVALID_PARAMETER; } - #ifndef _MSC_VER handle = get_qpl_handle(); - if (handle) { +#ifndef _MSC_VER + if (!handle) { + + SE_PROD_LOG("Couldn't find the platform library. %s\n", dlerror()); + return ret_val; + } + else { p_sgx_get_quote_config = (sgx_get_quote_config_func_t)dlsym(handle, "sgx_ql_get_quote_config"); error1 = dlerror(); p_sgx_free_quote_config = (sgx_free_quote_config_func_t)dlsym(handle, "sgx_ql_free_quote_config"); error2 = dlerror(); - if ((NULL == error1) && - (NULL != p_sgx_get_quote_config) && - (NULL == error2) && - (NULL != p_sgx_free_quote_config)){ - SE_TRACE(SE_TRACE_DEBUG, "Found the sgx_ql_get_quote_config and sgx_ql_free_quote_config API.\n"); - SE_TRACE(SE_TRACE_DEBUG, "Request the Quote Config data.\n"); - ret_val = p_sgx_get_quote_config(p_pck_cert_id, &p_pck_cert_config); - if (SGX_QL_SUCCESS != ret_val) { - SE_PROD_LOG("Error returned from the p_sgx_get_quote_config API. 0x%04x\n", ret_val); - goto CLEANUP; - } - if(NULL == p_pck_cert_config) { - ret_val = SGX_QL_NO_PLATFORM_CERT_DATA; - SE_PROD_LOG("p_sgx_get_quote_config returned NULL for p_pck_cert_config.\n"); - goto CLEANUP; - } - if(p_pck_cert_config->version != SGX_QL_CONFIG_VERSION_1) { - SE_PROD_LOG("p_sgx_get_quote_config returned incompatible pck_cert_config version.\n"); - ret_val = SGX_QL_NO_PLATFORM_CERT_DATA; - goto CLEANUP; - } - if(0 != memcpy_s(p_cert_cpu_svn, sizeof(*p_cert_cpu_svn), &p_pck_cert_config->cert_cpu_svn, sizeof(p_pck_cert_config->cert_cpu_svn))) { - ret_val = SGX_QL_ERROR_UNEXPECTED; - goto CLEANUP; - } - *p_cert_pce_isv_svn = p_pck_cert_config->cert_pce_isv_svn; - if(NULL == p_cert_data) { - // The caller only needs the TCBm and/or the required buffer size. - // Return the required buffer size. - *p_cert_data_size = p_pck_cert_config->cert_data_size; - } - else { - // The caller wants the TCBm and the required buffer size. - if(*p_cert_data_size < p_pck_cert_config->cert_data_size) { - // The buffer passed in to this API is not large enouge to contain the provider library's returned cert data. - // This shouldn't happen since the passed in value should be the result of calling this function - // with the inputted p_cert_data equal to NULL just befor this caller. - SE_PROD_LOG("sgx_ql_get_quote_config returned a cert_data_size too large to fit in inputted buffer.\n"); - ret_val = SGX_QL_ERROR_INVALID_PARAMETER; - goto CLEANUP; - } - if(NULL == p_pck_cert_config->p_cert_data) { - SE_PROD_LOG("sgx_ql_get_quote_config returned NULL for p_cert_data.\n"); - ret_val = SGX_QL_NO_PLATFORM_CERT_DATA; - goto CLEANUP; - } - // Copy the returned cert data - if(0 != memcpy_s(p_cert_data, *p_cert_data_size, p_pck_cert_config->p_cert_data, p_pck_cert_config->cert_data_size)) { - ret_val = SGX_QL_ERROR_UNEXPECTED; - goto CLEANUP; - } - // Return the number of bytes copied. - *p_cert_data_size = p_pck_cert_config->cert_data_size; - } - } else { + if ((NULL != error1) || + (NULL == p_sgx_get_quote_config) || + (NULL != error2) || + (NULL == p_sgx_free_quote_config)) { SE_PROD_LOG("Couldn't find 'sgx_ql_get_quote_config()' and 'sgx_ql_free_quote_config()' in the platform library. %s\n", dlerror()); + goto CLEANUP; } - } else { - SE_PROD_LOG("Couldn't find the platform library. %s\n", dlerror()); - } - CLEANUP: - if(NULL != p_sgx_free_quote_config){ - if(NULL != p_pck_cert_config) { - p_sgx_free_quote_config(p_pck_cert_config); - } +#else + if (handle == NULL) { + SE_PROD_LOG("Couldn't find the platform library. %d\n", GetLastError()); + return ret_val; } - #else - handle = LoadLibrary(TEXT(SGX_QL_QUOTE_CONFIG_LIB_FILE_NAME)); - if (handle != NULL) { - SE_TRACE(SE_TRACE_DEBUG, "Found the Quote's dependent library. %s.\n", SGX_QL_QUOTE_CONFIG_LIB_FILE_NAME); + else { + SE_TRACE(SE_TRACE_DEBUG, "Found the Quote's dependent library.\n"); p_sgx_get_quote_config = (sgx_get_quote_config_func_t)GetProcAddress(handle, "sgx_ql_get_quote_config"); p_sgx_free_quote_config = (sgx_free_quote_config_func_t)GetProcAddress(handle, "sgx_ql_free_quote_config"); - if ((NULL != p_sgx_get_quote_config) && - (NULL != p_sgx_free_quote_config)){ - SE_TRACE(SE_TRACE_DEBUG, "Found the sgx_ql_get_quote_config and sgx_ql_free_quote_config API.\n"); - SE_TRACE(SE_TRACE_DEBUG, "Request the Quote Config data.\n"); - ret_val = p_sgx_get_quote_config(p_pck_cert_id, &p_pck_cert_config); - if (SGX_QL_SUCCESS != ret_val) { - SE_TRACE(SE_TRACE_ERROR, "Error returned from the p_sgx_get_quote_config API. 0x%04x\n", ret_val); - goto CLEANUP; - } - if (NULL == p_pck_cert_config) { - ret_val = SGX_QL_NO_PLATFORM_CERT_DATA; - SE_TRACE(SE_TRACE_ERROR, "p_sgx_get_quote_config returned NULL for p_pck_cert_config.\n"); + + if ((NULL == p_sgx_get_quote_config) || + (NULL == p_sgx_free_quote_config)) + { + SE_PROD_LOG("Couldn't find 'sgx_ql_get_quote_config()' and 'sgx_ql_free_quote_config()' in the platform library. %d\n", GetLastError()); + goto CLEANUP; + } +#endif + SE_TRACE(SE_TRACE_DEBUG, "Found the sgx_ql_get_quote_config and sgx_ql_free_quote_config API.\n"); + SE_TRACE(SE_TRACE_DEBUG, "Request the Quote Config data.\n"); + ret_val = p_sgx_get_quote_config(p_pck_cert_id, &p_pck_cert_config); + if (TEE_ATT_SUCCESS != ret_val) { + SE_PROD_LOG("Error returned from the p_sgx_get_quote_config API. 0x%04x\n", ret_val); + goto CLEANUP; + } + if (NULL == p_pck_cert_config) { + ret_val = TEE_ATT_NO_PLATFORM_CERT_DATA; + SE_PROD_LOG("p_sgx_get_quote_config returned NULL for p_pck_cert_config.\n"); + goto CLEANUP; + } + if (p_pck_cert_config->version != SGX_QL_CONFIG_VERSION_1) { + SE_PROD_LOG("p_sgx_get_quote_config returned incompatible pck_cert_config version.\n"); + ret_val = TEE_ATT_NO_PLATFORM_CERT_DATA; + goto CLEANUP; + } + if (0 != memcpy_s(p_cert_cpu_svn, sizeof(*p_cert_cpu_svn), &p_pck_cert_config->cert_cpu_svn, sizeof(p_pck_cert_config->cert_cpu_svn))) { + ret_val = TEE_ATT_ERROR_UNEXPECTED; + goto CLEANUP; + } + *p_cert_pce_isv_svn = p_pck_cert_config->cert_pce_isv_svn; + if (NULL == p_cert_data) { + // The caller only needs the TCBm and/or the required buffer size. + // Return the required buffer size. + *p_cert_data_size = p_pck_cert_config->cert_data_size; + } + else { + // The caller wants the TCBm and the required buffer size. + if (*p_cert_data_size < p_pck_cert_config->cert_data_size) { + // The buffer passed in to this API is not large enouge to contain the provider library's returned cert data. + // This shouldn't happen since the passed in value should be the result of calling this function + // with the inputted p_cert_data equal to NULL just befor this caller. + SE_PROD_LOG("sgx_ql_get_quote_config returned a cert_data_size too large to fit in inputted buffer.\n"); + ret_val = TEE_ATT_ERROR_INVALID_PARAMETER; goto CLEANUP; } - if (p_pck_cert_config->version != SGX_QL_CONFIG_VERSION_1) { - SE_TRACE(SE_TRACE_ERROR, "p_sgx_get_quote_config returned incompatible pck_cert_config version.\n"); - ret_val = SGX_QL_NO_PLATFORM_CERT_DATA; + if (NULL == p_pck_cert_config->p_cert_data) { + SE_PROD_LOG("sgx_ql_get_quote_config returned NULL for p_cert_data.\n"); + ret_val = TEE_ATT_NO_PLATFORM_CERT_DATA; goto CLEANUP; } - if (0 != memcpy_s(p_cert_cpu_svn, sizeof(*p_cert_cpu_svn), &p_pck_cert_config->cert_cpu_svn, sizeof(p_pck_cert_config->cert_cpu_svn))) { - ret_val = SGX_QL_ERROR_UNEXPECTED; + // Copy the returned cert data + if (0 != memcpy_s(p_cert_data, *p_cert_data_size, p_pck_cert_config->p_cert_data, p_pck_cert_config->cert_data_size)) { + ret_val = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } - *p_cert_pce_isv_svn = p_pck_cert_config->cert_pce_isv_svn; - if (NULL == p_cert_data) { - // The caller only needs the TCBm and/or the required buffer size. - // Return the required buffer size. - *p_cert_data_size = p_pck_cert_config->cert_data_size; - } - else { - // The caller wants the TCBm and the required buffer size. - if (*p_cert_data_size < p_pck_cert_config->cert_data_size) { - // The buffer passed in to this API is not large enouge to contain the provider library's returned cert data. - // This shouldn't happen since the passed in value should be the result of calling this function - // with the inputted p_cert_data equal to NULL just befor this caller. - SE_TRACE(SE_TRACE_ERROR, "sgx_ql_get_quote_config returned a cert_data_size too large to fit in inputted buffer.\n"); - ret_val = SGX_QL_ERROR_INVALID_PARAMETER; - goto CLEANUP; - } - if (NULL == p_pck_cert_config->p_cert_data) { - SE_TRACE(SE_TRACE_ERROR, "sgx_ql_get_quote_config returned NULL for p_cert_data.\n"); - ret_val = SGX_QL_NO_PLATFORM_CERT_DATA; - goto CLEANUP; - } - // Copy the returned cert data - if (0 != memcpy_s(p_cert_data, *p_cert_data_size, p_pck_cert_config->p_cert_data, p_pck_cert_config->cert_data_size)) { - ret_val = SGX_QL_ERROR_UNEXPECTED; - goto CLEANUP; - } - // Return the number of bytes copied. - *p_cert_data_size = p_pck_cert_config->cert_data_size; - } - } - else { - SE_TRACE(SE_TRACE_WARNING, "Couldn't find 'sgx_ql_get_quote_config()' and 'sgx_ql_free_quote_config()' in the platform library.\n"); + // Return the number of bytes copied. + *p_cert_data_size = p_pck_cert_config->cert_data_size; } + } - else { - SE_TRACE(SE_TRACE_DEBUG, "Couldn't find the platform library. %s\n"); - } - CLEANUP: +CLEANUP: if (NULL != p_sgx_free_quote_config) { if (NULL != p_pck_cert_config) { p_sgx_free_quote_config(p_pck_cert_config); } } - if (NULL != handle) { - FreeLibrary(handle); - } - #endif - return(ret_val); } @@ -472,20 +336,42 @@ static quote3_error_t get_platform_quote_cert_data(sgx_ql_pck_cert_id_t *p_pck_c * * @return */ -static bool get_qe_path(const TCHAR *p_file_name, +bool tee_att_config_t::get_qe_path(tee_att_ae_type_t type, TCHAR *p_file_path, size_t buf_size) { - if(!p_file_name || !p_file_path) { + if(!p_file_path || buf_size == 0) { return false; } + const TCHAR* context_path, *p_file_name; + switch (type) + { + case TEE_ATT_TDQE: + context_path = tdqe_path; + p_file_name = TDQE_ENCLAVE_NAME; + break; + case TEE_ATT_QPL: + context_path = qpl_path; + p_file_name = TEE_ATT_QUOTE_CONFIG_LIB_FILE_NAME; + break; + case TEE_ATT_IDE: + context_path = ide_path; + p_file_name = ID_ENCLAVE_NAME; + break; + default: + return false; + } #ifndef _MSC_VER Dl_info dl_info; - if(g_ql_global_data.tdqe_path[0]) + if(*context_path) { - strncpy(p_file_path, g_ql_global_data.tdqe_path, buf_size -1); - p_file_path[buf_size - 1] = '\0'; //null terminate the string + size_t len = strnlen(context_path, MAX_PATH); + if( len > buf_size -1) { + return false; + } + strncpy(p_file_path, context_path, len); + p_file_path[len] = '\0'; //null terminate the string return true; } else if(0 != dladdr(__builtin_return_address(0), &dl_info) && @@ -520,6 +406,13 @@ static bool get_qe_path(const TCHAR *p_file_name, (void)strncat(p_file_path,p_file_name, strnlen(p_file_name,buf_size)); #else HMODULE hModule = NULL; + if (*context_path) + { + if (_tcsncpy_s(p_file_path, buf_size - 1, context_path, MAX_PATH)) + return false; + p_file_path[buf_size - 1] = '\0'; //null terminate the string + return true; + } #ifndef AESM_ECDSA_BUNDLE if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, _T(__FUNCTION__), &hModule)) return false; @@ -548,15 +441,10 @@ static bool get_qe_path(const TCHAR *p_file_name, /** - * - * @param p_qe_eid - * @param p_qe_attributes - * @param p_launch_token - * - * @return SGX_QL_SUCCESS - * @return SGX_QL_ENCLAVE_LOAD_ERROR - * @return SGX_QL_ERROR_UNEXPECTED - * @return SGX_QL_OUT_OF_EPC + * @return TEE_ATT_SUCCESS + * @return TEE_ATT_ENCLAVE_LOAD_ERROR + * @return TEE_ATT_ERROR_UNEXPECTED + * @return TEE_ATT_OUT_OF_EPC * @return SGX_ERROR_ENCLAVE_FILE_ACCESS The QE file cannot be found or accessed. * @return SGX_ERROR_OUT_OF_MEMORY * @return SGX_ERROR_INVALID_ENCLAVE Enclave file parser failed. @@ -581,122 +469,112 @@ static bool get_qe_path(const TCHAR *p_file_name, * @return SGX_ERROR_INVALID_ENCLAVE_ID */ -static quote3_error_t load_qe(sgx_enclave_id_t *p_qe_eid, - sgx_misc_attribute_t *p_qe_attributes, - sgx_launch_token_t *p_launch_token) -{ - quote3_error_t ret_val = SGX_QL_SUCCESS; +tee_att_error_t tee_att_config_t::load_qe(bool *is_fresh_loaded) { + tee_att_error_t ret_val = TEE_ATT_SUCCESS; sgx_status_t sgx_status = SGX_SUCCESS; int launch_token_updated = 0; TCHAR qe_enclave_path[MAX_PATH] = _T(""); - memset(p_launch_token, 0, sizeof(*p_launch_token)); - int rc = se_mutex_lock(&g_ql_global_data.m_enclave_load_mutex); + int rc = se_mutex_lock(&m_enclave_load_mutex); if (0 == rc) { SE_TRACE(SE_TRACE_ERROR, "Failed to lock mutex\n"); - return SGX_QL_ENCLAVE_LOAD_ERROR; + return TEE_ATT_ENCLAVE_LOAD_ERROR; + } + + if (is_fresh_loaded) { + *is_fresh_loaded =false; } // Load the TDQE - if (g_ql_global_data.m_eid == 0) { - if (!get_qe_path(TDQE_ENCLAVE_NAME, qe_enclave_path, MAX_PATH)) { + if (m_eid == 0) { + if (!get_qe_path(TEE_ATT_TDQE, qe_enclave_path, MAX_PATH)) { SE_TRACE(SE_TRACE_ERROR, "Couldn't find QE file.\n"); - ret_val = SGX_QL_ENCLAVE_LOAD_ERROR; + ret_val = TEE_ATT_ENCLAVE_LOAD_ERROR; goto CLEANUP; } SE_TRACE(SE_TRACE_DEBUG, "Call sgx_create_enclave for QE. %s\n", qe_enclave_path); sgx_status = sgx_create_enclave(qe_enclave_path, 0, - p_launch_token, + &m_launch_token, &launch_token_updated, - p_qe_eid, - p_qe_attributes); + &m_eid, + &m_attributes); if (SGX_SUCCESS != sgx_status) { SE_PROD_LOG("Error, call sgx_create_enclave QE fail [%s], SGXError:%04x.\n", __FUNCTION__, sgx_status); if (sgx_status == SGX_ERROR_OUT_OF_EPC) { - ret_val = SGX_QL_OUT_OF_EPC; + ret_val = TEE_ATT_OUT_OF_EPC; } else { - ret_val = (quote3_error_t)sgx_status; + ret_val = (tee_att_error_t)sgx_status; } goto CLEANUP; } - g_ql_global_data.m_eid = *p_qe_eid; - if(0 != memcpy_s(&g_ql_global_data.m_launch_token, sizeof(g_ql_global_data.m_launch_token), - p_launch_token, sizeof(*p_launch_token))) { - ret_val = SGX_QL_ERROR_UNEXPECTED; - goto CLEANUP; + + if (is_fresh_loaded) { + *is_fresh_loaded = true; } - g_ql_global_data.m_attributes = *p_qe_attributes; + } else { - SE_TRACE(SE_TRACE_DEBUG, "QE already loaded. %d\n", g_ql_global_data.m_eid); - *p_qe_eid = g_ql_global_data.m_eid; - if(0 != memcpy_s(p_launch_token, sizeof(*p_launch_token), - &g_ql_global_data.m_launch_token, sizeof(g_ql_global_data.m_launch_token))) { - ret_val = SGX_QL_ERROR_UNEXPECTED; - goto CLEANUP; - } - *p_qe_attributes = g_ql_global_data.m_attributes; + SE_TRACE(SE_TRACE_DEBUG, "QE already loaded. %d\n", m_eid); } CLEANUP: - rc = se_mutex_unlock(&g_ql_global_data.m_enclave_load_mutex); + rc = se_mutex_unlock(&m_enclave_load_mutex); if (0 == rc) { SE_TRACE(SE_TRACE_ERROR, "Failed to unlock mutex.\n"); - ret_val = SGX_QL_ERROR_UNEXPECTED; + ret_val = TEE_ATT_ERROR_UNEXPECTED; } return ret_val; -} + } /** * * @return */ -static void unload_qe() +void tee_att_config_t::unload_qe() { - int rc = se_mutex_lock(&g_ql_global_data.m_enclave_load_mutex); + int rc = se_mutex_lock(&m_enclave_load_mutex); if (0 == rc) { SE_TRACE(SE_TRACE_ERROR, "Failed to lock mutex\n"); return; } // Unload the QE enclave - if ((0 != g_ql_global_data.m_eid) && - (g_ql_global_data.m_load_policy != SGX_QL_PERSISTENT)) { - SE_TRACE(SE_TRACE_DEBUG, "Unload QE enclave 0X%lX\n", g_ql_global_data.m_eid); - sgx_destroy_enclave(g_ql_global_data.m_eid); - g_ql_global_data.m_eid = 0; + if (0 != m_eid) { + SE_TRACE(SE_TRACE_DEBUG, "Unload QE enclave 0X%lX\n", m_eid); + sgx_destroy_enclave(m_eid); + m_eid = 0; } - rc = se_mutex_unlock(&g_ql_global_data.m_enclave_load_mutex); + rc = se_mutex_unlock(&m_enclave_load_mutex); if (0 == rc) { SE_TRACE(SE_TRACE_ERROR, "Failed to unlock mutex\n"); } } -static quote3_error_t load_id_enclave(sgx_enclave_id_t* p_qe_eid) +tee_att_error_t tee_att_config_t::load_id_enclave(sgx_enclave_id_t* p_id_enclave_eid) { - quote3_error_t ret_val = SGX_QL_SUCCESS; + tee_att_error_t ret_val = TEE_ATT_SUCCESS; sgx_status_t sgx_status = SGX_SUCCESS; int launch_token_updated = 0; TCHAR id_enclave_path[MAX_PATH] = _T(""); sgx_launch_token_t launch_token = { 0 }; - int rc = se_mutex_lock(&g_ql_global_data.m_enclave_load_mutex); + int rc = se_mutex_lock(&m_enclave_load_mutex); if (0 == rc) { SE_TRACE(SE_TRACE_ERROR, "Failed to lock mutex\n"); - return SGX_QL_ENCLAVE_LOAD_ERROR; + return TEE_ATT_ENCLAVE_LOAD_ERROR; } // Load the ID ENCLAVE - if (!get_qe_path(ID_ENCLAVE_NAME, id_enclave_path, MAX_PATH)) { + if (!get_qe_path(TEE_ATT_IDE, id_enclave_path, MAX_PATH)) { SE_TRACE(SE_TRACE_ERROR, "Couldn't find ID_ENCLAVE file.\n"); - ret_val = SGX_QL_ENCLAVE_LOAD_ERROR; + ret_val = TEE_ATT_ENCLAVE_LOAD_ERROR; goto CLEANUP; } SE_TRACE(SE_TRACE_DEBUG, "Call sgx_create_enclave for ID_ENCLAVE. %s\n", id_enclave_path); @@ -704,51 +582,54 @@ static quote3_error_t load_id_enclave(sgx_enclave_id_t* p_qe_eid) 0, &launch_token, &launch_token_updated, - p_qe_eid, + p_id_enclave_eid, NULL); if (SGX_SUCCESS != sgx_status) { - SE_PROD_LOG("Error, call sgx_create_enclave ID_ENCLAVE fail [%s], SGXError:%04x.\n", __FUNCTION__, sgx_status); + SE_TRACE(SE_TRACE_ERROR, "Error, call sgx_create_enclave ID_ENCLAVE fail [%s], SGXError:%04x.\n", __FUNCTION__, sgx_status); + SE_TRACE(SE_TRACE_ERROR, "Failed to load enclave.\n"); if (sgx_status == SGX_ERROR_OUT_OF_EPC) { - ret_val = SGX_QL_OUT_OF_EPC; + ret_val = TEE_ATT_OUT_OF_EPC; } else { - ret_val = (quote3_error_t)sgx_status; + ret_val = (tee_att_error_t)sgx_status; } goto CLEANUP; } CLEANUP: - rc = se_mutex_unlock(&g_ql_global_data.m_enclave_load_mutex); + rc = se_mutex_unlock(&m_enclave_load_mutex); if (0 == rc) { SE_TRACE(SE_TRACE_ERROR, "Failed to unlock mutex.\n"); - ret_val = SGX_QL_ERROR_UNEXPECTED; + ret_val = TEE_ATT_ERROR_UNEXPECTED; } return ret_val; } -static quote3_error_t load_id_enclave_get_id(sgx_key_128bit_t* p_id) +tee_att_error_t tee_att_config_t::load_id_enclave_get_id(sgx_key_128bit_t* p_id) { - quote3_error_t ret_val = SGX_QL_SUCCESS; + tee_att_error_t ret_val = TEE_ATT_SUCCESS; sgx_status_t sgx_status = SGX_SUCCESS; sgx_status_t ecall_ret = SGX_SUCCESS; sgx_enclave_id_t id_enclave_eid = 0; ret_val = load_id_enclave(&id_enclave_eid); - if (ret_val != SGX_QL_SUCCESS) + if (ret_val != TEE_ATT_SUCCESS) { return ret_val; } sgx_status = ide_get_id(id_enclave_eid, &ecall_ret, p_id); if (SGX_SUCCESS != sgx_status) { SE_PROD_LOG("Failed call into the ID_ENCLAVE. 0x%04x.\n", sgx_status); - ret_val = (quote3_error_t)sgx_status; + ret_val = (tee_att_error_t)sgx_status; goto CLEANUP; } if (SGX_SUCCESS != ecall_ret) { SE_TRACE(SE_TRACE_ERROR, "Failed to get QE_ID. 0x%04x.\n", ecall_ret); - ret_val = (quote3_error_t)ecall_ret; + ret_val = (tee_att_error_t)ecall_ret; goto CLEANUP; } + SE_TRACE(SE_TRACE_DEBUG, "TDQE_ID:\n"); + PRINT_BYTE_ARRAY(SE_TRACE_DEBUG, p_id, sizeof(*p_id)); CLEANUP: if (0 != id_enclave_eid) { @@ -762,7 +643,7 @@ static quote3_error_t load_id_enclave_get_id(sgx_key_128bit_t* p_id) * * note: this function is called in lock area of global ecdsa blob mutex */ -static quote3_error_t getencryptedppid(sgx_target_info_t& pce_target_info, uint8_t *p_buf, uint32_t buf_size) +tee_att_error_t tee_att_config_t::getencryptedppid(sgx_target_info_t& pce_target_info, uint8_t *p_buf, uint32_t buf_size) { tdqe_error_t tdqe_error = TDQE_ERROR_UNEXPECTED; sgx_status_t sgx_status = SGX_SUCCESS; @@ -776,15 +657,15 @@ static quote3_error_t getencryptedppid(sgx_target_info_t& pce_target_info, uint8 uint8_t signature_scheme; if (!p_buf || buf_size < REF_RSA_OAEP_3072_MOD_SIZE) - return SGX_QL_ERROR_INVALID_PARAMETER; + return TEE_ATT_ERROR_INVALID_PARAMETER; - if (g_ql_global_data.m_pencryptedppid) + if (m_pencryptedppid) { - memcpy_s(p_buf, buf_size, g_ql_global_data.m_pencryptedppid, REF_RSA_OAEP_3072_MOD_SIZE); - return SGX_QL_SUCCESS; + memcpy_s(p_buf, buf_size, m_pencryptedppid, REF_RSA_OAEP_3072_MOD_SIZE); + return TEE_ATT_SUCCESS; } - sgx_status = get_pce_encrypt_key(g_ql_global_data.m_eid, + sgx_status = get_pce_encrypt_key(m_eid, (uint32_t*)&tdqe_error, &pce_target_info, &tdqe_report, @@ -794,12 +675,12 @@ static quote3_error_t getencryptedppid(sgx_target_info_t& pce_target_info, uint8 enc_public_key); if (SGX_SUCCESS != sgx_status) { SE_TRACE(SE_TRACE_ERROR, "Failed call into the TDQE. 0x%04x.\n", sgx_status); - return (quote3_error_t)sgx_status; + return (tee_att_error_t)sgx_status; } if (TDQE_SUCCESS != tdqe_error) { SE_TRACE(SE_TRACE_ERROR, "Failed to generated PCE encryption key.\n"); - return (quote3_error_t)tdqe_error; + return (tee_att_error_t)tdqe_error; } pce_error = sgx_get_pce_info(&tdqe_report, @@ -819,28 +700,28 @@ static quote3_error_t getencryptedppid(sgx_target_info_t& pce_target_info, uint8 if (signature_scheme != PCE_NIST_P256_ECDSA_SHA256) { SE_TRACE(SE_TRACE_ERROR, "PCE returned incorrect signature scheme.\n"); - return SGX_QL_ERROR_INVALID_PCE_SIG_SCHEME; + return TEE_ATT_ERROR_INVALID_PCE_SIG_SCHEME; } if (encrypted_ppid_ret_size != REF_RSA_OAEP_3072_MOD_SIZE) { SE_TRACE(SE_TRACE_ERROR, "PCE returned unexpected returned encrypted PPID size.\n"); - return SGX_QL_ERROR_UNEXPECTED; + return TEE_ATT_ERROR_UNEXPECTED; } - g_ql_global_data.m_pencryptedppid = (uint8_t *)malloc(sizeof(uint8_t) * REF_RSA_OAEP_3072_MOD_SIZE); - if (!g_ql_global_data.m_pencryptedppid) { + m_pencryptedppid = (uint8_t *)malloc(sizeof(uint8_t) * REF_RSA_OAEP_3072_MOD_SIZE); + if (!m_pencryptedppid) { SE_TRACE(SE_TRACE_ERROR, "Fail to allocate memory.\n"); - return SGX_QL_ERROR_OUT_OF_MEMORY; + return TEE_ATT_ERROR_OUT_OF_MEMORY; } - if (0 != memcpy_s(g_ql_global_data.m_pencryptedppid, REF_RSA_OAEP_3072_MOD_SIZE, encrypted_ppid, REF_RSA_OAEP_3072_MOD_SIZE) || - 0 != memcpy_s(p_buf, buf_size, g_ql_global_data.m_pencryptedppid, REF_RSA_OAEP_3072_MOD_SIZE) || - 0 != memcpy_s(&g_ql_global_data.m_pce_info, sizeof(g_ql_global_data.m_pce_info), &pce_info, sizeof (pce_info))) { + if (0 != memcpy_s(m_pencryptedppid, REF_RSA_OAEP_3072_MOD_SIZE, encrypted_ppid, REF_RSA_OAEP_3072_MOD_SIZE) || + 0 != memcpy_s(p_buf, buf_size, m_pencryptedppid, REF_RSA_OAEP_3072_MOD_SIZE) || + 0 != memcpy_s(&m_pce_info, sizeof(m_pce_info), &pce_info, sizeof (pce_info))) { SE_TRACE(SE_TRACE_ERROR, "Fail to copy memory.\n"); - return SGX_QL_ERROR_UNEXPECTED; + return TEE_ATT_ERROR_UNEXPECTED; } - return SGX_QL_SUCCESS; + return TEE_ATT_SUCCESS; } /** @@ -850,17 +731,17 @@ static quote3_error_t getencryptedppid(sgx_target_info_t& pce_target_info, uint8 * @param buf_size Size in bytes pointed to by p_buf. Must be no larger than MAX_PATH. * @param p_label String of the label for the data to be stored. Must not be NULL. * - * @return SGX_QE_PLATFORM_LIB_UNAVAILABLE - * @return SGX_QL_ERROR_UNEXPECTED - * @return SGX_QL_ERROR_INVALID_PARAMETER - * @return SGX_QL_FILE_ACCESS_ERROR - * @return SGX_QL_SUCCESS + * @return TEE_ATT_PLATFORM_LIB_UNAVAILABLE + * @return TEE_ATT_ERROR_UNEXPECTED + * @return TEE_ATT_ERROR_INVALID_PARAMETER + * @return TEE_ATT_FILE_ACCESS_ERROR + * @return TEE_ATT_SUCCESS */ -static quote3_error_t write_persistent_data(const uint8_t *p_buf, +tee_att_error_t tee_att_config_t::write_persistent_data(const uint8_t *p_buf, uint32_t buf_size, const char *p_label) { - quote3_error_t ret_val = SGX_QL_PLATFORM_LIB_UNAVAILABLE; + tee_att_error_t ret_val = TEE_ATT_PLATFORM_LIB_UNAVAILABLE; sgx_write_persistent_data_func_t p_sgx_qe_write_persistent_data; #ifndef _MSC_VER void *handle; @@ -872,11 +753,11 @@ static quote3_error_t write_persistent_data(const uint8_t *p_buf, if((NULL == p_buf) || (0 == buf_size)|| (NULL == p_label)) { - return(SGX_QL_ERROR_INVALID_PARAMETER); + return(TEE_ATT_ERROR_INVALID_PARAMETER); } - #ifndef _MSC_VER handle = get_qpl_handle(); +#ifndef _MSC_VER if (handle) { p_sgx_qe_write_persistent_data = (sgx_write_persistent_data_func_t)dlsym(handle, "sgx_ql_write_persistent_data"); if ((error = dlerror()) == NULL && @@ -885,7 +766,7 @@ static quote3_error_t write_persistent_data(const uint8_t *p_buf, ret_val = p_sgx_qe_write_persistent_data(p_buf, buf_size, p_label); - if (SGX_QL_SUCCESS != ret_val) { + if (TEE_ATT_SUCCESS != ret_val) { SE_PROD_LOG("Error returned from the sgx_ql_write_persistent_data API. 0x%04x\n", ret_val); } } else { @@ -894,29 +775,26 @@ static quote3_error_t write_persistent_data(const uint8_t *p_buf, } else { SE_PROD_LOG("Couldn't find the platform library. %s\n", dlerror()); } - #else - handle = LoadLibrary(TEXT(SGX_QL_QUOTE_CONFIG_LIB_FILE_NAME)); +#else if (handle != NULL) { - SE_TRACE(SE_TRACE_DEBUG, "Found the Quote's dependent library. %s.\n", SGX_QL_QUOTE_CONFIG_LIB_FILE_NAME); p_sgx_qe_write_persistent_data = (sgx_write_persistent_data_func_t)GetProcAddress(handle, "sgx_ql_write_persistent_data"); if (NULL != p_sgx_qe_write_persistent_data) { SE_TRACE(SE_TRACE_DEBUG, "Found the sgx_ql_write_persistent_data API.\n"); ret_val = p_sgx_qe_write_persistent_data(p_buf, buf_size, p_label); - if (SGX_QL_SUCCESS != ret_val) { + if (TEE_ATT_SUCCESS != ret_val) { SE_TRACE(SE_TRACE_ERROR, "Error returned from the sgx_ql_write_persistent_data API. 0x%04x\n", ret_val); } } else { SE_TRACE(SE_TRACE_WARNING, "Couldn't find 'sgx_ql_write_persistent_data()' in the platform library. %s\n"); } - FreeLibrary(handle); } else { SE_TRACE(SE_TRACE_DEBUG, "Couldn't find the platform library. %s\n"); } - #endif +#endif //CLEANUP: return(ret_val); @@ -929,17 +807,17 @@ static quote3_error_t write_persistent_data(const uint8_t *p_buf, * @param p_buf_size Size in bytes pointed to by p_buf. Must not be NULL. * @param p_label String of the label for the data to be stored. Must not be NULL. * - * @return SGX_QL_SUCCESS - * @return SGX_QE_PLATFORM_LIB_UNAVAILABLE - * @return SGX_QL_ERROR_UNEXPECTED - * @return SGX_QL_ERROR_INVALID_PARAMETER - * @return SGX_QL_FILE_ACCESS_ERROR + * @return TEE_ATT_SUCCESS + * @return TEE_ATT_PLATFORM_LIB_UNAVAILABLE + * @return TEE_ATT_ERROR_UNEXPECTED + * @return TEE_ATT_ERROR_INVALID_PARAMETER + * @return TEE_ATT_FILE_ACCESS_ERROR */ -static quote3_error_t read_persistent_data(uint8_t *p_buf, +tee_att_error_t tee_att_config_t::read_persistent_data(uint8_t *p_buf, uint32_t *p_buf_size, const char *p_label) { - quote3_error_t ret_val = SGX_QL_PLATFORM_LIB_UNAVAILABLE; + tee_att_error_t ret_val = TEE_ATT_PLATFORM_LIB_UNAVAILABLE; sgx_read_persistent_data_func_t p_sgx_qe_read_persistent_data; #ifndef _MSC_VER @@ -952,11 +830,11 @@ static quote3_error_t read_persistent_data(uint8_t *p_buf, if((NULL == p_buf) || (NULL == p_buf_size)|| (NULL == p_label)) { - return(SGX_QL_ERROR_INVALID_PARAMETER); + return(TEE_ATT_ERROR_INVALID_PARAMETER); } - #ifndef _MSC_VER handle = get_qpl_handle(); +#ifndef _MSC_VER if (handle) { p_sgx_qe_read_persistent_data = (sgx_read_persistent_data_func_t)dlsym(handle, "sgx_ql_read_persistent_data"); if ((error = dlerror()) == NULL && @@ -965,7 +843,7 @@ static quote3_error_t read_persistent_data(uint8_t *p_buf, ret_val = p_sgx_qe_read_persistent_data(p_buf, p_buf_size, p_label); - if (SGX_QL_SUCCESS != ret_val) { + if (TEE_ATT_SUCCESS != ret_val) { SE_PROD_LOG("Error returned from the sgx_ql_read_persistent_data API. 0x%04x\n", ret_val); } } else { @@ -975,23 +853,21 @@ static quote3_error_t read_persistent_data(uint8_t *p_buf, SE_PROD_LOG("Couldn't find the platform library. %s\n", dlerror()); } #else - handle = LoadLibrary(TEXT(SGX_QL_QUOTE_CONFIG_LIB_FILE_NAME)); if (handle != NULL) { - SE_TRACE(SE_TRACE_DEBUG, "Found the Quote's dependent library. %s.\n", SGX_QL_QUOTE_CONFIG_LIB_FILE_NAME); + SE_TRACE(SE_TRACE_DEBUG, "Found the Quote's dependent library.\n"); p_sgx_qe_read_persistent_data = (sgx_read_persistent_data_func_t)GetProcAddress(handle, "sgx_ql_read_persistent_data"); if (NULL != p_sgx_qe_read_persistent_data) { SE_TRACE(SE_TRACE_DEBUG, "Found the sgx_ql_read_persistent_data API.\n"); ret_val = p_sgx_qe_read_persistent_data(p_buf, p_buf_size, p_label); - if (SGX_QL_SUCCESS != ret_val) { + if (TEE_ATT_SUCCESS != ret_val) { SE_TRACE(SE_TRACE_ERROR, "Error returned from the sgx_ql_read_persistent_data API. 0x%04x\n", ret_val); } } else { SE_TRACE(SE_TRACE_WARNING, "Couldn't find 'sgx_ql_write_persistent_data()' in the platform library. %s\n"); } - FreeLibrary(handle); } else { SE_TRACE(SE_TRACE_DEBUG, "Couldn't find the platform library. %s\n"); @@ -1010,23 +886,21 @@ static quote3_error_t read_persistent_data(uint8_t *p_buf, * @param p_encrypted_ppid * @param encrypted_ppid_size * @param certification_key_type - * @param p_tdqe_eid * - * @return SGX_QL_SUCCESS - * @return SGX_QL_ERROR_INVALID_PARAMETER + * @return TEE_ATT_SUCCESS + * @return TEE_ATT_ERROR_INVALID_PARAMETER * @return errors from PCE translator from sgx_pce_sign_report() * @return ecall errors * @return errors from TDQE's store_cert_data() * */ -static quote3_error_t certify_key(uint8_t *p_ecdsa_blob, +tee_att_error_t tee_att_config_t::certify_key(uint8_t *p_ecdsa_blob, ref_plaintext_ecdsa_data_sdk_t* p_plaintext_data, uint8_t *p_encrypted_ppid, uint32_t encrypted_ppid_size, - sgx_ql_cert_key_type_t certification_key_type, - sgx_enclave_id_t *p_tdqe_eid) + sgx_ql_cert_key_type_t certification_key_type) { - quote3_error_t refqt_ret = SGX_QL_ERROR_UNEXPECTED; + tee_att_error_t refqt_ret = TEE_ATT_ERROR_UNEXPECTED; sgx_status_t sgx_status = SGX_SUCCESS; tdqe_error_t tdqe_error = TDQE_ERROR_UNEXPECTED; sgx_pce_error_t pce_error; @@ -1036,18 +910,18 @@ static quote3_error_t certify_key(uint8_t *p_ecdsa_blob, // Verify inputs if((NULL == p_ecdsa_blob) || (NULL == p_plaintext_data) || - (NULL == p_tdqe_eid)) { - return(SGX_QL_ERROR_INVALID_PARAMETER); + (0 == m_eid)) { + return(TEE_ATT_ERROR_INVALID_PARAMETER); } if(NULL != p_encrypted_ppid) { if(encrypted_ppid_size != REF_RSA_OAEP_3072_MOD_SIZE) { - return(SGX_QL_ERROR_INVALID_PARAMETER); + return(TEE_ATT_ERROR_INVALID_PARAMETER); } } if (PPID_RSA3072_ENCRYPTED != certification_key_type) { - return(SGX_QL_ERROR_INVALID_PARAMETER); + return(TEE_ATT_ERROR_INVALID_PARAMETER); } SE_TRACE(SE_TRACE_DEBUG, "Certify Key.\n"); @@ -1073,12 +947,12 @@ static quote3_error_t certify_key(uint8_t *p_ecdsa_blob, // Update the signature data and the report that was signed. if(0 != memcpy_s(&p_plaintext_data->qe_report_cert_key_sig, sizeof(p_plaintext_data->qe_report_cert_key_sig), &pce_sig, sizeof(pce_sig))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } // Update the ECDSA key blob with certification data SE_TRACE(SE_TRACE_DEBUG, "Update ECDSA blob with cert data.\n"); - sgx_status = store_cert_data(*p_tdqe_eid, + sgx_status = store_cert_data(m_eid, (uint32_t*)&tdqe_error, p_plaintext_data, certification_key_type, @@ -1089,23 +963,23 @@ static quote3_error_t certify_key(uint8_t *p_ecdsa_blob, if (SGX_SUCCESS != sgx_status) { SE_TRACE(SE_TRACE_ERROR, "Failed call into the TDQE. 0x%04x\n", sgx_status); // /todo: May want to retry on SGX_ERROR_ENCLAVE_LOST caused by power transition - refqt_ret = (quote3_error_t)sgx_status; + refqt_ret = (tee_att_error_t)sgx_status; goto CLEANUP; } if (TDQE_SUCCESS != tdqe_error) { SE_TRACE(SE_TRACE_ERROR, "Failed to generate ECDSA blob. 0x%04x.\n", tdqe_error); - refqt_ret = (quote3_error_t)tdqe_error; + refqt_ret = (tee_att_error_t)tdqe_error; goto CLEANUP; } else { SE_TRACE(SE_TRACE_DEBUG, "Certification done. Store updated ECDSA blob to disk.\n"); refqt_ret = write_persistent_data(p_ecdsa_blob, SGX_QL_TRUSTED_ECDSA_BLOB_SIZE_SDK, ECDSA_BLOB_LABEL); - if (refqt_ret != SGX_QL_SUCCESS) { + if (refqt_ret != TEE_ATT_SUCCESS) { // This should not be a critical failure but a warning. The ECDSA key is still in memory. SE_TRACE(SE_TRACE_WARNING, "Warning, unable to store resealed ECDSA blob to persistent storage.\n"); SE_TRACE(SE_TRACE_DEBUG, "File storage is not required for the QE_Library. Library will use ECDSA Blob cached in memory.\n"); - refqt_ret = SGX_QL_SUCCESS; + refqt_ret = TEE_ATT_SUCCESS; } } @@ -1126,24 +1000,24 @@ static quote3_error_t certify_key(uint8_t *p_ecdsa_blob, * @param refresh_att_key * @param pub_key_id * - * @return SGX_QL_SUCCESS - * @return SGX_QL_ERROR_INVALID_PARAMETER - * @return SGX_PCE_INVALID_PARAMETER->SGX_QL_ERROR_UNEXPECTED - * @return SGX_PCE_INTERFACE_UNAVAILABLE->SGX_QL_INTERFACE_UNAVAILABLE - * @return SGX_PCE_OUT_OF_EPC->SGX_QL_OUT_OF_EPC + * @return TEE_ATT_SUCCESS + * @return TEE_ATT_ERROR_INVALID_PARAMETER + * @return SGX_PCE_INVALID_PARAMETER->TEE_ATT_ERROR_UNEXPECTED + * @return SGX_PCE_INTERFACE_UNAVAILABLE->TEE_ATT_INTERFACE_UNAVAILABLE + * @return SGX_PCE_OUT_OF_EPC->TEE_ATT_OUT_OF_EPC * @return Errors from load_qe() * @return Errors from failed ecall (need to handle at least ENCLAVE_LOST) * @return TDQE_ERROR_INVALID_PLATFORM * @return TDQE_ERROR_INVALID_PARAMETER * @return TDQE_ERROR_CRYPTO Error generating the PPID Encryption key. * @return TDQE_ERROR_UNEXPECTED - * @return SGX_PCE_INVALID_REPORT QE.REPORT verification failed.->SGX_QL_ERROR_UNEXPECTED - * @return SGX_PCE_CRYPTO_ERROR QE.REPORT.ReportData hash compare failed.-> SGX_QL_ERROR_UNEXPECTED - * @return SGX_PCE_INVALID_PRIVILEGE QE doesn't have the prov bit set.-> SGX_QL_ERROR_UNEXPECTED (for produciton + * @return SGX_PCE_INVALID_REPORT QE.REPORT verification failed.->TEE_ATT_ERROR_UNEXPECTED + * @return SGX_PCE_CRYPTO_ERROR QE.REPORT.ReportData hash compare failed.-> TEE_ATT_ERROR_UNEXPECTED + * @return SGX_PCE_INVALID_PRIVILEGE QE doesn't have the prov bit set.-> TEE_ATT_ERROR_UNEXPECTED (for produciton * release. - * @return SGX_PCE_UNEXPECTED->SGX_QL_ERROR_UNEXPECTED - * @return SGX_QL_ERROR_INVALID_PCE_SIG_SCHEME PCE used and unexpected/unsupported signature scheme. - * @return SGX_QL_ERROR_UNEXPECTED + * @return SGX_PCE_UNEXPECTED->TEE_ATT_ERROR_UNEXPECTED + * @return TEE_ATT_ERROR_INVALID_PCE_SIG_SCHEME PCE used and unexpected/unsupported signature scheme. + * @return TEE_ATT_ERROR_UNEXPECTED * @return TDQE_ERROR_ATT_KEY_GEN Error generated the attestaion key. * @return TDQE_ERROR_CRYPTO Error generating QE_ID. * @return TDQE_ERROR_OUT_OF_MEMORY @@ -1155,21 +1029,18 @@ static quote3_error_t certify_key(uint8_t *p_ecdsa_blob, * or was already verified once. * */ -static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_type, +tee_att_error_t tee_att_config_t::ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_type, sgx_target_info_t *p_qe_target_info, bool refresh_att_key, ref_sha256_hash_t *p_pub_key_id) { - quote3_error_t refqt_ret = SGX_QL_SUCCESS; + tee_att_error_t refqt_ret = TEE_ATT_SUCCESS; sgx_status_t sgx_status = SGX_SUCCESS; - sgx_enclave_id_t tdqe_eid = 0; - sgx_launch_token_t launch_token = {0}; tdqe_error_t tdqe_error = TDQE_ERROR_UNEXPECTED; uint8_t resealed = 0; ref_sha256_hash_t blob_ecdsa_id; sgx_target_info_t pce_target_info; sgx_isv_svn_t pce_isv_svn; - sgx_misc_attribute_t tdqe_attributes; //int enclave_lost_retry_time = 1; bool gen_new_key = false; sgx_psvn_t pce_cert_psvn; @@ -1182,16 +1053,17 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ ref_plaintext_ecdsa_data_sdk_t *p_seal_data_plain_text; uint8_t encrypted_ppid[REF_RSA_OAEP_3072_MOD_SIZE]; int blob_mutex_rc = 0; + bool is_fresh_loaded = false; // Verify inputs if (PPID_RSA3072_ENCRYPTED != certification_key_type) { SE_TRACE(SE_TRACE_ERROR, "Invalid certification key type.\n"); - return(SGX_QL_ERROR_INVALID_PARAMETER); + return(TEE_ATT_ERROR_INVALID_PARAMETER); } if (NULL == p_qe_target_info) { SE_TRACE(SE_TRACE_ERROR, "Invalid qe target info.\n"); - return(SGX_QL_ERROR_INVALID_PARAMETER); + return(TEE_ATT_ERROR_INVALID_PARAMETER); } // Get PCE Target Info @@ -1205,29 +1077,30 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ // Load the QE enclave SE_TRACE(SE_TRACE_DEBUG, "Call Load the QE.\n"); - refqt_ret = load_qe(&tdqe_eid, - &tdqe_attributes, - &launch_token); - if (SGX_QL_SUCCESS != refqt_ret) + refqt_ret = load_qe(&is_fresh_loaded); + if (TEE_ATT_SUCCESS != refqt_ret) { goto CLEANUP; } + if (is_fresh_loaded) { + m_raw_pce_isvsvn = pce_isv_svn; + } // Compose the target_info from the attributes returned by sgx_create_enclave and mr_enclave from qe report. memset(p_qe_target_info, 0, sizeof(sgx_target_info_t)); if(0 != memcpy_s(&p_qe_target_info->attributes, sizeof(p_qe_target_info->attributes), - &tdqe_attributes.secs_attr, sizeof(tdqe_attributes.secs_attr))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + &m_attributes.secs_attr, sizeof(m_attributes.secs_attr))) { + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } if(0 != memcpy_s(&p_qe_target_info->misc_select, sizeof(p_qe_target_info->misc_select), - &tdqe_attributes.misc_select, sizeof(tdqe_attributes.misc_select))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + &m_attributes.misc_select, sizeof(m_attributes.misc_select))) { + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } - blob_mutex_rc = se_mutex_lock(&g_ql_global_data.m_ecdsa_blob_mutex); + blob_mutex_rc = se_mutex_lock(&m_ecdsa_blob_mutex); if (0 == blob_mutex_rc) { SE_TRACE(SE_TRACE_ERROR, "Failed to lock mutex\n"); goto CLEANUP; @@ -1241,29 +1114,29 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ gen_new_key = true; break; } - uint32_t blob_size_read = sizeof(g_ql_global_data.m_ecdsa_blob); + uint32_t blob_size_read = sizeof(m_ecdsa_blob); // Get ECDSA Blob if exists SE_TRACE(SE_TRACE_DEBUG, "Read ECDSA blob.\n"); - refqt_ret = read_persistent_data((uint8_t*)g_ql_global_data.m_ecdsa_blob, + refqt_ret = read_persistent_data((uint8_t*)m_ecdsa_blob, &blob_size_read, ECDSA_BLOB_LABEL); - if (SGX_QL_SUCCESS != refqt_ret) { + if (TEE_ATT_SUCCESS != refqt_ret) { // Ignore errors since persistent storage is not required. Blob in memory may still be OK so continue to try to verify the cached blob. SE_TRACE(SE_TRACE_WARNING, "ECDSA Blob doesn't exist is persistent storage. Try to use the cached version.\n"); - refqt_ret = SGX_QL_SUCCESS; + refqt_ret = TEE_ATT_SUCCESS; } - else if (blob_size_read != sizeof(g_ql_global_data.m_ecdsa_blob)) { + else if (blob_size_read != sizeof(m_ecdsa_blob)) { // If the blob was successfully read from persistent storage, verify its size. - SE_TRACE(SE_TRACE_ERROR, "Invalid ECDSA Blob file size. blob_size_read = %uld, sizeof(g_ecdsa_blob) = %uld. Since caller requested use any key, generate a new key.\n", blob_size_read, (uint32_t)sizeof(g_ql_global_data.m_ecdsa_blob)); + SE_TRACE(SE_TRACE_ERROR, "Invalid ECDSA Blob file size. blob_size_read = %uld, sizeof(g_ecdsa_blob) = %uld. Since caller requested use any key, generate a new key.\n", blob_size_read, (uint32_t)sizeof(m_ecdsa_blob)); gen_new_key = true; break; } memset(&tdqe_report_body, 0, sizeof(tdqe_report_body)); // Verify the cached blob. - sgx_status = verify_blob(tdqe_eid, + sgx_status = verify_blob(m_eid, (uint32_t*)&tdqe_error, - (uint8_t*)g_ql_global_data.m_ecdsa_blob, - sizeof(g_ql_global_data.m_ecdsa_blob), + (uint8_t*)m_ecdsa_blob, + sizeof(m_ecdsa_blob), &resealed, &tdqe_report_body, sizeof(blob_ecdsa_id), @@ -1271,7 +1144,7 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ if (SGX_SUCCESS != sgx_status) { SE_TRACE(SE_TRACE_ERROR, "Failed call into the TDQE. 0x%04x\n", sgx_status); ///todo: May want to retry on SGX_ERROR_ENCLAVE_LOST caused by power transition or return a differnet error - refqt_ret = (quote3_error_t)sgx_status; + refqt_ret = (tee_att_error_t)sgx_status; goto CLEANUP; } if (TDQE_SUCCESS != tdqe_error) { @@ -1283,20 +1156,24 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ p_qe_target_info->mr_enclave = tdqe_report_body.mr_enclave; if (resealed) { SE_TRACE(SE_TRACE_DEBUG, "ECDSA Blob was resealed. Store it disk.\n"); - refqt_ret = write_persistent_data((uint8_t*)g_ql_global_data.m_ecdsa_blob, - sizeof(g_ql_global_data.m_ecdsa_blob), + refqt_ret = write_persistent_data((uint8_t *)m_ecdsa_blob, + sizeof(m_ecdsa_blob), ECDSA_BLOB_LABEL); - if (refqt_ret != SGX_QL_SUCCESS) { + if (refqt_ret != TEE_ATT_SUCCESS) { // Don't need to error since the blob is still good in memory. - ///todo: What is the best way to notify the requester that the blob was not stored to disk? + /// todo: What is the best way to notify the requester that the blob was not stored to disk? SE_TRACE(SE_TRACE_WARNING, "Warning, unable to store resealed ECDSA blob to persistent storage.\n"); SE_TRACE(SE_TRACE_DEBUG, "File storage is not required for the QE_Library. Library will use ECDSA Blob cached in memory.\n"); - refqt_ret = SGX_QL_SUCCESS; + refqt_ret = TEE_ATT_SUCCESS; } + // Resealed means that uCode has been updated or TDQE has been updated. Re-generate AK + SE_TRACE(SE_TRACE_DEBUG, "ECDSA Blob was resealed. It means the TDQE or CPUSVN has been upgraded.\n"); + gen_new_key = true; + break; } - p_sealed_ecdsa = reinterpret_cast(g_ql_global_data.m_ecdsa_blob); - p_seal_data_plain_text = reinterpret_cast(g_ql_global_data.m_ecdsa_blob + sizeof(sgx_sealed_data_t) + p_sealed_ecdsa->plain_text_offset); + p_sealed_ecdsa = reinterpret_cast(m_ecdsa_blob); + p_seal_data_plain_text = reinterpret_cast(m_ecdsa_blob + sizeof(sgx_sealed_data_t) + p_sealed_ecdsa->plain_text_offset); // Check to see if the requested certification type matches the type in the blob. if(p_seal_data_plain_text->certification_key_type != certification_key_type) { SE_TRACE(SE_TRACE_ERROR, "Requested certificaiton_key_type doesn't match existing blob's type, Gen and certify new key.\n"); @@ -1307,7 +1184,13 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ //new key if((tdqe_report_body.isv_svn > p_seal_data_plain_text->cert_qe_isv_svn) || (0 != memcmp(&p_seal_data_plain_text->raw_cpu_svn, &tdqe_report_body.cpu_svn, sizeof(p_seal_data_plain_text->raw_cpu_svn)))) { - SE_TRACE(SE_TRACE_ERROR, "Platform TCB has increased, Requested certificaiton_key_type doesn't match existing blob's type, Gen and certify new key.\n"); + SE_TRACE(SE_TRACE_ERROR, "Platform TCB has increased, gen and certify new key.\n"); + gen_new_key = true; + break; + } + // PCE's raw isvsvn changed, catch it here and generate a new key + if (m_raw_pce_isvsvn != p_seal_data_plain_text->raw_pce_info.pce_isv_svn) { + SE_TRACE(SE_TRACE_ERROR, "PCE's raw isvsvn changed, gen and certify new key.\n"); gen_new_key = true; break; } @@ -1319,31 +1202,29 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ break; } if(0 != memcpy_s(p_pub_key_id, sizeof(*p_pub_key_id), &blob_ecdsa_id, sizeof(blob_ecdsa_id))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } SE_TRACE(SE_TRACE_DEBUG, "Using ECDSA_ID from ECDSA Blob. ECDSA_ID:\n"); PRINT_BYTE_ARRAY(SE_TRACE_DEBUG, (uint8_t *)&blob_ecdsa_id, sizeof(blob_ecdsa_id)); SE_TRACE(SE_TRACE_DEBUG, "\n"); - if (SGX_QL_SUCCESS != (refqt_ret = getencryptedppid(pce_target_info, encrypted_ppid, REF_RSA_OAEP_3072_MOD_SIZE))){ + if (TEE_ATT_SUCCESS != (refqt_ret = getencryptedppid(pce_target_info, encrypted_ppid, REF_RSA_OAEP_3072_MOD_SIZE))){ SE_TRACE(SE_TRACE_DEBUG, "Fail to retrieve encrypted PPID.\n"); goto CLEANUP; } - - if (NULL == g_ql_global_data.m_qe_id) + if (NULL == m_qe_id) { - - g_ql_global_data.m_qe_id = (sgx_key_128bit_t*)malloc(sizeof(sgx_key_128bit_t)); - if (!g_ql_global_data.m_qe_id) { + m_qe_id = (sgx_key_128bit_t*)malloc(sizeof(sgx_key_128bit_t)); + if (!m_qe_id) { SE_TRACE(SE_TRACE_ERROR, "Fail to allocate memory.\n"); - refqt_ret = SGX_QL_ERROR_OUT_OF_MEMORY; + refqt_ret = TEE_ATT_ERROR_OUT_OF_MEMORY; goto CLEANUP; } - refqt_ret = load_id_enclave_get_id(g_ql_global_data.m_qe_id); - if (SGX_QL_SUCCESS != refqt_ret) { + refqt_ret = load_id_enclave_get_id(m_qe_id); + if (TEE_ATT_SUCCESS != refqt_ret) { goto CLEANUP; } } @@ -1359,13 +1240,13 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ // the value used to certify existing attestation key. // Get the TCB the PCE should use to ceritfy the attestaion key. Find and call the platform software's - // sgx_ql_get_quote_config(). If it is not available or the API returns SGX_QL_NO_PLATFORM_CERT_DATA, then use + // sgx_ql_get_quote_config(). If it is not available or the API returns TEE_ATT_NO_PLATFORM_CERT_DATA, then use // the platform's raw TCB to certify the key. cert_data_size = 0; - pck_cert_id.p_qe3_id = (uint8_t*)g_ql_global_data.m_qe_id; - pck_cert_id.qe3_id_size = sizeof(*g_ql_global_data.m_qe_id); - pck_cert_id.p_platform_cpu_svn = &tdqe_report_body.cpu_svn; - pck_cert_id.p_platform_pce_isv_svn = &pce_isv_svn; + pck_cert_id.p_qe3_id = (uint8_t*)m_qe_id; + pck_cert_id.qe3_id_size = sizeof(*m_qe_id); + pck_cert_id.p_platform_cpu_svn = &p_seal_data_plain_text->cert_cpu_svn; + pck_cert_id.p_platform_pce_isv_svn = &p_seal_data_plain_text->cert_pce_info.pce_isv_svn; pck_cert_id.p_encrypted_ppid = encrypted_ppid; pck_cert_id.encrypted_ppid_size = REF_RSA_OAEP_3072_MOD_SIZE; pck_cert_id.crypto_suite = PCE_ALG_RSA_OAEP_3072; @@ -1375,12 +1256,12 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ &pce_cert_psvn.isv_svn, &cert_data_size, NULL); - if (refqt_ret != SGX_QL_SUCCESS) { - if (refqt_ret != SGX_QL_PLATFORM_LIB_UNAVAILABLE) { + if (refqt_ret != TEE_ATT_SUCCESS) { + if (refqt_ret != TEE_ATT_PLATFORM_LIB_UNAVAILABLE) { // The dependent library was found but it returned an error goto CLEANUP; } - refqt_ret = SGX_QL_SUCCESS; + refqt_ret = TEE_ATT_SUCCESS; if(pce_isv_svn > p_seal_data_plain_text->cert_pce_info.pce_isv_svn) { SE_TRACE(SE_TRACE_DEBUG, "Using raw-PCE_ISVSVN to certify the key and it has increased. Recertify.\n"); @@ -1391,14 +1272,14 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ memset(&plaintext_data, 0, sizeof(plaintext_data)); if(0 != memcpy_s(&plaintext_data.cert_cpu_svn, sizeof(plaintext_data.cert_cpu_svn), &pce_cert_psvn.cpu_svn, sizeof(pce_cert_psvn.cpu_svn))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } plaintext_data.cert_pce_info.pce_isv_svn = pce_cert_psvn.isv_svn; plaintext_data.cert_pce_info.pce_id = p_seal_data_plain_text->cert_pce_info.pce_id; if(0 != memcpy_s(&plaintext_data.raw_cpu_svn, sizeof(plaintext_data.raw_cpu_svn), &tdqe_report_body.cpu_svn, sizeof(tdqe_report_body.cpu_svn))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } plaintext_data.raw_pce_info.pce_isv_svn = pce_isv_svn; @@ -1406,27 +1287,26 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ // For recertification, pull out out the certification data from the blob that doesn't need to change. if(0 != memcpy_s(&plaintext_data.qe_report, sizeof(plaintext_data.qe_report), &p_seal_data_plain_text->qe_report, sizeof(p_seal_data_plain_text->qe_report))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } if (0 != memcpy_s(&plaintext_data.qe_id, sizeof(plaintext_data.qe_id), - g_ql_global_data.m_qe_id, sizeof(*g_ql_global_data.m_qe_id))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + m_qe_id, sizeof(*m_qe_id))) { + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } plaintext_data.signature_scheme = p_seal_data_plain_text->signature_scheme; ///todo: Not likely that the signature scheme changed but may want to re-get from PCE. It is just more involved. if(0 != memcpy_s(&plaintext_data.pce_target_info, sizeof(plaintext_data.pce_target_info), &pce_target_info, sizeof(pce_target_info))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } plaintext_data.certification_key_type = certification_key_type; //Cert key request it checked if it changed above. If changed, recertification is not allowed. - refqt_ret = certify_key(g_ql_global_data.m_ecdsa_blob, + refqt_ret = certify_key(m_ecdsa_blob, &plaintext_data, NULL, 0, - certification_key_type, - &tdqe_eid); + certification_key_type); } } else { @@ -1442,14 +1322,14 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ memset(&plaintext_data, 0, sizeof(plaintext_data)); if(0 != memcpy_s(&plaintext_data.cert_cpu_svn, sizeof(plaintext_data.cert_cpu_svn), &pce_cert_psvn.cpu_svn, sizeof(pce_cert_psvn.cpu_svn))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } plaintext_data.cert_pce_info.pce_isv_svn = pce_cert_psvn.isv_svn; plaintext_data.cert_pce_info.pce_id = p_seal_data_plain_text->cert_pce_info.pce_id; if(0 != memcpy_s(&plaintext_data.raw_cpu_svn, sizeof(plaintext_data.raw_cpu_svn), &tdqe_report_body.cpu_svn, sizeof(tdqe_report_body.cpu_svn))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } plaintext_data.raw_pce_info.pce_isv_svn = pce_isv_svn; @@ -1457,27 +1337,26 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ // For recertification, pull out out the certification data from the blob that doesn't need to change. if(0 != memcpy_s(&plaintext_data.qe_report, sizeof(plaintext_data.qe_report), &p_seal_data_plain_text->qe_report, sizeof(p_seal_data_plain_text->qe_report))){ - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } if (0 != memcpy_s(&plaintext_data.qe_id, sizeof(plaintext_data.qe_id), - g_ql_global_data.m_qe_id, sizeof(*g_ql_global_data.m_qe_id))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + m_qe_id, sizeof(*m_qe_id))) { + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } plaintext_data.signature_scheme = p_seal_data_plain_text->signature_scheme; ///todo: Not likely that the signature scheme changed but may want to re-get from PCE. It is just more involved. if(0 != memcpy_s(&plaintext_data.pce_target_info, sizeof(plaintext_data.pce_target_info), &pce_target_info, sizeof(pce_target_info))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } plaintext_data.certification_key_type = certification_key_type; //Cert key request it checked if it changed above. If changed, recertification is not allowed. - refqt_ret = certify_key(g_ql_global_data.m_ecdsa_blob, + refqt_ret = certify_key(m_ecdsa_blob, &plaintext_data, NULL, 0, - certification_key_type, - &tdqe_eid); + certification_key_type); } } } while (0); @@ -1493,20 +1372,20 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ SE_TRACE(SE_TRACE_DEBUG, "Generate and certify a new ECDSA attestation key\n"); if (PPID_RSA3072_ENCRYPTED == certification_key_type) { - if (SGX_QL_SUCCESS != (refqt_ret = getencryptedppid(pce_target_info, encrypted_ppid, REF_RSA_OAEP_3072_MOD_SIZE))) { + if (TEE_ATT_SUCCESS != (refqt_ret = getencryptedppid(pce_target_info, encrypted_ppid, REF_RSA_OAEP_3072_MOD_SIZE))) { SE_TRACE(SE_TRACE_DEBUG, "Fail to retrieve encrypted PPID.\n"); goto CLEANUP; } } else { SE_TRACE(SE_TRACE_ERROR, "certification_key_type not supported.\n"); - refqt_ret = SGX_QL_ERROR_INVALID_PARAMETER; + refqt_ret = TEE_ATT_ERROR_INVALID_PARAMETER; goto CLEANUP; } // Generate the ECDSA key SE_TRACE(SE_TRACE_DEBUG, "Get ATT Key.\n"); - sgx_status = gen_att_key(tdqe_eid, + sgx_status = gen_att_key(m_eid, (uint32_t*)&tdqe_error, - g_ql_global_data.m_ecdsa_blob, + m_ecdsa_blob, SGX_QL_TRUSTED_ECDSA_BLOB_SIZE_SDK, &pce_target_info, &tdqe_report, @@ -1515,63 +1394,62 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ if (SGX_SUCCESS != sgx_status) { SE_TRACE(SE_TRACE_ERROR, "Failed call into the TDQE. 0x%04x.\n", sgx_status); // /todo: May want to retry on SGX_ERROR_ENCLAVE_LOST caused by power transition - refqt_ret = (quote3_error_t)sgx_status; + refqt_ret = (tee_att_error_t)sgx_status; goto CLEANUP; } if (TDQE_SUCCESS != tdqe_error) { SE_TRACE(SE_TRACE_ERROR, "Failed to generate attestation key. 0x%04x\n", tdqe_error); - refqt_ret = (quote3_error_t)tdqe_error; + refqt_ret = (tee_att_error_t)tdqe_error; goto CLEANUP; } if(0 != memcpy_s(&p_qe_target_info->mr_enclave, sizeof(p_qe_target_info->mr_enclave), &tdqe_report.body.mr_enclave, sizeof(tdqe_report.body.mr_enclave))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } - if (NULL == g_ql_global_data.m_qe_id) + if (NULL == m_qe_id) { - - g_ql_global_data.m_qe_id = (sgx_key_128bit_t*)malloc(sizeof(sgx_key_128bit_t)); - if (!g_ql_global_data.m_qe_id) { + m_qe_id = (sgx_key_128bit_t*)malloc(sizeof(sgx_key_128bit_t)); + if (!m_qe_id) { SE_TRACE(SE_TRACE_ERROR, "Fail to allocate memory.\n"); - refqt_ret = SGX_QL_ERROR_OUT_OF_MEMORY; + refqt_ret = TEE_ATT_ERROR_OUT_OF_MEMORY; goto CLEANUP; } - refqt_ret = load_id_enclave_get_id(g_ql_global_data.m_qe_id); - if (SGX_QL_SUCCESS != refqt_ret) { + refqt_ret = load_id_enclave_get_id(m_qe_id); + if (TEE_ATT_SUCCESS != refqt_ret) { goto CLEANUP; } } // Certify the key // Get the certification data from the platform, if available - p_sealed_ecdsa = reinterpret_cast(g_ql_global_data.m_ecdsa_blob); - p_seal_data_plain_text = reinterpret_cast(g_ql_global_data.m_ecdsa_blob + sizeof(sgx_sealed_data_t) + p_sealed_ecdsa->plain_text_offset); + p_sealed_ecdsa = reinterpret_cast(m_ecdsa_blob); + p_seal_data_plain_text = reinterpret_cast(m_ecdsa_blob + sizeof(sgx_sealed_data_t) + p_sealed_ecdsa->plain_text_offset); cert_data_size = 0; memset(&plaintext_data, 0, sizeof(plaintext_data)); - pck_cert_id.p_qe3_id = (uint8_t*)g_ql_global_data.m_qe_id; - pck_cert_id.qe3_id_size = sizeof(*g_ql_global_data.m_qe_id); + pck_cert_id.p_qe3_id = (uint8_t*)m_qe_id; + pck_cert_id.qe3_id_size = sizeof(*m_qe_id); pck_cert_id.p_platform_cpu_svn = &tdqe_report.body.cpu_svn; - pck_cert_id.p_platform_pce_isv_svn = &g_ql_global_data.m_pce_info.pce_isv_svn; + pck_cert_id.p_platform_pce_isv_svn = &m_pce_info.pce_isv_svn; pck_cert_id.p_encrypted_ppid = encrypted_ppid; pck_cert_id.encrypted_ppid_size = REF_RSA_OAEP_3072_MOD_SIZE; pck_cert_id.crypto_suite = PCE_ALG_RSA_OAEP_3072; - pck_cert_id.pce_id = g_ql_global_data.m_pce_info.pce_id; + pck_cert_id.pce_id = m_pce_info.pce_id; refqt_ret = get_platform_quote_cert_data(&pck_cert_id, &pce_cert_psvn.cpu_svn, &pce_cert_psvn.isv_svn, &cert_data_size, NULL); - if (refqt_ret != SGX_QL_SUCCESS) { - if (refqt_ret != SGX_QL_PLATFORM_LIB_UNAVAILABLE) { + if (refqt_ret != TEE_ATT_SUCCESS) { + if (refqt_ret != TEE_ATT_PLATFORM_LIB_UNAVAILABLE) { // The dependent library was found but it returned an error goto CLEANUP; } SE_TRACE(SE_TRACE_DEBUG, "Platform Quote Config callback is not available, use the platform's raw TCB.\n"); - refqt_ret = SGX_QL_SUCCESS; + refqt_ret = TEE_ATT_SUCCESS; // Use the raw TCB of the platform and the EncPPID certification type pce_cert_psvn.cpu_svn = tdqe_report.body.cpu_svn; pce_cert_psvn.isv_svn = pce_isv_svn; @@ -1582,69 +1460,64 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ // generate a sealed blob. if(0 != memcpy_s(&plaintext_data.cert_cpu_svn, sizeof(plaintext_data.cert_cpu_svn), &pce_cert_psvn.cpu_svn, sizeof(pce_cert_psvn.cpu_svn))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } plaintext_data.cert_pce_info.pce_isv_svn = pce_cert_psvn.isv_svn; plaintext_data.cert_pce_info.pce_id = 0; if(0 != memcpy_s(&plaintext_data.raw_cpu_svn, sizeof(plaintext_data.raw_cpu_svn), &tdqe_report.body.cpu_svn, sizeof(tdqe_report.body.cpu_svn))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } - plaintext_data.raw_pce_info.pce_isv_svn = g_ql_global_data.m_pce_info.pce_isv_svn; - plaintext_data.raw_pce_info.pce_id = g_ql_global_data.m_pce_info.pce_id; + plaintext_data.raw_pce_info.pce_isv_svn = m_pce_info.pce_isv_svn; + plaintext_data.raw_pce_info.pce_id = m_pce_info.pce_id; if(0 != memcpy_s(&plaintext_data.qe_report, sizeof(plaintext_data.qe_report), &tdqe_report, sizeof(tdqe_report))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } if (0 != memcpy_s(&plaintext_data.qe_id, sizeof(plaintext_data.qe_id), - g_ql_global_data.m_qe_id, sizeof(*g_ql_global_data.m_qe_id))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + m_qe_id, sizeof(*m_qe_id))) { + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } plaintext_data.signature_scheme = PCE_NIST_P256_ECDSA_SHA256; if(0 != memcpy_s(&plaintext_data.pce_target_info, sizeof(plaintext_data.pce_target_info), &pce_target_info, sizeof(pce_target_info))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } plaintext_data.certification_key_type = certification_key_type; - refqt_ret = certify_key(g_ql_global_data.m_ecdsa_blob, + refqt_ret = certify_key(m_ecdsa_blob, &plaintext_data, encrypted_ppid, REF_RSA_OAEP_3072_MOD_SIZE, - certification_key_type, - &tdqe_eid); - if (SGX_QL_SUCCESS != refqt_ret) { + certification_key_type); + if (TEE_ATT_SUCCESS != refqt_ret) { SE_TRACE(SE_TRACE_DEBUG, "Failed to cerify key.\n"); goto CLEANUP; } - SE_TRACE(SE_TRACE_DEBUG, "TDQE_ID:\n"); - PRINT_BYTE_ARRAY(SE_TRACE_DEBUG, &p_seal_data_plain_text->qe_id, sizeof(p_seal_data_plain_text->qe_id)); SE_TRACE(SE_TRACE_DEBUG, "Generated and certified a new key. ECDSA_ID:\n"); PRINT_BYTE_ARRAY(SE_TRACE_DEBUG, &tdqe_report.body.report_data, sizeof(sgx_sha256_hash_t)); // Write the ECDSA_ID to the output buffer if(0 != memcpy_s(p_pub_key_id, sizeof(*p_pub_key_id), &tdqe_report.body.report_data, sizeof(*p_pub_key_id))) { - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } } CLEANUP: if(0 != blob_mutex_rc ) { - blob_mutex_rc = se_mutex_unlock(&g_ql_global_data.m_ecdsa_blob_mutex); + blob_mutex_rc = se_mutex_unlock(&m_ecdsa_blob_mutex); if (0 == blob_mutex_rc) { SE_TRACE(SE_TRACE_ERROR, "Failed to unlock mutex"); - return SGX_QL_ERROR_UNEXPECTED; + return TEE_ATT_ERROR_UNEXPECTED; } } - unload_qe(); - return(refqt_ret); } @@ -1655,33 +1528,27 @@ static quote3_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_ * @param certification_key_type * @param p_quote_size * -* @return SGX_QL_SUCCESS -* @return SGX_QL_ERROR_INVALID_PARAMETER +* @return TEE_ATT_SUCCESS +* @return TEE_ATT_ERROR_INVALID_PARAMETER * @return Errors from load_qe() * @return Errors from an ecall -* @return SGX_QL_ATT_KEY_NOT_INITIALIZED The Attestaion key has not been generated, certified or requires +* @return TEE_ATT_ATT_KEY_NOT_INITIALIZED The Attestaion key has not been generated, certified or requires * recertification yet. Need to call InitQuote first/again to get attestaion key regenerated/receritifed. -* @return SGX_QL_ATT_KEY_CERT_DATA_INVALID Quote certification data from the platform library is invalid. +* @return TEE_ATT_ATT_KEY_CERT_DATA_INVALID Quote certification data from the platform library is invalid. * */ -static quote3_error_t ecdsa_get_quote_size(sgx_ql_cert_key_type_t certification_key_type, +tee_att_error_t tee_att_config_t::ecdsa_get_quote_size(sgx_ql_cert_key_type_t certification_key_type, uint32_t* p_quote_size) { - quote3_error_t refqt_ret = SGX_QL_SUCCESS; + tee_att_error_t refqt_ret = TEE_ATT_SUCCESS; sgx_status_t sgx_status = SGX_SUCCESS; tdqe_error_t tdqe_error = TDQE_ERROR_UNEXPECTED; uint32_t cert_data_size; sgx_sealed_data_t *p_sealed_ecdsa; ref_plaintext_ecdsa_data_sdk_t *p_seal_data_plain_text; sgx_report_body_t tdqe_report_body; - sgx_pce_error_t pce_error; - sgx_target_info_t pce_target_info; - sgx_isv_svn_t pce_isv_svn; sgx_psvn_t pce_cert_psvn; - sgx_enclave_id_t tdqe_eid = 0; - sgx_launch_token_t launch_token = {0}; - sgx_misc_attribute_t tdqe_attributes; uint8_t resealed = 0; sgx_ql_pck_cert_id_t pck_cert_id; uint32_t blob_size_read; @@ -1691,12 +1558,12 @@ static quote3_error_t ecdsa_get_quote_size(sgx_ql_cert_key_type_t certification_ // Only RSA-3072-OAEP Encrypted PPID certification type in the reference. if (PPID_RSA3072_ENCRYPTED != certification_key_type) { SE_TRACE(SE_TRACE_ERROR, "Invalid certification key type."); - return(SGX_QL_ERROR_INVALID_PARAMETER); + return(TEE_ATT_ERROR_INVALID_PARAMETER); } if (NULL == p_quote_size) { SE_TRACE(SE_TRACE_ERROR, "p_quote_size is NULL."); - return(SGX_QL_ERROR_INVALID_PARAMETER); + return(TEE_ATT_ERROR_INVALID_PARAMETER); } SE_TRACE(SE_TRACE_DEBUG, "sizeof(sgx_quote4_t) = %d.\n", (unsigned int)sizeof(sgx_quote4_t)); @@ -1708,54 +1575,42 @@ static quote3_error_t ecdsa_get_quote_size(sgx_ql_cert_key_type_t certification_ SE_TRACE(SE_TRACE_DEBUG, "authentication_data_size = %d.\n", (unsigned int)REF_ECDSDA_AUTHENTICATION_DATA_SIZE); SE_TRACE(SE_TRACE_DEBUG, "sizeof(ref_ppid_rsa3072_encrypted_cert_info_t) = %d.\n", (unsigned int)sizeof(sgx_ql_ppid_rsa3072_encrypted_cert_info_t)); - // Get PCE Target Info - pce_error = sgx_pce_get_target(&pce_target_info, &pce_isv_svn); - if (SGX_PCE_SUCCESS != pce_error) { - SE_TRACE(SE_TRACE_ERROR, "Error, call sgx_pce_get_target [%s], pce_error:%04x.\n", __FUNCTION__, pce_error); - refqt_ret = translate_pce_errors(pce_error); - goto CLEANUP; - } - // Load the TDQE SE_TRACE(SE_TRACE_DEBUG, "Call Load the QE.\n"); - refqt_ret = load_qe(&tdqe_eid, - &tdqe_attributes, - &launch_token); - if (SGX_QL_SUCCESS != refqt_ret) - { + refqt_ret = load_qe(); + if (TEE_ATT_SUCCESS != refqt_ret) { goto CLEANUP; - } - blob_mutex_rc = se_mutex_lock(&g_ql_global_data.m_ecdsa_blob_mutex); + blob_mutex_rc = se_mutex_lock(&m_ecdsa_blob_mutex); if (0 == blob_mutex_rc) { SE_TRACE(SE_TRACE_ERROR, "Failed to lock mutex\n"); goto CLEANUP; } - blob_size_read = sizeof(g_ql_global_data.m_ecdsa_blob); + blob_size_read = sizeof(m_ecdsa_blob); // Get ECDSA Blob if exists SE_TRACE(SE_TRACE_DEBUG, "Read ECDSA blob from persistent storage.\n"); - refqt_ret = read_persistent_data((uint8_t*)g_ql_global_data.m_ecdsa_blob, + refqt_ret = read_persistent_data((uint8_t*)m_ecdsa_blob, &blob_size_read, ECDSA_BLOB_LABEL); - if (SGX_QL_SUCCESS != refqt_ret) { + if (TEE_ATT_SUCCESS != refqt_ret) { // Ignore errors since persistent storage is not required. Blob in memory may still be OK and continue to try to verify the cached blob. SE_TRACE(SE_TRACE_WARNING, "ECDSA Blob doesn't exist is persistent storage. Try to use the cached version.\n"); - refqt_ret = SGX_QL_SUCCESS; + refqt_ret = TEE_ATT_SUCCESS; } - else if (blob_size_read != sizeof(g_ql_global_data.m_ecdsa_blob)) { + else if (blob_size_read != sizeof(m_ecdsa_blob)) { // If the blob was successfully read from persistent storage, verify its size. - SE_TRACE(SE_TRACE_ERROR, "Invalid ECDSA Blob file size. blob_size_read = %uld, sizeof(g_ecdsa_blob) = %uld. Since caller requested use any key, generate a new key.\n", blob_size_read, (uint32_t)sizeof(g_ql_global_data.m_ecdsa_blob)); - refqt_ret = SGX_QL_ATT_KEY_NOT_INITIALIZED; + SE_TRACE(SE_TRACE_ERROR, "Invalid ECDSA Blob file size. blob_size_read = %uld, sizeof(g_ecdsa_blob) = %uld. Since caller requested use any key, generate a new key.\n", blob_size_read, (uint32_t)sizeof(m_ecdsa_blob)); + refqt_ret = TEE_ATT_ATT_KEY_NOT_INITIALIZED; goto CLEANUP; } memset(&tdqe_report_body, 0, sizeof(tdqe_report_body)); // If exists, verify blob. - sgx_status = verify_blob(tdqe_eid, + sgx_status = verify_blob(m_eid, (uint32_t*)&tdqe_error, - (uint8_t*)g_ql_global_data.m_ecdsa_blob, - sizeof(g_ql_global_data.m_ecdsa_blob), + (uint8_t*)m_ecdsa_blob, + sizeof(m_ecdsa_blob), &resealed, &tdqe_report_body, 0, @@ -1763,39 +1618,51 @@ static quote3_error_t ecdsa_get_quote_size(sgx_ql_cert_key_type_t certification_ if (SGX_SUCCESS != sgx_status) { SE_TRACE(SE_TRACE_ERROR, "Failed call into the TDQE. 0x%04x\n", sgx_status); ///todo: May want to retry on SGX_ERROR_ENCLAVE_LOST caused by power transition or return a different error - refqt_ret = (quote3_error_t)sgx_status; + refqt_ret = (tee_att_error_t)sgx_status; goto CLEANUP; } if (TDQE_SUCCESS != tdqe_error) { SE_TRACE(SE_TRACE_ERROR, "Invalid ECDSA Blob verificaton. 0x%04x, generate a new key.\n", tdqe_error); ///todo: Do we want to force the caller to generate the attestation key again when the ECDSA blob fails? // May want to add logic to the DCAP wrappers to automatically call init_quote on this failure. - refqt_ret = SGX_QL_ATT_KEY_NOT_INITIALIZED; + refqt_ret = TEE_ATT_ATT_KEY_NOT_INITIALIZED; goto CLEANUP; } if (resealed) { SE_TRACE(SE_TRACE_DEBUG, "ECDSA Blob was resealed. Store it disk.\n"); - refqt_ret = write_persistent_data((uint8_t*)g_ql_global_data.m_ecdsa_blob, - sizeof(g_ql_global_data.m_ecdsa_blob), + refqt_ret = write_persistent_data((uint8_t *)m_ecdsa_blob, + sizeof(m_ecdsa_blob), ECDSA_BLOB_LABEL); - if (refqt_ret != SGX_QL_SUCCESS) { + if (refqt_ret != TEE_ATT_SUCCESS) { // Don't need to error since the blob is still good in memory. // /todo: What is the best way to notify the requester that the blob was not stored? SE_TRACE(SE_TRACE_WARNING, "Warning, unable to store resealed ECDSA blob to persistent storage.\n"); SE_TRACE(SE_TRACE_DEBUG, "File storage is not required for the QE_Library. Library will use ECDSA Blob cached in memory.\n"); - refqt_ret = SGX_QL_SUCCESS; + refqt_ret = TEE_ATT_SUCCESS; } + SE_TRACE(SE_TRACE_DEBUG, "ECDSA Blob was resealed. It means the TDQE or CPUSVN has been upgraded.\n"); + refqt_ret = TEE_ATT_ATT_KEY_NOT_INITIALIZED; + goto CLEANUP; } + SE_TRACE(SE_TRACE_DEBUG, "Successfully verified ECDSA Blob.\n"); - p_sealed_ecdsa = reinterpret_cast(g_ql_global_data.m_ecdsa_blob); - p_seal_data_plain_text = reinterpret_cast(g_ql_global_data.m_ecdsa_blob + sizeof(sgx_sealed_data_t) + p_sealed_ecdsa->plain_text_offset); + p_sealed_ecdsa = reinterpret_cast(m_ecdsa_blob); + p_seal_data_plain_text = reinterpret_cast(m_ecdsa_blob + sizeof(sgx_sealed_data_t) + p_sealed_ecdsa->plain_text_offset); + + // PCE's raw isvsvn changed, catch it here and generate a new key + if (m_raw_pce_isvsvn != p_seal_data_plain_text->raw_pce_info.pce_isv_svn) { + SE_TRACE(SE_TRACE_ERROR, "PCE's raw isvsvn changed\n"); + refqt_ret = TEE_ATT_ATT_KEY_NOT_INITIALIZED; + goto CLEANUP; + } + cert_data_size = 0; pck_cert_id.p_qe3_id = (uint8_t*)&p_seal_data_plain_text->qe_id; pck_cert_id.qe3_id_size = sizeof(p_seal_data_plain_text->qe_id); - pck_cert_id.p_platform_cpu_svn = &tdqe_report_body.cpu_svn; - pck_cert_id.p_platform_pce_isv_svn = &pce_isv_svn; + pck_cert_id.p_platform_cpu_svn = &p_seal_data_plain_text->cert_cpu_svn; + pck_cert_id.p_platform_pce_isv_svn = &p_seal_data_plain_text->cert_pce_info.pce_isv_svn; pck_cert_id.p_encrypted_ppid = NULL; pck_cert_id.encrypted_ppid_size = 0; pck_cert_id.crypto_suite = PCE_ALG_RSA_OAEP_3072; @@ -1806,8 +1673,8 @@ static quote3_error_t ecdsa_get_quote_size(sgx_ql_cert_key_type_t certification_ &cert_data_size, NULL); // Use the default certification data when there is no data from platform library. - if (refqt_ret != SGX_QL_SUCCESS) { - if (refqt_ret != SGX_QL_PLATFORM_LIB_UNAVAILABLE) { + if (refqt_ret != TEE_ATT_SUCCESS) { + if (refqt_ret != TEE_ATT_PLATFORM_LIB_UNAVAILABLE) { // The dependent library was found but it returned an error goto CLEANUP; } @@ -1820,21 +1687,22 @@ static quote3_error_t ecdsa_get_quote_size(sgx_ql_cert_key_type_t certification_ sizeof(sgx_ql_certification_data_t) + sizeof(sgx_qe_report_certification_data_t) + sizeof(sgx_ql_ppid_rsa3072_encrypted_cert_info_t); // RSA3072_ENC_PPID + PCE CPUSVN + PCE ISVSNV + PCEID - refqt_ret = SGX_QL_SUCCESS; + refqt_ret = TEE_ATT_SUCCESS; } else { // Verify that the cert_data_size is reasonable. if((cert_data_size > MAX_CERT_DATA_SIZE) || (cert_data_size < MIN_CERT_DATA_SIZE)) { - refqt_ret = SGX_QL_ATT_KEY_CERT_DATA_INVALID; + refqt_ret = TEE_ATT_ATT_KEY_CERT_DATA_INVALID; goto CLEANUP; } //Check to make sure that the TCBm of from the platform library matches the Cert TCB in the ECDSA blob. + //We've change to use the TCBm to get the cert data, so below check is redundant. But I think it's OK to leave it here. if((0 != memcmp(&p_seal_data_plain_text->cert_cpu_svn, &pce_cert_psvn.cpu_svn, sizeof(p_seal_data_plain_text->cert_cpu_svn))) || (p_seal_data_plain_text->cert_pce_info.pce_isv_svn != pce_cert_psvn.isv_svn)) { SE_TRACE(SE_TRACE_ERROR, "TCBm in ECDSA blob doesn't match the value returned by the platform lib. %d and %d\n", p_seal_data_plain_text->cert_pce_info.pce_isv_svn, pce_cert_psvn.isv_svn); - refqt_ret = SGX_QL_ATT_KEY_NOT_INITIALIZED; + refqt_ret = TEE_ATT_ATT_KEY_NOT_INITIALIZED; goto CLEANUP; } // Overflow will not occur since the cer_data_size is limited above @@ -1850,15 +1718,13 @@ static quote3_error_t ecdsa_get_quote_size(sgx_ql_cert_key_type_t certification_ CLEANUP: if(0 != blob_mutex_rc ) { - blob_mutex_rc = se_mutex_unlock(&g_ql_global_data.m_ecdsa_blob_mutex); + blob_mutex_rc = se_mutex_unlock(&m_ecdsa_blob_mutex); if (0 == blob_mutex_rc) { SE_TRACE(SE_TRACE_ERROR, "Failed to unlock mutex"); - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; } } - unload_qe(); - return(refqt_ret); } @@ -1866,18 +1732,17 @@ static quote3_error_t ecdsa_get_quote_size(sgx_ql_cert_key_type_t certification_ * This is the ECDSA-P256 specific get quote code. The generic quote interfaces have been converted/reduced to the ECDSA * specific inputs. The method will return the quote dependent on the certification key type. * -* @param certification_key_type * @param p_app_report * @param p_quote * @param quote_size * -* @return SGX_QL_SUCCESS +* @return TEE_ATT_SUCCESS * @return Return codes from load_qe. -* @return SGX_QL_ATT_KEY_NOT_INITIALIZED The Attestaion key has not been generated, certified or requires +* @return TEE_ATT_ATT_KEY_NOT_INITIALIZED The Attestaion key has not been generated, certified or requires * recertification yet. Need to call InitQuote first/again to get attestaion key regenerated/receritifed. * @return ///todo: List out ecall errors. - * @return SGX_QL_ATT_KEY_CERT_DATA_INVALID Quote certification data from the platform library is invalid. -* @return SGX_QL_ERROR_OUT_OF_MEMORY +* @return TEE_ATT_ATT_KEY_CERT_DATA_INVALID Quote certification data from the platform library is invalid. +* @return TEE_ATT_ERROR_OUT_OF_MEMORY * @return TDQE_ERROR_INVALID_PLATFORM * @return TDQE_ERROR_INVALID_PARAMETER * @return TDQE_ERROR_INVALID_REPORT @@ -1887,22 +1752,16 @@ static quote3_error_t ecdsa_get_quote_size(sgx_ql_cert_key_type_t certification_ * @return TDQE_ERROR_OUT_OF_MEMORY * @return SGX_ERROR_INVALID_PARAMETER */ -static quote3_error_t ecdsa_get_quote(const sgx_report2_t *p_app_report, +tee_att_error_t tee_att_config_t::ecdsa_get_quote(const sgx_report2_t *p_app_report, sgx_quote4_t *p_quote, uint32_t quote_size) { - quote3_error_t refqt_ret = SGX_QL_SUCCESS; + tee_att_error_t refqt_ret = TEE_ATT_SUCCESS; sgx_status_t sgx_status = SGX_SUCCESS; - sgx_launch_token_t launch_token = {0}; - sgx_misc_attribute_t tdqe_attributes; - sgx_enclave_id_t tdqe_eid = 0; tdqe_error_t tdqe_error = TDQE_ERROR_UNEXPECTED; uint8_t resealed = 0; - uint32_t blob_size_read = sizeof(g_ql_global_data.m_ecdsa_blob); + uint32_t blob_size_read = sizeof(m_ecdsa_blob); sgx_sha256_hash_t blob_ecdsa_id; - sgx_isv_svn_t cur_pce_isv_svn = {0}; - sgx_target_info_t pce_target_info; - sgx_pce_error_t pce_error; uint32_t cert_data_size; sgx_ql_pck_cert_id_t pck_cert_id; sgx_sealed_data_t *p_sealed_ecdsa; @@ -1916,54 +1775,50 @@ static quote3_error_t ecdsa_get_quote(const sgx_report2_t *p_app_report, if (NULL == p_app_report || NULL == p_quote) { SE_TRACE(SE_TRACE_ERROR, "Invalid input pointer.\n"); - return(SGX_QL_ERROR_INVALID_PARAMETER); + return(TEE_ATT_ERROR_INVALID_PARAMETER); } // Load the TDQE - memset(&launch_token, 0, sizeof(sgx_launch_token_t)); SE_TRACE(SE_TRACE_DEBUG, "Load the TDQE. %s\n", TDQE_ENCLAVE_NAME); // Load the QE enclave - refqt_ret = load_qe(&tdqe_eid, - &tdqe_attributes, - &launch_token); - if (SGX_QL_SUCCESS != refqt_ret) - { + refqt_ret = load_qe(); + if (TEE_ATT_SUCCESS != refqt_ret) { goto CLEANUP; } - blob_mutex_rc = se_mutex_lock(&g_ql_global_data.m_ecdsa_blob_mutex); + blob_mutex_rc = se_mutex_lock(&m_ecdsa_blob_mutex); if (0 == blob_mutex_rc) { SE_TRACE(SE_TRACE_ERROR, "Failed to lock mutex\n"); goto CLEANUP; } SE_TRACE(SE_TRACE_DEBUG, "Read and verify ecdsa blob\n"); - blob_size_read = sizeof(g_ql_global_data.m_ecdsa_blob); + blob_size_read = sizeof(m_ecdsa_blob); // Get ECDSA Blob if exists SE_TRACE(SE_TRACE_DEBUG, "Read ECDSA blob.\n"); - refqt_ret = read_persistent_data((uint8_t*)g_ql_global_data.m_ecdsa_blob, + refqt_ret = read_persistent_data((uint8_t*)m_ecdsa_blob, &blob_size_read, ECDSA_BLOB_LABEL); - if (SGX_QL_SUCCESS != refqt_ret) { + if (TEE_ATT_SUCCESS != refqt_ret) { // Ignore errors since persistent storage is not required. Blob in memory may still be OK and continue to try to verify the cached blob. ///todo: May want to have a library configuration option that requires persistent storage. Then treat the //failures accordingly SE_TRACE(SE_TRACE_WARNING, "ECDSA Blob doesn't exist is persistent storage. Try to use the cached version.\n"); - refqt_ret = SGX_QL_SUCCESS; + refqt_ret = TEE_ATT_SUCCESS; } - else if (blob_size_read != sizeof(g_ql_global_data.m_ecdsa_blob)) { + else if (blob_size_read != sizeof(m_ecdsa_blob)) { // If the blob was successfully read from persistent storage, verify its size. - SE_TRACE(SE_TRACE_ERROR, "Invalid ECDSA Blob file size. blob_size_read = %uld, sizeof(g_ecdsa_blob) = %uld. Since caller requested use any key, generate a new key.\n", blob_size_read, (uint32_t)sizeof(g_ql_global_data.m_ecdsa_blob)); - refqt_ret = SGX_QL_ATT_KEY_NOT_INITIALIZED; + SE_TRACE(SE_TRACE_ERROR, "Invalid ECDSA Blob file size. blob_size_read = %uld, sizeof(g_ecdsa_blob) = %uld. Since caller requested use any key, generate a new key.\n", blob_size_read, (uint32_t)sizeof(m_ecdsa_blob)); + refqt_ret = TEE_ATT_ATT_KEY_NOT_INITIALIZED; goto CLEANUP; } memset(&tdqe_report_body, 0, sizeof(tdqe_report_body)); // If exists, verify blob. SE_TRACE(SE_TRACE_DEBUG, "Verify blob\n"); - sgx_status = verify_blob(tdqe_eid, + sgx_status = verify_blob(m_eid, (uint32_t*)&tdqe_error, - (uint8_t*)g_ql_global_data.m_ecdsa_blob, - sizeof(g_ql_global_data.m_ecdsa_blob), + (uint8_t*)m_ecdsa_blob, + sizeof(m_ecdsa_blob), &resealed, &tdqe_report_body, sizeof(blob_ecdsa_id), @@ -1971,48 +1826,50 @@ static quote3_error_t ecdsa_get_quote(const sgx_report2_t *p_app_report, if (SGX_SUCCESS != sgx_status) { SE_TRACE(SE_TRACE_ERROR, "Failed call into the TDQE. 0x%04x\n", sgx_status); // /todo: May want to retry on SGX_ERROR_ENCLAVE_LOST caused by power transition or return a differnent error. - refqt_ret = (quote3_error_t)sgx_status; + refqt_ret = (tee_att_error_t)sgx_status; goto CLEANUP; } if (TDQE_SUCCESS != tdqe_error) { SE_TRACE(SE_TRACE_ERROR, "Invalid ECDSA Blob verification. 0x%04x\n", tdqe_error); - refqt_ret = SGX_QL_ATT_KEY_NOT_INITIALIZED; + refqt_ret = TEE_ATT_ATT_KEY_NOT_INITIALIZED; goto CLEANUP; } if (resealed) { - SE_TRACE(SE_TRACE_DEBUG, "ECDSA Blob was resealed. Store it.\n"); - refqt_ret = write_persistent_data((uint8_t*)g_ql_global_data.m_ecdsa_blob, - sizeof(g_ql_global_data.m_ecdsa_blob), + SE_TRACE(SE_TRACE_DEBUG, "ECDSA Blob was resealed. Store it disk.\n"); + refqt_ret = write_persistent_data((uint8_t *)m_ecdsa_blob, + sizeof(m_ecdsa_blob), ECDSA_BLOB_LABEL); - if (refqt_ret != SGX_QL_SUCCESS) { + if (refqt_ret != TEE_ATT_SUCCESS) { // Don't need to error since the blob is still good in memory. - ///todo: What is the best way to notify the requester that the blob was not stored? + // /todo: What is the best way to notify the requester that the blob was not stored? SE_TRACE(SE_TRACE_WARNING, "Warning, unable to store resealed ECDSA blob to persistent storage.\n"); SE_TRACE(SE_TRACE_DEBUG, "File storage is not required for the QE_Library. Library will use ECDSA Blob cached in memory.\n"); - refqt_ret = SGX_QL_SUCCESS; + refqt_ret = TEE_ATT_SUCCESS; } + SE_TRACE(SE_TRACE_DEBUG, "ECDSA Blob was resealed. It means the TDQE or CPUSVN has been upgraded.\n"); + refqt_ret = TEE_ATT_ATT_KEY_NOT_INITIALIZED; + goto CLEANUP; } SE_TRACE(SE_TRACE_DEBUG, "Using ECDSA_ID:\n"); PRINT_BYTE_ARRAY(SE_TRACE_DEBUG, (uint8_t *)&blob_ecdsa_id, sizeof(blob_ecdsa_id)); - // Call into the PCE to get the current platform's PCE ISVSVN - pce_error = sgx_pce_get_target(&pce_target_info, - &cur_pce_isv_svn); - if (SGX_PCE_SUCCESS != pce_error) { - SE_TRACE(SE_TRACE_ERROR, "Error in call to sgx_pce_get_target(). 0x%04x\n", pce_error); - refqt_ret = translate_pce_errors(pce_error); + // See if we can get the certification data from the platform library. + p_sealed_ecdsa = reinterpret_cast(m_ecdsa_blob); + p_seal_data_plain_text = reinterpret_cast(m_ecdsa_blob + sizeof(sgx_sealed_data_t) + p_sealed_ecdsa->plain_text_offset); + + // PCE's raw isvsvn changed, catch it here and generate a new key + if (m_raw_pce_isvsvn != p_seal_data_plain_text->raw_pce_info.pce_isv_svn) { + SE_TRACE(SE_TRACE_ERROR, "PCE's raw isvsvn changed\n"); + refqt_ret = TEE_ATT_ATT_KEY_NOT_INITIALIZED; goto CLEANUP; } - // See if we can get the certification data from the platform library. - p_sealed_ecdsa = reinterpret_cast(g_ql_global_data.m_ecdsa_blob); - p_seal_data_plain_text = reinterpret_cast(g_ql_global_data.m_ecdsa_blob + sizeof(sgx_sealed_data_t) + p_sealed_ecdsa->plain_text_offset); cert_data_size = 0; pck_cert_id.p_qe3_id = (uint8_t*)&p_seal_data_plain_text->qe_id; pck_cert_id.qe3_id_size = sizeof(p_seal_data_plain_text->qe_id); - pck_cert_id.p_platform_cpu_svn = &tdqe_report_body.cpu_svn; - pck_cert_id.p_platform_pce_isv_svn = &cur_pce_isv_svn; + pck_cert_id.p_platform_cpu_svn = &p_seal_data_plain_text->cert_cpu_svn; + pck_cert_id.p_platform_pce_isv_svn = &p_seal_data_plain_text->cert_pce_info.pce_isv_svn; pck_cert_id.p_encrypted_ppid = NULL; pck_cert_id.encrypted_ppid_size = 0; pck_cert_id.crypto_suite = PCE_ALG_RSA_OAEP_3072; @@ -2022,17 +1879,17 @@ static quote3_error_t ecdsa_get_quote(const sgx_report2_t *p_app_report, &pce_cert_psvn.isv_svn, &cert_data_size, NULL); - if (refqt_ret == SGX_QL_SUCCESS) { + if (refqt_ret == TEE_ATT_SUCCESS) { // Verify that the cert_data_size is reasonable. if((cert_data_size > MAX_CERT_DATA_SIZE) || (cert_data_size < MIN_CERT_DATA_SIZE)) { - refqt_ret = SGX_QL_ATT_KEY_CERT_DATA_INVALID; + refqt_ret = TEE_ATT_ATT_KEY_CERT_DATA_INVALID; goto CLEANUP; } // malloc the buffer to get the cert data and call again p_certification_data = (sgx_ql_certification_data_t *)malloc(sizeof(*p_certification_data) + cert_data_size); if(NULL == p_certification_data) { - refqt_ret = SGX_QL_ERROR_OUT_OF_MEMORY; + refqt_ret = TEE_ATT_ERROR_OUT_OF_MEMORY; goto CLEANUP; } @@ -2042,16 +1899,17 @@ static quote3_error_t ecdsa_get_quote(const sgx_report2_t *p_app_report, &pce_cert_psvn.isv_svn, &cert_data_size, p_certification_data->certification_data); - if (refqt_ret != SGX_QL_SUCCESS) { + if (refqt_ret != TEE_ATT_SUCCESS) { // Really shouldn't fail here if we passed the first call. - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; goto CLEANUP; } - //Check to make sure that the TCBm of from the platform library matches the Cert TCB in the ECDSA blob. + // Check to make sure that the TCBm of from the platform library matches the Cert TCB in the ECDSA blob. + // We've change to use the TCBm to get the cert data, so below check is redundant. But I think it's OK to leave it here. if((0 != memcmp(&p_seal_data_plain_text->cert_cpu_svn, &pce_cert_psvn.cpu_svn, sizeof(p_seal_data_plain_text->cert_cpu_svn))) || (p_seal_data_plain_text->cert_pce_info.pce_isv_svn != pce_cert_psvn.isv_svn)) { SE_TRACE(SE_TRACE_ERROR, "TCBm in ECDSA blob doesn't match the value returned by the platform lib. %d and %d\n", p_seal_data_plain_text->cert_pce_info.pce_isv_svn, pce_cert_psvn.isv_svn); - refqt_ret = SGX_QL_ATT_KEY_NOT_INITIALIZED; + refqt_ret = TEE_ATT_ATT_KEY_NOT_INITIALIZED; goto CLEANUP; } //Verify that the size of the quote is large enough to accomodate the cert data returned from the platform library @@ -2063,7 +1921,7 @@ static quote3_error_t ecdsa_get_quote(const sgx_report2_t *p_app_report, sizeof(sgx_ql_certification_data_t) + sizeof(sgx_qe_report_certification_data_t) + cert_data_size)) { - refqt_ret = SGX_QL_ERROR_INVALID_PARAMETER; + refqt_ret = TEE_ATT_ERROR_INVALID_PARAMETER; goto CLEANUP; } p_certification_data->cert_key_type = PCK_CERT_CHAIN; @@ -2071,7 +1929,7 @@ static quote3_error_t ecdsa_get_quote(const sgx_report2_t *p_app_report, } else { - if (refqt_ret != SGX_QL_PLATFORM_LIB_UNAVAILABLE) { + if (refqt_ret != TEE_ATT_PLATFORM_LIB_UNAVAILABLE) { // The dependent library was found but it returned an error goto CLEANUP; } @@ -2081,14 +1939,14 @@ static quote3_error_t ecdsa_get_quote(const sgx_report2_t *p_app_report, // the library was available before it should be available now. // // This is the normal flow when there is no provider library. - refqt_ret = SGX_QL_SUCCESS; + refqt_ret = TEE_ATT_SUCCESS; } SE_TRACE(SE_TRACE_DEBUG, "Call TDQE gen_quote\n"); - sgx_status = gen_quote(tdqe_eid, + sgx_status = gen_quote(m_eid, (uint32_t*)&tdqe_error, - (uint8_t*)g_ql_global_data.m_ecdsa_blob, - (uint32_t)sizeof(g_ql_global_data.m_ecdsa_blob), + (uint8_t*)m_ecdsa_blob, + (uint32_t)sizeof(m_ecdsa_blob), p_app_report, NULL, NULL, @@ -2100,12 +1958,12 @@ static quote3_error_t ecdsa_get_quote(const sgx_report2_t *p_app_report, if (SGX_SUCCESS != sgx_status) { SE_TRACE(SE_TRACE_ERROR, "Failed call into the TDQE. 0x%04x\n", sgx_status); ///todo: May want to retry on SGX_ERROR_ENCLAVE_LOST caused by power transition - refqt_ret = (quote3_error_t)sgx_status; + refqt_ret = (tee_att_error_t)sgx_status; goto CLEANUP; } if (TDQE_SUCCESS != tdqe_error) { SE_TRACE(SE_TRACE_ERROR, "Gen Quote failed. 0x%04x\n", tdqe_error); - refqt_ret = (quote3_error_t)tdqe_error; + refqt_ret = (tee_att_error_t)tdqe_error; goto CLEANUP; } SE_TRACE(SE_TRACE_DEBUG, "Get quote success\n"); @@ -2116,382 +1974,12 @@ static quote3_error_t ecdsa_get_quote(const sgx_report2_t *p_app_report, } if(0 != blob_mutex_rc ) { - blob_mutex_rc = se_mutex_unlock(&g_ql_global_data.m_ecdsa_blob_mutex); + blob_mutex_rc = se_mutex_unlock(&m_ecdsa_blob_mutex); if (0 == blob_mutex_rc) { SE_TRACE(SE_TRACE_ERROR, "Failed to unlock mutex"); - refqt_ret = SGX_QL_ERROR_UNEXPECTED; + refqt_ret = TEE_ATT_ERROR_UNEXPECTED; } } - unload_qe(); - return(refqt_ret); } - -/** - * Set the load policy of TD QE and pce - * @param policy - * - * @return SGX_QL_SUCCESS - * @return SGX_QL_ERROR_UNEXPECTED - * - */ -quote3_error_t td_set_enclave_load_policy(sgx_ql_request_policy_t policy) -{ - quote3_error_t refqt_ret = SGX_QL_ERROR_UNEXPECTED; - sgx_pce_error_t pce_error; - int rc = 0; - - rc = se_mutex_lock(&g_ql_global_data.m_enclave_load_mutex); - if (0 == rc) { - SE_TRACE(SE_TRACE_ERROR, "Failed to lock mutex\n"); - refqt_ret = SGX_QL_ERROR_UNEXPECTED; - goto CLEANUP; - } - - g_ql_global_data.m_load_policy = policy; - refqt_ret = SGX_QL_SUCCESS; - - rc = se_mutex_unlock(&g_ql_global_data.m_enclave_load_mutex); - if (0 == rc) { - SE_TRACE(SE_TRACE_ERROR, "Failed to unlock mutex.\n"); - refqt_ret = SGX_QL_ERROR_UNEXPECTED; - } - pce_error = sgx_set_pce_enclave_load_policy(policy); - if (SGX_PCE_SUCCESS != pce_error) { - refqt_ret = translate_pce_errors(pce_error); - goto CLEANUP; - } - - CLEANUP: - - // Unload the qe if the policy was changed to ephemeral and the enclave is loaded. - unload_qe(); - - return(refqt_ret); -} - -/** - * Set the full path of TD QE - * - * @param p_path The full path of the TD QE - * - * @return SGX_QL_SUCCESS - * @return SGX_QL_ERROR_INVALID_PARAMETER - * - */ -quote3_error_t td_set_qe_path(const char* p_path) -{ - size_t len = 0; - if (NULL == p_path) { - return SGX_QL_ERROR_INVALID_PARAMETER; - } - len = strnlen(p_path, sizeof(g_ql_global_data.tdqe_path)); - // Make sure there is enough space for the '\0', - // after this line len <= sizeof(g_ql_global_data.tdqe_path) - 1 - if(len > sizeof(g_ql_global_data.tdqe_path) - 1) - return SGX_QL_ERROR_INVALID_PARAMETER; -#ifndef _MSC_VER - strncpy(g_ql_global_data.tdqe_path, p_path, sizeof(g_ql_global_data.tdqe_path) - 1); -#else - strncpy_s(g_ql_global_data.tdqe_path, sizeof(g_ql_global_data.tdqe_path), p_path, sizeof(g_ql_global_data.tdqe_path)); -#endif - g_ql_global_data.tdqe_path[len] = '\0'; - return SGX_QL_SUCCESS; -} - -/** - * Set the full path of QPL - * - * @param p_path The full path of the QPL - * - * @return SGX_QL_SUCCESS - * @return SGX_QL_ERROR_INVALID_PARAMETER - * - */ -quote3_error_t td_set_qpl_path(const char* p_path) -{ - size_t len = 0; - if (NULL == p_path) { - return SGX_QL_ERROR_INVALID_PARAMETER; - } - len = strnlen(p_path, sizeof(g_ql_global_data.qpl_path)); - // Make sure there is enough space for the '\0', - // after this line len <= sizeof(g_ql_global_data.qpl_path) - 1 - if(len > sizeof(g_ql_global_data.qpl_path) - 1) - return SGX_QL_ERROR_INVALID_PARAMETER; -#ifndef _MSC_VER - strncpy(g_ql_global_data.qpl_path, p_path, sizeof(g_ql_global_data.qpl_path) - 1); -#else - strncpy_s(g_ql_global_data.qpl_path, sizeof(g_ql_global_data.qpl_path), p_path, sizeof(g_ql_global_data.qpl_path)); -#endif - g_ql_global_data.qpl_path[len] = '\0'; - return SGX_QL_SUCCESS; -} - -quote3_error_t td_init_quote(sgx_ql_cert_key_type_t certification_key_type, - bool refresh_att_key) -{ - sgx_status_t sgx_status = SGX_SUCCESS; - tdqe_error_t tdqe_error = TDQE_SUCCESS; - quote3_error_t ret_val = SGX_QL_SUCCESS; - sgx_target_info_t tdqe_target_info; - ref_sha256_hash_t hash = {0}; - - memset(&tdqe_target_info, 0, sizeof(tdqe_target_info)); - ret_val = ecdsa_init_quote(certification_key_type, &tdqe_target_info, refresh_att_key, &hash); - if(SGX_QL_SUCCESS != ret_val) { - if((ret_val < SGX_QL_ERROR_MIN) || - (ret_val > SGX_QL_ERROR_MAX)) - { - sgx_status = (sgx_status_t)ret_val; - tdqe_error = (tdqe_error_t)ret_val; - - // Translate TDQE errors - switch(tdqe_error) - { - case TDQE_ERROR_INVALID_PARAMETER: - ret_val = SGX_QL_ERROR_INVALID_PARAMETER; - break; - - case TDQE_ERROR_OUT_OF_MEMORY: - ret_val = SGX_QL_ERROR_OUT_OF_MEMORY; - break; - - case TDQE_ERROR_UNEXPECTED: - case TDQE_ERROR_CRYPTO: // Error generating the QE_ID (or decypting PPID not supported in release). Unexpected error. - case TDQE_ERROR_ATT_KEY_GEN: // Error generating the ECDSA Attestation key. - case TDQE_ECDSABLOB_ERROR: // Should be unexpected since the blob was either generated or regenerated during this call - ret_val = SGX_QL_ERROR_UNEXPECTED; - break; - - default: - // Translate SDK errors - switch (sgx_status) - { - case SGX_ERROR_INVALID_PARAMETER: - ret_val = SGX_QL_ERROR_INVALID_PARAMETER; - break; - - case SGX_ERROR_OUT_OF_MEMORY: - ret_val = SGX_QL_ERROR_OUT_OF_MEMORY; - break; - - case SGX_ERROR_ENCLAVE_FILE_ACCESS: - ret_val = SGX_QL_ENCLAVE_LOAD_ERROR; - break; - - case SGX_ERROR_ENCLAVE_LOST: - ret_val = SGX_QL_ENCLAVE_LOST; - break; - - // Unexpected enclave loading errorsReturn codes from load_qe - case SGX_ERROR_INVALID_ENCLAVE: - case SGX_ERROR_UNDEFINED_SYMBOL: - case SGX_ERROR_MODE_INCOMPATIBLE: - case SGX_ERROR_INVALID_METADATA: - case SGX_ERROR_MEMORY_MAP_CONFLICT: - case SGX_ERROR_INVALID_VERSION: - case SGX_ERROR_INVALID_ATTRIBUTE: - case SGX_ERROR_NDEBUG_ENCLAVE: - case SGX_ERROR_INVALID_MISC: - //case SE_ERROR_INVALID_LAUNCH_TOKEN: ///todo: Internal error should be scrubbed before here. - case SGX_ERROR_DEVICE_BUSY: - case SGX_ERROR_NO_DEVICE: - case SGX_ERROR_INVALID_SIGNATURE: - //case SE_ERROR_INVALID_MEASUREMENT: ///todo: Internal error should be scrubbed before here. - //case SE_ERROR_INVALID_ISVSVNLE: ///todo: Internal error should be scrubbed before here. - case SGX_ERROR_INVALID_ENCLAVE_ID: - ret_val = SGX_QL_ENCLAVE_LOAD_ERROR; - break; - case SGX_ERROR_SERVICE_INVALID_PRIVILEGE: - ret_val = SGX_QL_ERROR_INVALID_PRIVILEGE; - break; - - case SGX_ERROR_UNEXPECTED: - ret_val = SGX_QL_ERROR_UNEXPECTED; - break; - - default: - ret_val = SGX_QL_ERROR_UNEXPECTED; - break; - } - break; - } - } - } - - return(ret_val); -} - - -quote3_error_t td_get_quote_size(sgx_ql_cert_key_type_t certification_key_type, - uint32_t *p_quote_size) -{ - sgx_status_t sgx_status = SGX_SUCCESS; - quote3_error_t ret_val = SGX_QL_SUCCESS; - - ret_val = ecdsa_get_quote_size(certification_key_type, p_quote_size); - if(SGX_QL_SUCCESS != ret_val) { - if((ret_val < SGX_QL_ERROR_MIN) || - (ret_val > SGX_QL_ERROR_MAX)) - { - sgx_status = (sgx_status_t)ret_val; - - // Translate SDK errors - switch(sgx_status) - { - case SGX_ERROR_OUT_OF_MEMORY: - ret_val = SGX_QL_ERROR_OUT_OF_MEMORY; - break; - - case SGX_ERROR_ENCLAVE_FILE_ACCESS: - ret_val = SGX_QL_ENCLAVE_LOAD_ERROR; - break; - - // Unexpected enclave loading errorsReturn codes from load_qe - case SGX_ERROR_INVALID_ENCLAVE: - case SGX_ERROR_UNDEFINED_SYMBOL: - case SGX_ERROR_MODE_INCOMPATIBLE: - case SGX_ERROR_INVALID_METADATA: - case SGX_ERROR_MEMORY_MAP_CONFLICT: - case SGX_ERROR_INVALID_VERSION: - case SGX_ERROR_INVALID_ATTRIBUTE: - case SGX_ERROR_NDEBUG_ENCLAVE: - case SGX_ERROR_INVALID_MISC: - //case SE_ERROR_INVALID_LAUNCH_TOKEN: ///todo: Internal error should be scrubbed before here. - case SGX_ERROR_DEVICE_BUSY: - case SGX_ERROR_NO_DEVICE: - case SGX_ERROR_INVALID_SIGNATURE: - //case SE_ERROR_INVALID_MEASUREMENT: ///todo: Internal error should be scrubbed before here. - //case SE_ERROR_INVALID_ISVSVNLE: ///todo: Internal error should be scrubbed before here. - case SGX_ERROR_INVALID_ENCLAVE_ID: - ret_val = SGX_QL_ENCLAVE_LOAD_ERROR; - break; - case SGX_ERROR_SERVICE_INVALID_PRIVILEGE: - ret_val = SGX_QL_ERROR_INVALID_PRIVILEGE; - break; - - case SGX_ERROR_ENCLAVE_LOST: - ret_val = SGX_QL_ENCLAVE_LOST; - break; - - case SGX_ERROR_UNEXPECTED: - ret_val = SGX_QL_ERROR_UNEXPECTED; - break; - - default: - ret_val = SGX_QL_ERROR_UNEXPECTED; - break; - } - } - } - - return(ret_val); -} - - -quote3_error_t td_get_quote( - const sgx_report2_t *p_app_report, - sgx_quote4_t *p_quote, - uint32_t quote_size) -{ - sgx_status_t sgx_status = SGX_SUCCESS; - tdqe_error_t tdqe_error = TDQE_SUCCESS; - quote3_error_t ret_val = SGX_QL_SUCCESS; - - ret_val = ecdsa_get_quote(p_app_report, p_quote, quote_size); - if(SGX_QL_SUCCESS != ret_val) { - if((ret_val < SGX_QL_ERROR_MIN) || - (ret_val > SGX_QL_ERROR_MAX)) - { - sgx_status = (sgx_status_t)ret_val; - tdqe_error = (tdqe_error_t)ret_val; - - // Translate TDQE errors - switch(tdqe_error) - { - case TDQE_ERROR_INVALID_PARAMETER: - ret_val = SGX_QL_ERROR_INVALID_PARAMETER; - break; - - case TDQE_ERROR_INVALID_REPORT: - ret_val = SGX_QL_INVALID_REPORT; - break; - - case TDQE_ERROR_CRYPTO: - // Error generating QE_ID. Shouldn't happen - ret_val = SGX_QL_ERROR_UNEXPECTED; - break; - - case TDQE_ERROR_OUT_OF_MEMORY: - ret_val = SGX_QL_ERROR_OUT_OF_MEMORY; - break; - - case TDQE_UNABLE_TO_GENERATE_QE_REPORT: - ret_val = SGX_QL_UNABLE_TO_GENERATE_QE_REPORT; - break; - - case TDQE_REPORT_FORMAT_NOT_SUPPORTED: - ret_val = SGX_QL_QE_REPORT_UNSUPPORTED_FORMAT; - break; - - default: - // Translate SDK errors - switch (sgx_status) - { - case SGX_ERROR_INVALID_PARAMETER: - ret_val = SGX_QL_ERROR_INVALID_PARAMETER; - break; - - case SGX_ERROR_ENCLAVE_FILE_ACCESS: - ret_val = SGX_QL_ENCLAVE_LOAD_ERROR; - break; - - case SGX_ERROR_OUT_OF_MEMORY: - ret_val = SGX_QL_ERROR_OUT_OF_MEMORY; - break; - - case SGX_ERROR_ENCLAVE_LOST: - ret_val = SGX_QL_ENCLAVE_LOST; - break; - - // Unexpected enclave loading errorsReturn codes from load_qe - case SGX_ERROR_INVALID_ENCLAVE: - case SGX_ERROR_UNDEFINED_SYMBOL: - case SGX_ERROR_MODE_INCOMPATIBLE: - case SGX_ERROR_INVALID_METADATA: - case SGX_ERROR_MEMORY_MAP_CONFLICT: - case SGX_ERROR_INVALID_VERSION: - case SGX_ERROR_INVALID_ATTRIBUTE: - case SGX_ERROR_NDEBUG_ENCLAVE: - case SGX_ERROR_INVALID_MISC: - //case SE_ERROR_INVALID_LAUNCH_TOKEN: ///todo: Internal error should be scrubbed before here. - case SGX_ERROR_DEVICE_BUSY: - case SGX_ERROR_NO_DEVICE: - case SGX_ERROR_INVALID_SIGNATURE: - //case SE_ERROR_INVALID_MEASUREMENT: ///todo: Internal error should be scrubbed before here. - //case SE_ERROR_INVALID_ISVSVNLE: ///todo: Internal error should be scrubbed before here. - case SGX_ERROR_INVALID_ENCLAVE_ID: - ret_val = SGX_QL_ENCLAVE_LOAD_ERROR; - break; - case SGX_ERROR_SERVICE_INVALID_PRIVILEGE: - ret_val = SGX_QL_ERROR_INVALID_PRIVILEGE; - break; - - case SGX_ERROR_UNEXPECTED: - ret_val = SGX_QL_ERROR_UNEXPECTED; - break; - - default: - ret_val = SGX_QL_ERROR_UNEXPECTED; - break; - } - break; - } - } - } - - return(ret_val); -} - diff --git a/QuoteGeneration/quote_wrapper/tdx_quote/td_ql_logic.h b/QuoteGeneration/quote_wrapper/tdx_quote/td_ql_logic.h index 84216239..b3c094fb 100644 --- a/QuoteGeneration/quote_wrapper/tdx_quote/td_ql_logic.h +++ b/QuoteGeneration/quote_wrapper/tdx_quote/td_ql_logic.h @@ -29,36 +29,148 @@ * */ /** - * File: td_ql_logic.h - * - * Description: API definitions for TD quote library + * File: td_ql_logic.h + * + * Description: internal API definitions for TD quote library * */ #ifndef _TD_QL_LOGIC_H_ #define _TD_QL_LOGIC_H_ +#include "se_thread.h" #include "sgx_ql_lib_common.h" +#include "sgx_quote.h" #include "sgx_quote_4.h" +#include "td_ql_wrapper.h" +#include "quoting_enclave_tdqe.h" -#if defined(__cplusplus) -extern "C" { +#ifndef _MSC_VER + #include + #include + #define TCHAR char + #define _T(x) (x) +#else +#include +#include #endif -quote3_error_t td_set_enclave_load_policy(sgx_ql_request_policy_t policy); -quote3_error_t td_init_quote(sgx_ql_cert_key_type_t certification_key_type, - bool refresh_att_key); -quote3_error_t td_get_quote_size(sgx_ql_cert_key_type_t certification_key_type, - uint32_t *p_quote_size); -quote3_error_t td_get_quote(const sgx_report2_t *p_app_report, - sgx_quote4_t *p_quote, - uint32_t quote_size); +#define MAX_PATH 260 + + /** + * Used to keep track of the TDQE's load status. Allows for + * thread safe updating of the load policy and the storage of + * target information of the QE when the policy is + * persistent mode. Also contains the global ecdsa_blob and + * provides thread safe access to he blob. + */ +struct tee_att_config_t { +private: + se_mutex_t m_enclave_load_mutex; + se_mutex_t m_ecdsa_blob_mutex; + sgx_enclave_id_t m_eid; + sgx_misc_attribute_t m_attributes; + sgx_launch_token_t m_launch_token; + uint8_t m_ecdsa_blob[SGX_QL_TRUSTED_ECDSA_BLOB_SIZE_SDK]; + uint8_t* m_pencryptedppid; + sgx_pce_info_t m_pce_info; + sgx_key_128bit_t* m_qe_id; + sgx_isv_svn_t m_raw_pce_isvsvn; +#ifndef _MSC_VER + void * +#else + HMODULE +#endif + m_qpl_handle; +public: + TCHAR tdqe_path[MAX_PATH]; + TCHAR qpl_path[MAX_PATH]; + TCHAR ide_path[MAX_PATH]; -quote3_error_t td_set_qe_path(const char *p_path); -quote3_error_t td_set_qpl_path(const char *p_path); -void *get_qpl_handle(); -#if defined(__cplusplus) -} + tee_att_config_t() : + m_eid(0), + m_pencryptedppid(NULL), + m_qe_id(NULL), + m_raw_pce_isvsvn(0xFFFF), + m_qpl_handle(NULL) + { + se_mutex_init(&m_enclave_load_mutex); + se_mutex_init(&m_ecdsa_blob_mutex); + memset(&m_attributes, 0, sizeof(m_attributes)); + memset(&m_launch_token, 0, sizeof(m_launch_token)); + memset(m_ecdsa_blob, 0, sizeof(m_ecdsa_blob)); + memset(&m_pce_info, 0, sizeof(m_pce_info)); + memset(tdqe_path, 0, sizeof(tdqe_path)); + memset(qpl_path, 0, sizeof(qpl_path)); + memset(ide_path, 0, sizeof(ide_path)); + } + tee_att_config_t(const tee_att_config_t&); + void unload_qe(); + tee_att_config_t& operator=(const tee_att_config_t&); + ~tee_att_config_t() { + unload_qe(); + se_mutex_destroy(&m_enclave_load_mutex); + se_mutex_destroy(&m_ecdsa_blob_mutex); + if (m_pencryptedppid) + { + free(m_pencryptedppid); + m_pencryptedppid = NULL; + } + if (m_qe_id) + { + free(m_qe_id); + m_qe_id = NULL; + } + if (m_qpl_handle) + { +#ifndef _MSC_VER + dlclose(m_qpl_handle); +#else + FreeLibrary(m_qpl_handle); #endif + m_qpl_handle = NULL; + } + } + tee_att_error_t ecdsa_init_quote(sgx_ql_cert_key_type_t certification_key_type, + sgx_target_info_t* p_qe_target_info, + bool refresh_att_key, + ref_sha256_hash_t* p_pub_key_id); + tee_att_error_t ecdsa_get_quote_size(sgx_ql_cert_key_type_t certification_key_type, + uint32_t* p_quote_size); + tee_att_error_t ecdsa_get_quote(const sgx_report2_t* p_app_report, + sgx_quote4_t* p_quote, + uint32_t quote_size); +private: +#ifndef _MSC_VER + void* +#else + HMODULE #endif + get_qpl_handle(); + bool get_qe_path(tee_att_ae_type_t type, + TCHAR* p_file_path, + size_t buf_size); + tee_att_error_t load_qe(bool *is_fresh_loaded = nullptr); + tee_att_error_t load_id_enclave(sgx_enclave_id_t* p_id_enclave_eid); + tee_att_error_t load_id_enclave_get_id(sgx_key_128bit_t* p_id); + tee_att_error_t getencryptedppid(sgx_target_info_t& pce_target_info, uint8_t* p_buf, uint32_t buf_size); + + tee_att_error_t write_persistent_data(const uint8_t* p_buf, + uint32_t buf_size, + const char* p_label); + tee_att_error_t read_persistent_data(uint8_t* p_buf, + uint32_t* p_buf_size, + const char* p_label); + tee_att_error_t certify_key(uint8_t* p_ecdsa_blob, + ref_plaintext_ecdsa_data_sdk_t* p_plaintext_data, + uint8_t* p_encrypted_ppid, + uint32_t encrypted_ppid_size, + sgx_ql_cert_key_type_t certification_key_type); + tee_att_error_t get_platform_quote_cert_data(sgx_ql_pck_cert_id_t* p_pck_cert_id, + sgx_cpu_svn_t* p_cert_cpu_svn, + sgx_isv_svn_t* p_cert_pce_isv_svn, + uint32_t* p_cert_data_size, + uint8_t* p_cert_data); +}; +#endif \ No newline at end of file diff --git a/QuoteGeneration/quote_wrapper/tdx_quote/td_ql_wrapper.cpp b/QuoteGeneration/quote_wrapper/tdx_quote/td_ql_wrapper.cpp new file mode 100644 index 00000000..15899254 --- /dev/null +++ b/QuoteGeneration/quote_wrapper/tdx_quote/td_ql_wrapper.cpp @@ -0,0 +1,564 @@ +/* + * 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. + * + */ +/** + * File: td_ql_wrapper.cpp + */ +#include +#include + +#include "sgx_urts.h" +#include "util.h" +#include "td_ql_wrapper.h" +#include "td_ql_logic.h" +#include "quoting_enclave_tdqe.h" + +#ifndef _MSC_VER + extern errno_t memcpy_s(void *dest, size_t numberOfElements, const void *src, size_t count); +#endif +#define MAX_PATH 260 + +uint8_t g_tdqe_mrsigner[32] = { 0x8c, 0x4f, 0x57, 0x75, 0xd7, 0x96, 0x50, 0x3e, 0x96, 0x13, 0x7f, 0x77, 0xc6, 0x8a, 0x82, 0x9a, + 0x00, 0x56, 0xac, 0x8d, 0xed, 0x70, 0x14, 0x0b, 0x08, 0x1b, 0x09, 0x44, 0x90, 0xc5, 0x7b, 0xff }; +uint8_t g_tdqe_ext_prod_id[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +uint8_t g_tdqe_config_id[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // QE's Config ID + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +uint8_t g_tdqe_family_id[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // QE's family_id + +/* Set the default Attestation Key Identity for the TDX Quoting Library. This is the ECDSA TDQE's identity and + ECDSA-256 */ +extern const sgx_ql_att_key_id_t g_default_ecdsa_p256_att_key_id = +{ + 0, // ID + 0, // Version + 32, // Number of bytes in MRSIGNER + { 0x8c, 0x4f, 0x57, 0x75, 0xd7, 0x96, 0x50, 0x3e, 0x96, 0x13, 0x7f, 0x77, 0xc6, 0x8a, 0x82, 0x9a, + 0x00, 0x56, 0xac, 0x8d, 0xed, 0x70, 0x14, 0x0b, 0x08, 0x1b, 0x09, 0x44, 0x90, 0xc5, 0x7b, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // Production TDQE's MRSIGNER + 2, // TDQE's Legacy Prod ID + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // QE's extended_prod_id + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // QE's Config ID + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // QE's family_id + SGX_QL_ALG_ECDSA_P256 // Supported QE3's algorithm_id +}; + + +tee_att_error_t tee_att_create_context(const tee_att_att_key_id_t* p_att_key_id, + const char* p_qe_path, + tee_att_config_t** pp_context) +{ + // Verify inputs + if (NULL == pp_context) + { + return(TEE_ATT_ERROR_INVALID_PARAMETER); + } + + if (NULL != p_att_key_id) + { + // Verify the Attestation key identity is supported. + if (0 != p_att_key_id->base.id) + { + return(TEE_ATT_UNSUPPORTED_ATT_KEY_ID); + } + if (0 != p_att_key_id->base.version) + { + return(TEE_ATT_UNSUPPORTED_ATT_KEY_ID); + } + if (32 != p_att_key_id->base.mrsigner_length) + { + return(TEE_ATT_UNSUPPORTED_ATT_KEY_ID); + } + if (0 != memcmp(p_att_key_id->base.mrsigner, g_tdqe_mrsigner, 32)) + { + return(TEE_ATT_UNSUPPORTED_ATT_KEY_ID); + } + else + { + if (2 != p_att_key_id->base.prod_id) + { + return(TEE_ATT_UNSUPPORTED_ATT_KEY_ID); + } + if (SGX_QL_ALG_ECDSA_P256 != p_att_key_id->base.algorithm_id) + { + return(TEE_ATT_UNSUPPORTED_ATT_KEY_ID); + } + } + } + tee_att_config_t* p_context = new tee_att_config_t(); + + if (NULL != p_qe_path) + { + size_t len = strnlen(p_qe_path, MAX_PATH); + // Make sure there is enough space for the '\0', + // after this line len <= sizeof(this->qe3_path) - 1 + if (len > MAX_PATH - 1) + { + delete p_context; + return TEE_ATT_ERROR_INVALID_PARAMETER; + + } +#ifndef _MSC_VER + strncpy(p_context->tdqe_path, p_qe_path, MAX_PATH - 1); +#else + MultiByteToWideChar(CP_ACP, 0, p_qe_path, (int)len, p_context->tdqe_path, MAX_PATH); +#endif + p_context->tdqe_path[len] = '\0'; + } + *pp_context = p_context; + return TEE_ATT_SUCCESS; + +} + +tee_att_error_t tee_att_free_context(tee_att_config_t* p_context) +{ + if (NULL == p_context) + { + return(TEE_ATT_ERROR_INVALID_PARAMETER); + } + delete p_context; + + return(TEE_ATT_SUCCESS); +} + +tee_att_error_t tee_att_init_quote(const tee_att_config_t* p_context, + sgx_target_info_t* p_qe_target_info, + bool refresh_att_key, + size_t* p_pub_key_id_size, + uint8_t* p_pub_key_id) +{ + + sgx_status_t sgx_status = SGX_SUCCESS; + tdqe_error_t tdqe_error = TDQE_SUCCESS; + tee_att_error_t ret_val = TEE_ATT_SUCCESS; + + if (NULL == p_context) + { + return(TEE_ATT_ERROR_INVALID_PARAMETER); + } + + if (NULL == p_pub_key_id_size) { + SE_TRACE(SE_TRACE_ERROR, "Invalid pub key id size pointer.\n"); + return(TEE_ATT_ERROR_INVALID_PARAMETER); + } + if (NULL == p_pub_key_id) { + // Caller is requesting the required size of buffer to hold the key id. + *p_pub_key_id_size = sizeof(ref_sha256_hash_t); + return(TEE_ATT_SUCCESS); + } + if (*p_pub_key_id_size != sizeof(ref_sha256_hash_t)) { + SE_TRACE(SE_TRACE_ERROR, "Invalid pub key id size. %d\n", (int)*p_pub_key_id_size); + return(TEE_ATT_ERROR_INVALID_PARAMETER); + } + // Choose the default certification key type supported by the reference. + sgx_ql_cert_key_type_t certification_key_type = PPID_RSA3072_ENCRYPTED; + + ret_val = const_cast(p_context)->ecdsa_init_quote(certification_key_type, p_qe_target_info, refresh_att_key, (ref_sha256_hash_t *)p_pub_key_id); + if (TEE_ATT_SUCCESS != ret_val) { + if ((ret_val < TEE_ATT_ERROR_MIN) || + (ret_val > TEE_ATT_ERROR_MAX)) + { + sgx_status = (sgx_status_t)ret_val; + tdqe_error = (tdqe_error_t)ret_val; + + // Translate TDQE errors + switch (tdqe_error) + { + case TDQE_ERROR_INVALID_PARAMETER: + ret_val = TEE_ATT_ERROR_INVALID_PARAMETER; + break; + + case TDQE_ERROR_OUT_OF_MEMORY: + ret_val = TEE_ATT_ERROR_OUT_OF_MEMORY; + break; + + case TDQE_ERROR_UNEXPECTED: + case TDQE_ERROR_CRYPTO: // Error generating the QE_ID (or decypting PPID not supported in release). Unexpected error. + case TDQE_ERROR_ATT_KEY_GEN: // Error generating the ECDSA Attestation key. + case TDQE_ECDSABLOB_ERROR: // Should be unexpected since the blob was either generated or regenerated during this call + ret_val = TEE_ATT_ERROR_UNEXPECTED; + break; + + default: + // Translate SDK errors + switch (sgx_status) + { + case SGX_ERROR_INVALID_PARAMETER: + ret_val = TEE_ATT_ERROR_INVALID_PARAMETER; + break; + + case SGX_ERROR_OUT_OF_MEMORY: + ret_val = TEE_ATT_ERROR_OUT_OF_MEMORY; + break; + + case SGX_ERROR_ENCLAVE_FILE_ACCESS: + ret_val = TEE_ATT_ENCLAVE_LOAD_ERROR; + break; + + case SGX_ERROR_ENCLAVE_LOST: + ret_val = TEE_ATT_ENCLAVE_LOST; + break; + + // Unexpected enclave loading errorsReturn codes from load_qe + case SGX_ERROR_INVALID_ENCLAVE: + case SGX_ERROR_UNDEFINED_SYMBOL: + case SGX_ERROR_MODE_INCOMPATIBLE: + case SGX_ERROR_INVALID_METADATA: + case SGX_ERROR_MEMORY_MAP_CONFLICT: + case SGX_ERROR_INVALID_VERSION: + case SGX_ERROR_INVALID_ATTRIBUTE: + case SGX_ERROR_NDEBUG_ENCLAVE: + case SGX_ERROR_INVALID_MISC: + //case SE_ERROR_INVALID_LAUNCH_TOKEN: ///todo: Internal error should be scrubbed before here. + case SGX_ERROR_DEVICE_BUSY: + case SGX_ERROR_NO_DEVICE: + case SGX_ERROR_INVALID_SIGNATURE: + //case SE_ERROR_INVALID_MEASUREMENT: ///todo: Internal error should be scrubbed before here. + //case SE_ERROR_INVALID_ISVSVNLE: ///todo: Internal error should be scrubbed before here. + case SGX_ERROR_INVALID_ENCLAVE_ID: + ret_val = TEE_ATT_ENCLAVE_LOAD_ERROR; + break; + case SGX_ERROR_SERVICE_INVALID_PRIVILEGE: + ret_val = TEE_ATT_ERROR_INVALID_PRIVILEGE; + break; + + case SGX_ERROR_UNEXPECTED: + ret_val = TEE_ATT_ERROR_UNEXPECTED; + break; + + default: + ret_val = TEE_ATT_ERROR_UNEXPECTED; + break; + } + break; + } + } + } + + return(ret_val); +} + +tee_att_error_t tee_att_get_quote_size(const tee_att_config_t* p_context, + uint32_t* p_quote_size) +{ + sgx_status_t sgx_status = SGX_SUCCESS; + tee_att_error_t ret_val = TEE_ATT_SUCCESS; + sgx_ql_cert_key_type_t certification_key_type = PPID_RSA3072_ENCRYPTED; + + if (NULL == p_context) + { + return(TEE_ATT_ERROR_INVALID_PARAMETER); + } + if (NULL == p_quote_size) { + SE_TRACE(SE_TRACE_ERROR, "Invalid quote size pointer.\n"); + return(TEE_ATT_ERROR_INVALID_PARAMETER); + } + + ret_val = const_cast(p_context)->ecdsa_get_quote_size(certification_key_type, p_quote_size); + if (TEE_ATT_SUCCESS != ret_val) { + if ((ret_val < TEE_ATT_ERROR_MIN) || + (ret_val > TEE_ATT_ERROR_MAX)) + { + sgx_status = (sgx_status_t)ret_val; + + // Translate SDK errors + switch (sgx_status) + { + case SGX_ERROR_OUT_OF_MEMORY: + ret_val = TEE_ATT_ERROR_OUT_OF_MEMORY; + break; + + case SGX_ERROR_ENCLAVE_FILE_ACCESS: + ret_val = TEE_ATT_ENCLAVE_LOAD_ERROR; + break; + + // Unexpected enclave loading errorsReturn codes from load_qe + case SGX_ERROR_INVALID_ENCLAVE: + case SGX_ERROR_UNDEFINED_SYMBOL: + case SGX_ERROR_MODE_INCOMPATIBLE: + case SGX_ERROR_INVALID_METADATA: + case SGX_ERROR_MEMORY_MAP_CONFLICT: + case SGX_ERROR_INVALID_VERSION: + case SGX_ERROR_INVALID_ATTRIBUTE: + case SGX_ERROR_NDEBUG_ENCLAVE: + case SGX_ERROR_INVALID_MISC: + //case SE_ERROR_INVALID_LAUNCH_TOKEN: ///todo: Internal error should be scrubbed before here. + case SGX_ERROR_DEVICE_BUSY: + case SGX_ERROR_NO_DEVICE: + case SGX_ERROR_INVALID_SIGNATURE: + //case SE_ERROR_INVALID_MEASUREMENT: ///todo: Internal error should be scrubbed before here. + //case SE_ERROR_INVALID_ISVSVNLE: ///todo: Internal error should be scrubbed before here. + case SGX_ERROR_INVALID_ENCLAVE_ID: + ret_val = TEE_ATT_ENCLAVE_LOAD_ERROR; + break; + case SGX_ERROR_SERVICE_INVALID_PRIVILEGE: + ret_val = TEE_ATT_ERROR_INVALID_PRIVILEGE; + break; + + case SGX_ERROR_ENCLAVE_LOST: + ret_val = TEE_ATT_ENCLAVE_LOST; + break; + + case SGX_ERROR_UNEXPECTED: + ret_val = TEE_ATT_ERROR_UNEXPECTED; + break; + + default: + ret_val = TEE_ATT_ERROR_UNEXPECTED; + break; + } + } + } + + return(ret_val); +} + +tee_att_error_t tee_att_get_quote(const tee_att_config_t* p_context, + const uint8_t* p_report, + uint32_t report_size, + sgx_qe_report_info_t* p_qe_report_info, + uint8_t* p_quote, + uint32_t quote_size) +{ + + sgx_status_t sgx_status = SGX_SUCCESS; + tdqe_error_t tdqe_error = TDQE_SUCCESS; + tee_att_error_t ret_val = TEE_ATT_SUCCESS; + + UNUSED(p_qe_report_info); + + if (NULL == p_context) + { + return(TEE_ATT_ERROR_INVALID_PARAMETER); + } + if (NULL == p_report) { + return(TEE_ATT_ERROR_INVALID_PARAMETER); + } + if (report_size != sizeof(sgx_report2_t)) { + SE_TRACE(SE_TRACE_ERROR, "Invalid report size. %ud\n", report_size); + return(TEE_ATT_ERROR_INVALID_PARAMETER); + } + + ret_val = const_cast(p_context)->ecdsa_get_quote( + (sgx_report2_t*)p_report, (sgx_quote4_t*)p_quote, quote_size); + if (TEE_ATT_SUCCESS != ret_val) { + if ((ret_val < TEE_ATT_ERROR_MIN) || + (ret_val > TEE_ATT_ERROR_MAX)) + { + sgx_status = (sgx_status_t)ret_val; + tdqe_error = (tdqe_error_t)ret_val; + + // Translate TDQE errors + switch (tdqe_error) + { + case TDQE_ERROR_INVALID_PARAMETER: + ret_val = TEE_ATT_ERROR_INVALID_PARAMETER; + break; + + case TDQE_ERROR_INVALID_REPORT: + ret_val = TEE_ATT_INVALID_REPORT; + break; + + case TDQE_ERROR_CRYPTO: + // Error generating QE_ID. Shouldn't happen + ret_val = TEE_ATT_ERROR_UNEXPECTED; + break; + + case TDQE_ERROR_OUT_OF_MEMORY: + ret_val = TEE_ATT_ERROR_OUT_OF_MEMORY; + break; + + case TDQE_UNABLE_TO_GENERATE_QE_REPORT: + ret_val = TEE_ATT_UNABLE_TO_GENERATE_QE_REPORT; + break; + + case TDQE_REPORT_FORMAT_NOT_SUPPORTED: + ret_val = TEE_ATT_QE_REPORT_UNSUPPORTED_FORMAT; + break; + + default: + // Translate SDK errors + switch (sgx_status) + { + case SGX_ERROR_INVALID_PARAMETER: + ret_val = TEE_ATT_ERROR_INVALID_PARAMETER; + break; + + case SGX_ERROR_ENCLAVE_FILE_ACCESS: + ret_val = TEE_ATT_ENCLAVE_LOAD_ERROR; + break; + + case SGX_ERROR_OUT_OF_MEMORY: + ret_val = TEE_ATT_ERROR_OUT_OF_MEMORY; + break; + + case SGX_ERROR_ENCLAVE_LOST: + ret_val = TEE_ATT_ENCLAVE_LOST; + break; + + // Unexpected enclave loading errorsReturn codes from load_qe + case SGX_ERROR_INVALID_ENCLAVE: + case SGX_ERROR_UNDEFINED_SYMBOL: + case SGX_ERROR_MODE_INCOMPATIBLE: + case SGX_ERROR_INVALID_METADATA: + case SGX_ERROR_MEMORY_MAP_CONFLICT: + case SGX_ERROR_INVALID_VERSION: + case SGX_ERROR_INVALID_ATTRIBUTE: + case SGX_ERROR_NDEBUG_ENCLAVE: + case SGX_ERROR_INVALID_MISC: + //case SE_ERROR_INVALID_LAUNCH_TOKEN: ///todo: Internal error should be scrubbed before here. + case SGX_ERROR_DEVICE_BUSY: + case SGX_ERROR_NO_DEVICE: + case SGX_ERROR_INVALID_SIGNATURE: + //case SE_ERROR_INVALID_MEASUREMENT: ///todo: Internal error should be scrubbed before here. + //case SE_ERROR_INVALID_ISVSVNLE: ///todo: Internal error should be scrubbed before here. + case SGX_ERROR_INVALID_ENCLAVE_ID: + ret_val = TEE_ATT_ENCLAVE_LOAD_ERROR; + break; + case SGX_ERROR_SERVICE_INVALID_PRIVILEGE: + ret_val = TEE_ATT_ERROR_INVALID_PRIVILEGE; + break; + + case SGX_ERROR_UNEXPECTED: + ret_val = TEE_ATT_ERROR_UNEXPECTED; + break; + + default: + ret_val = TEE_ATT_ERROR_UNEXPECTED; + break; + } + break; + } + } + } + + return(ret_val); +} + +tee_att_error_t tee_att_get_keyid(const tee_att_config_t* p_context, + tee_att_att_key_id_t* p_att_key_id) +{ + if (NULL == p_context || NULL == p_att_key_id) + return TEE_ATT_ERROR_INVALID_PARAMETER; + + memset(p_att_key_id, 0, sizeof(tee_att_att_key_id_t)); + memcpy_s(&p_att_key_id->base, sizeof(p_att_key_id->base), + &g_default_ecdsa_p256_att_key_id, sizeof(g_default_ecdsa_p256_att_key_id)); + return TEE_ATT_SUCCESS; +} + + +#ifndef _MSC_VER +static tee_att_error_t sgx_set_context_path(const tee_att_config_t* p_context, + tee_att_ae_type_t type, + const char* p_path) +{ + char* context_path; + if (NULL == p_context) + return TEE_ATT_ERROR_INVALID_PARAMETER; + + switch (type) + { + case TEE_ATT_TDQE: + context_path = const_cast (p_context->tdqe_path); + break; + case TEE_ATT_QPL: + context_path = const_cast (p_context->qpl_path); + break; + case TEE_ATT_IDE: + context_path = const_cast (p_context->ide_path); + break; + default: + return TEE_ATT_ERROR_INVALID_PARAMETER; + } + // p_path isn't NULL, caller has checked it. + // len <= sizeof(g_pce_status.pce_path) + size_t len = strnlen(p_path, MAX_PATH); + // Make sure there is enough space for the '\0', + // after this line len <= sizeof(this->qe3_path) - 1 + if (len > MAX_PATH - 1) + return TEE_ATT_ERROR_INVALID_PARAMETER; +#ifndef _MSC_VER + strncpy(context_path, p_path, MAX_PATH - 1); +#else + strncpy_s(context_path, MAX_PATH, p_path, MAX_PATH); +#endif + context_path[len] = '\0'; + return TEE_ATT_SUCCESS; +} + +#include +#include +tee_att_error_t tee_att_set_path(const tee_att_config_t* p_context, + tee_att_ae_type_t type, + const char* p_path) +{ + tee_att_error_t ret = TEE_ATT_SUCCESS; + sgx_pce_error_t pce_ret = SGX_PCE_SUCCESS; + struct stat info; + + if (!p_path) + return(TEE_ATT_ERROR_INVALID_PARAMETER); + + if (stat(p_path, &info) != 0) + return(TEE_ATT_ERROR_INVALID_PARAMETER); + else if ((info.st_mode & S_IFREG) == 0) + return(TEE_ATT_ERROR_INVALID_PARAMETER); + + switch (type) + { + case TEE_ATT_PCE: + pce_ret = sgx_set_pce_path(p_path); + switch (pce_ret) + { + case SGX_PCE_SUCCESS: + (void)sgx_set_pce_enclave_load_policy(SGX_QL_EPHEMERAL); + ret = TEE_ATT_SUCCESS; + break; + case SGX_PCE_INVALID_PARAMETER: + ret = TEE_ATT_ERROR_INVALID_PARAMETER; + break; + default: + ret = TEE_ATT_ERROR_UNEXPECTED; + break; + } + break; + default: + ret = sgx_set_context_path(p_context, type, p_path); + break; + } + return(ret); +} +#endif diff --git a/QuoteGeneration/quote_wrapper/tdx_quote/win/tdx_logic.def b/QuoteGeneration/quote_wrapper/tdx_quote/win/tdx_logic.def index 8b49bc64..24cd63b7 100644 --- a/QuoteGeneration/quote_wrapper/tdx_quote/win/tdx_logic.def +++ b/QuoteGeneration/quote_wrapper/tdx_quote/win/tdx_logic.def @@ -1,9 +1,9 @@ LIBRARY "sgx_tdx_logic" EXPORTS - td_set_enclave_load_policy @1 - td_set_qe_path @2 - td_set_qpl_path @3 - td_init_quote @4 - td_get_quote_size @5 - td_get_quote @6 + tee_att_create_context @1 + tee_att_free_context @2 + tee_att_init_quote @3 + tee_att_get_quote_size @4 + tee_att_get_quote @5 + tee_att_get_keyid @6 diff --git a/QuoteGeneration/quote_wrapper/tdx_quote/win/tdx_logic.vcxproj b/QuoteGeneration/quote_wrapper/tdx_quote/win/tdx_logic.vcxproj index 4507350d..7aed84b9 100644 --- a/QuoteGeneration/quote_wrapper/tdx_quote/win/tdx_logic.vcxproj +++ b/QuoteGeneration/quote_wrapper/tdx_quote/win/tdx_logic.vcxproj @@ -205,6 +205,7 @@ + @@ -213,6 +214,7 @@ + @@ -224,6 +226,10 @@ + 4201 + 4201 + 4201 + 4201 diff --git a/QuoteGeneration/quote_wrapper/tdx_quote/win/tdx_logic.vcxproj.filters b/QuoteGeneration/quote_wrapper/tdx_quote/win/tdx_logic.vcxproj.filters index a92883de..f43cc192 100644 --- a/QuoteGeneration/quote_wrapper/tdx_quote/win/tdx_logic.vcxproj.filters +++ b/QuoteGeneration/quote_wrapper/tdx_quote/win/tdx_logic.vcxproj.filters @@ -33,6 +33,9 @@ Generated Files + + Header Files + @@ -47,6 +50,9 @@ Generated Files + + Source Files + @@ -61,4 +67,4 @@ Source Files - + \ No newline at end of file diff --git a/QuoteVerification/QvE/Enclave/linux/config.xml b/QuoteVerification/QvE/Enclave/linux/config.xml index db73d2cb..80189904 100644 --- a/QuoteVerification/QvE/Enclave/linux/config.xml +++ b/QuoteVerification/QvE/Enclave/linux/config.xml @@ -1,7 +1,7 @@ 1 0x2 - 6 + 7 1 1 diff --git a/QuoteVerification/QvE/Enclave/qve.cpp b/QuoteVerification/QvE/Enclave/qve.cpp index 3738c71b..407dec81 100644 --- a/QuoteVerification/QvE/Enclave/qve.cpp +++ b/QuoteVerification/QvE/Enclave/qve.cpp @@ -337,11 +337,8 @@ static std::string bin2hex(char *in, uint32_t size) return result; } -#define SGX_TCB_LEVEL_LOWER false -#define SGX_TCB_LEVEL_EQUAL_OR_HIGHER true #define TCB_LEVELS_COUNT 16 -static bool isPCKCertSGXTCBLevelHigherOrEqual(const x509::PckCertificate& pckCert, - const json::TcbLevel& tcbLevel) +static bool isPCKCertSGXTCBLevelHigherOrEqual(const x509::PckCertificate& pckCert, const json::TcbLevel& tcbLevel) { for (unsigned int index = 0; index < TCB_LEVELS_COUNT; ++index) { @@ -350,29 +347,57 @@ static bool isPCKCertSGXTCBLevelHigherOrEqual(const x509::PckCertificate& pckCer if (componentValue < otherComponentValue) { // If *ANY* SGX_TCB_LEVEL component is lower then PCKCertSGXTCBLevel is considered lower - return SGX_TCB_LEVEL_LOWER; + return false; } } - return SGX_TCB_LEVEL_EQUAL_OR_HIGHER; + return true; +} + +static bool isPCKCertTdxTcbHigherOrEqual(const quote::TDReport& tdReport, const json::TcbLevel& tcbLevel) +{ + for(uint32_t index = 0; index < TCB_LEVELS_COUNT; ++index) + { + const auto componentValue = tdReport.teeTcbSvn[index]; + const auto otherComponentValue = tcbLevel.getTdxTcbComponent(index); + if(componentValue < otherComponentValue.getSvn()) + { + // If *ANY* SVN is lower then TCB level is considered lower + return false; + } + } + // but for TCB level to be considered higher it requires *EVERY* SVN to be higher or equal + return true; } -static time_t getMatchingTcbLevelTcbDate(const std::set> &tcbs, - const x509::PckCertificate &pckCert) +const json::TcbLevel& getMatchingTcbLevel(const json::TcbInfo *tcbInfo, + const x509::PckCertificate &pckCert, + const Quote "e) { + const auto &tcbs = tcbInfo->getTcbLevels(); const auto certPceSvn = pckCert.getTcb().getPceSvn(); for (const auto& tcb : tcbs) { if (isPCKCertSGXTCBLevelHigherOrEqual(pckCert, tcb) && certPceSvn >= tcb.getPceSvn()) { - return tcb.getTcbDate(); - } - } - return 0; -} - - + if (tcbInfo->getVersion() >= 3 && + tcbInfo->getId() == parser::json::TcbInfo::TDX_ID && + quote.getHeader().teeType == constants::TEE_TYPE_TDX) + { + if (isPCKCertTdxTcbHigherOrEqual(quote.getTdReport(), tcb)) + { + return tcb; + } + } + else + { + return tcb; + } + } + } + throw SGX_QL_TCBINFO_UNSUPPORTED_FORMAT; +} /** * Given a quote with cert type 5, extract PCK Cert chain and return it. @@ -529,13 +554,13 @@ quote3_error_t get_fmspc_ca_from_quote(const uint8_t* p_quote, uint32_t quote_si auto fmspc_from_cert = topmost_pck_cert.getFmspc(); auto issuer = topmost_cert->getIssuer().getCommonName(); if (issuer.find(PROCESSOR_ISSUER) != std::string::npos) { - if (memcpy_s(p_ca_from_quote, ca_from_quote_size, PROCESSOR_ISSUER_ID, sizeof(PROCESSOR_ISSUER_ID)) != 0) { + if (memcpy_s(p_ca_from_quote, sizeof(PROCESSOR_ISSUER_ID), PROCESSOR_ISSUER_ID, sizeof(PROCESSOR_ISSUER_ID)) != 0) { ret = SGX_QL_ERROR_UNEXPECTED; break; } } else if (issuer.find(PLATFORM_ISSUER) != std::string::npos) { - if (memcpy_s(p_ca_from_quote, ca_from_quote_size, PLATFORM_ISSUER_ID, sizeof(PLATFORM_ISSUER_ID)) != 0) { + if (memcpy_s(p_ca_from_quote, sizeof(PLATFORM_ISSUER_ID), PLATFORM_ISSUER_ID, sizeof(PLATFORM_ISSUER_ID)) != 0) { ret = SGX_QL_ERROR_UNEXPECTED; break; } @@ -792,11 +817,15 @@ static quote3_error_t qve_get_collateral_dates(const CertificateChain* p_cert_ch /** * Setup supplemental data. + * @param quote[IN] - Pointer to quote buffer. * @param chain[IN] - Pointer to CertificateChain object containing PCK Cert chain (for quote with cert type 5, this should be extracted from the quote). * @param tcb_info_obj[IN] - Pointer to TcbInfo object. * @param p_quote_collateral[IN] - Pointer to _sgx_ql_qve_collateral_t struct. + * @param crls[IN] - X.509 certificate CRL chain. * @param earliest_issue_date[IN] - value of the earliest issue date of all collaterals used in quote verification. - * @param p_supplemental_data[OUT] - Pointer to a supplemental data buffer. Must be allocated by caller (untrusted code). + * @param latest_issue_date[IN] - value of the latest issue date of all collaterals used in quote verification. + * @param earliest_expiration_date[IN] - value of the earliest expiration date of all collaterals used in quote verification. + * @param p_supplemental_data[IN/OUT] - Pointer to a supplemental data buffer. Must be allocated by caller (untrusted code). * @return Status code of the operation, one of: * - SGX_QL_SUCCESS @@ -807,10 +836,15 @@ static quote3_error_t qve_get_collateral_dates(const CertificateChain* p_cert_ch * - SGX_QL_QUOTE_CERTIFICATION_DATA_UNSUPPORTED * - SGX_QL_ERROR_UNEXPECTED **/ -static quote3_error_t qve_set_quote_supplemental_data(const CertificateChain *chain, const json::TcbInfo *tcb_info_obj, - uint16_t qe_report_isvsvn, const struct _sgx_ql_qve_collateral_t *p_quote_collateral, const char *crls[], - time_t earliest_issue_date, time_t latest_issue_date, time_t earliest_expiration_date, - uint8_t *p_supplemental_data) { +static quote3_error_t qve_set_quote_supplemental_data(const Quote "e, + const CertificateChain *chain, + const json::TcbInfo *tcb_info_obj, + const struct _sgx_ql_qve_collateral_t *p_quote_collateral, + const char *crls[], + time_t earliest_issue_date, + time_t latest_issue_date, + time_t earliest_expiration_date, + uint8_t *p_supplemental_data) { if (chain == NULL || tcb_info_obj == NULL || p_quote_collateral == NULL || @@ -823,10 +857,21 @@ static quote3_error_t qve_set_quote_supplemental_data(const CertificateChain *ch quote3_error_t ret = SGX_QL_ERROR_INVALID_PARAMETER; int version = 0; + uint32_t supp_ver = 0; sgx_ql_qv_supplemental_t* supplemental_data = reinterpret_cast (p_supplemental_data); + // the input supplemental data version should never be 0 + if (supplemental_data->version == 0) { + return SGX_QL_ERROR_INVALID_PARAMETER; + } + else { + // clear the memory + supp_ver = supplemental_data->version; + memset_s(supplemental_data, sizeof(sgx_ql_qv_supplemental_t), 0, sizeof(sgx_ql_qv_supplemental_t)); + } + //Set default values - memset_s(supplemental_data, sizeof(*supplemental_data), 0, sizeof(*supplemental_data)); + supplemental_data->version = supp_ver; supplemental_data->dynamic_platform = PCK_FLAG_UNDEFINED; supplemental_data->cached_keys = PCK_FLAG_UNDEFINED; supplemental_data->smt_enabled = PCK_FLAG_UNDEFINED; @@ -897,7 +942,8 @@ static quote3_error_t qve_set_quote_supplemental_data(const CertificateChain *ch } auto pck_cert_tcb = chain_pck_cert->getTcb(); - supplemental_data->version = SUPPLEMENTAL_DATA_VERSION; + //version should be set in wrapper functions + // supplemental_data->earliest_issue_date = earliest_issue_date; supplemental_data->latest_issue_date = latest_issue_date; supplemental_data->earliest_expiration_date = earliest_expiration_date; @@ -905,40 +951,84 @@ static quote3_error_t qve_set_quote_supplemental_data(const CertificateChain *ch //get matching QE identity TCB level // - auto qe_identity_tcb_levels = qe_identity_v2->getTcbLevels(); + try { + //get matching QE identity TCB level + // + auto qe_identity_tcb_levels = qe_identity_v2->getTcbLevels(); - //make sure QE identity has at least one TCBLevel - // - if (qe_identity_tcb_levels.empty()) { - ret = SGX_QL_QEIDENTITY_UNSUPPORTED_FORMAT; - break; - } - for (const auto & tcbLevel : qe_identity_tcb_levels) { - if (tcbLevel.getIsvsvn() <= qe_report_isvsvn) { - tm matching_qe_identity_tcb_date = tcbLevel.getTcbDate(); - qe_identity_date = intel::sgx::dcap::mktime(&matching_qe_identity_tcb_date); + //make sure QE identity has at least one TCBLevel + // + if (qe_identity_tcb_levels.empty()) { + ret = SGX_QL_QEIDENTITY_UNSUPPORTED_FORMAT; break; } - } + for (const auto & tcbLevel : qe_identity_tcb_levels) { + if (tcbLevel.getIsvsvn() <= quote.getQeReport().isvSvn) { + tm matching_qe_identity_tcb_date = tcbLevel.getTcbDate(); + qe_identity_date = intel::sgx::dcap::mktime(&matching_qe_identity_tcb_date); + break; + } + } + //get TCB date of TCB level in TCB Info + // + auto tcb = getMatchingTcbLevel(tcb_info_obj, *chain_pck_cert, quote); + auto matching_tcb_info_tcb_date = tcb.getTcbDate(); - //get TCB date of TCB level in TCB Info - // - auto matching_tcb_info_tcb_date = getMatchingTcbLevelTcbDate(tcb_info_obj->getTcbLevels(), *chain_pck_cert); + auto sa_list = tcb.getAdvisoryIDs(); - //make sure none of TCBLevel dates is 0 - // - if (qe_identity_date < 0 || matching_tcb_info_tcb_date < 0) { + //set SA list when version >= 3.1 + // + if (supplemental_data->major_version >= SUPPLEMENTAL_DATA_VERSION && + supplemental_data->minor_version >= SUPPLEMENTAL_V3_LATEST_MINOR_VERSION) { + + if (!sa_list.empty()) { + uint32_t sa_size = 0; + const char comma = ','; + const char terminator = '\0'; + char *p_sa = supplemental_data->sa_list; + + for (std::string sa : sa_list) { + sa_size += (uint32_t)sa.length() + 1; + + // sanity check + if (sa_size > MAX_SA_LIST_SIZE) { + ret = SGX_QL_ERROR_UNEXPECTED; + break; + } + memcpy_s(p_sa, sa.length(), sa.c_str(), sa.length()); + // add comma for each sa + if (memcpy_s(p_sa + sa.length(), 1, &comma, 1) != 0) { + ret = SGX_QL_ERROR_UNEXPECTED; + break; + } + p_sa += sa.length() + 1; + } + + // add null terminator in the end + memset_s(p_sa - 1, 1, terminator, 1); + } + } + + //sanity check for TCB dates + // + if (qe_identity_date < 0 || matching_tcb_info_tcb_date < 0) { + ret = SGX_QL_ERROR_UNEXPECTED; + break; + } + //compare TCB info TCB level date and QE identity TCB level date, return the smaller one + // + if (qe_identity_date <= matching_tcb_info_tcb_date) { + supplemental_data->tcb_level_date_tag = qe_identity_date; + } + else { + supplemental_data->tcb_level_date_tag = matching_tcb_info_tcb_date; + } + } + + catch(...) { ret = SGX_QL_ERROR_UNEXPECTED; break; } - //compare TCB info TCB level date and QE identity TCB level date, return the smaller one - // - if (qe_identity_date <= matching_tcb_info_tcb_date) { - supplemental_data->tcb_level_date_tag = qe_identity_date; - } - else { - supplemental_data->tcb_level_date_tag = matching_tcb_info_tcb_date; - } //make sure that long int value returned in getCrlNum doesn't overflow // @@ -1120,7 +1210,11 @@ quote3_error_t sgx_qve_get_quote_supplemental_data_version( (sgx_is_within_enclave(p_version, sizeof(*p_version)) == 0)) { return SGX_QL_ERROR_INVALID_PARAMETER; } - *p_version = SUPPLEMENTAL_DATA_VERSION; + supp_ver_t tmp; + tmp.major_version = SUPPLEMENTAL_DATA_VERSION; + tmp.minor_version = SUPPLEMENTAL_V3_LATEST_MINOR_VERSION; + + *p_version = tmp.version; return SGX_QL_SUCCESS; } @@ -1266,7 +1360,7 @@ static bool is_collateral_deep_copied(const struct _sgx_ql_qve_collateral_t *p_q * @param p_quote_verification_result[OUT] - Address of the outputted quote verification result. * @param p_qve_report_info[IN/OUT] - This parameter is optional. If not NULL, the QvE will generate a report with using the target_info provided in the sgx_ql_qe_report_info_t structure. * @param supplemental_data_size[IN] - Size of the buffer pointed to by p_supplemental_data (in bytes). - * @param p_supplemental_data[OUT] - The parameter is optional. If it is NULL, supplemental_data_size must be 0. + * @param p_supplemental_data[IN/OUT] - The parameter is optional. If it is NULL, supplemental_data_size must be 0. * * @return Status code of the operation, one of: * - SGX_QL_SUCCESS @@ -1314,7 +1408,6 @@ quote3_error_t sgx_qve_verify_quote( if (p_supplemental_data) { if (supplemental_data_size == sizeof(sgx_ql_qv_supplemental_t) && sgx_is_within_enclave(p_supplemental_data, supplemental_data_size)) { - memset_s(p_supplemental_data, supplemental_data_size, 0, supplemental_data_size); } else { outputs_set = 0; @@ -1568,8 +1661,16 @@ quote3_error_t sgx_qve_verify_quote( { ret = status_error_to_quote3_error(STATUS_UNSUPPORTED_QUOTE_FORMAT); } - auto qe_report_isvsvn = quote.getQeReport().isvSvn; - ret = qve_set_quote_supplemental_data(&chain, &tcb_info_obj, qe_report_isvsvn, p_quote_collateral, crls.data(), earliest_issue_date, latest_issue_date, earliest_expiration_date, p_supplemental_data); + + ret = qve_set_quote_supplemental_data(quote, + &chain, + &tcb_info_obj, + p_quote_collateral, + crls.data(), + earliest_issue_date, + latest_issue_date, + earliest_expiration_date, + p_supplemental_data); if (ret != SGX_QL_SUCCESS) { break; } diff --git a/QuoteVerification/QvE/Enclave/qve.edl b/QuoteVerification/QvE/Enclave/qve.edl index ee5c1d4c..4be349e5 100644 --- a/QuoteVerification/QvE/Enclave/qve.edl +++ b/QuoteVerification/QvE/Enclave/qve.edl @@ -107,7 +107,7 @@ struct _sgx_ql_qve_collateral_t [out, count=1]sgx_ql_qv_result_t *p_quote_verification_result, [in, out, count=1]sgx_ql_qe_report_info_t *p_qve_report_info, uint32_t supplemental_data_size, - [out, size=supplemental_data_size] uint8_t *p_supplemental_data); + [in, out, size=supplemental_data_size] uint8_t *p_supplemental_data); }; diff --git a/QuoteVerification/QvE/Enclave/win/config.xml b/QuoteVerification/QvE/Enclave/win/config.xml index 2c67a958..f89d26bd 100644 --- a/QuoteVerification/QvE/Enclave/win/config.xml +++ b/QuoteVerification/QvE/Enclave/win/config.xml @@ -1,7 +1,7 @@ 1 0x2 - 6 + 7 1 1 diff --git a/QuoteVerification/QvE/Include/sgx_qve_def.h b/QuoteVerification/QvE/Include/sgx_qve_def.h index fd994e2b..6995973d 100644 --- a/QuoteVerification/QvE/Include/sgx_qve_def.h +++ b/QuoteVerification/QvE/Include/sgx_qve_def.h @@ -42,6 +42,8 @@ #endif //DEBUG_MODE #define SUPPLEMENTAL_DATA_VERSION 3 +#define LEGACY_SUPPLEMENTAL_MINOR_VERSION 0 +#define SUPPLEMENTAL_V3_LATEST_MINOR_VERSION 1 #define QVE_COLLATERAL_VERSION1 0x1 #define QVE_COLLATERAL_VERSION3 0x3 #define QVE_COLLATERAL_VERSOIN31 0x00010003 @@ -82,4 +84,25 @@ #define EXPECTED_CERTIFICATE_COUNT_IN_PCK_CHAIN 3 +// Nameless struct generates C4201 warning in MS compiler, but it is allowed in c++ 11 standard +// Should remove the pragma after Microsoft fixes this issue +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4201) +#endif + +//Quote verfication supplemental data version +//Use for checking and assigning supplemental data version +typedef union _supp_ver_t{ + uint32_t version; + struct { + uint16_t major_version; + uint16_t minor_version; + }; +} supp_ver_t; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + #endif //_SGX_QVE_DEF_H_ diff --git a/QuoteVerification/QvE/Include/sgx_qve_header.h b/QuoteVerification/QvE/Include/sgx_qve_header.h index 11db8104..82cc045f 100644 --- a/QuoteVerification/QvE/Include/sgx_qve_header.h +++ b/QuoteVerification/QvE/Include/sgx_qve_header.h @@ -76,11 +76,29 @@ typedef enum _pck_cert_flag_enum_t { #define ROOT_KEY_ID_SIZE 48 #define PLATFORM_INSTANCE_ID_SIZE 16 +// Each Intel Advisory size is ~16 bytes +// Assume each TCB level has 10 advisoryIDs at the very most +#define MAX_SA_LIST_SIZE 160 + +// Nameless struct generates C4201 warning in MS compiler, but it is allowed in c++ 11 standard +// Should remove the pragma after Microsoft fixes this issue +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4201) +#endif /** Contains data that will allow an alternative quote verification policy. */ typedef struct _sgx_ql_qv_supplemental_t { - uint32_t version; ///< Supplemental data version + union { + uint32_t version; ///< 'version' is the backward compatible legacy representation + struct { + uint16_t major_version; ///< If this major version doesn't change, the size of the structure may change and new fields appended to the end but old minor version structure can still be 'cast' + ///< If this major version does change, then the structure has been modified in a way that makes the older definitions non-backwards compatible. i.e. You cannot 'cast' older definitions + uint16_t minor_version; ///< If this version changes, new fields have been appended to the end of the previous minor version definition of the structure + ///< Set to 1 to support SA_List. Set to 0 to support everything except the SA List + }; + }; time_t earliest_issue_date; ///< Earliest issue date of all the collateral (UTC) time_t latest_issue_date; ///< Latest issue date of all the collateral (UTC) time_t earliest_expiration_date; ///< Earliest expiration date of all the collateral (UTC) @@ -105,7 +123,25 @@ typedef struct _sgx_ql_qv_supplemental_t pck_cert_flag_enum_t cached_keys; ///< Indicate whether platform root keys are cached by SGX Registration Backend pck_cert_flag_enum_t smt_enabled; ///< Indicate whether a plat form has SMT (simultaneous multithreading) enabled + char sa_list[MAX_SA_LIST_SIZE]; ///< String of comma separated list of Security Advisory IDs + } sgx_ql_qv_supplemental_t; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +/** Descriptor of the supplemental data requestor structure. Used when requesting supplemental data from the DCAP quote verification API */ +typedef struct _tee_supp_data_descriptor_t +{ + uint16_t major_version; ///< Input. Major version of supplemental data + ///< If == 0, then return latest version of the sgx_ql_qv_supplemental_t structure + ///< If <= latest supported, return the latest minor version associated with that major version + ///< > latest supported, return an error (SGX_QL_SUPPLEMENTAL_DATA_VERSION_NOT_SUPPORTED) + + uint32_t data_size; ///< Input. Supplemental data size of `p_data`, which returned by API `tee_get_supplemental_data_version_and_size()` + uint8_t *p_data; ///< Output. Pointer to supplemental data +}tee_supp_data_descriptor_t; + #endif //_QVE_HEADER_H_ diff --git a/QuoteVerification/dcap_quoteverify/dcap_quoteverify_api.txt b/QuoteVerification/dcap_quoteverify/dcap_quoteverify_api.txt index 1a7b540b..4d5f8ac1 100644 --- a/QuoteVerification/dcap_quoteverify/dcap_quoteverify_api.txt +++ b/QuoteVerification/dcap_quoteverify/dcap_quoteverify_api.txt @@ -26,7 +26,7 @@ Parameters: supplemental_data_size [In] Size of the buffer pointed to by p_supplemental_data (in bytes). The value should match the value retuned by the sgx_qve_get_supplemental_data_size(). - p_supplemental_data [Out] + p_supplemental_data [In/Out] The parameter is optional. If it is NULL, supplemental_data_size must be 0. This data can be used by the CSP or Relying Party to enforce a different quote verification policy than enforced by this API. diff --git a/QuoteVerification/dcap_quoteverify/inc/sgx_dcap_quoteverify.h b/QuoteVerification/dcap_quoteverify/inc/sgx_dcap_quoteverify.h index 70bc6bc2..4531ce6c 100644 --- a/QuoteVerification/dcap_quoteverify/inc/sgx_dcap_quoteverify.h +++ b/QuoteVerification/dcap_quoteverify/inc/sgx_dcap_quoteverify.h @@ -163,7 +163,6 @@ quote3_error_t sgx_qv_set_path(sgx_qv_path_type_t path_type, #endif - /** * Get TDX supplemental data required size. * @param p_data_size[OUT] - Pointer to hold the size of the buffer in bytes required to contain all of the supplemental data. @@ -176,6 +175,7 @@ quote3_error_t sgx_qv_set_path(sgx_qv_path_type_t path_type, **/ quote3_error_t tdx_qv_get_quote_supplemental_data_size(uint32_t *p_data_size); + /** * Perform TDX ECDSA quote verification. * @@ -212,6 +212,101 @@ quote3_error_t tdx_qv_verify_quote( uint8_t *p_supplemental_data); +/** + * Get quote verification collateral. + * + * @param p_quote[IN] - Pointer to TDX/SGX Quote. + * @param quote_size[IN] - Size of the buffer pointed to by p_quote (in bytes). + * @param p_quote_collateral[OUT] - This is a pointer to the Quote Certification Collateral retrieved based on Quote + * @param p_collateral_size[OUT] - This is the sizeof collateral including the size of nested fileds + * + * @return Status code of the operation, one of: + * - SGX_QL_SUCCESS + * - SGX_QL_ERROR_INVALID_PARAMETER + * - SGX_QL_PLATFORM_LIB_UNAVAILABLE + * - SGX_QL_PCK_CERT_CHAIN_ERROR + * - SGX_QL_PCK_CERT_UNSUPPORTED_FORMAT + * - SGX_QL_QUOTE_FORMAT_UNSUPPORTED + * - SGX_QL_OUT_OF_MEMORY + * - SGX_QL_NO_QUOTE_COLLATERAL_DATA + * - SGX_QL_ERROR_UNEXPECTED + **/ +quote3_error_t tee_qv_get_collateral( + const uint8_t *p_quote, + uint32_t quote_size, + uint8_t **pp_quote_collateral, + uint32_t *p_collateral_size); + + +/** + * Free quote verification collateral buffer, which returned by `tee_qv_get_collateral` + * + * @param p_quote_collateral[IN] - Pointer to collateral + * + * @return Status code of the operation, one of: + * - SGX_QL_SUCCESS + * - SGX_QL_ERROR_INVALID_PARAMETER + * - SGX_QL_QUOTE_FORMAT_UNSUPPORTED + **/ +quote3_error_t tee_qv_free_collateral(uint8_t *p_quote_collateral); + + +/** + * Get supplemental data latest version and required size, support both SGX and TDX + * + * @param p_quote[IN] - Pointer to SGX or TDX Quote. + * @param quote_size[IN] - Size of the buffer pointed to by p_quote (in bytes). + * @param p_version[OUT] - Optional. Pointer to hold latest version of the supplemental data. + * @param p_data_size[OUT] - Optional. Pointer to hold the size of the buffer in bytes required to contain all of the supplemental data. + **/ +quote3_error_t tee_get_supplemental_data_version_and_size( + const uint8_t *p_quote, + uint32_t quote_size, + uint32_t *p_version, + uint32_t *p_data_size); + + +/** + * Perform quote verification for SGX and TDX + * This API works the same as the old one, but takes a new parameter to describe the supplemental data (p_supp_data_descriptor) + * + * @param p_quote[IN] - Pointer to SGX or TDX Quote. + * @param quote_size[IN] - Size of the buffer pointed to by p_quote (in bytes). + * @param p_quote_collateral[IN] - This is a pointer to the Quote Certification Collateral provided by the caller. + * @param expiration_check_date[IN] - This is the date that the QvE will use to determine if any of the inputted collateral have expired. + * @param p_collateral_expiration_status[OUT] - Address of the outputted expiration status. This input must not be NULL. + * @param p_quote_verification_result[OUT] - Address of the outputted quote verification result. + * @param p_qve_report_info[IN/OUT] - This parameter can be used in 2 ways. + * If p_qve_report_info is NOT NULL, the API will use Intel QvE to perform quote verification, and QvE will generate a report using the target_info in sgx_ql_qe_report_info_t structure. + * if p_qve_report_info is NULL, the API will use QVL library to perform quote verification, not that the results can not be cryptographically authenticated in this mode. + * @param p_supp_datal_descriptor[IN/OUT] - Pointer to tee_supp_data_descriptor_t structure + * You can specify the major version of supplemental data by setting p_supp_datal_descriptor->major_version + * If p_supp_datal_descriptor == NULL, no supplemental data is returned + * If p_supp_datal_descriptor->major_version == 0, then return the latest version of the sgx_ql_qv_supplemental_t structure + * If p_supp_datal_descriptor <= latest supported version, return the latest minor version associated with that major version + * If p_supp_datal_descriptor > latest supported version, return an error SGX_QL_SUPPLEMENTAL_DATA_VERSION_NOT_SUPPORTED + * + * @return Status code of the operation, one of: + * - SGX_QL_SUCCESS + * - SGX_QL_ERROR_INVALID_PARAMETER + * - SGX_QL_QUOTE_FORMAT_UNSUPPORTED + * - SGX_QL_QUOTE_CERTIFICATION_DATA_UNSUPPORTED + * - SGX_QL_UNABLE_TO_GENERATE_REPORT + * - SGX_QL_CRL_UNSUPPORTED_FORMAT + * - SGX_QL_SUPPLEMENTAL_DATA_VERSION_NOT_SUPPORTED + * - SGX_QL_ERROR_UNEXPECTED + **/ +quote3_error_t tee_verify_quote( + const uint8_t *p_quote, + uint32_t quote_size, + const uint8_t *p_quote_collateral, + const time_t expiration_check_date, + uint32_t *p_collateral_expiration_status, + sgx_ql_qv_result_t *p_quote_verification_result, + sgx_ql_qe_report_info_t *p_qve_report_info, + tee_supp_data_descriptor_t *p_supp_data_descriptor); + + #if defined(__cplusplus) } #endif diff --git a/QuoteVerification/dcap_quoteverify/inc/sgx_dcap_qv_internal.h b/QuoteVerification/dcap_quoteverify/inc/sgx_dcap_qv_internal.h index c647458d..57bc9c50 100644 --- a/QuoteVerification/dcap_quoteverify/inc/sgx_dcap_qv_internal.h +++ b/QuoteVerification/dcap_quoteverify/inc/sgx_dcap_qv_internal.h @@ -45,6 +45,9 @@ extern "C" { #endif +#define SGX_QUOTE_TYPE 0x0 +#define TDX_QUOTE_TYPE 0x81 + typedef enum { SGX_EVIDENCE = 0, TDX_EVIDENCE, diff --git a/QuoteVerification/dcap_quoteverify/linux/config.cpp b/QuoteVerification/dcap_quoteverify/linux/config.cpp index 80e6d972..c1e5c2a0 100644 --- a/QuoteVerification/dcap_quoteverify/linux/config.cpp +++ b/QuoteVerification/dcap_quoteverify/linux/config.cpp @@ -46,6 +46,7 @@ #define PATH_SEPARATOR '/' #define SGX_URTS_LIB_FILE_NAME "libsgx_urts.so.1" +#define SGX_URTS_LIB_FILE_NAME_V2 "libsgx_urts.so.2" void *g_urts_handle = NULL; se_mutex_t g_urts_mutex; @@ -278,9 +279,13 @@ bool sgx_dcap_load_urts() g_urts_handle = dlopen(SGX_URTS_LIB_FILE_NAME, RTLD_LAZY); if (g_urts_handle == NULL) { - fputs(dlerror(), stderr); - SE_TRACE(SE_TRACE_DEBUG, "Couldn't find urts library: %s\n", SGX_URTS_LIB_FILE_NAME); - break; + //try to load urts v2 + g_urts_handle = dlopen(SGX_URTS_LIB_FILE_NAME_V2, RTLD_LAZY); + if (g_urts_handle == NULL) { + fputs(dlerror(), stderr); + SE_TRACE(SE_TRACE_DEBUG, "Couldn't find urts library: %s, %s\n", SGX_URTS_LIB_FILE_NAME, SGX_URTS_LIB_FILE_NAME_V2); + break; + } } //search for sgx_create_enclave symbol in urts library diff --git a/QuoteVerification/dcap_quoteverify/linux/sgx_dcap_quoteverify.lds b/QuoteVerification/dcap_quoteverify/linux/sgx_dcap_quoteverify.lds index 29343385..9652a931 100644 --- a/QuoteVerification/dcap_quoteverify/linux/sgx_dcap_quoteverify.lds +++ b/QuoteVerification/dcap_quoteverify/linux/sgx_dcap_quoteverify.lds @@ -8,6 +8,10 @@ global: sgx_qv_set_path; tdx_qv_get_quote_supplemental_data_size; tdx_qv_verify_quote; + tee_qv_get_collateral; + tee_qv_free_collateral; + tee_get_supplemental_data_version_and_size; + tee_verify_quote; local: *; }; diff --git a/QuoteVerification/dcap_quoteverify/sgx_dcap_quoteverify.cpp b/QuoteVerification/dcap_quoteverify/sgx_dcap_quoteverify.cpp index 26aa51ae..f8662ec5 100644 --- a/QuoteVerification/dcap_quoteverify/sgx_dcap_quoteverify.cpp +++ b/QuoteVerification/dcap_quoteverify/sgx_dcap_quoteverify.cpp @@ -47,7 +47,6 @@ #include "se_memcpy.h" #include "sgx_urts_wrapper.h" - sgx_create_enclave_func_t p_sgx_urts_create_enclave = NULL; sgx_destroy_enclave_func_t p_sgx_urts_destroy_enclave = NULL; sgx_ecall_func_t p_sgx_urts_ecall = NULL; @@ -338,10 +337,11 @@ static sgx_status_t initialize_enclave(sgx_enclave_id_t* eid) } /** - * Get supplemental data required size. + * Internal function - get supplemental data size and version. **/ -quote3_error_t tee_get_verification_supplemental_data_size( +static quote3_error_t get_verification_supplemental_data_size_and_version( uint32_t *p_data_size, + uint32_t *p_version, tee_evidence_type_t tee_type) { if (NULL_POINTER(p_data_size)) { @@ -352,7 +352,10 @@ quote3_error_t tee_get_verification_supplemental_data_size( if (tee_type != SGX_EVIDENCE && tee_type != TDX_EVIDENCE) return SGX_QL_ERROR_INVALID_PARAMETER; - uint32_t trusted_version = 0, untrusted_version = 0; + supp_ver_t trusted_version; + supp_ver_t untrusted_version; + trusted_version.version = 0; + untrusted_version.version = 0; uint32_t trusted_size = 0, untrusted_size = 0; bool VerNumMismatch = false; sgx_status_t load_ret = SGX_ERROR_UNEXPECTED; @@ -392,9 +395,9 @@ quote3_error_t tee_get_verification_supplemental_data_size( //call SGX QvE ECALL to get supplemental data version // - qve_ret = p_trusted_qv->tee_get_supplemental_data_version(&trusted_version); + qve_ret = p_trusted_qv->tee_get_supplemental_data_version(&trusted_version.version); if (qve_ret != SGX_QL_SUCCESS) { - trusted_version = 0; + trusted_version.version = 0; break; } @@ -409,7 +412,7 @@ quote3_error_t tee_get_verification_supplemental_data_size( do { //call untrusted API to get supplemental data version // - qve_ret = p_untrusted_qv->tee_get_supplemental_data_version(&untrusted_version); + qve_ret = p_untrusted_qv->tee_get_supplemental_data_version(&untrusted_version.version); if (qve_ret != SGX_QL_SUCCESS) { SE_TRACE(SE_TRACE_DEBUG, "Error: untrusted API qvl_get_quote_supplemental_data_version failed: 0x%04x\n", qve_ret); *p_data_size = 0; @@ -426,17 +429,22 @@ quote3_error_t tee_get_verification_supplemental_data_size( } if (VerNumMismatch) { - if (trusted_version != untrusted_version || trusted_size != untrusted_size) { + if (trusted_version.version != untrusted_version.version || trusted_size != untrusted_size) { SE_TRACE(SE_TRACE_DEBUG, "Error: Quote supplemental data version is different between trusted QvE and untrusted QVL.\n"); - SE_TRACE(SE_TRACE_DEBUG, "Supplemental version from QvE: %d,\t size: %d\n", trusted_version, trusted_size); - SE_TRACE(SE_TRACE_DEBUG, "Supplemental version from QVL: %d,\t size: %d\n", untrusted_version, untrusted_size); + SE_TRACE(SE_TRACE_DEBUG, "Supplemental version from QvE, major version: %d, minor version: %d,\t size: %d\n", + trusted_version.major_version, trusted_version.minor_version, trusted_size); + SE_TRACE(SE_TRACE_DEBUG, "Supplemental version from QVL, major version: %d, minor version: %d,\t size: %d\n", + untrusted_version.major_version, untrusted_version.minor_version, untrusted_size); *p_data_size = 0; qve_ret = SGX_QL_ERROR_QVL_QVE_MISMATCH; break; } } - *p_data_size = untrusted_size; + if (p_data_size != NULL) + *p_data_size = untrusted_size; + if (p_version != NULL) + *p_version = untrusted_version.version; } while (0) ; @@ -453,6 +461,36 @@ quote3_error_t tee_get_verification_supplemental_data_size( return qve_ret; } + +/** + * Get supplemental data latest version and required size. + **/ +quote3_error_t tee_get_supplemental_data_version_and_size( + const uint8_t *p_quote, + uint32_t quote_size, + uint32_t *p_version, + uint32_t *p_data_size) { + + if (p_quote == NULL || quote_size == 0 || + (p_version == NULL && p_data_size == NULL)) + return SGX_QL_ERROR_INVALID_PARAMETER; + + tee_evidence_type_t tee_type = UNKNOWN_QUOTE_TYPE; + // check quote type + uint32_t *p_type = (uint32_t *) (p_quote + sizeof(uint16_t) * 2); + + if (*p_type == SGX_QUOTE_TYPE) + tee_type = SGX_EVIDENCE; + else if (*p_type == TDX_QUOTE_TYPE) + tee_type = TDX_EVIDENCE; + else + return SGX_QL_ERROR_INVALID_PARAMETER; + + return get_verification_supplemental_data_size_and_version(p_data_size, p_version, tee_type); + +} + + /** * Perform ECDSA quote verification **/ @@ -484,11 +522,13 @@ quote3_error_t tee_verify_evidence( //parse quote header to get tee type, only support SGX and TDX by now tee_evidence_type_t tee_type = UNKNOWN_QUOTE_TYPE; - const sgx_quote_header_t *p_header = reinterpret_cast (p_quote); - uint32_t quote_type = p_header->att_key_data_0; - if (quote_type == 0) + + // check quote type + uint32_t *p_type = (uint32_t *) (p_quote + sizeof(uint16_t) * 2); + + if (*p_type == SGX_QUOTE_TYPE) tee_type = SGX_EVIDENCE; - else if (quote_type == 0x81) + else if (*p_type == TDX_QUOTE_TYPE) tee_type = TDX_EVIDENCE; else //quote type is not supported @@ -499,9 +539,9 @@ quote3_error_t tee_verify_evidence( if (p_supplemental_data) { quote3_error_t tmp_ret = SGX_QL_ERROR_UNEXPECTED; uint32_t tmp_size = 0; - tmp_ret = tee_get_verification_supplemental_data_size(&tmp_size, tee_type); + tmp_ret = get_verification_supplemental_data_size_and_version(&tmp_size, NULL, tee_type); - if (tmp_ret != SGX_QL_SUCCESS || tmp_size > supplemental_data_size) { + if (tmp_ret != SGX_QL_SUCCESS || tmp_size != supplemental_data_size) { if (p_quote_verification_result) { *p_quote_verification_result = SGX_QL_QV_RESULT_UNSPECIFIED; @@ -673,7 +713,7 @@ quote3_error_t sgx_qv_free_qve_identity( **/ quote3_error_t sgx_qv_get_quote_supplemental_data_size(uint32_t *p_data_size) { - return tee_get_verification_supplemental_data_size(p_data_size, SGX_EVIDENCE); + return get_verification_supplemental_data_size_and_version(p_data_size, NULL, SGX_EVIDENCE); } /** @@ -690,7 +730,21 @@ quote3_error_t sgx_qv_verify_quote( uint32_t supplemental_data_size, uint8_t *p_supplemental_data) { - return tee_verify_evidence( + quote3_error_t ret = SGX_QL_SUCCESS; + + // set supplemental version if necessary + if (p_supplemental_data != NULL && supplemental_data_size > 0) { + try { + reinterpret_cast (p_supplemental_data)->version = SUPPLEMENTAL_DATA_VERSION; + } + + catch(...) { + // cannot access p_supplemental_data field + return SGX_QL_ERROR_INVALID_PARAMETER; + } + } + + ret = tee_verify_evidence( p_quote, quote_size, p_quote_collateral, @@ -700,6 +754,13 @@ quote3_error_t sgx_qv_verify_quote( p_qve_report_info, supplemental_data_size, p_supplemental_data); + + // clear version info + if (ret != SGX_QL_SUCCESS && p_supplemental_data != NULL) { + memset(p_supplemental_data, 0, sizeof(*p_supplemental_data)); + } + + return ret; } /** @@ -707,7 +768,7 @@ quote3_error_t sgx_qv_verify_quote( **/ quote3_error_t tdx_qv_get_quote_supplemental_data_size(uint32_t *p_data_size) { - return tee_get_verification_supplemental_data_size(p_data_size, TDX_EVIDENCE); + return get_verification_supplemental_data_size_and_version(p_data_size, NULL, TDX_EVIDENCE); } /** @@ -724,18 +785,246 @@ quote3_error_t tdx_qv_verify_quote( uint32_t supplemental_data_size, uint8_t *p_supplemental_data) { - return tee_verify_evidence( + quote3_error_t ret = SGX_QL_SUCCESS; + + // set supplemental version if necessary + if (p_supplemental_data != NULL && supplemental_data_size > 0) { + try { + reinterpret_cast (p_supplemental_data)->version = SUPPLEMENTAL_DATA_VERSION; + } + + catch(...) { + // cannot access p_supplemental_data field + return SGX_QL_ERROR_INVALID_PARAMETER; + } + } + + ret = tee_verify_evidence( + p_quote, + quote_size, + p_quote_collateral, + expiration_check_date, + p_collateral_expiration_status, + p_quote_verification_result, + p_qve_report_info, + supplemental_data_size, + p_supplemental_data); + + // clear version info + if (ret != SGX_QL_SUCCESS && p_supplemental_data != NULL) { + memset(p_supplemental_data, 0, sizeof(*p_supplemental_data)); + } + + return ret; +} + + +/** + * @brief retrieve verification colloateral + * + */ +quote3_error_t tee_qv_get_collateral( + const uint8_t *p_quote, + uint32_t quote_size, + uint8_t **pp_quote_collateral, + uint32_t *p_collateral_size) +{ + quote3_error_t ret = SGX_QL_SUCCESS; + unsigned char fmspc_from_quote[FMSPC_SIZE] = {0}; + unsigned char ca_from_quote[CA_SIZE] = {0}; + if (p_quote == NULL || quote_size < QUOTE_MIN_SIZE || pp_quote_collateral == NULL || *pp_quote_collateral != NULL || p_collateral_size == NULL) + return SGX_QL_ERROR_INVALID_PARAMETER; + // skip version and att_key_type in SGX or TDX quote + uint32_t quote_type = *((uint32_t *)(p_quote + sizeof(uint16_t) + sizeof(uint16_t))); + *p_collateral_size = 0; + + ret = qvl_get_fmspc_ca_from_quote( p_quote, quote_size, - p_quote_collateral, + fmspc_from_quote, + FMSPC_SIZE, + ca_from_quote, + CA_SIZE); + if (ret != SGX_QL_SUCCESS) + { + return ret; + } + if (quote_type == SGX_QUOTE_TYPE) + { // little endian 0x0 means SGX + ret = sgx_dcap_retrieve_verification_collateral((const char *)fmspc_from_quote, + FMSPC_SIZE, + (const char *)ca_from_quote, + (sgx_ql_qve_collateral_t **)pp_quote_collateral); + if (ret == SGX_QL_SUCCESS) + { + *p_collateral_size = + (uint32_t)sizeof(sgx_ql_qve_collateral_t) + + ((sgx_ql_qve_collateral_t *)(*pp_quote_collateral)) + ->pck_crl_issuer_chain_size + + ((sgx_ql_qve_collateral_t *)(*pp_quote_collateral)) + ->root_ca_crl_size + + ((sgx_ql_qve_collateral_t *)(*pp_quote_collateral)) + ->pck_crl_size + + ((sgx_ql_qve_collateral_t *)(*pp_quote_collateral)) + ->tcb_info_issuer_chain_size + + ((sgx_ql_qve_collateral_t *)(*pp_quote_collateral)) + ->qe_identity_issuer_chain_size + + ((sgx_ql_qve_collateral_t *)(*pp_quote_collateral)) + ->qe_identity_size + + ((sgx_ql_qve_collateral_t *)(*pp_quote_collateral)) + ->tcb_info_size; + } + } + else if (quote_type == TDX_QUOTE_TYPE) + { // little endian 0x81 means TDX + ret = tdx_dcap_retrieve_verification_collateral((const char *)fmspc_from_quote, + FMSPC_SIZE, + (const char *)ca_from_quote, + (tdx_ql_qve_collateral_t **)pp_quote_collateral); + if (ret == SGX_QL_SUCCESS) + { + *p_collateral_size = + (uint32_t)sizeof(tdx_ql_qve_collateral_t) + + ((tdx_ql_qve_collateral_t *)(*pp_quote_collateral)) + ->pck_crl_issuer_chain_size + + ((tdx_ql_qve_collateral_t *)(*pp_quote_collateral)) + ->root_ca_crl_size + + ((tdx_ql_qve_collateral_t *)(*pp_quote_collateral)) + ->pck_crl_size + + ((tdx_ql_qve_collateral_t *)(*pp_quote_collateral)) + ->tcb_info_issuer_chain_size + + ((tdx_ql_qve_collateral_t *)(*pp_quote_collateral)) + ->qe_identity_issuer_chain_size + + ((tdx_ql_qve_collateral_t *)(*pp_quote_collateral)) + ->qe_identity_size + + ((tdx_ql_qve_collateral_t *)(*pp_quote_collateral)) + ->tcb_info_size; + } + } + else + { + // quote type is not supported + ret = SGX_QL_ERROR_INVALID_PARAMETER; + } + + return ret; +} + + +/** + * @brief free verification colloateral + * + */ +quote3_error_t tee_qv_free_collateral(uint8_t *p_quote_collateral) +{ + quote3_error_t ret = SGX_QL_SUCCESS; + if (p_quote_collateral == NULL) + + return SGX_QL_ERROR_INVALID_PARAMETER; + + const sgx_ql_qve_collateral_t *p_collater = + reinterpret_cast(p_quote_collateral); + if (p_collater->tee_type == SGX_QUOTE_TYPE) + { + ret = sgx_dcap_free_verification_collateral((sgx_ql_qve_collateral_t *)p_quote_collateral); + } + else if (p_collater->tee_type == TDX_QUOTE_TYPE) + { + ret = tdx_dcap_free_verification_collateral((tdx_ql_qve_collateral_t *)p_quote_collateral); + } + else + { + // quote type is not supported + ret = SGX_QL_ERROR_INVALID_PARAMETER; + } + return ret; +} + + +/** + * Perform quote verification for SGX and TDX + * This API works the same as the old one, but takes a new parameter to describe the supplemental data (p_supp_data_descriptor) + **/ +quote3_error_t tee_verify_quote( + const uint8_t *p_quote, + uint32_t quote_size, + const uint8_t *p_quote_collateral, + const time_t expiration_check_date, + uint32_t *p_collateral_expiration_status, + sgx_ql_qv_result_t *p_quote_verification_result, + sgx_ql_qe_report_info_t *p_qve_report_info, + tee_supp_data_descriptor_t *p_supp_data_descriptor) +{ + quote3_error_t ret = SGX_QL_SUCCESS; + supp_ver_t latest_version; + uint32_t supp_data_size = 0; + uint32_t tmp_size = 0; + uint8_t *p_supp_data = NULL; + + // only check quote, other parameters will be checked in internal functions + if (p_quote == NULL || quote_size == 0) + return SGX_QL_ERROR_INVALID_PARAMETER; + + ret = tee_get_supplemental_data_version_and_size(p_quote, quote_size, &latest_version.version, &tmp_size); + + if (ret != SGX_QL_SUCCESS) + return ret; + + try { + // check supplemental descriptor + if (p_supp_data_descriptor != NULL) { + + if (p_supp_data_descriptor->p_data == NULL) + return SGX_QL_ERROR_INVALID_PARAMETER; + + if (p_supp_data_descriptor->major_version > latest_version.major_version) + return SGX_QL_SUPPLEMENTAL_DATA_VERSION_NOT_SUPPORTED; + + // major version <= latest support version + else { + // Only support major version 0 and 3 in current stage + if ((p_supp_data_descriptor->major_version != 0 && p_supp_data_descriptor->major_version != SUPPLEMENTAL_DATA_VERSION) || + p_supp_data_descriptor->data_size != tmp_size) + return SGX_QL_ERROR_INVALID_PARAMETER; + + // only support version 3 by now, may add additional logic to match major version and minor version in future + memset(p_supp_data_descriptor->p_data, 0, p_supp_data_descriptor->data_size); + + // set version in supplemental data + reinterpret_cast (p_supp_data_descriptor->p_data)->major_version = SUPPLEMENTAL_DATA_VERSION; + reinterpret_cast (p_supp_data_descriptor->p_data)->minor_version = SUPPLEMENTAL_V3_LATEST_MINOR_VERSION; + + // size will be checked in internal logic + supp_data_size = p_supp_data_descriptor->data_size; + p_supp_data = p_supp_data_descriptor->p_data; + } + } + } + + catch (...) { + return SGX_QL_ERROR_INVALID_PARAMETER; + } + + ret = tee_verify_evidence( + p_quote, + quote_size, + reinterpret_cast (p_quote_collateral), expiration_check_date, p_collateral_expiration_status, p_quote_verification_result, p_qve_report_info, - supplemental_data_size, - p_supplemental_data); + supp_data_size, + p_supp_data); + + if (ret != SGX_QL_SUCCESS && p_supp_data_descriptor->p_data != NULL) { + // defense in depth + memset(p_supp_data_descriptor->p_data, 0, sizeof(sgx_ql_qve_collateral_t)); + } + + return ret; } + #ifndef _MSC_VER #include diff --git a/QuoteVerification/dcap_quoteverify/win/sgx_dcap_quoteverify.def b/QuoteVerification/dcap_quoteverify/win/sgx_dcap_quoteverify.def index bb399305..f87da73f 100644 --- a/QuoteVerification/dcap_quoteverify/win/sgx_dcap_quoteverify.def +++ b/QuoteVerification/dcap_quoteverify/win/sgx_dcap_quoteverify.def @@ -6,3 +6,7 @@ EXPORTS sgx_qv_set_enclave_load_policy @3 sgx_qv_get_qve_identity @4 sgx_qv_free_qve_identity @5 + tee_qv_get_collateral @6 + tee_qv_free_collateral @7 + tee_get_supplemental_data_version_and_size @8 + tee_verify_quote @9 \ No newline at end of file diff --git a/QuoteVerification/dcap_tvl/sgx_dcap_tvl.cpp b/QuoteVerification/dcap_tvl/sgx_dcap_tvl.cpp index 4d4282a0..7386e4cf 100644 --- a/QuoteVerification/dcap_tvl/sgx_dcap_tvl.cpp +++ b/QuoteVerification/dcap_tvl/sgx_dcap_tvl.cpp @@ -61,7 +61,7 @@ const std::string QVE_MRSIGNER = "8C4F5775D796503E96137F77C68A829A0056AC8DED7014 const sgx_prod_id_t QVE_PRODID = 2; //Defense in depth, QvE ISV SVN in report must be greater or equal to hardcode QvE ISV SVN -const sgx_isv_svn_t LEAST_QVE_ISVSVN = 6; +const sgx_isv_svn_t LEAST_QVE_ISVSVN = 7; quote3_error_t sgx_tvl_verify_qve_report_and_identity( const uint8_t *p_quote, diff --git a/QuoteVerification/prepare_sgxssl.cmd b/QuoteVerification/prepare_sgxssl.cmd index 68863205..2f3c15fb 100644 --- a/QuoteVerification/prepare_sgxssl.cmd +++ b/QuoteVerification/prepare_sgxssl.cmd @@ -39,17 +39,17 @@ set top_dir=%~dp0 set sgxssl_dir=%top_dir%\sgxssl set openssl_out_dir=%sgxssl_dir%\openssl_source -set openssl_ver_name=openssl-1.1.1o +set openssl_ver_name=openssl-1.1.1q set sgxssl_github_archive=https://github.com/intel/intel-sgx-ssl/archive -set sgxssl_ver_name=win_2.16_1.1.1o +set sgxssl_ver_name=win_2.17_1.1.1q set sgxssl_ver=%sgxssl_ver_name% set build_script=%sgxssl_dir%\Windows\build_package.cmd set server_url_path=https://www.openssl.org/source/ set full_openssl_url=%server_url_path%/%openssl_ver_name%.tar.gz -set sgxssl_chksum=E25CF02BF48FA279CFCB6B134ACB0A1FB04B84F680B40F32EF03AFF7368BE1E6 -set openssl_chksum=9384A2B0570DD80358841464677115DF785EDB941C71211F75076D72FE6B438F +set sgxssl_chksum=6BCC533BD89FFC4E0A5E7FB7B4FB8D8CC2BFF6B421B9D7EF1F0156B99BABF1D9 +set openssl_chksum=D7939CE614029CDFF0B6C20F0E2E5703158A489A72B2507B8BD51BF8C8FD10CA if not exist %sgxssl_dir% ( diff --git a/QuoteVerification/prepare_sgxssl.sh b/QuoteVerification/prepare_sgxssl.sh index a0685adc..00a2c7ec 100755 --- a/QuoteVerification/prepare_sgxssl.sh +++ b/QuoteVerification/prepare_sgxssl.sh @@ -34,16 +34,16 @@ ARG1=${1:-build} top_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" sgxssl_dir=$top_dir/sgxssl openssl_out_dir=$sgxssl_dir/openssl_source -openssl_ver_name=openssl-1.1.1o -sgxssl_github_archive=https://github.com/01org/intel-sgx-ssl/archive -sgxssl_file_name=lin_2.17_1.1.1o +openssl_ver_name=openssl-1.1.1q +sgxssl_github_archive=https://github.com/intel/intel-sgx-ssl/archive +sgxssl_file_name=lin_2.18_1.1.1q 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 -sgxssl_chksum=f0ed7bd37b45fd2350ec835a9c56b5590554e13b94471a38d3379054448a6d4b -openssl_chksum=9384a2b0570dd80358841464677115df785edb941c71211f75076d72fe6b438f +sgxssl_chksum=6c33d2178b6b01bdbb1f97804ae14aec13544b0cb45902a0906c20ef7b4032bc +openssl_chksum=d7939ce614029cdff0b6c20f0e2e5703158a489a72b2507b8bd51bf8c8fd10ca rm -f check_sum_sgxssl.txt check_sum_openssl.txt if [ ! -f $build_script ]; then wget $sgxssl_github_archive/$sgxssl_file_name.zip -P $sgxssl_dir/ || exit 1 diff --git a/SampleCode/JavaQuoteVerificationSample/Makefile b/SampleCode/JavaQuoteVerificationSample/Makefile new file mode 100644 index 00000000..c823974b --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/Makefile @@ -0,0 +1,81 @@ +# +# 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. +# +# + + + + +ifdef DEBUG + COMMON_FLAGS += -ggdb -DDEBUG -UNDEBUG +else + COMMON_FLAGS += -O2 -D_FORTIFY_SOURCE=2 -UDEBUG -DNDEBUG +endif + +COMMON_FLAGS += -ffunction-sections -fdata-sections + +# turn on compiler warnings as much as possible +COMMON_FLAGS += -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 + +# additional warnings flags for C +CFLAGS += -Wjump-misses-init -Wstrict-prototypes -Wunsuffixed-float-constants + +CFLAGS += $(COMMON_FLAGS) + +JAVA_HOME=$(shell readlink -f /usr/bin/javac | sed "s:bin/javac::") + +all: lib_jni_dcap_quoteverify +JNI_WRAPPER_VERSION = 1 +jni_dcap_quoteverify_lib := libjni_dcap_quoteverify.so + + +QvL_BUILD_PATH := ../../QuoteVerification/dcap_quoteverify/linux +JNI_C_SRCS := src/main/c/jni/sgx_dcap_quoteverify_wrap.c +JNI_C_SRCS += src/main/c/jni/jni_native_lib_init.c +JNI_C_OBJS := $(JNI_C_SRCS:.c=.o) + +INCLUDE_DIR = -I$(JAVA_HOME)/include +INCLUDE_DIR += -I$(JAVA_HOME)/include/linux +CFLAGS += $(INCLUDE_DIR) +CFLAGS += -fvisibility=hidden + +lib_jni_dcap_quoteverify: $(JNI_C_OBJS) + $(CC) -shared -Wl,-soname=$(jni_dcap_quoteverify_lib) -o src/main/c/lib/$(jni_dcap_quoteverify_lib).$(JNI_WRAPPER_VERSION) $^ + ldconfig -n src/main/c/lib + +%.o : %.c + $(CC) $(CFLAGS) -fPIC -o $@ -c $< + +clean: + $(RM) $(JNI_C_OBJS) src/main/c/lib/*.so* + +.PHONYT: clean all diff --git a/SampleCode/JavaQuoteVerificationSample/README.md b/SampleCode/JavaQuoteVerificationSample/README.md new file mode 100644 index 00000000..a9cadd86 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/README.md @@ -0,0 +1,49 @@ +## Linux +Supported operating systems: +* Ubuntu* 18.04 LTS Desktop 64bits +* Ubuntu* 18.04 LTS Server 64bits +* Ubuntu* 20.04 LTS Server 64bits + +Requirements: +* make +* gcc +* g++ +* maven +* JDK `1.8+` + +Prerequisite: +* Intel(R) SGX DCAP Driver +* Intel(R) SGX SDK +* Intel(R) SGX DCAP Packages +* Intel(R) SGX DCAP PCCS (Provisioning Certificate Caching Service) + +*Please refer to SGX DCAP Linux installation guide "https://download.01.org/intel-sgx/sgx-dcap/#version#/linux/docs/Intel_SGX_DCAP_Linux_SW_Installation_Guide.pdf" to install above dependencies*
+*Note that you need to change **\#version\#** to actual version number in URL, such as 1.4.* + +1. Generate an ECDSA quote with certification data of type 5 using QuoteGenerationSample +``` + $ cd SampleCode/QuoteGenerationSample/ + $ make + $ ./app +``` +Update environment variables +``` + $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${Project_basedir}/src/main/c/lib +``` +2. Build and test *JavaQuoteVerificationSample* to verify a given quote + +2.1 Compile package +``` + $ mvn compile package +``` +2.2 Run verify quote command, here use the demo quote in ${Project_basedir}/src/main/resources +``` + $ java -jar ./target/JavaQuoteVerificationSample-1.0.jar -q +``` + +2.2 Clean +- If you want to clean the files generated by previous `mvn compile` command, enter the following command: +``` + $ mvn clean +``` + diff --git a/SampleCode/JavaQuoteVerificationSample/pom.xml b/SampleCode/JavaQuoteVerificationSample/pom.xml new file mode 100644 index 00000000..fe31c364 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/pom.xml @@ -0,0 +1,160 @@ + + + + 4.0.0 + + com.intel.sgx + JavaQuoteVerificationSample + 1.0 + + JavaQuoteVerificationSample + https://github.com/intel/SGXDataCenterAttestationPrimitives + + + UTF-8 + 1.7 + 1.7 + + + + + junit + junit + 4.11 + test + + + net.sourceforge.argparse4j + argparse4j + 0.9.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + ${skipTests} + + + + + org.apache.maven.plugins + maven-clean-plugin + 3.1.0 + + + + src/main/c/lib + + *.so + *.so.1 + + + + src/main/c/jni + + *.o + + + + + + + + maven-resources-plugin + 3.0.2 + + + maven-compiler-plugin + 3.8.0 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 + + + + maven-site-plugin + 3.7.1 + + + maven-project-info-reports-plugin + 3.0.0 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.0 + + + + true + + com.intel.sgx.Demo + + + + + + + maven-assembly-plugin + + + + >com.intel.sgx.App + + + + jar-with-dependencies + + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + compile + + exec + + + + + make + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.3.0 + + + copy-dependencies + package + + copy-dependencies + + + ${project.build.directory} + false + false + true + + + + + + + \ No newline at end of file diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/c/jni/com_intel_sgx_SgxDcapVerifyQuoteJNI.h b/SampleCode/JavaQuoteVerificationSample/src/main/c/jni/com_intel_sgx_SgxDcapVerifyQuoteJNI.h new file mode 100644 index 00000000..0858e62a --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/c/jni/com_intel_sgx_SgxDcapVerifyQuoteJNI.h @@ -0,0 +1,99 @@ +/* + * 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. + * + */ + +/* Header for class com_intel_sgx_SgxDcapVerifyQuoteJNI */ +#include + +#ifndef _Included_com_intel_sgx_SgxDcapVerifyQuoteJNI +#define _Included_com_intel_sgx_SgxDcapVerifyQuoteJNI +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_intel_sgx_SgxDcapVerifyQuoteJNI + * Method: sgx_qv_verify_quote + * Signature: ([B[B[B[B[B[B[B[BJ)Lcom/intel/sgx/result/SgxDcapQuoteVerifyResult; + */ +JNIEXPORT jobject JNICALL Java_com_intel_sgx_SgxDcapVerifyQuoteJNI_sgx_1qv_1verify_1quote + (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jlong); + +/* + * Class: com_intel_sgx_SgxDcapVerifyQuoteJNI + * Method: sgx_qv_get_qve_identity + * Signature: ()Lcom/intel/sgx/identity/QveIdentity; + */ +JNIEXPORT jobject JNICALL Java_com_intel_sgx_SgxDcapVerifyQuoteJNI_sgx_1qv_1get_1qve_1identity + (JNIEnv *, jobject); + +/* + * Class: com_intel_sgx_SgxDcapVerifyQuoteJNI + * Method: sgx_qv_set_path + * Signature: (ILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_com_intel_sgx_SgxDcapVerifyQuoteJNI_sgx_1qv_1set_1path + (JNIEnv *, jobject, jint, jstring); + +/* + * Class: com_intel_sgx_SgxDcapVerifyQuoteJNI + * Method: sgx_qv_set_enclave_load_policy + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_intel_sgx_SgxDcapVerifyQuoteJNI_sgx_1qv_1set_1enclave_1load_1policy + (JNIEnv *, jobject, jint); + +/* + * Class: com_intel_sgx_SgxDcapVerifyQuoteJNI + * Method: tee_qv_get_collateral + * Signature: ([B)Lcom/intel/sgx/collateral/Collateral; + */ +JNIEXPORT jobject JNICALL Java_com_intel_sgx_SgxDcapVerifyQuoteJNI_tee_1qv_1get_1collateral + (JNIEnv *, jobject, jbyteArray); + +/* + * Class: com_intel_sgx_SgxDcapVerifyQuoteJNI + * Method: tee_verify_quote + * Signature: ([B[B[B[B[B[B[B[BJSI)Lcom/intel/sgx/result/TeeDcapQuoteVerifyResult; + */ +JNIEXPORT jobject JNICALL Java_com_intel_sgx_SgxDcapVerifyQuoteJNI_tee_1verify_1quote + (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jlong, jshort, jint); + +/* + * Class: com_intel_sgx_SgxDcapVerifyQuoteJNI + * Method: tee_get_supplemental_data_version_and_size + * Signature: ([B)Lcom/intel/sgx/result/supplementalResult; + */ +JNIEXPORT jobject JNICALL Java_com_intel_sgx_SgxDcapVerifyQuoteJNI_tee_1get_1supplemental_1data_1version_1and_1size + (JNIEnv *, jobject, jbyteArray); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/c/jni/jni_native_lib_init.c b/SampleCode/JavaQuoteVerificationSample/src/main/c/jni/jni_native_lib_init.c new file mode 100644 index 00000000..364ea831 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/c/jni/jni_native_lib_init.c @@ -0,0 +1,129 @@ +/* + * 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. + * + */ + + +#include "jni_native_lib_init.h" +#include +#include +#include +#include +static void *lib_handle = NULL; + +static char *lib_name = "libsgx_dcap_quoteverify.so"; +sgx_qv_free_qve_identity_t qvl_sgx_qv_free_qve_identity = NULL; +sgx_qv_get_quote_supplemental_data_size_t + qvl_sgx_qv_get_quote_supplemental_data_size = NULL; +sgx_qv_get_qve_identity_t qvl_sgx_qv_get_qve_identity = NULL; +sgx_qv_set_enclave_load_policy_t qvl_sgx_qv_set_enclave_load_policy = NULL; +sgx_qv_set_path_t qvl_sgx_qv_set_path = NULL; +sgx_qv_verify_quote_t qvl_sgx_qv_verify_quote = NULL; +tee_qv_get_collateral_t qvl_tee_qv_get_collateral = NULL; +tee_qv_free_collateral_t qvl_tee_qv_free_collateral = NULL; +tee_get_supplemental_data_version_and_size_t qvl_tee_get_supplemental_data_version_and_size = NULL; +tee_tee_verify_quote_t qvl_tee_verify_quote = NULL; + +static char const *const sym_names[] = { + [0] = "sgx_qv_free_qve_identity", + [1] = "sgx_qv_get_quote_supplemental_data_size", + [2] = "sgx_qv_get_qve_identity", + [3] = "sgx_qv_set_enclave_load_policy", + [4] = "sgx_qv_set_path", + [5] = "sgx_qv_verify_quote", + [6] = "tee_qv_get_collateral", + [7] = "tee_qv_free_collateral", + [8] = "tee_get_supplemental_data_version_and_size", + [9] = "tee_verify_quote", +}; +#define CHECK(cond, fmt, ...) \ + do { \ + if (!(cond)) { \ + fprintf(stderr, "libsgx_dcap_quoteverify.so.1: " fmt "\n", \ + ##__VA_ARGS__); \ + exit(EXIT_FAILURE); \ + } \ + dlerror(); \ + } while (0) + +__attribute__((constructor)) +int load_lib() { + lib_handle = dlopen(lib_name, RTLD_LAZY | RTLD_GLOBAL); + CHECK(lib_handle, "failed to load library via dlopen: %s", dlerror()); + + qvl_sgx_qv_free_qve_identity = + (sgx_qv_free_qve_identity_t)dlsym(lib_handle, sym_names[0]); + CHECK(qvl_sgx_qv_free_qve_identity, "failed to resolve symbol '%s'", + sym_names[0]); + + qvl_sgx_qv_get_quote_supplemental_data_size = + (sgx_qv_get_quote_supplemental_data_size_t)dlsym(lib_handle, + sym_names[1]); + CHECK(qvl_sgx_qv_get_quote_supplemental_data_size, + "failed to resolve symbol '%s'", sym_names[1]); + + qvl_sgx_qv_get_qve_identity = + (sgx_qv_get_qve_identity_t)dlsym(lib_handle, sym_names[2]); + CHECK(qvl_sgx_qv_get_qve_identity, + "failed to resolve symbol '%s'", sym_names[2]); + + qvl_sgx_qv_set_enclave_load_policy = + (sgx_qv_set_enclave_load_policy_t)dlsym(lib_handle, sym_names[3]); + CHECK(qvl_sgx_qv_set_enclave_load_policy, "failed to resolve symbol '%s'", + sym_names[3]); + + qvl_sgx_qv_set_path = + (sgx_qv_set_path_t)dlsym(lib_handle,sym_names[4]); + CHECK(qvl_sgx_qv_set_path, "failed to resolve symbol '%s'", + sym_names[4]); + + qvl_sgx_qv_verify_quote = + (sgx_qv_verify_quote_t)dlsym(lib_handle, sym_names[5]); + CHECK(qvl_sgx_qv_verify_quote, "failed to resolve symbol '%s'", sym_names[5]); + + qvl_tee_qv_get_collateral = (tee_qv_get_collateral_t)dlsym(lib_handle, sym_names[6]); + CHECK(qvl_tee_qv_get_collateral, "failed to resolve symbol '%s'", sym_names[6]); + + qvl_tee_qv_free_collateral = (tee_qv_free_collateral_t)dlsym(lib_handle, sym_names[7]); + CHECK(qvl_tee_qv_free_collateral, "failed to resolve symbol '%s'", sym_names[7]); + + qvl_tee_get_supplemental_data_version_and_size = (tee_get_supplemental_data_version_and_size_t)dlsym(lib_handle, sym_names[8]); + CHECK(qvl_tee_get_supplemental_data_version_and_size, "failed to resolve symbol '%s'", sym_names[8]); + + qvl_tee_verify_quote = (tee_tee_verify_quote_t)dlsym(lib_handle, sym_names[9]); + CHECK(qvl_tee_verify_quote, "failed to resolve symbol '%s'", sym_names[9]); + return 0; +} + +__attribute__((destructor)) +void unload_lib() { + if (NULL != lib_handle) { + dlclose(lib_handle); + } +} \ No newline at end of file diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/c/jni/jni_native_lib_init.h b/SampleCode/JavaQuoteVerificationSample/src/main/c/jni/jni_native_lib_init.h new file mode 100644 index 00000000..ec58b805 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/c/jni/jni_native_lib_init.h @@ -0,0 +1,95 @@ +/* + * 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. + * + */ + + +#ifndef _JNI_NATIVE_LIB_INIT_ +#define _JNI_NATIVE_LIB_INIT_ +#include + +int load_lib(void); +void unload_lib(void); + +typedef quote3_error_t (*sgx_qv_free_qve_identity_t)( + uint8_t *p_qveid, uint8_t *p_qveid_issue_chain, uint8_t *p_root_ca_crl); +extern sgx_qv_free_qve_identity_t qvl_sgx_qv_free_qve_identity; +typedef quote3_error_t (*sgx_qv_get_quote_supplemental_data_size_t)( + uint32_t *p_data_size); +extern sgx_qv_get_quote_supplemental_data_size_t + qvl_sgx_qv_get_quote_supplemental_data_size; +typedef quote3_error_t (*sgx_qv_get_qve_identity_t)( + uint8_t **pp_qveid, uint32_t *p_qveid_size, uint8_t **pp_qveid_issue_chain, + uint32_t *p_qveid_issuer_chain_size, uint8_t **pp_root_ca_crl, + uint16_t *p_root_ca_crl_size); +extern sgx_qv_get_qve_identity_t qvl_sgx_qv_get_qve_identity; +typedef quote3_error_t (*sgx_qv_set_enclave_load_policy_t)( + sgx_ql_request_policy_t policy); +extern sgx_qv_set_enclave_load_policy_t qvl_sgx_qv_set_enclave_load_policy; +typedef quote3_error_t (*sgx_qv_set_path_t)(sgx_qv_path_type_t path_type, + const char *p_path); +extern sgx_qv_set_path_t qvl_sgx_qv_set_path; +typedef quote3_error_t (*sgx_qv_verify_quote_t)( + const uint8_t *p_quote, uint32_t quote_size, + const sgx_ql_qve_collateral_t *p_quote_collateral, + const time_t expiration_check_date, + uint32_t *p_collateral_expiration_status, + sgx_ql_qv_result_t *p_quote_verification_result, + sgx_ql_qe_report_info_t *p_qve_report_info, uint32_t supplemental_data_size, + uint8_t *p_supplemental_data); +extern sgx_qv_verify_quote_t qvl_sgx_qv_verify_quote; + +typedef quote3_error_t (*tee_qv_get_collateral_t)( + const uint8_t *p_quote, + uint32_t quote_size, + uint8_t **pp_quote_collateral, + uint32_t *p_collateral_size); +extern tee_qv_get_collateral_t qvl_tee_qv_get_collateral; + +typedef quote3_error_t (*tee_qv_free_collateral_t)(uint8_t *p_quote_collateral); +extern tee_qv_free_collateral_t qvl_tee_qv_free_collateral; + +typedef quote3_error_t (*tee_get_supplemental_data_version_and_size_t)( + const uint8_t *p_quote, + uint32_t quote_size, + uint32_t *p_version, + uint32_t *p_data_size); +extern tee_get_supplemental_data_version_and_size_t qvl_tee_get_supplemental_data_version_and_size; + +typedef quote3_error_t (*tee_tee_verify_quote_t)( + const uint8_t *p_quote, + uint32_t quote_size, + const uint8_t *p_quote_collateral, + const time_t expiration_check_date, + uint32_t *p_collateral_expiration_status, + sgx_ql_qv_result_t *p_quote_verification_result, + sgx_ql_qe_report_info_t *p_qve_report_info, + tee_supp_data_descriptor_t *p_supp_data_descriptor); +extern tee_tee_verify_quote_t qvl_tee_verify_quote; +#endif diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/c/jni/sgx_dcap_quoteverify_wrap.c b/SampleCode/JavaQuoteVerificationSample/src/main/c/jni/sgx_dcap_quoteverify_wrap.c new file mode 100644 index 00000000..1929cc26 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/c/jni/sgx_dcap_quoteverify_wrap.c @@ -0,0 +1,1170 @@ +/* + * 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. + * + */ + + +#include "jni_native_lib_init.h" +#include +#include +#include +#include +#include +#include +#include "com_intel_sgx_SgxDcapVerifyQuoteJNI.h" + +/* Support for throwing Java exceptions */ +typedef enum { + DCAP_JavaOutOfMemoryError = 1, + DCAP_JavaIOException, + DCAP_JavaRuntimeException, + DCAP_JavaIndexOutOfBoundsException, + DCAP_JavaArithmeticException, + DCAP_JavaIllegalArgumentException, + DCAP_JavaNullPointerException, + DCAP_JavaDirectorPureVirtual, + DCAP_JavaUnknownError, + DCAP_JavaIllegalStateException, +} DCAP_JavaExceptionCodes; + +typedef struct { + DCAP_JavaExceptionCodes code; + const char *java_exception; +} DCAP_JavaExceptions_t; + + +static void DCAP_JavaThrowException(JNIEnv *jenv, DCAP_JavaExceptionCodes code, const char *msg) { + jclass excep; + static const DCAP_JavaExceptions_t java_exceptions[] = { + { DCAP_JavaOutOfMemoryError, "java/lang/OutOfMemoryError" }, + { DCAP_JavaIOException, "java/io/IOException" }, + { DCAP_JavaRuntimeException, "java/lang/RuntimeException" }, + { DCAP_JavaIndexOutOfBoundsException, "java/lang/IndexOutOfBoundsException" }, + { DCAP_JavaArithmeticException, "java/lang/ArithmeticException" }, + { DCAP_JavaIllegalArgumentException, "java/lang/IllegalArgumentException" }, + { DCAP_JavaNullPointerException, "java/lang/NullPointerException" }, + { DCAP_JavaDirectorPureVirtual, "java/lang/RuntimeException" }, + { DCAP_JavaUnknownError, "java/lang/UnknownError" }, + { DCAP_JavaIllegalStateException, "java/lang/IllegalStateException" }, + { (DCAP_JavaExceptionCodes)0, "java/lang/UnknownError" } + }; + const DCAP_JavaExceptions_t *except_ptr = java_exceptions; + + while (except_ptr->code != code && except_ptr->code) + except_ptr++; + + (*jenv)->ExceptionClear(jenv); + excep = (*jenv)->FindClass(jenv, except_ptr->java_exception); + if (excep) + (*jenv)->ThrowNew(jenv, excep, msg); +} + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief set the full path of QVE and QPL library + * The function takes the enum and the corresponding full path + * + * @param path_type Set type path of SGX_QV_QVE_PATH or SGX_QV_QPL_PATH + * @param p_path It should be a valid full path + * + * @return SGX_QL_SUCCESS Successfully set the full path + * @return SGX_QL_ERROR_INVALID_PARAMETER p_path is not a valid full path or the path is too long + */ +JNIEXPORT jint JNICALL Java_com_intel_sgx_SgxDcapVerifyQuoteJNI_sgx_1qv_1set_1path(JNIEnv *jenv, jobject jobj, jint jlibType, + jstring jpath) { + (void)jenv; + (void)jobj; + quote3_error_t ret = SGX_QL_SUCCESS; + + const char *cpath = (*jenv)->GetStringUTFChars(jenv, jpath, NULL); + if (NULL == cpath) + return __LINE__; + if (NULL == qvl_sgx_qv_set_path) { + if (load_lib()){ + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to Link Error libsgx_dcap_quoteverify.so"); + return __LINE__; + } + } + + if (jlibType == 0) { + ret = qvl_sgx_qv_set_path(SGX_QV_QVE_PATH, cpath); + } else if (jlibType == 1) { + ret = qvl_sgx_qv_set_path(SGX_QV_QPL_PATH, cpath); + } + + (*jenv)->ReleaseStringUTFChars(jenv, jpath, cpath); // release resources + + return ret; +} + +/** + * @brief Get SGX QvE identity and Root CA CRL + * + * @param jenv + * @param jobj + * @return jobject + */ +JNIEXPORT jobject JNICALL Java_com_intel_sgx_SgxDcapVerifyQuoteJNI_sgx_1qv_1get_1qve_1identity(JNIEnv *jenv, jobject jobj) { + uint8_t *pp_qveid = NULL; + jsize p_qveid_size = 0; + uint8_t *pp_qveid_issue_chain = NULL; + uint32_t p_qveid_issue_chain_size = 0; + uint8_t *pp_root_ca_crl = NULL; + uint16_t p_root_ca_crl_size = 0; + + jobject qveIdentityObj = NULL; + jclass cls_QveIdentity =NULL; + jmethodID meth_qveIdentityInit = NULL; + (void)jobj; + if (NULL == qvl_sgx_qv_get_qve_identity) { + if (load_lib()){ + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to Link Error libsgx_dcap_quoteverify.so"); + return NULL; + } + } + + quote3_error_t ret = qvl_sgx_qv_get_qve_identity( + &pp_qveid, (uint32_t *)&p_qveid_size, &pp_qveid_issue_chain, + &p_qveid_issue_chain_size, &pp_root_ca_crl, &p_root_ca_crl_size); + if (ret != SGX_QL_SUCCESS) { + return NULL; + } + + jbyteArray tmp_identity_array = (*jenv)->NewByteArray(jenv, p_qveid_size); + if ((*jenv)->GetArrayLength(jenv, tmp_identity_array) != p_qveid_size) { + (*jenv)->DeleteLocalRef(jenv, tmp_identity_array); + tmp_identity_array = (*jenv)->NewByteArray(jenv, p_qveid_size); + } + void *tmp_buf = + (*jenv)->GetPrimitiveArrayCritical(jenv, (jarray)tmp_identity_array, 0); + memcpy((void *)tmp_buf, (void *)pp_qveid, (size_t)p_qveid_size); + (*jenv)->ReleasePrimitiveArrayCritical(jenv, tmp_identity_array, tmp_buf, 0); + + jbyteArray tmp_issue_chain_array = + (*jenv)->NewByteArray(jenv, (int)p_qveid_issue_chain_size); + if ((*jenv)->GetArrayLength(jenv, tmp_issue_chain_array) != + (int)p_qveid_issue_chain_size) { + (*jenv)->DeleteLocalRef(jenv, tmp_issue_chain_array); + tmp_issue_chain_array = (*jenv)->NewByteArray(jenv, (int)p_qveid_issue_chain_size); + } + tmp_buf = + (*jenv)->GetPrimitiveArrayCritical(jenv, (jarray)tmp_issue_chain_array, 0); + memcpy((void *)tmp_buf, (void *)pp_qveid_issue_chain, + p_qveid_issue_chain_size); + (*jenv)->ReleasePrimitiveArrayCritical(jenv, tmp_issue_chain_array, tmp_buf, 0); + + jbyteArray tmp_root_ca_crl_array = + (*jenv)->NewByteArray(jenv, p_root_ca_crl_size); + if ((*jenv)->GetArrayLength(jenv, tmp_root_ca_crl_array) != + p_root_ca_crl_size) { + (*jenv)->DeleteLocalRef(jenv, tmp_root_ca_crl_array); + tmp_root_ca_crl_array = (*jenv)->NewByteArray(jenv, p_root_ca_crl_size); + } + tmp_buf = + (*jenv)->GetPrimitiveArrayCritical(jenv, (jarray)tmp_root_ca_crl_array, 0); + memcpy((void *)tmp_buf, (void *)pp_root_ca_crl, p_root_ca_crl_size); + (*jenv)->ReleasePrimitiveArrayCritical(jenv, tmp_root_ca_crl_array, tmp_buf, 0); + + // free the related memory + if (NULL != pp_qveid && NULL != pp_qveid_issue_chain && + NULL != pp_root_ca_crl) { + sgx_qv_free_qve_identity(pp_qveid, pp_qveid_issue_chain, pp_root_ca_crl); + } + + cls_QveIdentity = (*jenv)->FindClass(jenv, "com/intel/sgx/identity/QveIdentity"); + if(NULL == cls_QveIdentity){ + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to find class com/intel/sgx/identity/QveIdentity"); + qveIdentityObj = NULL; + goto FINI; + } + // Get the Method ID of the constructor which takes 3 bytes + meth_qveIdentityInit = + (*jenv)->GetMethodID(jenv, cls_QveIdentity, "", "([B[B[B)V"); + if (NULL == meth_qveIdentityInit) { + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to find init for com/intel/sgx/identity/QveIdentity"); + qveIdentityObj = NULL; + goto FINI; + } + // Call back constructor to allocate a new instance, with an int argument + qveIdentityObj = + (*jenv)->NewObject(jenv, cls_QveIdentity, meth_qveIdentityInit, tmp_identity_array, + tmp_issue_chain_array, tmp_root_ca_crl_array); + +FINI: + // TODO release resource + (*jenv)->DeleteLocalRef(jenv, tmp_identity_array); + (*jenv)->DeleteLocalRef(jenv, tmp_issue_chain_array); + (*jenv)->DeleteLocalRef(jenv, tmp_root_ca_crl_array); + return qveIdentityObj; +} + +/** + * @brief + * When the Quoting Verification Library is linked to a process, it needs to know the proper enclave loading policy. + * The library may be linked with a long lived process, such as a service, where it can load the enclaves and leave + * them loaded (persistent). This better ensures that the enclaves will be available upon quote requests and not subject + * to EPC limitations if loaded on demand. However, if the Quoting library is linked with an application process, there + * may be many applications with the Quoting library and a better utilization of EPC is to load and unloaded the quoting + * enclaves on demand (ephemeral). The library will be shipped with a default policy of loading enclaves and leaving + * them loaded until the library is unloaded (PERSISTENT). If the policy is set to EPHEMERAL, then the QE and PCE will + * be loaded and unloaded on-demand. If either enclave is already loaded when the policy is change to EPHEMERAL, the + * enclaves will be unloaded before returning. + * @param jenv + * @param jobj + * @param jpolicy Sets the requested enclave loading policy to either SGX_QL_PERSISTENT, SGX_QL_EPHEMERAL or SGX_QL_DEFAULT + * @return SGX_QL_SUCCESS Successfully set the enclave loading policy for the quoting library's enclaves. + * @return SGX_QL_UNSUPPORTED_LOADING_POLICY The selected policy is not support by the quoting library. + * @return SGX_QL_ERROR_UNEXPECTED Unexpected internal error. + */ +JNIEXPORT jint JNICALL Java_com_intel_sgx_SgxDcapVerifyQuoteJNI_sgx_1qv_1set_1enclave_1load_1policy(JNIEnv *jenv, jobject jobj, + jint jpolicy) { + (void)jenv; + (void)jobj; + + quote3_error_t ret = SGX_QL_SUCCESS; + if (NULL == qvl_sgx_qv_set_enclave_load_policy) { + if (load_lib()){ + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to Link Error libsgx_dcap_quoteverify.so"); + return __LINE__; + } + } + if (0 == jpolicy) { + ret = qvl_sgx_qv_set_enclave_load_policy(SGX_QL_PERSISTENT); + } else if (1 == jpolicy) { + ret = qvl_sgx_qv_set_enclave_load_policy(SGX_QL_EPHEMERAL); + } + + return ret; +} + + +/** + * @brief Perform ECDSA quote verification + * + * @param jenv + * @param jobj + * @param quote[IN] - Pointer to SGX Quote + * @param pck_crl[IN] - PCK crl + * @param pck_crl_issuer [IN] - PCK crl issuer + * @param qe_identity [IN] - QE Identity + * @param qe_identity_issuer [IN] - QE Identity issuer + * @param tcb_info [IN] - TCB Info + * @param tcb_info_issuer [IN] - TCB Info issuer + * @param root_ca_crl [IN] - Root CA CRL + * @param jexpiration_check_date[IN] - This is the date that the QvE will use to determine if any of the inputted collateral have expired + * @return jobject include Status code of the quote verification and quote verification result + * - status code should be one of + * - SGX_QL_SUCCESS + * - SGX_QL_ERROR_INVALID_PARAMETER + * - SGX_QL_QUOTE_FORMAT_UNSUPPORTED + * - SGX_QL_QUOTE_CERTIFICATION_DATA_UNSUPPORTED + * - SGX_QL_UNABLE_TO_GENERATE_REPORT + * - SGX_QL_CRL_UNSUPPORTED_FORMAT + */ +JNIEXPORT jobject JNICALL Java_com_intel_sgx_SgxDcapVerifyQuoteJNI_sgx_1qv_1verify_1quote(JNIEnv *jenv, jobject jobj, jbyteArray quote, + jbyteArray pck_crl, jbyteArray pck_crl_issuer, + jbyteArray qe_identity, + jbyteArray qe_identity_issuer, jbyteArray tcb_info, + jbyteArray tcb_info_issuer, jbyteArray root_ca_crl, + jlong jexpiration_check_date) { + + quote3_error_t dcap_ret = SGX_QL_ERROR_UNEXPECTED; + uint32_t supplemental_data_size = 0; + uint8_t *p_supplemental_data = NULL; + sgx_ql_qve_collateral_t *p_quote_collateral = NULL; + jobject obj_qe_report = NULL; + jobject obj_supplemental = NULL; + char exception_buf[BUFSIZ] = {'\0'}; + + jbyteArray out_platform_instance_id_byte_array = NULL; + jint dynamic_platform = 0; + jint cached_keys = 0; + jint smt_enabled = 0; + + (void)jobj; + if (NULL == qvl_sgx_qv_verify_quote || + NULL == qvl_sgx_qv_get_quote_supplemental_data_size) { + if (load_lib()){ + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to Link Error libsgx_dcap_quoteverify.so"); + return NULL; + } + } + + // critical error quote should not be NULL + if (NULL == quote) { + DCAP_JavaThrowException(jenv, DCAP_JavaIllegalArgumentException, "quote parameter should not be NULL"); + return NULL; + } + // Convert byte array to char array + jbyte *quote_array = (*jenv)->GetByteArrayElements(jenv, quote, NULL); + if (NULL == quote_array) { + return NULL; + } + jsize quote_size = (*jenv)->GetArrayLength(jenv, quote); + + /* + * if any element is NULL, will treat collateral be NULL + *collateral can be NULL, if not NULL should be input for verification + */ + if (NULL != pck_crl && NULL != pck_crl_issuer && NULL != qe_identity && + NULL != qe_identity_issuer && NULL != tcb_info && + NULL != tcb_info_issuer && NULL != root_ca_crl) { + jsize tmp_len = 0; + jbyte *tmp_byte = NULL; + p_quote_collateral = + (sgx_ql_qve_collateral_t *)malloc(sizeof(sgx_ql_qve_collateral_t)); + // hard code to 3, will be input from caller + p_quote_collateral->version = 3; + + tmp_len = (*jenv)->GetArrayLength(jenv, pck_crl); + tmp_byte = (*jenv)->GetByteArrayElements(jenv, pck_crl, NULL); + p_quote_collateral->pck_crl = + (char *)malloc((size_t)tmp_len + 1); // 1 byte for NULL + p_quote_collateral->pck_crl_size = (uint32_t)(tmp_len + 1); + memset(p_quote_collateral->pck_crl, 0,(size_t) tmp_len + 1); + memcpy(p_quote_collateral->pck_crl, tmp_byte, (size_t)tmp_len); + (*jenv)->ReleaseByteArrayElements(jenv, pck_crl, tmp_byte, 0); + + tmp_len = (*jenv)->GetArrayLength(jenv, pck_crl_issuer); + tmp_byte = (*jenv)->GetByteArrayElements(jenv, pck_crl_issuer, NULL); + p_quote_collateral->pck_crl_issuer_chain = + (char *)malloc((size_t)tmp_len + 1); // 1 byte for NULL + p_quote_collateral->pck_crl_issuer_chain_size = (uint32_t)(tmp_len + 1); + memset(p_quote_collateral->pck_crl_issuer_chain, 0, (size_t)tmp_len + 1); + memcpy(p_quote_collateral->pck_crl_issuer_chain, tmp_byte, (size_t)tmp_len); + (*jenv)->ReleaseByteArrayElements(jenv, pck_crl_issuer, tmp_byte, 0); + + tmp_len = (*jenv)->GetArrayLength(jenv, qe_identity); + tmp_byte = (*jenv)->GetByteArrayElements(jenv, qe_identity, NULL); + p_quote_collateral->qe_identity = + (char *)malloc((size_t)tmp_len + 1); // 1 byte for NULL + p_quote_collateral->qe_identity_size = (uint32_t)(tmp_len + 1); + memset(p_quote_collateral->qe_identity, 0, (size_t)tmp_len + 1); + memcpy(p_quote_collateral->qe_identity, tmp_byte, (size_t)tmp_len); + (*jenv)->ReleaseByteArrayElements(jenv, qe_identity, tmp_byte, 0); + + tmp_len = (*jenv)->GetArrayLength(jenv, qe_identity_issuer); + tmp_byte = (*jenv)->GetByteArrayElements(jenv, qe_identity_issuer, NULL); + p_quote_collateral->qe_identity_issuer_chain = + (char *)malloc((size_t)tmp_len + 1); // 1 byte for NULL + p_quote_collateral->qe_identity_issuer_chain_size = (uint32_t)(tmp_len + 1); + memset(p_quote_collateral->qe_identity_issuer_chain, 0, (size_t)tmp_len + 1); + memcpy(p_quote_collateral->qe_identity_issuer_chain, tmp_byte, (size_t)tmp_len); + (*jenv)->ReleaseByteArrayElements(jenv, qe_identity_issuer, tmp_byte, 0); + + tmp_len = (*jenv)->GetArrayLength(jenv, tcb_info); + tmp_byte = (*jenv)->GetByteArrayElements(jenv, tcb_info, NULL); + p_quote_collateral->tcb_info = + (char *)malloc((size_t)tmp_len + 1); // 1 byte for NULL + p_quote_collateral->tcb_info_size = (uint32_t)(tmp_len + 1); + memset(p_quote_collateral->tcb_info, 0, (size_t)tmp_len + 1); + memcpy(p_quote_collateral->tcb_info, tmp_byte, (size_t)tmp_len); + (*jenv)->ReleaseByteArrayElements(jenv, tcb_info, tmp_byte, 0); + + tmp_len = (*jenv)->GetArrayLength(jenv, tcb_info_issuer); + tmp_byte = (*jenv)->GetByteArrayElements(jenv, tcb_info_issuer, NULL); + p_quote_collateral->tcb_info_issuer_chain = + (char *)malloc((size_t)tmp_len + 1); // 1 byte for NULL + p_quote_collateral->tcb_info_issuer_chain_size = (uint32_t)(tmp_len + 1); + memset(p_quote_collateral->tcb_info_issuer_chain, 0, (size_t)tmp_len + 1); + memcpy(p_quote_collateral->tcb_info_issuer_chain, tmp_byte, (size_t)tmp_len); + (*jenv)->ReleaseByteArrayElements(jenv, tcb_info_issuer, tmp_byte, 0); + + tmp_len = (*jenv)->GetArrayLength(jenv, root_ca_crl); + tmp_byte = (*jenv)->GetByteArrayElements(jenv, root_ca_crl, NULL); + p_quote_collateral->root_ca_crl = + (char *)malloc((size_t)tmp_len + 1); // 1 byte for NULL + p_quote_collateral->root_ca_crl_size = (uint32_t)(tmp_len + 1); + memset(p_quote_collateral->root_ca_crl, 0, (size_t)tmp_len + 1); + memcpy(p_quote_collateral->root_ca_crl, tmp_byte, (size_t)tmp_len); + (*jenv)->ReleaseByteArrayElements(jenv, root_ca_crl, tmp_byte, 0); + } + // call DCAP quote verify library to get supplemental data size + // + dcap_ret = qvl_sgx_qv_get_quote_supplemental_data_size(&supplemental_data_size); + if (SGX_QL_SUCCESS == dcap_ret) { + p_supplemental_data = (uint8_t *)malloc(supplemental_data_size); + if (NULL == p_supplemental_data) { + supplemental_data_size = 0; + } + } + + uint32_t collateral_expiration_status; + sgx_ql_qv_result_t quote_verification_result; + + // call sgx_qv_verify_quote from library + quote3_error_t qvl_ret = qvl_sgx_qv_verify_quote( + (const uint8_t *)quote_array, (uint32_t)quote_size, p_quote_collateral, jexpiration_check_date, + &collateral_expiration_status, "e_verification_result, NULL, //p_qve_report_info always is NULL, and always use QVL library to perform quote verfication + supplemental_data_size, p_supplemental_data); + + if (SGX_QL_SUCCESS != qvl_ret) { + if ((*jenv)->ExceptionCheck(jenv)) { + (*jenv)->ExceptionClear(jenv); + /* code to handle exception */ + } + sprintf(exception_buf, "Quote verify failed with 0x%x", qvl_ret); + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, exception_buf); + return NULL; + } + // Get SgxDcapQuoteVerifyResult class + jclass cls_dcap_quote_verify_result = + (*jenv)->FindClass(jenv, "com/intel/sgx/result/SgxDcapQuoteVerifyResult"); + if (NULL == cls_dcap_quote_verify_result) { + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to find class com/intel/sgx/result/SgxDcapQuoteVerifyResult"); + return NULL; + } + // Get the method ID of the constructor of CollateralExpiration class + jmethodID meth_dcap_quote_verify_result_init = (*jenv)->GetMethodID( + jenv, cls_dcap_quote_verify_result, "", "(ILcom/intel/sgx/collateral/CollateralExpiration;Lcom/intel/sgx/result/SgxQlQvResult;Lcom/intel/sgx/report/SgxQlQeReportInfo;Lcom/intel/sgx/supplement/Supplemental;)V"); + if (NULL == meth_dcap_quote_verify_result_init) return NULL; + + // Get CollateralExpiration class + jclass cls_collateral_expiration_status = + (*jenv)->FindClass(jenv, "com/intel/sgx/collateral/CollateralExpiration"); + if (NULL == cls_collateral_expiration_status) { + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to find class com/intel/sgx/collateral/CollateralExpiration"); + return NULL; + } + // Get the method ID of the constructor of CollateralExpiration class + jmethodID meth_collateral_expiration_status_init = (*jenv)->GetMethodID( + jenv, cls_collateral_expiration_status, "", "(I)V"); + if (NULL == meth_collateral_expiration_status_init) { + sprintf(exception_buf, "Can't find function init"); + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, exception_buf); + return NULL; + } + // call back constructor to allocate a new instance + jobject obj_collateral_expiration_status = (*jenv)->NewObject( + jenv, cls_collateral_expiration_status, + meth_collateral_expiration_status_init, collateral_expiration_status); + + // Get SgxQlQvResult class + jclass cls_ql_qv_result = + (*jenv)->FindClass(jenv, "com/intel/sgx/result/SgxQlQvResult"); + if (NULL == cls_ql_qv_result) { + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to find class com/intel/sgx/result/SgxQlQvResult"); + return NULL; + } + // Get the method ID of the constructor of SgxQlQvResult class + jmethodID meth_ql_qv_result_static = (*jenv)->GetStaticMethodID( + jenv, cls_ql_qv_result, "fromStatus", "(I)Lcom/intel/sgx/result/SgxQlQvResult;"); + if (NULL == meth_ql_qv_result_static) { + sprintf(exception_buf, "Can't find function fromStatus"); + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, exception_buf); + return NULL; + } + // call back function to get a new instance + jobject obj_ql_qv_result = (*jenv)->CallStaticObjectMethod( + jenv, cls_ql_qv_result, meth_ql_qv_result_static, + quote_verification_result); + + if (SGX_QL_SUCCESS == qvl_ret && 0 != supplemental_data_size) { + // Get Supplemental class + jclass cls_supplemental = + (*jenv)->FindClass(jenv, "com/intel/sgx/supplement/Supplemental"); + if (NULL == cls_supplemental) { + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to find class com/intel/sgx/supplement/Supplemental"); + return NULL; + } + // Get the method ID of the constructor of Supplemental class + jmethodID meth_supplemental_init = (*jenv)->GetMethodID( + jenv, cls_supplemental, "", + "(SSJJJJIII[B[BLcom/intel/sgx/report/SgxCpuSvn;SSIB[BIIILjava/lang/String;)V"); + if (NULL == meth_supplemental_init) { + sprintf(exception_buf, "Can't find constructor function "); + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, exception_buf); + return NULL; + } + + // Get SgxCpuSvn class + jclass cls_sgx_cpu_svn = + (*jenv)->FindClass(jenv, "com/intel/sgx/report/SgxCpuSvn"); + if (NULL == cls_sgx_cpu_svn) { + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to find class com/intel/sgx/report/SgxCpuSvn"); + return NULL; + } + // get byte array for rootKeyId + jbyteArray out_root_key_id_byte_array = (*jenv)->NewByteArray(jenv, ROOT_KEY_ID_SIZE); + if (NULL == out_root_key_id_byte_array) return NULL; + (*jenv)->SetByteArrayRegion(jenv, out_root_key_id_byte_array, 0, ROOT_KEY_ID_SIZE, (const signed char *)(((sgx_ql_qv_supplemental_t *)p_supplemental_data)->root_key_id)); + + + // get byte array for pck_ppid + jbyteArray out_pck_ppid_byte_array = (*jenv)->NewByteArray(jenv, 16); // 16 bytes for PPID + if (NULL == out_pck_ppid_byte_array) return NULL; + (*jenv)->SetByteArrayRegion(jenv, out_pck_ppid_byte_array, 0, 16, (const signed char *)(((sgx_ql_qv_supplemental_t *)p_supplemental_data)->pck_ppid)); + + // Get the method ID of the constructor of SgxCpuSvn class + jmethodID meth_sgx_cpu_svn_init = + (*jenv)->GetMethodID(jenv, cls_sgx_cpu_svn, "", "([B)V"); + // get byte array for SgxCpuSvn + jbyteArray tmp_cpu_svn_byte_array = (*jenv)->NewByteArray(jenv, SGX_CPUSVN_SIZE); + if (NULL == tmp_cpu_svn_byte_array) return NULL; + (*jenv)->SetByteArrayRegion(jenv, tmp_cpu_svn_byte_array, 0, SGX_CPUSVN_SIZE, (const signed char *)(((sgx_ql_qv_supplemental_t *)p_supplemental_data)->tcb_cpusvn.svn)); + // call back constructor to allocate a new SgxCpuSvn object + jobject obj_sgx_cpu_svn = (*jenv)->NewObject(jenv, cls_sgx_cpu_svn, meth_sgx_cpu_svn_init, tmp_cpu_svn_byte_array); + + + //<sgx_type) == x509_scalable || (((sgx_ql_qv_supplemental_t *)p_supplemental_data)->sgx_type) == x509_scalableWithIntegrity) + { + out_platform_instance_id_byte_array = (*jenv)->NewByteArray(jenv, PLATFORM_INSTANCE_ID_SIZE); + if (NULL == out_platform_instance_id_byte_array) + return NULL; + (*jenv)->SetByteArrayRegion(jenv, out_platform_instance_id_byte_array, 0, PLATFORM_INSTANCE_ID_SIZE, (const signed char *)(((sgx_ql_qv_supplemental_t *)p_supplemental_data)->platform_instance_id)); + dynamic_platform = ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->dynamic_platform; + cached_keys = ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->cached_keys; + smt_enabled = ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->smt_enabled; + } + + //call back constructor of Supplemental class + obj_supplemental = (*jenv)->NewObject(jenv, cls_supplemental, meth_supplemental_init, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->major_version, //tricky code to set version, suppose version less than uint16_t + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->minor_version, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->earliest_issue_date, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->latest_issue_date, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->earliest_expiration_date, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->tcb_level_date_tag, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->pck_crl_num, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->root_ca_crl_num, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->tcb_eval_ref_num, + out_root_key_id_byte_array, + out_pck_ppid_byte_array, + obj_sgx_cpu_svn, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->tcb_pce_isvsvn, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->pce_id, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->tee_type, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->sgx_type, + out_platform_instance_id_byte_array, + dynamic_platform, + cached_keys, + smt_enabled, + NULL // for old api alway return null for sa_list + ); + } + + + // call back constructor to allocate a new instance of SgxDcapQuoteVerifyResult + jobject obj_dcap_quote_verify_result = (*jenv)->NewObject( + jenv, cls_dcap_quote_verify_result, + meth_dcap_quote_verify_result_init, qvl_ret, obj_collateral_expiration_status, obj_ql_qv_result, obj_qe_report, obj_supplemental); + + (*jenv)->ReleaseByteArrayElements(jenv, quote, quote_array, 0); + if (NULL != p_quote_collateral) { + if (NULL != p_quote_collateral->pck_crl) { + free(p_quote_collateral->pck_crl); + } + if (NULL != p_quote_collateral->pck_crl_issuer_chain) { + free(p_quote_collateral->pck_crl_issuer_chain); + } + if (NULL != p_quote_collateral->qe_identity) { + free(p_quote_collateral->qe_identity); + } + if (NULL != p_quote_collateral->qe_identity_issuer_chain) { + free(p_quote_collateral->qe_identity_issuer_chain); + } + if (NULL != p_quote_collateral->tcb_info) { + free(p_quote_collateral->tcb_info); + } + if (NULL != p_quote_collateral->tcb_info_issuer_chain) { + free(p_quote_collateral->tcb_info_issuer_chain); + } + if (NULL != p_quote_collateral->root_ca_crl) { + free(p_quote_collateral->root_ca_crl); + } + free(p_quote_collateral); + } + if (NULL != p_supplemental_data) { + free(p_supplemental_data); + } + return obj_dcap_quote_verify_result; +} + + +/** + * @brief Return collater of quote + * + * @param jenv + * @param jobj + * @param quote + * @return + */ +JNIEXPORT jobject JNICALL Java_com_intel_sgx_SgxDcapVerifyQuoteJNI_tee_1qv_1get_1collateral(JNIEnv *jenv, jobject jobj, jbyteArray quote) +{ + char exception_buf[BUFSIZ] = {'\0'}; + quote3_error_t dcap_ret = SGX_QL_ERROR_UNEXPECTED; + unsigned char * p_quote_collateral = NULL; + uint32_t collateral_size = 0; + uint16_t major_version = 0; + uint16_t minor_version = 0; + jstring pck_crl_issuer_chain; + jstring root_ca_crl; + jstring pck_crl; + jstring tcb_info_issuer_chain; + jstring tcb_info; + jstring qe_identity_issuer_chain; + jstring qe_identity; + + uint32_t tee_type; + + (void)jobj; + // critical error quote should not be NULL + if (NULL == quote) + { + DCAP_JavaThrowException(jenv, DCAP_JavaIllegalArgumentException, "quote parameter should not be NULL"); + return NULL; + } + if (NULL == qvl_tee_qv_get_collateral || NULL == qvl_tee_qv_free_collateral) { + if (load_lib()){ + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to Link Error libsgx_dcap_quoteverify.so"); + return NULL; + } + } + jclass jexceptionCls = (*jenv)->FindClass(jenv, "java/lang/Exception"); + if (NULL == jexceptionCls) { + return NULL; + } + // Convert byte array to char array + jbyte *quote_array = (*jenv)->GetByteArrayElements(jenv, quote, NULL); + if (NULL == quote_array) + { + return NULL; + } + jsize quote_size = (*jenv)->GetArrayLength(jenv, quote); + + // call tee_qv_get_collateral from library + dcap_ret = qvl_tee_qv_get_collateral((const unsigned char *)quote_array, (uint32_t)quote_size, &p_quote_collateral, + &collateral_size); + if (SGX_QL_SUCCESS != dcap_ret && NULL != p_quote_collateral) { + if ((*jenv)->ExceptionCheck(jenv)) { + (*jenv)->ExceptionClear(jenv); + /* code to handle exception */ + } + sprintf(exception_buf, "Get supplement data failed with 0x%x", dcap_ret); + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, exception_buf); + return NULL; + } + + // Get Collateral class + jclass cls_collateral = + (*jenv)->FindClass(jenv, "com/intel/sgx/collateral/Collateral"); + if (NULL == cls_collateral) { + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to find class com/intel/sgx/collateral/Collateral"); + return NULL; + } + // Get the method ID of the constructor of CollateralExpiration class + jmethodID meth_collateral_init = (*jenv)->GetMethodID( + jenv, cls_collateral, "", "(SSILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + if (NULL == meth_collateral_init) return NULL; + + sgx_ql_qve_collateral_t* p_sgx_collateral = NULL; + + p_sgx_collateral = (sgx_ql_qve_collateral_t*)p_quote_collateral; + + if(p_sgx_collateral->version >= 3){ + // suppose the version should no never more than uint16 + major_version = p_sgx_collateral->major_version; + minor_version = p_sgx_collateral->minor_version;; + }else{ + // if version less than 3, the minor version should be 0 + // a little trick here, the version suppose no more than 2^15, then is safe to convert to uint16_t + major_version = (uint16_t)(p_sgx_collateral->version); + minor_version = 0; + } + tee_type = p_sgx_collateral->tee_type; + pck_crl_issuer_chain = (*jenv)->NewStringUTF(jenv, p_sgx_collateral->pck_crl_issuer_chain); + root_ca_crl= (*jenv)->NewStringUTF(jenv, p_sgx_collateral->root_ca_crl); + pck_crl = (*jenv)->NewStringUTF(jenv, p_sgx_collateral->pck_crl); + tcb_info = (*jenv)->NewStringUTF(jenv, p_sgx_collateral->tcb_info); + qe_identity_issuer_chain = (*jenv)->NewStringUTF(jenv, p_sgx_collateral->qe_identity_issuer_chain); + qe_identity = (*jenv)->NewStringUTF(jenv, p_sgx_collateral->qe_identity); + tcb_info_issuer_chain = (*jenv)->NewStringUTF(jenv, p_sgx_collateral->tcb_info_issuer_chain); + + // call back constructor to allocate a new instance of Collateral + jobject obj_collateral = (*jenv)->NewObject( + jenv, cls_collateral, + meth_collateral_init, major_version, minor_version, tee_type, pck_crl_issuer_chain, root_ca_crl, pck_crl, tcb_info_issuer_chain, tcb_info, qe_identity_issuer_chain, qe_identity); + // clean up + qvl_tee_qv_free_collateral(p_quote_collateral); + return obj_collateral; +} + +/** + * @brief Perform ECDSA quote verification + * + * @param jenv + * @param jobj + * @param quote + * @param pck_crl + * @param pck_crl_issuer + * @param qe_identity + * @param qe_identity_issuer + * @param tcb_info + * @param tcb_info_issuer + * @param root_ca_crl + * @param jexpiration_check_date + * @param suppl_version + * @param suppl_size + * @return jobject include Status code of the quote verification and quote verification result + * - status code should be one of + * - SGX_QL_SUCCESS + * - SGX_QL_ERROR_INVALID_PARAMETER + * - SGX_QL_QUOTE_FORMAT_UNSUPPORTED + * - SGX_QL_QUOTE_CERTIFICATION_DATA_UNSUPPORTED + * - SGX_QL_UNABLE_TO_GENERATE_REPORT + * - SGX_QL_CRL_UNSUPPORTED_FORMAT + */ +JNIEXPORT jobject JNICALL Java_com_intel_sgx_SgxDcapVerifyQuoteJNI_tee_1verify_1quote(JNIEnv *jenv, jobject jobj, jbyteArray quote, + jbyteArray pck_crl, jbyteArray pck_crl_issuer, + jbyteArray qe_identity, + jbyteArray qe_identity_issuer, jbyteArray tcb_info, + jbyteArray tcb_info_issuer, jbyteArray root_ca_crl, + jlong jexpiration_check_date, jshort suppl_version, jint suppl_size) + { + char exception_buf[BUFSIZ] = {'\0'}; + + quote3_error_t dcap_ret = SGX_QL_ERROR_UNEXPECTED; + uint8_t *p_supplemental_data = NULL; + sgx_ql_qve_collateral_t *p_quote_collateral = NULL; + jobject obj_qe_report = NULL; + jobject obj_supplemental = NULL; + uint32_t latest_suppl_version = 0; + uint32_t latest_suppl_size = 0; + jstring sa_list= NULL; + jbyteArray out_platform_instance_id_byte_array = NULL; + jint dynamic_platform = 0; + jint cached_keys = 0; + jint smt_enabled = 0; + + (void)jobj; + if (NULL == qvl_sgx_qv_verify_quote || + NULL == qvl_sgx_qv_get_quote_supplemental_data_size) { + if (load_lib()){ + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to Link Error libsgx_dcap_quoteverify.so"); + return NULL; + } + } + jclass jexceptionCls = (*jenv)->FindClass(jenv, "java/lang/Exception"); + if (NULL == jexceptionCls) { + return NULL; + } + + // critical error quote should not be NULL + if (NULL == quote) { + DCAP_JavaThrowException(jenv, DCAP_JavaIllegalArgumentException, "quote parameter should not be NULL"); + return NULL; + } + // Convert byte array to char array + jbyte *quote_array = (*jenv)->GetByteArrayElements(jenv, quote, NULL); + if (NULL == quote_array) { + return NULL; + } + jsize quote_size = (*jenv)->GetArrayLength(jenv, quote); + + /* + * if any element is NULL, will treat collateral be NULL + *collateral can be NULL, if not NULL should be input for verification + */ + if (NULL != pck_crl && NULL != pck_crl_issuer && NULL != qe_identity && + NULL != qe_identity_issuer && NULL != tcb_info && + NULL != tcb_info_issuer && NULL != root_ca_crl) { + jsize tmp_len = 0; + jbyte *tmp_byte = NULL; + p_quote_collateral = + (sgx_ql_qve_collateral_t *)malloc(sizeof(sgx_ql_qve_collateral_t)); + // hard code to 3, will be input from caller + p_quote_collateral->version = 3; + + tmp_len = (*jenv)->GetArrayLength(jenv, pck_crl); + tmp_byte = (*jenv)->GetByteArrayElements(jenv, pck_crl, NULL); + p_quote_collateral->pck_crl = + (char *)malloc((size_t)tmp_len + 1); // 1 byte for NULL + p_quote_collateral->pck_crl_size = (uint32_t)(tmp_len + 1); + memset(p_quote_collateral->pck_crl, 0, (size_t)tmp_len + 1); + memcpy(p_quote_collateral->pck_crl, tmp_byte, (size_t)tmp_len); + (*jenv)->ReleaseByteArrayElements(jenv, pck_crl, tmp_byte, 0); + + tmp_len = (*jenv)->GetArrayLength(jenv, pck_crl_issuer); + tmp_byte = (*jenv)->GetByteArrayElements(jenv, pck_crl_issuer, NULL); + p_quote_collateral->pck_crl_issuer_chain = + (char *)malloc((size_t)tmp_len + 1); // 1 byte for NULL + p_quote_collateral->pck_crl_issuer_chain_size = (uint32_t)(tmp_len + 1); + memset(p_quote_collateral->pck_crl_issuer_chain, 0, (size_t)tmp_len + 1); + memcpy(p_quote_collateral->pck_crl_issuer_chain, tmp_byte, (size_t)tmp_len); + (*jenv)->ReleaseByteArrayElements(jenv, pck_crl_issuer, tmp_byte, 0); + + tmp_len = (*jenv)->GetArrayLength(jenv, qe_identity); + tmp_byte = (*jenv)->GetByteArrayElements(jenv, qe_identity, NULL); + p_quote_collateral->qe_identity = + (char *)malloc((size_t)tmp_len + 1); // 1 byte for NULL + p_quote_collateral->qe_identity_size = (uint32_t)(tmp_len + 1); + memset(p_quote_collateral->qe_identity, 0, (size_t)tmp_len + 1); + memcpy(p_quote_collateral->qe_identity, tmp_byte, (size_t)tmp_len); + (*jenv)->ReleaseByteArrayElements(jenv, qe_identity, tmp_byte, 0); + + tmp_len = (*jenv)->GetArrayLength(jenv, qe_identity_issuer); + tmp_byte = (*jenv)->GetByteArrayElements(jenv, qe_identity_issuer, NULL); + p_quote_collateral->qe_identity_issuer_chain = + (char *)malloc((size_t)tmp_len + 1); // 1 byte for NULL + p_quote_collateral->qe_identity_issuer_chain_size = (uint32_t)(tmp_len + 1); + memset(p_quote_collateral->qe_identity_issuer_chain, 0, (size_t)tmp_len + 1); + memcpy(p_quote_collateral->qe_identity_issuer_chain, tmp_byte, (size_t)tmp_len); + (*jenv)->ReleaseByteArrayElements(jenv, qe_identity_issuer, tmp_byte, 0); + + tmp_len = (*jenv)->GetArrayLength(jenv, tcb_info); + tmp_byte = (*jenv)->GetByteArrayElements(jenv, tcb_info, NULL); + p_quote_collateral->tcb_info = + (char *)malloc((size_t)tmp_len + 1); // 1 byte for NULL + p_quote_collateral->tcb_info_size = (uint32_t)(tmp_len + 1); + memset(p_quote_collateral->tcb_info, 0, (size_t)tmp_len + 1); + memcpy(p_quote_collateral->tcb_info, tmp_byte, (size_t)tmp_len); + (*jenv)->ReleaseByteArrayElements(jenv, tcb_info, tmp_byte, 0); + + tmp_len = (*jenv)->GetArrayLength(jenv, tcb_info_issuer); + tmp_byte = (*jenv)->GetByteArrayElements(jenv, tcb_info_issuer, NULL); + p_quote_collateral->tcb_info_issuer_chain = + (char *)malloc((size_t)tmp_len + 1); // 1 byte for NULL + p_quote_collateral->tcb_info_issuer_chain_size = (uint32_t)(tmp_len + 1); + memset(p_quote_collateral->tcb_info_issuer_chain, 0, (size_t)tmp_len + 1); + memcpy(p_quote_collateral->tcb_info_issuer_chain, tmp_byte, (size_t)tmp_len); + (*jenv)->ReleaseByteArrayElements(jenv, tcb_info_issuer, tmp_byte, 0); + + tmp_len = (*jenv)->GetArrayLength(jenv, root_ca_crl); + tmp_byte = (*jenv)->GetByteArrayElements(jenv, root_ca_crl, NULL); + p_quote_collateral->root_ca_crl = + (char *)malloc((size_t)tmp_len + 1); // 1 byte for NULL + p_quote_collateral->root_ca_crl_size = (uint32_t)(tmp_len + 1); + memset(p_quote_collateral->root_ca_crl, 0, (size_t)tmp_len + 1); + memcpy(p_quote_collateral->root_ca_crl, tmp_byte, (size_t)tmp_len); + (*jenv)->ReleaseByteArrayElements(jenv, root_ca_crl, tmp_byte, 0); + } + // call DCAP quote verify library to get supplemental data size and version + // + dcap_ret =tee_get_supplemental_data_version_and_size((const unsigned char *)quote_array, (uint32_t)quote_size, &latest_suppl_version, &latest_suppl_size); + if (SGX_QL_SUCCESS == dcap_ret) { + if((suppl_version == 0 || (uint32_t)suppl_version == latest_suppl_version) && (uint32_t)suppl_size == latest_suppl_size) + p_supplemental_data = (uint8_t *)malloc(latest_suppl_size); + if (NULL == p_supplemental_data) { + latest_suppl_size = 0; + } + }else { + //something worng and unable to get supplement data size and version + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to get supplement data size and verson"); + return NULL; + } + + uint32_t collateral_expiration_status; + sgx_ql_qv_result_t quote_verification_result; + + // call sgx_qv_verify_quote from library + quote3_error_t qvl_ret = qvl_sgx_qv_verify_quote( + (const unsigned char *)quote_array, (unsigned int)quote_size, p_quote_collateral, jexpiration_check_date, + &collateral_expiration_status, "e_verification_result, NULL, //p_qve_report_info always is NULL, and always use QVL library to perform quote verfication + latest_suppl_size, p_supplemental_data); + + if (SGX_QL_SUCCESS != qvl_ret) { + if ((*jenv)->ExceptionCheck(jenv)) { + (*jenv)->ExceptionClear(jenv); + /* code to handle exception */ + } + sprintf(exception_buf, "Quote verify failed with 0x%x", qvl_ret); + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, exception_buf ); + return NULL; + } + // Get SgxDcapQuoteVerifyResult class + jclass cls_tee_dcap_quote_verify_result = + (*jenv)->FindClass(jenv, "com/intel/sgx/result/TeeDcapQuoteVerifyResult"); + if (NULL == cls_tee_dcap_quote_verify_result) { + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to find class com/intel/sgx/result/TeeDcapQuoteVerifyResult"); + return NULL; + } + // Get the method ID of the constructor of CollateralExpiration class + jmethodID meth_tee_dcap_quote_verify_result_init = (*jenv)->GetMethodID( + jenv, cls_tee_dcap_quote_verify_result, "", "(ILcom/intel/sgx/collateral/CollateralExpiration;Lcom/intel/sgx/result/SgxQlQvResult;Lcom/intel/sgx/report/SgxQlQeReportInfo;Lcom/intel/sgx/supplement/TeeSupplemental;)V"); + if (NULL == meth_tee_dcap_quote_verify_result_init) return NULL; + + // Get CollateralExpiration class + jclass cls_collateral_expiration_status = + (*jenv)->FindClass(jenv, "com/intel/sgx/collateral/CollateralExpiration"); + if (NULL == cls_collateral_expiration_status) { + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to find class com/intel/sgx/collateral/CollateralExpiration"); + return NULL; + } + // Get the method ID of the constructor of CollateralExpiration class + jmethodID meth_collateral_expiration_status_init = (*jenv)->GetMethodID( + jenv, cls_collateral_expiration_status, "", "(I)V"); + if (NULL == meth_collateral_expiration_status_init) { + sprintf(exception_buf, "Can't find function init"); + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, exception_buf); + return NULL; + } + // call back constructor to allocate a new instance + jobject obj_collateral_expiration_status = (*jenv)->NewObject( + jenv, cls_collateral_expiration_status, + meth_collateral_expiration_status_init, collateral_expiration_status); + + // Get SgxQlQvResult class + jclass cls_ql_qv_result = + (*jenv)->FindClass(jenv, "com/intel/sgx/result/SgxQlQvResult"); + if (NULL == cls_ql_qv_result) { + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to find class com/intel/sgx/result/SgxQlQvResult"); + return NULL; + } + // Get the method ID of the constructor of SgxQlQvResult class + jmethodID meth_ql_qv_result_static = (*jenv)->GetStaticMethodID( + jenv, cls_ql_qv_result, "fromStatus", "(I)Lcom/intel/sgx/result/SgxQlQvResult;"); + if (NULL == meth_ql_qv_result_static) { + sprintf(exception_buf, "Can't find function fromStatus"); + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, exception_buf); + return NULL; + } + // call back function to get a new instance + jobject obj_ql_qv_result = (*jenv)->CallStaticObjectMethod( + jenv, cls_ql_qv_result, meth_ql_qv_result_static, + quote_verification_result); + + if (SGX_QL_SUCCESS == qvl_ret && 0 != latest_suppl_size) { + // Get Supplemental class + jclass cls_supplemental = + (*jenv)->FindClass(jenv, "com/intel/sgx/supplement/Supplemental"); + if (NULL == cls_supplemental) { + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to find class com/intel/sgx/supplement/Supplemental"); + return NULL; + } + // Get the method ID of the constructor of Supplemental class + jmethodID meth_supplemental_init = (*jenv)->GetMethodID( + jenv, cls_supplemental, "", + "(SSJJJJIII[B[BLcom/intel/sgx/report/SgxCpuSvn;SSIB[BIIILjava/lang/String;)V"); + if (NULL == meth_supplemental_init) { + sprintf(exception_buf, "Can't find constructor function "); + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, exception_buf); + return NULL; + } + + // Get SgxCpuSvn class + jclass cls_sgx_cpu_svn = + (*jenv)->FindClass(jenv, "com/intel/sgx/report/SgxCpuSvn"); + if (NULL == cls_sgx_cpu_svn) { + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "com/intel/sgx/report/SgxCpuSvn"); + return NULL; + } + // get byte array for rootKeyId + jbyteArray out_root_key_id_byte_array = (*jenv)->NewByteArray(jenv, ROOT_KEY_ID_SIZE); + if (NULL == out_root_key_id_byte_array) return NULL; + (*jenv)->SetByteArrayRegion(jenv, out_root_key_id_byte_array, 0, ROOT_KEY_ID_SIZE, (const signed char *)(((sgx_ql_qv_supplemental_t *)p_supplemental_data)->root_key_id)); + + + // get byte array for pck_ppid + jbyteArray out_pck_ppid_byte_array = (*jenv)->NewByteArray(jenv, 16); // 16 bytes for PPID + if (NULL == out_pck_ppid_byte_array) return NULL; + (*jenv)->SetByteArrayRegion(jenv, out_pck_ppid_byte_array, 0, 16, (const signed char *)(((sgx_ql_qv_supplemental_t *)p_supplemental_data)->pck_ppid)); + + // Get the method ID of the constructor of SgxCpuSvn class + jmethodID meth_sgx_cpu_svn_init = + (*jenv)->GetMethodID(jenv, cls_sgx_cpu_svn, "", "([B)V"); + // get byte array for SgxCpuSvn + jbyteArray tmp_cpu_svn_byte_array = (*jenv)->NewByteArray(jenv, SGX_CPUSVN_SIZE); + if (NULL == tmp_cpu_svn_byte_array) return NULL; + (*jenv)->SetByteArrayRegion(jenv, tmp_cpu_svn_byte_array, 0, SGX_CPUSVN_SIZE, (const signed char *)(((sgx_ql_qv_supplemental_t *)p_supplemental_data)->tcb_cpusvn.svn)); + // call back constructor to allocate a new SgxCpuSvn object + jobject obj_sgx_cpu_svn = (*jenv)->NewObject(jenv, cls_sgx_cpu_svn, meth_sgx_cpu_svn_init, tmp_cpu_svn_byte_array); + + //<sgx_type) == x509_scalable || (((sgx_ql_qv_supplemental_t *)p_supplemental_data)->sgx_type) == x509_scalableWithIntegrity) + { + out_platform_instance_id_byte_array = (*jenv)->NewByteArray(jenv, PLATFORM_INSTANCE_ID_SIZE); + if (NULL == out_platform_instance_id_byte_array) + return NULL; + (*jenv)->SetByteArrayRegion(jenv, out_platform_instance_id_byte_array, 0, PLATFORM_INSTANCE_ID_SIZE, (const signed char *)(((sgx_ql_qv_supplemental_t *)p_supplemental_data)->platform_instance_id)); + dynamic_platform = ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->dynamic_platform; + cached_keys = ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->cached_keys; + smt_enabled = ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->smt_enabled; + } + + //get sa_list + if(NULL != ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->sa_list){ + sa_list = (*jenv)->NewStringUTF(jenv, ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->sa_list); + } + //call back constructor of Supplemental class + obj_supplemental = (*jenv)->NewObject(jenv, cls_supplemental, meth_supplemental_init, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->major_version, //tricky code to set version, suppose version less than uint16_t + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->minor_version, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->earliest_issue_date, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->latest_issue_date, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->earliest_expiration_date, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->tcb_level_date_tag, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->pck_crl_num, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->root_ca_crl_num, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->tcb_eval_ref_num, + out_root_key_id_byte_array, + out_pck_ppid_byte_array, + obj_sgx_cpu_svn, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->tcb_pce_isvsvn, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->pce_id, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->tee_type, + ((sgx_ql_qv_supplemental_t *)p_supplemental_data)->sgx_type, + out_platform_instance_id_byte_array, + dynamic_platform, + cached_keys, + smt_enabled, + sa_list + ); + } + + + // Get Supplemental class + jclass cls_tee_supplemental = + (*jenv)->FindClass(jenv, "com/intel/sgx/supplement/TeeSupplemental"); + if (NULL == cls_tee_supplemental) { + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "com/intel/sgx/supplement/TeeSupplemental"); + return NULL; + } + // Get the method ID of the constructor of Supplemental class + jmethodID meth_tee_supplemental_init = (*jenv)->GetMethodID( + jenv, cls_tee_supplemental, "", + "(SLcom/intel/sgx/supplement/Supplemental;)V"); + if (NULL == meth_tee_supplemental_init) { + sprintf(exception_buf, "Can't find constructor function "); + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, exception_buf); + return NULL; + } + jobject obj_tee_supplemental = (*jenv)->NewObject(jenv, cls_tee_supplemental, meth_tee_supplemental_init, (uint16_t)latest_suppl_version, obj_supplemental); + + // call back constructor to allocate a new instance of SgxDcapQuoteVerifyResult + jobject obj_dcap_quote_verify_result = (*jenv)->NewObject( + jenv, cls_tee_dcap_quote_verify_result, + meth_tee_dcap_quote_verify_result_init, qvl_ret, obj_collateral_expiration_status, obj_ql_qv_result, obj_qe_report, obj_tee_supplemental); + + (*jenv)->ReleaseByteArrayElements(jenv, quote, quote_array, 0); + if (NULL != p_quote_collateral) { + if (NULL != p_quote_collateral->pck_crl) { + free(p_quote_collateral->pck_crl); + } + if (NULL != p_quote_collateral->pck_crl_issuer_chain) { + free(p_quote_collateral->pck_crl_issuer_chain); + } + if (NULL != p_quote_collateral->qe_identity) { + free(p_quote_collateral->qe_identity); + } + if (NULL != p_quote_collateral->qe_identity_issuer_chain) { + free(p_quote_collateral->qe_identity_issuer_chain); + } + if (NULL != p_quote_collateral->tcb_info) { + free(p_quote_collateral->tcb_info); + } + if (NULL != p_quote_collateral->tcb_info_issuer_chain) { + free(p_quote_collateral->tcb_info_issuer_chain); + } + if (NULL != p_quote_collateral->root_ca_crl) { + free(p_quote_collateral->root_ca_crl); + } + free(p_quote_collateral); + } + if (NULL != p_supplemental_data) { + free(p_supplemental_data); + } + return obj_dcap_quote_verify_result; +} + + +JNIEXPORT jobject JNICALL Java_com_intel_sgx_SgxDcapVerifyQuoteJNI_tee_1get_1supplemental_1data_1version_1and_1size(JNIEnv *jenv, jobject jobj, jbyteArray quote) +{ + char exception_buf[BUFSIZ] = {'\0'}; + + quote3_error_t dcap_ret = SGX_QL_ERROR_UNEXPECTED; + uint32_t supplemental_data_size = 0; + uint32_t supplemental_data_version = 0; + + (void)jobj; + if (NULL == qvl_tee_get_supplemental_data_version_and_size) { + if (load_lib()){ + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to Link Error libsgx_dcap_quoteverify.so"); + return NULL; + } + } + jclass jexceptionCls = (*jenv)->FindClass(jenv, "java/lang/Exception"); + if (NULL == jexceptionCls) { + return NULL; + } + + // critical error quote should not be NULL + if (NULL == quote) { + DCAP_JavaThrowException(jenv, DCAP_JavaIllegalArgumentException, "quote parameter should not be NULL"); + return NULL; + } + // Convert byte array to char array + jbyte *quote_array = (*jenv)->GetByteArrayElements(jenv, quote, NULL); + if (NULL == quote_array) { + return NULL; + } + jsize quote_size = (*jenv)->GetArrayLength(jenv, quote); + + // call tee_get_supplemental_data_version_and_size to get size and version + dcap_ret = qvl_tee_get_supplemental_data_version_and_size((const uint8_t *)quote_array, (uint32_t)quote_size, &supplemental_data_version, &supplemental_data_size); + if (SGX_QL_SUCCESS != dcap_ret) { + if ((*jenv)->ExceptionCheck(jenv)) { + (*jenv)->ExceptionClear(jenv); + /* code to handle exception */ + } + sprintf(exception_buf, "Get supplement data failed with 0x%x", dcap_ret); + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, exception_buf); + return NULL; + } + + // Get supplementalResult class + jclass cls_supplementResult = + (*jenv)->FindClass(jenv, "com/intel/sgx/result/supplementalResult"); + if (NULL == cls_supplementResult) { + DCAP_JavaThrowException(jenv, DCAP_JavaRuntimeException, "Unable to find class com/intel/sgx/result/supplementalResult"); + return NULL; + } + // Get the method ID of the constructor of CollateralExpiration class + jmethodID meth_supplementResult_init = (*jenv)->GetMethodID( + jenv, cls_supplementResult, "", "(II)V"); + if (NULL == meth_supplementResult_init) return NULL; + // call back constructor to allocate a new instance of Collateral + jobject obj_supplementResult = (*jenv)->NewObject( + jenv, cls_supplementResult, + meth_supplementResult_init, supplemental_data_version, supplemental_data_size); + + return obj_supplementResult; +} +#ifdef __cplusplus +} +#endif diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/Demo.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/Demo.java new file mode 100644 index 00000000..a855b16e --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/Demo.java @@ -0,0 +1,85 @@ +/* + * 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. + * + */ + +package com.intel.sgx; + +import com.intel.sgx.collateral.Collateral; +import com.intel.sgx.result.SgxDcapQuoteVerifyResult; +import com.intel.sgx.result.TeeDcapQuoteVerifyResult; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import net.sourceforge.argparse4j.ArgumentParsers; +import net.sourceforge.argparse4j.impl.Arguments; +import net.sourceforge.argparse4j.inf.ArgumentParser; +import net.sourceforge.argparse4j.inf.ArgumentParserException; +import net.sourceforge.argparse4j.inf.Namespace; + +/** + * Demo for do quote verification and get quote collateral + * + */ +public class Demo { + public static void main(String[] args) throws IOException { + byte[] quoteBytes = null; + + ArgumentParser parser = + ArgumentParsers.newFor("Demo").build().defaultHelp(true); + parser.addArgument("-q", "--quote") + .required(true) + .type(Arguments.fileType().acceptSystemIn().verifyCanRead()) + .help("Please specify quote path to do verify"); + try { + Namespace ns = parser.parseArgs(args); + File quote = ns.get("quote"); + quoteBytes = Files.readAllBytes(quote.toPath()); + } catch (ArgumentParserException e) { + parser.handleError(e); + } + SgxDcapVerifyQuoteJNI Verifer = new SgxDcapVerifyQuoteJNI(); + + SgxDcapQuoteVerifyResult result = Verifer.sgxQvVerifyQuote(quoteBytes); + System.out.println("verify result is " + result.getVerifyResult()); + if (result.getSupplement() != null) { + byte[] cpu_svn = result.getSupplement().getTcb_cpusvn().getSvn(); + for (int i = 0; i < cpu_svn.length; i++) { + System.out.print(cpu_svn[i] + " "); + } + } + + Collateral collat = Verifer.teeQvGetCollateral(quoteBytes); + System.out.print(collat.toString()); + TeeDcapQuoteVerifyResult teeReult = Verifer.tee_verify_quote(quoteBytes, (short) 3, 0); + System.out.print(teeReult.getSupplement().toString()); + + } +} diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/SgxDcapVerifyQuoteJNI.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/SgxDcapVerifyQuoteJNI.java new file mode 100644 index 00000000..5246675a --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/SgxDcapVerifyQuoteJNI.java @@ -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. + * + */ + + +package com.intel.sgx; + + +import com.intel.sgx.identity.QveIdentity; +import com.intel.sgx.result.SgxDcapQuoteVerifyResult; +import com.intel.sgx.result.TeeDcapQuoteVerifyResult; +import com.intel.sgx.result.supplementalResult; +import com.intel.sgx.collateral.Collateral; + + +public class SgxDcapVerifyQuoteJNI { + + public SgxDcapVerifyQuoteJNI() {} + + + public QveIdentity sgxQvGetQveIdentity() { + QveIdentity qveidentity = sgx_qv_get_qve_identity(); + return qveidentity; + } + + + public int sgxQvSetPath(int type, String path) { + return sgx_qv_set_path(type, path); + } + + public int sgxQvSetEnclaveLoadPolicy(int policy) { + return sgx_qv_set_enclave_load_policy(policy); + } + + + public SgxDcapQuoteVerifyResult sgxQvVerifyQuote(byte[] quoteBytes) { + long expireTime = System.currentTimeMillis() / 1000; + return sgxQvVerifyQuote(quoteBytes, expireTime); + } + + public SgxDcapQuoteVerifyResult sgxQvVerifyQuote(byte[] quoteFilePath, long expireTime) { + return sgxQvVerifyQuote(quoteFilePath, null, null, null, null, null, + null, null, expireTime); + } + public SgxDcapQuoteVerifyResult sgxQvVerifyQuote(byte[] quoteBytes, byte[] pckBytes, + byte[] pckIssuerBytes, byte[] tcbBytes, + byte[] tcbIssuerBytes, + byte[] qeIdentityBytes, + byte[] qeIdentityIssuerBytes, + byte[] rootCaBytes, long expirationData) { + return sgx_qv_verify_quote( + quoteBytes, pckBytes, pckIssuerBytes, tcbBytes, tcbIssuerBytes, + qeIdentityBytes, qeIdentityIssuerBytes, rootCaBytes, expirationData); + } + + public TeeDcapQuoteVerifyResult tee_verify_quote(byte[] quoteBytes) { + long expireTime = System.currentTimeMillis() / 1000; + short default_version = 0; + int default_suppl_size = 0; + return tee_verify_quote(quoteBytes, expireTime, default_version, default_suppl_size); + } + + public TeeDcapQuoteVerifyResult tee_verify_quote(byte[] quoteBytes, short version, int suppl_size) { + long expireTime = System.currentTimeMillis() / 1000; + return tee_verify_quote(quoteBytes, expireTime, version, suppl_size); + } + + public TeeDcapQuoteVerifyResult tee_verify_quote(byte[] quoteBytes, long expireTime, short version, int suppl_size) { + return tee_verify_quote(quoteBytes, null, null, null, null, null, + null, null, expireTime, version, suppl_size); + } + + public Collateral teeQvGetCollateral(byte[] quoteBytes) { + return tee_qv_get_collateral(quoteBytes); + } + + static { + + try { + System.loadLibrary("jni_dcap_quoteverify"); + } catch (UnsatisfiedLinkError e) { + e.printStackTrace(); + System.exit(0); + } + } + + private native SgxDcapQuoteVerifyResult sgx_qv_verify_quote( + byte[] quote, byte[] pckfile, byte[] pckissuer, byte[] tcb, + byte[] tcbissuer, byte[] qeIdentity, byte[] qeIdentityissuer, + byte[] rootCA, long expirationData); + + private native QveIdentity sgx_qv_get_qve_identity(); + + private native int sgx_qv_set_path(int type, String path); + + private native int sgx_qv_set_enclave_load_policy(int policy); + + private native Collateral tee_qv_get_collateral(byte[] quote); + + private native TeeDcapQuoteVerifyResult tee_verify_quote( + byte[] quote, byte[] pckfile, byte[] pckissuer, byte[] tcb, + byte[] tcbissuer, byte[] qeIdentity, byte[] qeIdentityissuer, + byte[] rootCA, long expirationData, short version, int suppl_size); + + private native supplementalResult tee_get_supplemental_data_version_and_size(byte[] quote); +} diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/collateral/Collateral.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/collateral/Collateral.java new file mode 100644 index 00000000..ddadc2e6 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/collateral/Collateral.java @@ -0,0 +1,124 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.collateral; + +public class Collateral{ + private short major_version; + private short minor_version; + private int tee_type; + + private String pck_crl_issuer_chain; +// int pck_crl_issuer_chain_size; + + private String root_ca_crl; +// int root_ca_crl_size; + + private String pck_crl; +// int pck_crl_size; + + private String tcb_info_issuer_chain; +// int tcb_info_issuer_chain_size; + + private String tcb_info; +// int tcb_info_size; + + private String qe_identity_issuer_chain; +// int qe_identity_issuer_chain_size; + + private String qe_identity; +// int qe_identity_size; + + public Collateral(short major_version, short minor_version, int tee_type, String pck_crl_issuer_chain, + String root_ca_crl, String pck_crl, String tcb_info_issuer_chain, String tcb_info, + String qe_identity_issuer_chain, String qe_identity) { + this.major_version = major_version; + this.minor_version = minor_version; + this.tee_type = tee_type; + this.pck_crl_issuer_chain = pck_crl_issuer_chain; + this.root_ca_crl = root_ca_crl; + this.pck_crl = pck_crl; + this.tcb_info_issuer_chain = tcb_info_issuer_chain; + this.tcb_info = tcb_info; + this.qe_identity_issuer_chain = qe_identity_issuer_chain; + this.qe_identity = qe_identity; + } + + public short getMajor_version() { + return major_version; + } + + public short getMinor_version() { + return minor_version; + } + + public String getPck_crl() { + return pck_crl; + } + + public String getPck_crl_issuer_chain() { + return pck_crl_issuer_chain; + } + + public String getQe_identity() { + return qe_identity; + } + + public String getQe_identity_issuer_chain() { + return qe_identity_issuer_chain; + } + + public String getRoot_ca_crl() { + return root_ca_crl; + } + + public String getTcb_info() { + return tcb_info; + } + + public String getTcb_info_issuer_chain() { + return tcb_info_issuer_chain; + } + + public int getTee_type() { + return tee_type; + } + + @Override + public String toString() { + return "Collateral [major_version=" + major_version + ", minor_version=" + minor_version + ", tee_type=" + + tee_type + ", pck_crl_issuer_chain=" + pck_crl_issuer_chain + ", root_ca_crl=" + root_ca_crl + + ", pck_crl=" + pck_crl + ", tcb_info_issuer_chain=" + tcb_info_issuer_chain + ", tcb_info=" + tcb_info + + ", qe_identity_issuer_chain=" + qe_identity_issuer_chain + ", qe_identity=" + qe_identity + "]"; + } + +} diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/collateral/CollateralExpiration.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/collateral/CollateralExpiration.java new file mode 100644 index 00000000..ef4437b8 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/collateral/CollateralExpiration.java @@ -0,0 +1,48 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.collateral; + +public class CollateralExpiration{ + private int status; + public CollateralExpiration(int status) { + this.status = status; + } + public int getData() { + return this.status; + } + public void setData(int data){ + this.status = data; + return; + } +} + diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/identity/QveIdentity.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/identity/QveIdentity.java new file mode 100644 index 00000000..92f11460 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/identity/QveIdentity.java @@ -0,0 +1,90 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.identity; +/** + * + */ +public class QveIdentity { + + /** + * + */ + private byte[] identity; + + /** + * + */ + private byte[] issueChain; + + /** + * + */ + private byte[] rootCACrl; + + /** + * Default constructor + */ + public QveIdentity() { + } + + public QveIdentity(byte[] identity, byte[] issueChain, byte[] rootCACrl) { + this.identity = identity; + this.issueChain = issueChain; + this.rootCACrl = rootCACrl; + } + + public byte[] getIdentity() { + return identity; + } + + public byte[] getIssueChain() { + return issueChain; + } + + public byte[] getRootCACrl() { + return rootCACrl; + } + + public void setIdentity(byte[] identity) { + this.identity = identity; + } + + public void setIssueChain(byte[] issueChain) { + this.issueChain = issueChain; + } + + public void setRootCACrl(byte[] rootCACrl) { + this.rootCACrl = rootCACrl; + } + +} diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/libInfo/verifyLibInfo.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/libInfo/verifyLibInfo.java new file mode 100644 index 00000000..f5d31c27 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/libInfo/verifyLibInfo.java @@ -0,0 +1,62 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.libInfo; + +public class verifyLibInfo { + + private String path; + private int libType; + + + + public verifyLibInfo(String path, int libType) { + this.path = path; + this.libType = libType; + } + + public int getLibType() { + return libType; + } + + public String getPath() { + return path; + } + + public void setLibType(int libType) { + this.libType = libType; + } + + public void setPath(String path) { + this.path = path; + } +} diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxAttributes.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxAttributes.java new file mode 100644 index 00000000..f9bfd236 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxAttributes.java @@ -0,0 +1,79 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.report; + + +/** + * + */ +public class SgxAttributes { + + /** + * + */ + private long flags; + + /** + * + */ + private long xfrm; + + /** + * Default constructor + */ + public SgxAttributes() { + } + + public SgxAttributes(long flags, long xfrm) { + this.flags = flags; + this.xfrm = xfrm; + } + + public long getFlags() { + return flags; + } + + public long getXfrm() { + return xfrm; + } + + public void setFlags(long flags) { + this.flags = flags; + } + + public void setXfrm(long xfrm) { + this.xfrm = xfrm; + } + +} + diff --git a/SampleCode/TDQuoteVerificationSample/Enclave/Enclave.edl b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxCpuSvn.java similarity index 78% rename from SampleCode/TDQuoteVerificationSample/Enclave/Enclave.edl rename to SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxCpuSvn.java index 059f143d..4abff87e 100644 --- a/SampleCode/TDQuoteVerificationSample/Enclave/Enclave.edl +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxCpuSvn.java @@ -29,24 +29,34 @@ * */ -/* Enclave.edl - Top EDL file. */ -enclave { +package com.intel.sgx.report; - from "sgx_tstdc.edl" import *; - from "sgx_dcap_tvl.edl" import *; - /* Import ECALL/OCALL from sub-directory EDLs. - * [from]: specifies the location of EDL file. - * [import]: specifies the functions to import, - * [*]: implies to import all functions. + +public class SgxCpuSvn { + + /** + * 16 */ + private byte[] svn; + /** + * Default constructor + */ + public SgxCpuSvn() { + } - trusted { + public SgxCpuSvn(byte[] svn) { + this.svn = svn; + } - public sgx_status_t ecall_get_target_info([out] sgx_target_info_t* target_info); + public byte[] getSvn() { + return svn; + } - }; + public void setSvn(byte[] svn) { + this.svn = svn; + } -}; +} diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxMeasurement.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxMeasurement.java new file mode 100644 index 00000000..d791b843 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxMeasurement.java @@ -0,0 +1,65 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.report; + + +/** + * + */ +public class SgxMeasurement { + + /** + * 32 + */ + private byte[] m; + + /** + * Default constructor + */ + public SgxMeasurement() { + } + + public SgxMeasurement(byte[] m) { + this.m = m; + } + + public byte[] getM() { + return m; + } + + public void setM(byte[] m) { + this.m = m; + } + +} + diff --git a/QuoteGeneration/qcnl/inc/pckcert_provider.h b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxQlQeReportInfo.java similarity index 63% rename from QuoteGeneration/qcnl/inc/pckcert_provider.h rename to SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxQlQeReportInfo.java index aa04ad2b..f7317d99 100644 --- a/QuoteGeneration/qcnl/inc/pckcert_provider.h +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxQlQeReportInfo.java @@ -28,35 +28,61 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -/** File: pckcert_provider.h - * - * Description: Header file of PckCertProvider class - * + + +package com.intel.sgx.report; + + + +/** + * */ -#ifndef PCKCERTPROVIDER_H_ -#define PCKCERTPROVIDER_H_ -#pragma once - -#include "sgx_default_qcnl_wrapper.h" -#include - -using namespace std; - -class PckCertProvider { -private: -public: - PckCertProvider(); - ~PckCertProvider(); - - sgx_qcnl_error_t get_pck_cert_chain(const sgx_ql_pck_cert_id_t *p_pck_cert_id, - sgx_ql_config_t **pp_quote_config); - -protected: - sgx_qcnl_error_t build_pckcert_url(const string &base_url, - const sgx_ql_pck_cert_id_t *p_pck_cert_id, - string &url); - sgx_qcnl_error_t get_pck_cert_chain_from_url(const string &pck_url, - const sgx_ql_pck_cert_id_t *p_pck_cert_id, - sgx_ql_config_t **pp_quote_config); -}; -#endif \ No newline at end of file +public class SgxQlQeReportInfo { + + /** + * + */ + private SgxQuoteNonce nonce; + + + + /** + * + */ + private SgxTargetInfo appEnclaveTargetInfo; + + /** + * + */ + private SgxReport qeReport; + + /** + * Default constructor + */ + public SgxQlQeReportInfo() { + } + + public SgxTargetInfo getAppEnclaveTargetInfo() { + return appEnclaveTargetInfo; + } + + public SgxQuoteNonce getNonce() { + return nonce; + } + + public SgxReport getQeReport() { + return qeReport; + } + + public void setAppEnclaveTargetInfo(SgxTargetInfo appEnclaveTargetInfo) { + this.appEnclaveTargetInfo = appEnclaveTargetInfo; + } + public void setNonce(SgxQuoteNonce nonce) { + this.nonce = nonce; + } + + public void setQeReport(SgxReport qeReport) { + this.qeReport = qeReport; + } + +} diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxQuoteNonce.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxQuoteNonce.java new file mode 100644 index 00000000..bd474acf --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxQuoteNonce.java @@ -0,0 +1,61 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.report; + + + +/** + * + */ +public class SgxQuoteNonce { + + /** + * 4 + */ + private byte[] rand; + + /** + * Default constructor + */ + public SgxQuoteNonce() { + } + + public byte[] getRand() { + return rand; + } + + public void setRand(byte[] rand) { + this.rand = rand; + } + +} diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxReport.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxReport.java new file mode 100644 index 00000000..c3543281 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxReport.java @@ -0,0 +1,203 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.report; + + +/** + * + */ +public class SgxReport { + + /** + * + */ + private SgxCpuSvn cpuSvn; + + /** + * typedef uint32_t sgx_misc_select_t; + */ + private int miscSelect; + + /** + * + */ + private byte[] IsvExtProdID; + + /** + * + */ + private SgxAttributes attributes; + + /** + * + */ + private SgxMeasurement mrEnclave; + + /** + * + */ + private SgxMeasurement mrSigner; + + /** + * + */ + private byte[] configID; + + /** + * + */ + private short isvProdID; + + /** + * + */ + private short isvSvn; + + /** + * + */ + private short configSvn; + + /** + * + */ + private byte[] isvFamilyID; + + /** + * + */ + private SgxReportData reportData; + + /** + * Default constructor + */ + public SgxReport() { + } + + public SgxAttributes getAttributes() { + return attributes; + } + + public byte[] getConfigID() { + return configID; + } + + public short getConfigSvn() { + return configSvn; + } + + public SgxCpuSvn getCpuSvn() { + return cpuSvn; + } + + public byte[] getIsvExtProdID() { + return IsvExtProdID; + } + + public byte[] getIsvFamilyID() { + return isvFamilyID; + } + + public short getIsvProdID() { + return isvProdID; + } + + public short getIsvSvn() { + return isvSvn; + } + + public int getMiscSelect() { + return miscSelect; + } + + public SgxMeasurement getMrEnclave() { + return mrEnclave; + } + + public SgxMeasurement getMrSigner() { + return mrSigner; + } + + public SgxReportData getReportData() { + return reportData; + } + + public void setAttributes(SgxAttributes attributes) { + this.attributes = attributes; + } + + public void setConfigID(byte[] configID) { + this.configID = configID; + } + + public void setConfigSvn(short configSvn) { + this.configSvn = configSvn; + } + + public void setCpuSvn(SgxCpuSvn cpuSvn) { + this.cpuSvn = cpuSvn; + } + + public void setIsvExtProdID(byte[] isvExtProdID) { + IsvExtProdID = isvExtProdID; + } + + public void setIsvFamilyID(byte[] isvFamilyID) { + this.isvFamilyID = isvFamilyID; + } + + public void setIsvProdID(short isvProdID) { + this.isvProdID = isvProdID; + } + + public void setIsvSvn(short isvSvn) { + this.isvSvn = isvSvn; + } + + public void setMiscSelect(int miscSelect) { + this.miscSelect = miscSelect; + } + + public void setMrEnclave(SgxMeasurement mrEnclave) { + this.mrEnclave = mrEnclave; + } + + public void setMrSigner(SgxMeasurement mrSigner) { + this.mrSigner = mrSigner; + } + + public void setReportData(SgxReportData reportData) { + this.reportData = reportData; + } + +} diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxReportData.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxReportData.java new file mode 100644 index 00000000..78bd3281 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxReportData.java @@ -0,0 +1,60 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.report; + + +/** + * + */ +public class SgxReportData { + + /** + * 64 + */ + private byte[] d; + + /** + * Default constructor + */ + public SgxReportData() { + } + + public byte[] getD() { + return d; + } + + public void setD(byte[] d) { + this.d = d; + } + +} diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxTargetInfo.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxTargetInfo.java new file mode 100644 index 00000000..eb28c234 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/report/SgxTargetInfo.java @@ -0,0 +1,120 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.report; + +/** + * + */ +public class SgxTargetInfo { + + /** + * + */ + private SgxMeasurement mrEnclave; + + /** + * + */ + private SgxAttributes attributes; + + /** + * + */ + private short configSvn; + + /** + * + */ + private int miscSelect; + + /** + * + */ + private byte[] configID; + + /** + * Default constructor + */ + public SgxTargetInfo() { + } + + public SgxTargetInfo(SgxMeasurement mrEnclave, SgxAttributes attributes, short configSvn, int miscSelect, + byte[] configID) { + this.mrEnclave = mrEnclave; + this.attributes = attributes; + this.configSvn = configSvn; + this.miscSelect = miscSelect; + this.configID = configID; + } + public SgxAttributes getAttributes() { + return attributes; + } + + public byte[] getConfigID() { + return configID; + } + + public short getConfigSvn() { + return configSvn; + } + + public int getMiscSelect() { + return miscSelect; + } + + public SgxMeasurement getMrEnclave() { + return mrEnclave; + } + + public void setAttributes(SgxAttributes attributes) { + this.attributes = attributes; + } + + public void setConfigID(byte[] configID) { + this.configID = configID; + } + + public void setConfigSvn(short configSvn) { + this.configSvn = configSvn; + } + + public void setMiscSelect(int miscSelect) { + this.miscSelect = miscSelect; + } + + public void setMrEnclave(SgxMeasurement mrEnclave) { + this.mrEnclave = mrEnclave; + } + +} + diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/result/SgxDcapQuoteVerifyResult.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/result/SgxDcapQuoteVerifyResult.java new file mode 100644 index 00000000..05de78eb --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/result/SgxDcapQuoteVerifyResult.java @@ -0,0 +1,90 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.result; + +import com.intel.sgx.collateral.CollateralExpiration; +import com.intel.sgx.report.SgxQlQeReportInfo; +import com.intel.sgx.supplement.Supplemental; + +public class SgxDcapQuoteVerifyResult { + // + private int verifyResult; + private CollateralExpiration collExpire; + private SgxQlQvResult qlQvResult; + + private SgxQlQeReportInfo qeReport; + + private Supplemental supplement; + + public SgxDcapQuoteVerifyResult(int verifyResult, + CollateralExpiration collExpire, + SgxQlQvResult qlQvResult, + SgxQlQeReportInfo qeReport, + Supplemental supplement) { + + this.verifyResult = verifyResult; + this.collExpire = collExpire; + this.qlQvResult = qlQvResult; + this.qeReport = qeReport; + this.supplement = supplement; + } + + public CollateralExpiration getCollExpire() { return collExpire; } + public SgxQlQeReportInfo getQeReport() { return qeReport; } + + public SgxQlQvResult getQlQvResult() { return qlQvResult; } + + public Supplemental getSupplement() { return supplement; } + + public int getVerifyResult() { return verifyResult; } + + public void setCollExpire(CollateralExpiration collExpire) { + this.collExpire = collExpire; + } + + public void setQeReport(SgxQlQeReportInfo qeReport) { + this.qeReport = qeReport; + } + + public void setQlQvResult(SgxQlQvResult qlQvResult) { + this.qlQvResult = qlQvResult; + } + + public void setSupplement(Supplemental supplement) { + this.supplement = supplement; + } + + public void setVerifyResult(int verifyResult) { + this.verifyResult = verifyResult; + } +} diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/result/SgxQlQvResult.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/result/SgxQlQvResult.java new file mode 100644 index 00000000..da2fff9a --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/result/SgxQlQvResult.java @@ -0,0 +1,86 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.result; + +public enum SgxQlQvResult { + SGX_QL_QV_RESULT_OK(0x0000), /// < The Quote verification passed and is at the latest TCB level + SGX_QL_QV_RESULT_MIN(0xA001), + SGX_QL_QV_RESULT_CONFIG_NEEDED(0xA001), /// < The Quote verification passed and the + /// platform is patched to + /// < the latest TCB level but additional configuration of the SGX + /// < platform may be needed + SGX_QL_QV_RESULT_OUT_OF_DATE(0xA002), /// < The Quote is good but TCB level of the platform is out of date. + /// < The platform needs patching to be at the latest TCB level + SGX_QL_QV_RESULT_OUT_OF_DATE_CONFIG_NEEDED(0xA003), /// < The Quote is good but the TCB level of the platform is out + /// of + /// < date and additional configuration of the SGX Platform at its + /// < current patching level may be needed. The platform needs + /// < patching to be at the latest TCB level + SGX_QL_QV_RESULT_INVALID_SIGNATURE(0xA004), /// < The signature over the application report is invalid + SGX_QL_QV_RESULT_REVOKED(0xA005), /// < The attestation key or platform has been revoked + SGX_QL_QV_RESULT_UNSPECIFIED(0xA006), /// < The Quote verification failed due to an error in one of the input + SGX_QL_QV_RESULT_SW_HARDENING_NEEDED(0xA007), /// < The TCB level of the platform is up to date, but SGX SW + /// Hardening + /// < is needed + SGX_QL_QV_RESULT_CONFIG_AND_SW_HARDENING_NEEDED(0xA008), /// < The TCB level of the platform is up to date, but + /// additional + /// < configuration of the platform at its current patching level + /// < may be needed. Moreove, SGX SW Hardening is also needed + + SGX_QL_QV_RESULT_MAX(0xA0FF); + + private SgxQlQvResult(final int status) { + this.status = status; + } + + private int status; + + public int getQlQvResult() { + return this.status; + } + + public void setQlQvResult(int status) + { + this.status = status; + } + + public static SgxQlQvResult fromStatus(int status) { + for (SgxQlQvResult type : values()) { + if (type.getQlQvResult() == status) { + return type; + } + } + return null; + } +} + diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/result/TeeDcapQuoteVerifyResult.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/result/TeeDcapQuoteVerifyResult.java new file mode 100644 index 00000000..1e24c09b --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/result/TeeDcapQuoteVerifyResult.java @@ -0,0 +1,53 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.result; + +import com.intel.sgx.collateral.CollateralExpiration; +import com.intel.sgx.report.SgxQlQeReportInfo; +import com.intel.sgx.supplement.TeeSupplemental; + +public class TeeDcapQuoteVerifyResult extends quoteVerifyResult { + + private TeeSupplemental supplement; + + public TeeDcapQuoteVerifyResult(int verifyResult, CollateralExpiration collExpire, SgxQlQvResult qlQvResult, + SgxQlQeReportInfo qeReport, TeeSupplemental supplement) { + super(verifyResult, collExpire, qlQvResult, qeReport); + this.supplement = supplement; + } + + public TeeSupplemental getSupplement() { + return supplement; + } + +} diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/result/quoteVerifyResult.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/result/quoteVerifyResult.java new file mode 100644 index 00000000..f8c19807 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/result/quoteVerifyResult.java @@ -0,0 +1,67 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.result; + +import com.intel.sgx.collateral.CollateralExpiration; +import com.intel.sgx.report.SgxQlQeReportInfo; + +class quoteVerifyResult { + protected int verifyResult; + + protected CollateralExpiration collExpire; + + protected SgxQlQvResult qlQvResult; + + protected SgxQlQeReportInfo qeReport; + + + + public quoteVerifyResult(int verifyResult, CollateralExpiration collExpire, SgxQlQvResult qlQvResult, + SgxQlQeReportInfo qeReport) { + super(); + this.verifyResult = verifyResult; + this.collExpire = collExpire; + this.qlQvResult = qlQvResult; + this.qeReport = qeReport; + } + + public CollateralExpiration getCollExpire() { return collExpire; } + + public SgxQlQeReportInfo getQeReport() { return qeReport; } + + public SgxQlQvResult getQlQvResult() { return qlQvResult; } + + public int getVerifyResult() { return verifyResult; } + + +} diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/result/supplementalResult.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/result/supplementalResult.java new file mode 100644 index 00000000..34da94d5 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/result/supplementalResult.java @@ -0,0 +1,57 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.result; +public class supplementalResult { + private int version; + private int size; + + public supplementalResult(int version, int size) { + super(); + this.version = version; + this.size = size; + } + + public int getSize() { + return size; + } + public int getVersion() { + return version; + } + public void setSize(int size) { + this.size = size; + } + public void setVersion(int version) { + this.version = version; + } + +} diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/supplement/Supplemental.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/supplement/Supplemental.java new file mode 100644 index 00000000..96ae992b --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/supplement/Supplemental.java @@ -0,0 +1,271 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.supplement; + +import com.intel.sgx.report.SgxCpuSvn; + +/** + * + */ +public class Supplemental { + + /** + * Supplemental data version + */ + private short major_version; + private short minor_version; + + /** + * Earliest issue date of all the collateral (UTC) + */ + private long earliestIssueDate; + + /** + * Latest issue date of all the collateral (UTC) + */ + private long latestIssueDate; + + /** + * Earliest expiration date of all the collateral (UTC) + */ + private long earliestExpirationDate; + + /** + * The SGX TCB of the platform that generated the quote is not vulnerable + * to any Security Advisory with an SGX TCB impact released on or before this date + * See Intel Security Center Advisories + */ + private long tcbLevelDateTag; + + /** + * CRL Num from PCK Cert CRL + */ + private int pckCrlNum; + + /** + * CRL Num from Root CA CRL + */ + private int rootCaCrlNum; + + /** + * Lower number of the TCBInfo and QEIdentity + */ + private int tcbEvalRefNum; + + /** + * #define ROOT_KEY_ID_SIZE 48 + * ID of the collateral's root signer (hash of Root CA's public key SHA-384) + */ + private byte[] rootKeyId; + + /** + * typedef uint8_t sgx_key_128bit_t[16] + * PPID from remote platform. Can be used for platform ownership checks + */ + private byte[] pckPPID; + + /** + * CPUSVN of the remote platform's PCK Cert + */ + private SgxCpuSvn tcb_cpusvn; + + /** + * PCE_ISVNSVN of the remote platform's PCK Cert + */ + private short tcbPceIsvsvn; + + /** + * PCE_ID of the remote platform + */ + private short pceId; + + /** + * 0x00000000: SGX or 0x00000081: TDX + */ + private int teeType; + + /** + * Indicate the type of memory protection available on the platform, it should be one of + * Standard (0), Scalable (1) and Scalable with Integrity (2) + */ + private byte sgxType; + + // Multi-Package PCK cert related flags, they are only relevant to PCK Certificates issued by PCK Platform CA + /** + * #define PLATFORM_INSTANCE_ID_SIZE 48 + * IValue of Platform Instance ID, 16 bytes + */ + private byte[] platformInstanceID; + /** + * Indicate whether a platform can be extended with additional packages - via Package Add calls to SGX Registration Backend + */ + private int dynamicPlatform; + + /** + * Indicate whether platform root keys are cached by SGX Registration Backend + */ + private int cachedKeys; + + /** + * Indicate whether a plat form has SMT (simultaneous multithreading) enabled + */ + private int smtEnabled; + + + //String of comma separated list of Security Advisory IDs + + private String saList; + + + public Supplemental(short major_version, short minor_version, long earliestIssueDate, long latestIssueDate, + long earliestExpirationDate, long tcbLevelDateTag, int pckCrlNum, int rootCaCrlNum, int tcbEvalRefNum, + byte[] rootKeyId, byte[] pckPPID, SgxCpuSvn tcb_cpusvn, short tcbPceIsvsvn, short pceId, int teeType, + byte sgxType, byte[] platformInstanceID, int dynamicPlatform, int cachedKeys, int smtEnabled, + String saList) { + super(); + this.major_version = major_version; + this.minor_version = minor_version; + this.earliestIssueDate = earliestIssueDate; + this.latestIssueDate = latestIssueDate; + this.earliestExpirationDate = earliestExpirationDate; + this.tcbLevelDateTag = tcbLevelDateTag; + this.pckCrlNum = pckCrlNum; + this.rootCaCrlNum = rootCaCrlNum; + this.tcbEvalRefNum = tcbEvalRefNum; + this.rootKeyId = rootKeyId; + this.pckPPID = pckPPID; + this.tcb_cpusvn = tcb_cpusvn; + this.tcbPceIsvsvn = tcbPceIsvsvn; + this.pceId = pceId; + this.teeType = teeType; + this.sgxType = sgxType; + this.platformInstanceID = platformInstanceID; + this.dynamicPlatform = dynamicPlatform; + this.cachedKeys = cachedKeys; + this.smtEnabled = smtEnabled; + this.saList = saList; + } + + + public int getCachedKeys() { + return cachedKeys; + } + + + public int getDynamicPlatform() { + return dynamicPlatform; + } + + + public long getEarliestExpirationDate() { + return earliestExpirationDate; + } + + + public long getEarliestIssueDate() { + return earliestIssueDate; + } + + + public long getLatestIssueDate() { + return latestIssueDate; + } + + + public short getMajor_version() { + return major_version; + } + + + public short getMinor_version() { + return minor_version; + } + + + public short getPceId() { + return pceId; + } + + + public int getPckCrlNum() { + return pckCrlNum; + } + + public byte[] getPckPPID() { + return pckPPID; + } + + public byte[] getPlatformInstanceID() { + return platformInstanceID; + } + + public int getRootCaCrlNum() { + return rootCaCrlNum; + } + + public byte[] getRootKeyId() { + return rootKeyId; + } + + public String getSaList() { + return saList; + } + + public byte getSgxType() { + return sgxType; + } + + public int getSmtEnabled() { + return smtEnabled; + } + + public SgxCpuSvn getTcb_cpusvn() { + return tcb_cpusvn; + } + + public int getTcbEvalRefNum() { + return tcbEvalRefNum; + } + + public long getTcbLevelDateTag() { + return tcbLevelDateTag; + } + + public short getTcbPceIsvsvn() { + return tcbPceIsvsvn; + } + + public int getTeeType() { + return teeType; + } +} diff --git a/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/supplement/TeeSupplemental.java b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/supplement/TeeSupplemental.java new file mode 100644 index 00000000..fe685345 --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/main/java/com/intel/sgx/supplement/TeeSupplemental.java @@ -0,0 +1,52 @@ +/* + * 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. + * + */ + + +package com.intel.sgx.supplement; + +public class TeeSupplemental { + + private short major_version; + private Supplemental supplemental; + + public TeeSupplemental(short major_version, Supplemental supplemental) { + super(); + this.major_version = major_version; + this.supplemental = supplemental; + } + + public short getMajor_version() { + return major_version; + } + public Supplemental getSupplemental() { + return supplemental; + } +} diff --git a/SampleCode/JavaQuoteVerificationSample/src/test/java/com/intel/sgx/SgxDcapQuoteVerifyTest.java b/SampleCode/JavaQuoteVerificationSample/src/test/java/com/intel/sgx/SgxDcapQuoteVerifyTest.java new file mode 100644 index 00000000..a69893ee --- /dev/null +++ b/SampleCode/JavaQuoteVerificationSample/src/test/java/com/intel/sgx/SgxDcapQuoteVerifyTest.java @@ -0,0 +1,92 @@ +/* + * 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. + * + */ + + +package com.intel.sgx; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import com.intel.sgx.identity.QveIdentity; +import com.intel.sgx.result.SgxDcapQuoteVerifyResult; + +import org.junit.Test; +/** + * Unit test for simple App. + */ +public class SgxDcapQuoteVerifyTest { + private int retExpected = 0; + + @Test + public void testsgxQeGetTargetInfo() { + SgxDcapVerifyQuoteJNI c = new SgxDcapVerifyQuoteJNI(); + QveIdentity qveidentity = c.sgxQvGetQveIdentity(); + assertNotNull(qveidentity); + } + + @Test + public void testsgxQvSetPath() { + SgxDcapVerifyQuoteJNI c = new SgxDcapVerifyQuoteJNI(); + int ret = c.sgxQvSetPath(0, "/usr/lib/x86_64-linux-gnu/libsgx_qve.signed.so.1"); + assertEquals(retExpected, ret); + } + + @Test + public void testsgxQvSetEnclaveLoadPolicy() { + SgxDcapVerifyQuoteJNI c = new SgxDcapVerifyQuoteJNI(); + int ret = c.sgxQvSetEnclaveLoadPolicy(0); + assertEquals(retExpected, ret); + } + + + // @Test + // //shoulbe be enable after set the quotePATH + // public void testsgxQvVerifyQuote() { + // String quotePATH = ; + // Path path = Paths.get(quotePATH); + // SgxDcapVerifyQuoteJNI c = new SgxDcapVerifyQuoteJNI(); + // byte[] quoteBytes = null; + // try { + // quoteBytes = Files.readAllBytes(path); + // SgxDcapQuoteVerifyResult ret = c.sgxQvVerifyQuote(quoteBytes); + // assertEquals(retExpected, ret.getVerifyResult()); + // } catch (IOException e) { + // // TODO Auto-generated catch block + // e.printStackTrace(); + // } + + // } + +} diff --git a/SampleCode/QuoteGenerationSample/Enclave/Enclave.vcxproj b/SampleCode/QuoteGenerationSample/Enclave/Enclave.vcxproj index 420aaa34..95af3d6b 100644 --- a/SampleCode/QuoteGenerationSample/Enclave/Enclave.vcxproj +++ b/SampleCode/QuoteGenerationSample/Enclave/Enclave.vcxproj @@ -60,6 +60,12 @@ "$(SGXSDKInstallPath)\bin\win32\release\sgx_sign.exe" sign -key "$(ProjectDir)Enclave_private_sample.pem" -enclave "$(OutDir)Enclave.dll" -out "$(OutDir)Enclave.signed.dll" -config "$(ProjectDir)Enclave.config.xml" sign the enclave + + if not exist "$(SolutionDir)Enclave\Enclave_private_sample.pem" ("$(SGXSDKInstallPath)bin\win32\Release\ippRsaTool.exe" -genrsa "$(SolutionDir)Enclave\Enclave_private_sample.pem") + + + Generate enclave test key + diff --git a/SampleCode/QuoteGenerationSample/Enclave/Enclave_private_sample.pem b/SampleCode/QuoteGenerationSample/Enclave/Enclave_private_sample.pem deleted file mode 100644 index 056e43b1..00000000 --- a/SampleCode/QuoteGenerationSample/Enclave/Enclave_private_sample.pem +++ /dev/null @@ -1,39 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIG4QIBAAKCAYEAkj+OHOD9NYg+GFWalesDTpViDG21caYJuQtSqiebsbZsHvn8 -ErP3zfOTwIkBJkUNxHc4CBJe8UFB1Bke/q86eL2Cfwy50PrGxf0tmENFklRGFaFb -tyCsZYoJiOuRG9UxUj01NBYDy6cCi9s7UUyMrwPHxgRV4KtnhNmg0f2rCxXUkhx4 -m/jYZATj7b42DYxrb0iV8Z/WQ85KTyQlh43b3rJRZLvffsil5NqKMJJ9DK7xmzq8 -Ymns3rvqhJUUHvk4Ptj75yfZrNUNKJVf6eGs7514hRAuecNwBuA574vAlIJ3kAWB -UicVWUOSkTNMDHKyRUn077f2bJHnmu3EWUATw21gcLN2XP1p7tBglZejAJYYipYK -CQ19q542gIpZR5nMdKatGINPBB0yEV/TPKBV4rO4E2t659oaH6BR/VuNPDb/LdG0 -/dsItCZwUPM16dEVE+nVPG8uy1HNPbkapU5moEs6+QOOz3ERSuBVnsP0PsC6MdMx -MI+rtREVayZ2mj61AgEDAoIBgGF/tBNAqM5a1BA5EblHV4m47AhJI6EZW9CyNxwa -Z8vO8r9RUrcipTP3t9Wwq27Ys9hPerAMP0uA1o1mFKnKJvspAaoIe+CnLy6oyRAs -2Qw4LrkWPSTAcu5cBltHthKOIOF+I3gOrTJvVwfnfODdsx9X2oQC4+sc763mazap -HLIOjba9pb1QkEKt7UkpeV5dnPTbDqEVOYKJht9tblpekpR24O3SlP8wbpiRsXW2 -/gh0oRInKEGb8z8n8a24uBSmJHk7XF7aC/0k8ZOc4ONCA+yPZAB9+oehtjg3Ydke -/O00bTSUiDQtq+ZDXT12LLJnMw870HjWRG4rDQsVR99HfnaH5iW02HHfRpi2zzqn -pNlr9bjJIJIl7Pv4wigWtJRA7RwyGfQiar8xmDL8VBPYgAzjysWOCJw3FBfMBllN -bEsrMi8r9qq7/2MBk3rjsD67KRF+Z41yb44md3Pz+9I12+zwjU1tyWquEpu/PDa0 -Hl4u7yD25ap89+Z75tSURq6hKwKBwQCiQYJ2ViroJYYbsfKd37lMwV3at+pjStM1 -oQGrHBRgzlVji+rSkYAfFnjs++931JF68Yn1YYZ0TgLiLygcE+AZJXzaK1e+q0vH -FWyHQ6yRvaTEEbXMjVp9wz9U0vHc4Yap9eBhEfAYs+r1t20L1rNuTc+oQrN3Qz3l -11/M2wLcwlOz8Zc6SEUUsRBo5+uU6hjRcktaDffSvVOiY/uBN1QvmqO87kSOKXdB -ZddK0tatPXD7q7uDlXPi3KcSWRJgBnECgcEA5r5u4oqcyPgcr3gb9x7twAUEqZtM -SwYLfOwlfsEwz+V+XZrKMVETYMgNyAYZiQNUM36yRRUJUwNRKB6wbkD1+HwKXfjZ -84M0Qqi9Nlh/KLaDMVajYUc/s+XT75VYjFbiIGWlyT2+zJ7izy3oEwTiYRA4QtO6 -hkQ+Fhboqoxn7rPgMx4rw3jEivMCr7XB9s4+qDnujjWPo1rGbWclaMZIjUfDR/Cc -IUJ+H9ukAeLwBDzihLUdLT7D+HqUGe76NEaFAoHAbCusTuQcmsOuvSFMaT/Q3dY+ -kc/xl4c3eRYBHL1i6zQ47Qfx4bZVag77SKf0+o22UfZb+Ouu+DQB7B9wErfqu25T -PBzlKceH2g5IWi0dtn5t2AvOiF48U9d/jeH2k0EEcU6Vlgv1Zc1HTnpIso8iSYk1 -GtciT4IpQ+TqiJIB6IGNIqEPfDAuDctgRe/yY0a7NkwyPAlP4dONFu1SViTiymcX -00mDCXD6K5k6MeHkc35LUnJ9AmOilz3EtuYMQARLAoHBAJnUSexcaIX6vcpQEqS/ -SSquAxu83YdZXP3yw6nWIIqY/ukR3CDgt5Xas9quu7Cs4sz/IYNjW4ys4MVpyvQr -TqWoBulQkU0CItcbKM7lqhskV3Y5wkDaKnfujUpjkF2PQWruboYpKd2/Qd9z8Ayt -7EC1etc30a7YKWQPRccIRUnNQCIUHSz7LbH3Vx/OgU80KcV79F7OX8I8hEjvbkXZ -hbOFLNqgaBYsVBU9GAFB9VgolwMjaMjUgqWnDWafUXgvAwKBwFadxA0Nle+f6Q12 -vbxbPQ22BJfWM/+GuABaRDr2NR4BsvqgaU+c3LCYr1rv2GhGVoOOvvuAKJS4XJ8Z -FvsVnjPJfFfHZRisOdUDqif3Op1MUclqiWzkIPyP7388YVBDrtp1KrikIiXPojyx -PEJMeOpxqbNiiMCjhp0/NQ9umC15aNT9N0AsEwhV1HssARW587JC3heOCA2AInD0 -0miY3le4fHmF+H4gTKqiNbTGPnCp+D4h7mEgysJZUbSZcYZveA== ------END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/SampleCode/QuoteGenerationSample/Makefile b/SampleCode/QuoteGenerationSample/Makefile index 1758d9a3..6b15633b 100644 --- a/SampleCode/QuoteGenerationSample/Makefile +++ b/SampleCode/QuoteGenerationSample/Makefile @@ -121,6 +121,7 @@ ENCLAVE_LIBRARY_PATH := Enclave/ Enclave_Name := enclave.so Signed_Enclave_Name := enclave.signed.so Enclave_Config_File := Enclave/Enclave.config.xml +Enclave_Test_Key := Enclave/Enclave_private_sample.pem ifeq ($(SGX_DEBUG), 1) Build_Mode = HW_DEBUG @@ -191,7 +192,12 @@ $(Enclave_Name): Enclave/Enclave_t.o $(Enclave_Cpp_Objects) @echo "LINK => $@" $(Signed_Enclave_Name): $(Enclave_Name) - @$(SGX_ENCLAVE_SIGNER) sign -key Enclave/Enclave_private_sample.pem -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File) +ifeq ($(wildcard $(Enclave_Test_Key)),) + @echo "There is no enclave test key." + @echo "The project will generate a key for test." + @openssl genrsa -out $(Enclave_Test_Key) -3 3072 +endif + @$(SGX_ENCLAVE_SIGNER) sign -key $(Enclave_Test_Key) -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File) @rm -f $(Enclave_Name) @echo "SIGN => $@" diff --git a/SampleCode/QuoteGenerationSample/README.md b/SampleCode/QuoteGenerationSample/README.md index f29e9b9a..c459be3a 100644 --- a/SampleCode/QuoteGenerationSample/README.md +++ b/SampleCode/QuoteGenerationSample/README.md @@ -1,87 +1,100 @@ Intel(R) Software Guard Extensions Data Center Attestation Primitives (Intel(R) SGX DCAP) Quote Generation SampleCode ================================================ - -## Linux -Supported operating systems: -* Ubuntu* 18.04 LTS Desktop 64bits -* Ubuntu* 18.04 LTS Server 64bits +# Linux +## Supported 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 -* Red Hat Enterprise Linux Server release 8.2 64bits -* CentOS 8.2 64bits - -Requirements: +* Ubuntu\* 22.04 LTS Server 64bits +* Red Hat Enterprise Linux Server release 8.6 64bits +* CentOS Stream 8 64bits +* CentOS 8.3 64bits +* SUSE Linux Enterprise Server 15.4 64bits +* Anolis OS 8.6 64bits +* Debian 10 64bits +## Requirements: * make * gcc * g++ * bash shell - -Prerequisite: -* Intel(R) SGX DCAP Driver +## Prerequisite: +* Linux 5.11 and above, or Intel(R) SGX DCAP Driver * Intel(R) SGX SDK -* Intel(R) SGX DCAP Packages -* Intel(R) SGX DCAP PCCS (Provisioning Certificate Caching Service) -* If you want to use "out-of-process" quote generation, you need to install quote-ex package in Intel(R) SGX PSW Packages +* Intel(R) SGX DCAP Development Packages -*Please refer to SGX DCAP Linux installation guide "https://download.01.org/intel-sgx/sgx-dcap/#version#/linux/docs/Intel_SGX_DCAP_Linux_SW_Installation_Guide.pdf" to install above dependencies*
-*Note that you need to change **\#version\#** to actual version number in URL, such as 1.4.* +`libsgx-enclave-common-dev`, `libsgx-dcap-ql-dev` and `libsgx-dcap-default-qpl-dev`. Or `libsgx-enclave-common-devel`, `libsgx-dcap-ql-devel` and `libsgx-dcap-default-qpl-devel` +* Intel(R) SGX DCAP PCCS (Provisioning Certificate Caching Service) +* If you want to use "out-of-process" quote generation, you need to install `libsgx-quote-ex-dev` or `libsgx-quote-ex-devel` package in Intel(R) SGX PSW Packages -### Apps with "in-process" quote +*Please refer to [SGX DCAP Linux installation guide](https://download.01.org/intel-sgx/latest/dcap-latest/linux/docs/Intel_SGX_SW_Installation_Guide_for_Linux.pdf) to install above dependencies* +## Apps with "in-process" quote If your app uses Intel(R) SGX AESM service for "out-of-process" quote generation (quote generated in AESM process using Intel(R) signed PCE and QE), then the AESM installer will do the configuration described here and you can ignore this section. If your app is doing so-called "in-process" quote generation, i.e., it loads provisioning/quoting enclaves by itself including Intel(R) signed PCE, QE, then the app needs to be run with an uid in `sgx_prv` group. Use below command to add the user running the process to `sgx_prv` group, then run app again: ``` - $ sudo usermod -a -G sgx_prv +$ sudo usermod -a -G sgx_prv ``` -Note that you need to `open another terminal to make above command take effect`. +Note that you need to open another terminal to make above command take effect. Details please refer to driver [README](https://github.com/intel/SGXDataCenterAttestationPrimitives/tree/master/driver/linux#launching-an-enclave-with-provision-bit-set). -*Note:* Without proper access, the app will fail on loading the provisioning enclaves with error. e.g. SGX_ERROR_SERVICE_INVALID_PRIVILEGE(0x4004) from enclave loader. +*Note:* Without proper access, the app will fail on loading the provisioning enclaves with error. e.g. `SGX_ERROR_SERVICE_INVALID_PRIVILEGE(0x4004)` from enclave loader. +## Build and run QuoteGenerationSample to generate SGX ECDSA quote +Prepare Enclave test key(two options): +1. Install openssl first, then the project will generate a test key `Enclave_private_sample.pem` automatically when you build the project. +2. Rename your test key(3072-bit RSA private key) to `Enclave_private_sample.pem` and put it under the `Enclave` folder. -### Build and run QuoteGenerationSample to generate SGX ECDSA quote +"in-porc" Release build: +``` +$ make +``` +Or Debug build: +``` +$ make SGX_DEBUG=1 +``` +Run application in "in-proc" mode: +``` +$ ./app +``` +"out-of-proc" Release build: +``` +$ make OUT_OF_PROC=1 +``` +Or Debug build: +``` +$ make SGX_DEBUG=1 OUT_OF_PROC=1 +``` +**Note**: you need to install `libsgx-quote-ex-dev` or `libsgx-quote-ex-devel` package. -*Note that you need to install libsgx-quote-ex-dev package and all its dependencies and recommends in order to build and run this sample. Or you can remove the `-l$(Uae_Library_Name)` in Makefile. +Run application in "out-of-proc" mode: ``` - "in-porc" Release build: - $ make - Or Debug build: - $ make SGX_DEBUG=1 - Run application in "in-proc" mode: - $ ./app - - "out-of-proc" Release build: - $ make OUT_OF_PROC=1 - Or Debug build: - $ make SGX_DEBUG=1 OUT_OF_PROC=1 - Run application in "out-of-proc" mode: - $ SGX_AESM_ADDR=1 ./app +$ SGX_AESM_ADDR=1 ./app ``` -**Note**: Our libdcap_quoteprov.so is not built with Intel(R) Control Flow Enforcement Technology(CET) feature. If the sample is built with CET feature(it can be enabled by the compiler's default setting) and it is running on a CET enabled platform, you may encounter such an error message(or something similar): "Couldn't find the platform library. rebuild shared object with SHSTK support enabled". It means the system glibc enforces that a CET-enabled application can't load a non-CET shared library. You need to rebuild the sample by adding -fcf-protection=none option explicitly to disable CET. +**Note**: Our libdcap_quoteprov.so is not built with Intel(R) Control Flow Enforcement Technology(CET) feature. If the sample is built with CET feature(it can be enabled by the compiler's default setting) and it is running on a CET enabled platform, you may encounter such an error message(or something similar): "Couldn't find the platform library. rebuild shared object with SHSTK support enabled". It means the system glibc enforces that a CET-enabled application can't load a non-CET shared library. You need to rebuild the sample by adding `-fcf-protection=none` option explicitly to disable CET. -## Windows -Supported operating systems: - * Windows* Server 2016 (Long-Term Servicing Channel) - * Windows* Server 2019 (Long-Term Servicing Channel) +# Windows +## Supported operating systems: +* Windows* Server 2016 (Long-Term Servicing Channel) +* Windows* Server 2019 (Long-Term Servicing Channel) -Requirements: +## Requirements: * Microsoft Visual Studio 2019 or newer. -Prerequisite: +## Prerequisite: * Intel(R) SGX DCAP Driver * Intel(R) SGX SDK * Intel(R) SGX DCAP Packages * Intel(R) SGX DCAP PCCS (Provisioning Certificate Caching Service) +*Please refer to [SGX DCAP Windows installation guide](https://software.intel.com/en-us/sgx/sdk) to install above dependencies* -*Please refer to [SGX DCAP Windows installation guide](https://software.intel.com/en-us/sgx/sdk) to install above dependencies*
*Note that you need to sign in IDZ first, then download & extract product "Intel(R) Software Guard Extensions Data Center Attestation Primitives"* -Build and run QuoteGenerationSample to generate an ECDSA quote -``` - a. Open VS solution QuoteGenerationSample.sln, build with Debug/Release | x64 configuration - b. Run App.exe -``` +## Build and run QuoteGenerationSample to generate an ECDSA quote +1. Open VS solution QuoteGenerationSample.sln, build with `Debug/Release | x64` configuration +2. Run App.exe diff --git a/SampleCode/QuoteVerificationSample/App/App.cpp b/SampleCode/QuoteVerificationSample/App/App.cpp index ce3d06b2..7de12c6b 100644 --- a/SampleCode/QuoteVerificationSample/App/App.cpp +++ b/SampleCode/QuoteVerificationSample/App/App.cpp @@ -57,6 +57,14 @@ using namespace std; +typedef union _supp_ver_t{ + uint32_t version; + struct { + uint16_t major_version; + uint16_t minor_version; + }; +} supp_ver_t; + vector readBinaryContent(const string& filePath) { @@ -88,26 +96,35 @@ vector readBinaryContent(const string& filePath) int ecdsa_quote_verification(vector quote, bool use_qve) { - int ret = 0; - time_t current_time = 0; - uint32_t supplemental_data_size = 0; - uint8_t *p_supplemental_data = NULL; +#ifndef TD_ENV sgx_status_t sgx_ret = SGX_SUCCESS; - quote3_error_t dcap_ret = SGX_QL_ERROR_UNEXPECTED; - sgx_ql_qv_result_t quote_verification_result = SGX_QL_QV_RESULT_UNSPECIFIED; sgx_ql_qe_report_info_t qve_report_info; - unsigned char rand_nonce[16] = "59jslk201fgjmm;"; - uint32_t collateral_expiration_status = 1; - int updated = 0; + sgx_launch_token_t token = { 0 }; + unsigned char rand_nonce[16] = "59jslk201fgjmm;"; quote3_error_t verify_qveid_ret = SGX_QL_ERROR_UNEXPECTED; +#endif + + int ret = 0; + time_t current_time = 0; + quote3_error_t dcap_ret = SGX_QL_ERROR_UNEXPECTED; + uint32_t collateral_expiration_status = 1; + sgx_ql_qv_result_t quote_verification_result = SGX_QL_QV_RESULT_UNSPECIFIED; sgx_enclave_id_t eid = 0; - sgx_launch_token_t token = { 0 }; + + tee_supp_data_descriptor_t supp_data; + + // You can also set specify a major version in this structure, then we will always return supplemental data of the major version + // set major verison to 0 means always return latest supplemental data + memset(&supp_data, 0, sizeof(tee_supp_data_descriptor_t)); + + supp_ver_t latest_ver; // Trusted quote verification if (use_qve) { +#ifndef TD_ENV //set nonce // memcpy(qve_report_info.nonce.rand, rand_nonce, sizeof(rand_nonce)); @@ -138,15 +155,23 @@ int ecdsa_quote_verification(vector quote, bool use_qve) printf("\tError: sgx_qv_set_enclave_load_policy failed: 0x%04x\n", dcap_ret); } - //call DCAP quote verify library to get supplemental data size - // - dcap_ret = sgx_qv_get_quote_supplemental_data_size(&supplemental_data_size); - if (dcap_ret == SGX_QL_SUCCESS && supplemental_data_size == sizeof(sgx_ql_qv_supplemental_t)) { - printf("\tInfo: sgx_qv_get_quote_supplemental_data_size successfully returned.\n"); - p_supplemental_data = (uint8_t*)malloc(supplemental_data_size); - if (p_supplemental_data != NULL) { - memset(p_supplemental_data, 0, sizeof(supplemental_data_size)); + //call DCAP quote verify library to get supplemental latest version and data size + //version is a combination of major_version and minor version + //you can set the major version in 'supp_data.major_version' to get old version supplemental data + //only support major_version 3 right now + dcap_ret = tee_get_supplemental_data_version_and_size(quote.data(), + (uint32_t)quote.size(), + &latest_ver.version, + &supp_data.data_size); + + if (dcap_ret == SGX_QL_SUCCESS && supp_data.data_size == sizeof(sgx_ql_qv_supplemental_t)) { + printf("\tInfo: tee_get_quote_supplemental_data_version_and_size successfully returned.\n"); + printf("\tInfo: latest supplemental data major version: %d, minor version: %d, size: %d\n", latest_ver.major_version, latest_ver.minor_version, supp_data.data_size); + supp_data.p_data = (uint8_t*)malloc(supp_data.data_size); + if (supp_data.p_data != NULL) { + memset(supp_data.p_data, 0, supp_data.data_size); } + //Just print error in sample // else { @@ -155,12 +180,12 @@ int ecdsa_quote_verification(vector quote, bool use_qve) } else { if (dcap_ret != SGX_QL_SUCCESS) - printf("\tError: sgx_qv_get_quote_supplemental_data_size failed: 0x%04x\n", dcap_ret); + printf("\tError: tee_get_quote_supplemental_data_size failed: 0x%04x\n", dcap_ret); - if (supplemental_data_size != sizeof(sgx_ql_qv_supplemental_t)) + if (supp_data.data_size != sizeof(sgx_ql_qv_supplemental_t)) printf("\tWarning: Quote supplemental data size is different between DCAP QVL and QvE, please make sure you installed DCAP QVL and QvE from same release.\n"); - supplemental_data_size = 0; + supp_data.data_size = 0; } //set current time. This is only for sample use, please use trusted time in product. @@ -172,20 +197,19 @@ int ecdsa_quote_verification(vector quote, bool use_qve) //here you can choose 'trusted' or 'untrusted' quote verification by specifying parameter '&qve_report_info' //if '&qve_report_info' is NOT NULL, this API will call Intel QvE to verify quote //if '&qve_report_info' is NULL, this API will call 'untrusted quote verify lib' to verify quote, this mode doesn't rely on SGX capable system, but the results can not be cryptographically authenticated - dcap_ret = sgx_qv_verify_quote( + dcap_ret = tee_verify_quote( quote.data(), (uint32_t)quote.size(), NULL, current_time, &collateral_expiration_status, "e_verification_result, &qve_report_info, - supplemental_data_size, - p_supplemental_data); + &supp_data); if (dcap_ret == SGX_QL_SUCCESS) { - printf("\tInfo: App: sgx_qv_verify_quote successfully returned.\n"); + printf("\tInfo: App: tee_verify_quote successfully returned.\n"); } else { - printf("\tError: App: sgx_qv_verify_quote failed: 0x%04x\n", dcap_ret); + printf("\tError: App: tee_verify_quote failed: 0x%04x\n", dcap_ret); } @@ -193,11 +217,11 @@ int ecdsa_quote_verification(vector quote, bool use_qve) // e.g. You can check latest QvE ISVSVN from QvE configuration file on Github // https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/master/QuoteVerification/QvE/Enclave/linux/config.xml#L4 // or you can get latest QvE ISVSVN in QvE Identity JSON file from - // https://api.trustedservices.intel.com/sgx/certification/v3/qve/identity + // https://api.trustedservices.intel.com/sgx/certification/v4/qve/identity // Make sure you are using trusted & latest QvE ISV SVN as threshold // Warning: The function may return erroneous result if QvE ISV SVN has been modified maliciously. // - sgx_isv_svn_t qve_isvsvn_threshold = 6; + sgx_isv_svn_t qve_isvsvn_threshold = 7; //call sgx_dcap_tvl API in SampleISVEnclave to verify QvE's report and identity // @@ -209,8 +233,8 @@ int ecdsa_quote_verification(vector quote, bool use_qve) current_time, collateral_expiration_status, quote_verification_result, - p_supplemental_data, - supplemental_data_size, + supp_data.p_data, + supp_data.data_size, qve_isvsvn_threshold); if (sgx_ret != SGX_SUCCESS || verify_qveid_ret != SGX_QL_SUCCESS) { @@ -257,30 +281,44 @@ int ecdsa_quote_verification(vector quote, bool use_qve) //check supplemental data if necessary // - if (p_supplemental_data != NULL && supplemental_data_size > 0) { - sgx_ql_qv_supplemental_t *p = (sgx_ql_qv_supplemental_t*)p_supplemental_data; + if (dcap_ret == SGX_QL_SUCCESS && supp_data.p_data != NULL && supp_data.data_size > 0) { + sgx_ql_qv_supplemental_t *p = (sgx_ql_qv_supplemental_t*)supp_data.p_data; //you can check supplemental data based on your own attestation/verification policy //here we only print supplemental data version for demo usage // - printf("\tInfo: Supplemental data version: %d\n", p->version); - } + printf("\tInfo: Supplemental data Major Version: %d\n", p->major_version); + printf("\tInfo: Supplemental data Minor Version: %d\n", p->minor_version); + //print SA list if exist, SA list is supported from version 3.1 + // + if (p->version > 3 && strlen(p->sa_list) > 0) { + printf("\tInfo: Advisory ID: %s\n", p->sa_list); + } + } +#endif } - // Untrusted quote verification else { - //call DCAP quote verify library to get supplemental data size - // - dcap_ret = sgx_qv_get_quote_supplemental_data_size(&supplemental_data_size); - if (dcap_ret == SGX_QL_SUCCESS && supplemental_data_size == sizeof(sgx_ql_qv_supplemental_t)) { - printf("\tInfo: sgx_qv_get_quote_supplemental_data_size successfully returned.\n"); - p_supplemental_data = (uint8_t*)malloc(supplemental_data_size); - if (p_supplemental_data != NULL) { - memset(p_supplemental_data, 0, sizeof(supplemental_data_size)); + //call DCAP quote verify library to get supplemental latest version and data size + //version is a combination of major_version and minor version + //you can set the major version in 'supp_data.major_version' to get old version supplemental data + //only support major_version 3 right now + dcap_ret = tee_get_supplemental_data_version_and_size(quote.data(), + (uint32_t)quote.size(), + &latest_ver.version, + &supp_data.data_size); + + if (dcap_ret == SGX_QL_SUCCESS && supp_data.data_size == sizeof(sgx_ql_qv_supplemental_t)) { + printf("\tInfo: tee_get_quote_supplemental_data_version_and_size successfully returned.\n"); + printf("\tInfo: latest supplemental data major version: %d, minor version: %d, size: %d\n", latest_ver.major_version, latest_ver.minor_version, supp_data.data_size); + supp_data.p_data = (uint8_t*)malloc(supp_data.data_size); + if (supp_data.p_data != NULL) { + memset(supp_data.p_data, 0, supp_data.data_size); } + //Just print error in sample // else { @@ -289,12 +327,12 @@ int ecdsa_quote_verification(vector quote, bool use_qve) } else { if (dcap_ret != SGX_QL_SUCCESS) - printf("\tError: sgx_qv_get_quote_supplemental_data_size failed: 0x%04x\n", dcap_ret); + printf("\tError: tee_get_quote_supplemental_data_size failed: 0x%04x\n", dcap_ret); - if (supplemental_data_size != sizeof(sgx_ql_qv_supplemental_t)) + if (supp_data.data_size != sizeof(sgx_ql_qv_supplemental_t)) printf("\tWarning: Quote supplemental data size is different between DCAP QVL and QvE, please make sure you installed DCAP QVL and QvE from same release.\n"); - supplemental_data_size = 0; + supp_data.data_size = 0; } //set current time. This is only for sample purposes, in production mode a trusted time should be used. @@ -306,20 +344,19 @@ int ecdsa_quote_verification(vector quote, bool use_qve) //here you can choose 'trusted' or 'untrusted' quote verification by specifying parameter '&qve_report_info' //if '&qve_report_info' is NOT NULL, this API will call Intel QvE to verify quote //if '&qve_report_info' is NULL, this API will call 'untrusted quote verify lib' to verify quote, this mode doesn't rely on SGX capable system, but the results can not be cryptographically authenticated - dcap_ret = sgx_qv_verify_quote( + dcap_ret = tee_verify_quote( quote.data(), (uint32_t)quote.size(), NULL, current_time, &collateral_expiration_status, "e_verification_result, NULL, - supplemental_data_size, - p_supplemental_data); + &supp_data); if (dcap_ret == SGX_QL_SUCCESS) { - printf("\tInfo: App: sgx_qv_verify_quote successfully returned.\n"); + printf("\tInfo: App: tee_verify_quote successfully returned.\n"); } else { - printf("\tError: App: sgx_qv_verify_quote failed: 0x%04x\n", dcap_ret); + printf("\tError: App: tee_verify_quote failed: 0x%04x\n", dcap_ret); } //check verification result @@ -358,20 +395,25 @@ int ecdsa_quote_verification(vector quote, bool use_qve) //check supplemental data if necessary // - if (p_supplemental_data != NULL && supplemental_data_size > 0) { - sgx_ql_qv_supplemental_t *p = (sgx_ql_qv_supplemental_t*)p_supplemental_data; + if (dcap_ret == SGX_QL_SUCCESS && supp_data.p_data != NULL && supp_data.data_size > 0) { + sgx_ql_qv_supplemental_t *p = (sgx_ql_qv_supplemental_t*)supp_data.p_data; //you can check supplemental data based on your own attestation/verification policy //here we only print supplemental data version for demo usage // - printf("\tInfo: Supplemental data version: %d\n", p->version); - } + printf("\tInfo: Supplemental data Major Version: %d\n", p->major_version); + printf("\tInfo: Supplemental data Minor Version: %d\n", p->minor_version); + //print SA list if exist, SA list is supported from version 3.1 + // + if (p->version > 3 && strlen(p->sa_list) > 0) { + printf("\tInfo: Advisory ID: %s\n", p->sa_list); + } + } } - - if (p_supplemental_data) { - free(p_supplemental_data); + if (supp_data.p_data != NULL) { + free(supp_data.p_data); } if (eid) { @@ -426,17 +468,23 @@ int SGX_CDECL main(int argc, char *argv[]) //We demonstrate two different types of quote verification // a. Trusted quote verification - quote will be verified by Intel QvE // b. Untrusted quote verification - quote will be verified by untrusted QVL (Quote Verification Library) - // this mode doesn't rely on SGX capable system, but the results can not be cryptographically authenticated + // this mode doesn't rely on SGX/TDX capable system, but the results can not be cryptographically authenticated // +#ifndef TD_ENV // Trusted quote verification, ignore error checking printf("\nTrusted quote verification:\n"); ecdsa_quote_verification(quote, true); printf("\n===========================================\n"); - // Unrusted quote verification, ignore error checking printf("\nUntrusted quote verification:\n"); + +#else + // Quote verification inside TD + printf("\nQuote verification inside TD, support both SGX and TDX quote:\n"); +#endif + ecdsa_quote_verification(quote, false); printf("\n"); diff --git a/SampleCode/QuoteVerificationSample/Enclave/Enclave.vcxproj b/SampleCode/QuoteVerificationSample/Enclave/Enclave.vcxproj index 3500251d..21fe766c 100644 --- a/SampleCode/QuoteVerificationSample/Enclave/Enclave.vcxproj +++ b/SampleCode/QuoteVerificationSample/Enclave/Enclave.vcxproj @@ -79,6 +79,10 @@ "$(SGXSDKInstallPath)bin\x64\release\sgx_sign.exe" sign -key "Enclave_private_sample.pem" -enclave "$(OutDir)Enclave.dll" -out "$(OutDir)Enclave.signed.dll" -config "Enclave.config.xml" sign the enclave + + if not exist "$(SolutionDir)Enclave\Enclave_private_sample.pem" ("$(SGXSDKInstallPath)bin\win32\Release\ippRsaTool.exe" -genrsa "$(SolutionDir)Enclave\Enclave_private_sample.pem") + Generate enclave test key +
diff --git a/SampleCode/QuoteVerificationSample/Enclave/Enclave_private_sample.pem b/SampleCode/QuoteVerificationSample/Enclave/Enclave_private_sample.pem deleted file mode 100644 index 529d07be..00000000 --- a/SampleCode/QuoteVerificationSample/Enclave/Enclave_private_sample.pem +++ /dev/null @@ -1,39 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIG4gIBAAKCAYEAroOogvsj/fZDZY8XFdkl6dJmky0lRvnWMmpeH41Bla6U1qLZ -AmZuyIF+mQC/cgojIsrBMzBxb1kKqzATF4+XwPwgKz7fmiddmHyYz2WDJfAjIveJ -ZjdMjM4+EytGlkkJ52T8V8ds0/L2qKexJ+NBLxkeQLfV8n1mIk7zX7jguwbCG1Pr -nEMdJ3Sew20vnje+RsngAzdPChoJpVsWi/K7cettX/tbnre1DL02GXc5qJoQYk7b -3zkmhz31TgFrd9VVtmUGyFXAysuSAb3EN+5VnHGr0xKkeg8utErea2FNtNIgua8H -ONfm9Eiyaav1SVKzPHlyqLtcdxH3I8Wg7yqMsaprZ1n5A1v/levxnL8+It02KseD -5HqV4rf/cImSlCt3lpRg8U5E1pyFQ2IVEC/XTDMiI3c+AR+w2jSRB3Bwn9zJtFlW -KHG3m1xGI4ck+Lci1JvWWLXQagQSPtZTsubxTQNx1gsgZhgv1JHVZMdbVlAbbRMC -1nSuJNl7KPAS/VfzAgEDAoIBgHRXxaynbVP5gkO0ug6Qw/E27wzIw4SmjsxG6Wpe -K7kfDeRskKxESdsA/xCrKkwGwhcx1iIgS5+Qscd1Yg+1D9X9asd/P7waPmWoZd+Z -AhlKwhdPsO7PiF3e1AzHhGQwsUTt/Y/aSI1MpHBvy2/s1h9mFCslOUxTmWw0oj/Q -ldIEgWeNR72CE2+jFIJIyml6ftnb6qzPiga8Bm48ubKh0kvySOqnkmnPzgh+JBD6 -JnBmtZbfPT97bwTT+N6rnPqOOApvfHPf15kWI8yDbprG1l4OCUaIUH1AszxLd826 -5IPM+8gINLRDP1MA6azECPjTyHXhtnSIBZCyWSVkc05vYmNXYUNiXWMajcxW9M02 -wKzFELO8NCEAkaTPxwo4SCyIjUxiK1LbQ9h8PSy4c1+gGP4LAMR8xqP4QKg6zdu9 -osUGG/xRe/uufgTBFkcjqBHtK5L5VI0jeNIUAgW/6iNbYXjBMJ0GfauLs+g1VsOm -WfdgXzsb9DYdMa0OXXHypmV4GwKBwQDUwQj8RKJ6c8cT4vcWCoJvJF00+RFL+P3i -Gx2DLERxRrDa8AVGfqaCjsR+3vLgG8V/py+z+dxZYSqeB80Qeo6PDITcRKoeAYh9 -xlT3LJOS+k1cJcEmlbbO2IjLkTmzSwa80fWexKu8/Xv6vv15gpqYl1ngYoqJM3pd -vzmTIOi7MKSZ0WmEQavrZj8zK4endE3v0eAEeQ55j1GImbypSf7Idh7wOXtjZ7WD -Dg6yWDrri+AP/L3gClMj8wsAxMV4ZR8CgcEA0fzDHkFa6raVOxWnObmRoDhAtE0a -cjUj976NM5yyfdf2MrKy4/RhdTiPZ6b08/lBC/+xRfV3xKVGzacm6QjqjZrUpgHC -0LKiZaMtccCJjLtPwQd0jGQEnKfMFaPsnhOc5y8qVkCzVOSthY5qhz0XNotHHFmJ -gffVgB0iqrMTvSL7IA2yqqpOqNRlhaYhNl8TiFP3gIeMtVa9rZy31JPgT2uJ+kfo -gV7sdTPEjPWZd7OshGxWpT6QfVDj/T9T7L6tAoHBAI3WBf2DFvxNL2KXT2QHAZ9t -k3imC4f7U+wSE6zILaDZyzygA4RUbwG0gv8/TJVn2P/Eynf76DuWHGlaiLWnCbSz -Az2DHBQBBaku409zDQym3j1ugMRjzzSQWzJg0SIyBH3hTmnYcn3+Uqcp/lEBvGW6 -O+rsXFt3pukqJmIV8HzLGGaLm62BHUeZf3dyWm+i3p/hQAL7Xvu04QW70xuGqdr5 -afV7p5eaeQIJXyGQJ0eylV/90+qxjMKiB1XYg6WYvwKBwQCL/ddpgOdHJGN8uRom -e7Zq0Csi3hGheMKlKbN3vcxT5U7MdyHtTZZOJbTvxKNNUNYH/8uD+PqDGNneb29G -BfGzvI3EASyLIcGZF3OhKwZd0jUrWk2y7Vhob91jwp2+t73vdMbkKyI4mHOuXvGv -fg95si9oO7EBT+Oqvhccd2J+F1IVXncccYnF4u5ZGWt5lLewN/pVr7MjjykeaHqN -t+rfnQam2psA6fL4zS2zTmZPzR2tnY8Y1GBTi0Ko1OKd1HMCgcAb5cB/7/AQlhP9 -yQa04PLH9ygQkKKptZp7dy5WcWRx0K/hAHRoi2aw1wZqfm7VBNu2SLcs90kCCCxp -6C5sfJi6b8NpNbIPC+sc9wsFr7pGo9SFzQ78UlcWYK2Gu2FxlMjonhka5hvo4zvg -WxlpXKEkaFt3gLd92m/dMqBrHfafH7VwOJY2zT3WIpjwuk0ZzmRg5p0pG/svVQEH -NZmwRwlopysbR69B/n1nefJ84UO50fLh5s5Zr3gBRwbWNZyzhXk= ------END RSA PRIVATE KEY----- diff --git a/SampleCode/QuoteVerificationSample/Makefile b/SampleCode/QuoteVerificationSample/Makefile index 24cb41f7..12229782 100644 --- a/SampleCode/QuoteVerificationSample/Makefile +++ b/SampleCode/QuoteVerificationSample/Makefile @@ -85,15 +85,13 @@ else App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG endif +ifeq ($(TD_ENV), 1) + App_C_Flags += -DTD_ENV +endif + App_Cpp_Flags := $(App_C_Flags) App_Link_Flags := -L$(SGX_LIBRARY_PATH) -lsgx_dcap_quoteverify -l$(Urts_Library_Name) -lpthread -ldl -ifneq ($(SGX_MODE), HW) - App_Link_Flags += -lsgx_uae_service_sim -else - App_Link_Flags += -lsgx_uae_service -endif - App_Cpp_Objects := $(App_Cpp_Files:.cpp=.o) App_Name := app @@ -148,6 +146,7 @@ Enclave_Cpp_Objects := $(sort $(Enclave_Cpp_Files:.cpp=.o)) Enclave_Name := enclave.so Signed_Enclave_Name := enclave.signed.so Enclave_Config_File := Enclave/Enclave.config.xml +Enclave_Test_Key := Enclave/Enclave_private_sample.pem ifeq ($(SGX_MODE), HW) ifeq ($(SGX_DEBUG), 1) @@ -249,7 +248,12 @@ $(Enclave_Name): Enclave/Enclave_t.o $(Enclave_Cpp_Objects) echo "LINK => $@" $(Signed_Enclave_Name): $(Enclave_Name) - @$(SGX_ENCLAVE_SIGNER) sign -key Enclave/Enclave_private_sample.pem -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File) +ifeq ($(wildcard $(Enclave_Test_Key)),) + @echo "There is no enclave test key." + @echo "The project will generate a key for test." + @openssl genrsa -out $(Enclave_Test_Key) -3 3072 +endif + @$(SGX_ENCLAVE_SIGNER) sign -key $(Enclave_Test_Key) -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File) @echo "SIGN => $@" .PHONY: clean diff --git a/SampleCode/QuoteVerificationSample/README.md b/SampleCode/QuoteVerificationSample/README.md index 072314f0..4cb4fbb7 100644 --- a/SampleCode/QuoteVerificationSample/README.md +++ b/SampleCode/QuoteVerificationSample/README.md @@ -1,76 +1,86 @@ Intel(R) Software Guard Extensions Data Center Attestation Primitives (Intel(R) SGX DCAP) Quote Verification SampleCode ================================================ -## Linux -Supported operating systems: -* Ubuntu* 18.04 LTS Desktop 64bits -* Ubuntu* 18.04 LTS Server 64bits -* Ubuntu* 20.04 LTS Server 64bits -* Red Hat Enterprise Linux Server release 8.2 64bits -* CentOS 8.2 64bits +# Linux +## Supported 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 +* CentOS 8.3 64bits +* SUSE Linux Enterprise Server 15.4 64bits +* Anolis OS 8.6 64bits +* Debian 10 64bits -Requirements: +## Requirements: * make * gcc * g++ * bash shell -Prerequisite: -* Intel(R) SGX DCAP Driver +## Prerequisite: +* Linux 5.11 and above, or Intel(R) SGX DCAP Driver * Intel(R) SGX SDK -* Intel(R) SGX DCAP Packages -* Intel(R) SGX DCAP PCCS (Provisioning Certificate Caching Service) +* Intel(R) SGX DCAP Development Packages -*Please refer to SGX DCAP Linux installation guide "https://download.01.org/intel-sgx/sgx-dcap/#version#/linux/docs/Intel_SGX_DCAP_Linux_SW_Installation_Guide.pdf" to install above dependencies*
-*Note that you need to change **\#version\#** to actual version number in URL, such as 1.4.* +`libsgx-enclave-common-dev`, ` libsgx-dcap-quote-verify-dev` and `libsgx-dcap-default-qpl-dev`. Or `libsgx-enclave-common-devel`, ` libsgx-dcap-quote-verify-devel` and `libsgx-dcap-default-qpl-devel` +* Intel(R) SGX DCAP PCCS (Provisioning Certificate Caching Service) +*Please refer to [SGX DCAP Linux installation guide](https://download.01.org/intel-sgx/latest/dcap-latest/linux/docs/Intel_SGX_SW_Installation_Guide_for_Linux.pdf) to install above dependencies* +## Prepare quote file `quote.dat` +You need to follow [QuoteGenerationSample](../QuoteGenerationSample) to generate an ECDSA quote with certification data of type 5. +## Build QuoteVerificationSample -1. Generate an ECDSA quote with certification data of type 5 using QuoteGenerationSample +Release build: ``` - $ cd SampleCode/QuoteGenerationSample/ - $ make - $ ./app +$ make #You need to sign ISV enclave with your own key in this mode ``` +Or Debug build: -2. Build and run QuoteVerificationSample to verify a given quote +Prepare Enclave test key(two options): +1. Install openssl first, then the project will generate a test key `Enclave_private_sample.pem` automatically when you build the project. +2. Rename your test key(3072-bit RSA private key) to `Enclave_private_sample.pem` and put it under the `Enclave` folder. +``` +$ make SGX_DEBUG=1 +``` +## Run QuoteVerificationSample to verify a given SGX or TDX quote +``` +$ ./app -quote
``` - Release build: - $ make `#You need to sign ISV enclave with your own key in this mode` - Or Debug build: - $ make SGX_DEBUG=1 - $ ./app -quote
+## Build and run QuoteVerificationSample inside TD VM ``` -**Note**: Our libdcap_quoteprov.so is not built with Intel(R) Control Flow Enforcement Technology(CET) feature. If the sample is built with CET feature(it can be enabled by the compiler's default setting) and it is running on a CET enabled platform, you may encounter such an error message(or something similar): "Couldn't find the platform library. rebuild shared object with SHSTK support enabled". It means the system glibc enforces that a CET-enabled application can't load a non-CET shared library. You need to rebuild the sample by adding -fcf-protection=none option explicitly to disable CET. +$ make TD_ENV=1 SGX_DEBUG=1 +$ ./app -quote +``` + +**Note**: Our libdcap_quoteprov.so is not built with Intel(R) Control Flow Enforcement Technology(CET) feature. If the sample is built with CET feature(it can be enabled by the compiler's default setting) and it is running on a CET enabled platform, you may encounter such an error message(or something similar): "Couldn't find the platform library. rebuild shared object with SHSTK support enabled". It means the system glibc enforces that a CET-enabled application can't load a non-CET shared library. You need to rebuild the sample by adding `-fcf-protection=none` option explicitly to disable CET. -## Windows -Supported operating systems: - * Windows* Server 2016 (Long-Term Servicing Channel) - * Windows* Server 2019 (Long-Term Servicing Channel) +# Windows +## Supported operating systems: +* Windows* Server 2016 (Long-Term Servicing Channel) +* Windows* Server 2019 (Long-Term Servicing Channel) -Requirements: +## Requirements: * Microsoft Visual Studio 2019 or newer. -Prerequisite: +## Prerequisite: * Intel(R) SGX DCAP Driver * Intel(R) SGX SDK * Intel(R) SGX DCAP Packages * Intel(R) SGX DCAP PCCS (Provisioning Certificate Caching Service) - *Please refer to [SGX DCAP Windows installation guide](https://software.intel.com/en-us/sgx/sdk) to install above dependencies*
*Note that you need to sign in IDZ first, then download & extract product "Intel(R) Software Guard Extensions Data Center Attestation Primitives"* -1. Generate an ECDSA quote with certification data of type 5 using QuoteGenerationSample - You need to follow QuoteGenerationSample to setup env and run sample -``` - a. Open VS solution QuoteGenerationSample.sln, build with Debug/Release | x64 configuration - b. Run App.exe -``` +## Prepare quote file `quote.dat` +You need to follow [QuoteGenerationSample](../QuoteGenerationSample) to generate an ECDSA quote with certification data of type 5. -2. Build and run QuoteVerificationSample to verify a given quote -``` - a. Open VS solution QuoteVerificationSample.sln, butil with Debug/Release | x64 configuration - Note that Release mode need to sign ISV enclave with your own key - b. Run App.exe - > App.exe -quote +## Build and run QuoteVerificationSample to verify a given quote +1. Open VS solution QuoteVerificationSample.sln, butil with `Debug/Release | x64` configuration. Note that Release mode need to sign ISV enclave with your own key. +2. Run App.exe ``` +> App.exe -quote +``` \ No newline at end of file diff --git a/SampleCode/RustTDQuoteGenerationSample/.gitignore b/SampleCode/RustTDQuoteGenerationSample/.gitignore new file mode 100644 index 00000000..96ef6c0b --- /dev/null +++ b/SampleCode/RustTDQuoteGenerationSample/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/SampleCode/RustTDQuoteGenerationSample/Cargo.toml b/SampleCode/RustTDQuoteGenerationSample/Cargo.toml new file mode 100644 index 00000000..4436b21b --- /dev/null +++ b/SampleCode/RustTDQuoteGenerationSample/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "app" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +tdx-attest-rs = { path = "../../QuoteGeneration/quote_wrapper/tdx-attest-rs"} +rand = "0.8.5" diff --git a/SampleCode/RustTDQuoteGenerationSample/README.md b/SampleCode/RustTDQuoteGenerationSample/README.md new file mode 100644 index 00000000..782cddac --- /dev/null +++ b/SampleCode/RustTDQuoteGenerationSample/README.md @@ -0,0 +1,35 @@ +Intel(R) Software Guard Extensions Data Center Attestation Primitives (Intel(R) SGX DCAP) Rust TDQuote Generation SampleCode +================================================ + +## Linux +Supported operating systems: +* Ubuntu* 18.04 LTS Desktop 64bits +* Ubuntu* 18.04 LTS Server 64bits +* Ubuntu* 20.04 LTS Server 64bits +* Red Hat Enterprise Linux Server release 8.2 64bits +* CentOS 8.2 64bits + +Requirements: +* make +* gcc +* g++ +* bash shell +* clang +* Rust and Cargo + +Prerequisite: +* Intel(R) SGX SDK + +*Note that you need to install **libtdx-attest-dev** for this package.* + +Build and run *RustTDQuoteGenerationSample* to generate a TD quote + +``` +$ cargo build +$ ./target/debug/app +``` + +You can also combine building and running with a single Cargo command: +``` +$ cargo run +``` diff --git a/SampleCode/RustTDQuoteGenerationSample/src/main.rs b/SampleCode/RustTDQuoteGenerationSample/src/main.rs new file mode 100644 index 00000000..7cd28972 --- /dev/null +++ b/SampleCode/RustTDQuoteGenerationSample/src/main.rs @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2011-2022 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. + * + */ + +use tdx_attest_rs; +use rand::Rng; +use std::fs; + +fn main() { + let mut rng = rand::thread_rng(); + let report_data = tdx_attest_rs::tdx_report_data_t{ + d: [rng.gen::(); 64usize], + }; + println!("TDX report data: {:?}", report_data.d); + + let mut tdx_report = tdx_attest_rs::tdx_report_t{ + d: [0; 1024usize], + }; + let result = tdx_attest_rs::tdx_att_get_report(Some(&report_data), &mut tdx_report); + if result != tdx_attest_rs::tdx_attest_error_t::TDX_ATTEST_SUCCESS { + println!("Failed to get the report."); + return; + } + println!("TDX report: {:?}", tdx_report.d); + + let mut selected_att_key_id = tdx_attest_rs::tdx_uuid_t{ + d: [0; 16usize], + }; + let (result, quote) = tdx_attest_rs::tdx_att_get_quote(Some(&report_data), None, Some(&mut selected_att_key_id), 0); + if result != tdx_attest_rs::tdx_attest_error_t::TDX_ATTEST_SUCCESS { + println!("Failed to get the quote."); + return; + } + match quote { + Some(q) => { + println!("ATT key id: {:?}", selected_att_key_id); + println!("TDX quote data: {:?}", q); + println!("Successfully get the TD Quote."); + fs::write("quote.dat", q).expect("Unable to write quote file."); + }, + None => { + println!("Failed to get the quote."); + return; + }, + } + return; +} diff --git a/SampleCode/TDQuoteVerificationSample/App/App.cpp b/SampleCode/TDQuoteVerificationSample/App/App.cpp deleted file mode 100644 index 27126514..00000000 --- a/SampleCode/TDQuoteVerificationSample/App/App.cpp +++ /dev/null @@ -1,409 +0,0 @@ -/* - * 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. - * - */ - -#include -#include -#include -#include -#include -#include "sgx_urts.h" -#include -#ifdef TRUSTED_VERIFY -#include -#include "Enclave_u.h" -#endif -#include "sgx_ql_quote.h" -#include "sgx_dcap_quoteverify.h" - -#ifndef _MSC_VER - -#define SAMPLE_ISV_ENCLAVE "enclave.signed.so" -#define DEFAULT_QUOTE "../tdx-quote-generation-sample/quote.dat" - -#else - -#define SAMPLE_ISV_ENCLAVE "enclave.signed.dll" -#define DEFAULT_QUOTE "..\\..\\..\\TDQuoteGenerationSample\\x64\\Debug\\quote.dat" - -#define strncpy strncpy_s -#endif - - - -using namespace std; - - -vector readBinaryContent(const string& filePath) -{ - ifstream file(filePath, ios::binary); - if (!file.is_open()) - { - printf("Error: Unable to open quote file %s\n", filePath.c_str()); - return {}; - } - - file.seekg(0, ios_base::end); - streampos fileSize = file.tellg(); - - file.seekg(0, ios_base::beg); - vector retVal(fileSize); - file.read(reinterpret_cast(retVal.data()), fileSize); - file.close(); - return retVal; -} -#define PATHSIZE 0x418U - - -/** - * @param quote - ECDSA quote buffer - * @param use_qve - Set quote verification mode - * If true, quote verification will be performed by Intel QvE - * If false, quote verification will be performed by untrusted QVL - */ - -int ecdsa_quote_verification(vector quote, bool use_qve) -{ - int ret = 0; - time_t current_time = 0; - uint32_t supplemental_data_size = 0; - uint8_t *p_supplemental_data = NULL; - quote3_error_t dcap_ret = SGX_QL_ERROR_UNEXPECTED; - sgx_ql_qv_result_t quote_verification_result = SGX_QL_QV_RESULT_UNSPECIFIED; - uint32_t collateral_expiration_status = 1; - - -#ifdef TRUSTED_VERIFY - sgx_status_t sgx_ret = SGX_SUCCESS; - unsigned char rand_nonce[16] = "59jslk201fgjmm;"; - sgx_ql_qe_report_info_t qve_report_info; - sgx_launch_token_t token = { 0 }; - - int updated = 0; - quote3_error_t verify_qveid_ret = SGX_QL_ERROR_UNEXPECTED; - sgx_enclave_id_t eid = 0; - // Trusted quote verification - if (use_qve) { - - //set nonce - // - memcpy(qve_report_info.nonce.rand, rand_nonce, sizeof(rand_nonce)); - - //get target info of SampleISVEnclave. QvE will target the generated report to this enclave. - // - sgx_ret = sgx_create_enclave(SAMPLE_ISV_ENCLAVE, SGX_DEBUG_FLAG, &token, &updated, &eid, NULL); - if (sgx_ret != SGX_SUCCESS) { - printf("\tError: Failed to load Enclave, please make sure the environment is SGX capable(N.B SGX is not supported inside TD).\n"); - return -1; - } - sgx_status_t get_target_info_ret; - sgx_ret = ecall_get_target_info(eid, &get_target_info_ret, &qve_report_info.app_enclave_target_info); - if (sgx_ret != SGX_SUCCESS || get_target_info_ret != SGX_SUCCESS) { - printf("\tError in sgx_get_target_info. 0x%04x\n", get_target_info_ret); - } - else { - printf("\tInfo: get target info successfully returned.\n"); - } - - //call DCAP quote verify library to set QvE loading policy - // - dcap_ret = sgx_qv_set_enclave_load_policy(SGX_QL_DEFAULT); - if (dcap_ret == SGX_QL_SUCCESS) { - printf("\tInfo: sgx_qv_set_enclave_load_policy successfully returned.\n"); - } - else { - printf("\tError: sgx_qv_set_enclave_load_policy failed: 0x%04x\n", dcap_ret); - } - - - //call DCAP quote verify library to get supplemental data size - // - dcap_ret = tdx_qv_get_quote_supplemental_data_size(&supplemental_data_size); - if (dcap_ret == SGX_QL_SUCCESS) { - printf("\tInfo: tdx_qv_get_quote_supplemental_data_size successfully returned.\n"); - p_supplemental_data = (uint8_t*)malloc(supplemental_data_size); - if (p_supplemental_data != NULL) { - memset(p_supplemental_data, 0, sizeof(supplemental_data_size)); - } - //Just print error in sample - // - else { - printf("\tError: Cannot allocate memory for supplemental data.\n"); - } - } - else { - printf("\tError: tdx_qv_get_quote_supplemental_data_size failed: 0x%04x\n", dcap_ret); - supplemental_data_size = 0; - } - - //set current time. This is only for sample purposes, in production mode a trusted time should be used. - // - current_time = time(NULL); - - - //call DCAP quote verify library for quote verification - //here you can choose 'trusted' or 'untrusted' quote verification by specifying parameter '&qve_report_info' - //if '&qve_report_info' is NOT NULL, this API will call Intel QvE to verify quote - //if '&qve_report_info' is NULL, this API will call 'untrusted quote verify lib' to verify quote, this mode doesn't rely on SGX capable system, but the results can not be cryptographically authenticated - dcap_ret = tdx_qv_verify_quote( - quote.data(), (uint32_t)quote.size(), - NULL, - current_time, - &collateral_expiration_status, - "e_verification_result, - &qve_report_info, - supplemental_data_size, - p_supplemental_data); - if (dcap_ret == SGX_QL_SUCCESS) { - printf("\tInfo: App: tdx_qv_verify_quote successfully returned.\n"); - } else { - printf("\tError: App: tdx_qv_verify_quote failed: 0x%04x\n", dcap_ret); - } - - - // Threshold of QvE ISV SVN. The ISV SVN of QvE used to verify quote must be greater or equal to this threshold - // e.g. You can get latest QvE ISVSVN in QvE Identity JSON file from - // https://api.trustedservices.intel.com/sgx/certification/v4/qve/identity - // Make sure you are using trusted & latest QvE ISV SVN as threshold - // - sgx_isv_svn_t qve_isvsvn_threshold = 5; - - //call sgx_dcap_tvl API in SampleISVEnclave to verify QvE's report and identity - // - sgx_ret = sgx_tvl_verify_qve_report_and_identity(eid, - &verify_qveid_ret, - quote.data(), - (uint32_t) quote.size(), - &qve_report_info, - current_time, - collateral_expiration_status, - quote_verification_result, - p_supplemental_data, - supplemental_data_size, - qve_isvsvn_threshold); - - if (sgx_ret != SGX_SUCCESS || verify_qveid_ret != SGX_QL_SUCCESS) { - printf("\tError: Ecall: Verify QvE report and identity failed. 0x%04x\n", verify_qveid_ret); - } - else { - printf("\tInfo: Ecall: Verify QvE report and identity successfully returned.\n"); - } - - //check verification result - // - switch (quote_verification_result) - { - case SGX_QL_QV_RESULT_OK: - //check verification collateral expiration status - //this value should be considered in your own attestation/verification policy - // - if (collateral_expiration_status == 0) { - printf("\tInfo: App: Verification completed successfully.\n"); - ret = 0; - } - else { - printf("\tWarning: App: Verification completed, but collateral is out of date based on 'expiration_check_date' you provided.\n"); - ret = 1; - } - break; - case SGX_QL_QV_RESULT_CONFIG_NEEDED: - case SGX_QL_QV_RESULT_OUT_OF_DATE: - case SGX_QL_QV_RESULT_OUT_OF_DATE_CONFIG_NEEDED: - case SGX_QL_QV_RESULT_SW_HARDENING_NEEDED: - case SGX_QL_QV_RESULT_CONFIG_AND_SW_HARDENING_NEEDED: - printf("\tWarning: App: Verification completed with Non-terminal result: %x\n", quote_verification_result); - ret = 1; - break; - case SGX_QL_QV_RESULT_INVALID_SIGNATURE: - case SGX_QL_QV_RESULT_REVOKED: - case SGX_QL_QV_RESULT_UNSPECIFIED: - default: - printf("\tError: App: Verification completed with Terminal result: %x\n", quote_verification_result); - ret = -1; - break; - } - } - - - - // Untrusted quote verification - else { -#endif - //call DCAP quote verify library to get supplemental data size - // - (void)(use_qve); - dcap_ret = tdx_qv_get_quote_supplemental_data_size(&supplemental_data_size); - if (dcap_ret == SGX_QL_SUCCESS && supplemental_data_size == sizeof(sgx_ql_qv_supplemental_t)) { - printf("\tInfo: tdx_qv_get_quote_supplemental_data_size successfully returned.\n"); - p_supplemental_data = (uint8_t*)malloc(supplemental_data_size); - if (p_supplemental_data != NULL) { - memset(p_supplemental_data, 0, sizeof(supplemental_data_size)); - } - //Just print error in sample - // - else { - printf("\tError: Cannot allocate memory for supplemental data.\n"); - } - } - else { - printf("\tError: tdx_qv_get_quote_supplemental_data_size failed: 0x%04x\n", dcap_ret); - supplemental_data_size = 0; - } - - //set current time. This is only for sample purposes, in production mode a trusted time should be used. - // - current_time = time(NULL); - - - //call DCAP quote verify library for quote verification - dcap_ret = tdx_qv_verify_quote( - quote.data(), (uint32_t)quote.size(), - NULL, - current_time, - &collateral_expiration_status, - "e_verification_result, - NULL, - supplemental_data_size, - p_supplemental_data); - if (dcap_ret == SGX_QL_SUCCESS) { - printf("\tInfo: App: tdx_qv_verify_quote successfully returned.\n"); - } - else { - printf("\tError: App: tdx_qv_verify_quote failed: 0x%04x\n", dcap_ret); - } - - //check verification result - switch (quote_verification_result) - { - case SGX_QL_QV_RESULT_OK: - //check verification collateral expiration status - //this value should be considered in your own attestation/verification policy - // - if (collateral_expiration_status == 0) { - printf("\tInfo: App: Verification completed successfully.\n"); - ret = 0; - } - else { - printf("\tWarning: App: Verification completed, but collateral is out of date based on 'expiration_check_date' you provided.\n"); - ret = 1; - } - break; - case SGX_QL_QV_RESULT_CONFIG_NEEDED: - case SGX_QL_QV_RESULT_OUT_OF_DATE: - case SGX_QL_QV_RESULT_OUT_OF_DATE_CONFIG_NEEDED: - case SGX_QL_QV_RESULT_SW_HARDENING_NEEDED: - case SGX_QL_QV_RESULT_CONFIG_AND_SW_HARDENING_NEEDED: - printf("\tWarning: App: Verification completed with Non-terminal result: %x\n", quote_verification_result); - ret = 1; - break; - case SGX_QL_QV_RESULT_INVALID_SIGNATURE: - case SGX_QL_QV_RESULT_REVOKED: - case SGX_QL_QV_RESULT_UNSPECIFIED: - default: - printf("\tError: App: Verification completed with Terminal result: %x\n", quote_verification_result); - ret = -1; - break; - } - -#ifdef TRUSTED_VERIFY - } - - - if (eid) { - sgx_destroy_enclave(eid); - } -#endif - - if (p_supplemental_data) { - free(p_supplemental_data); - } - - return ret; -} - - -void usage() -{ - printf("\nUsage:\n"); - printf("\tPlease specify quote path, e.g. \"./app -quote \"\n"); - printf("\tDefault quote path is %s when no command line args\n\n", DEFAULT_QUOTE); -} - - -/* Application entry */ -int main(int argc, char *argv[]) -{ - vector quote; - - char quote_path[PATHSIZE] = { '\0' }; - - //Just for sample use, better to change solid command line args solution in production env - if (argc != 1 && argc != 3) { - usage(); - return 0; - } - - if (argv[1] && argv[2]) { - if (!strcmp(argv[1], "-quote")) { - strncpy(quote_path, argv[2], PATHSIZE-1); - quote_path[PATHSIZE-1]= '\0'; - } - } - - if (*quote_path == '\0') { - strncpy(quote_path, DEFAULT_QUOTE, PATHSIZE-1); - quote_path[PATHSIZE-1]= '\0'; - } - - //read quote from file - quote = readBinaryContent(quote_path); - if (quote.empty()) { - usage(); - return -1; - } - - printf("Info: ECDSA quote path: %s\n", quote_path); -#ifdef TRUSTED_VERIFY - // Trusted quote verification, ignore error checking - printf("\nTrusted quote verification:\n"); - ecdsa_quote_verification(quote, true); - - printf("\n===========================================\n"); -#endif - - - // quote verification, ignore error checking - printf("\nUntrusted quote verification:\n"); - ecdsa_quote_verification(quote, false); - - printf("\n"); - - return 0; -} diff --git a/SampleCode/TDQuoteVerificationSample/Enclave/Enclave.config.xml b/SampleCode/TDQuoteVerificationSample/Enclave/Enclave.config.xml deleted file mode 100644 index e94c9bc5..00000000 --- a/SampleCode/TDQuoteVerificationSample/Enclave/Enclave.config.xml +++ /dev/null @@ -1,12 +0,0 @@ - - 0 - 0 - 0x40000 - 0x100000 - 10 - 1 - - 0 - 0 - 0xFFFFFFFF - diff --git a/SampleCode/TDQuoteVerificationSample/Enclave/Enclave.lds b/SampleCode/TDQuoteVerificationSample/Enclave/Enclave.lds deleted file mode 100644 index f5f35d5b..00000000 --- a/SampleCode/TDQuoteVerificationSample/Enclave/Enclave.lds +++ /dev/null @@ -1,10 +0,0 @@ -enclave.so -{ - global: - g_global_data_sim; - g_global_data; - enclave_entry; - g_peak_heap_used; - local: - *; -}; diff --git a/SampleCode/TDQuoteVerificationSample/Enclave/Enclave_private_sample.pem b/SampleCode/TDQuoteVerificationSample/Enclave/Enclave_private_sample.pem deleted file mode 100644 index 529d07be..00000000 --- a/SampleCode/TDQuoteVerificationSample/Enclave/Enclave_private_sample.pem +++ /dev/null @@ -1,39 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIG4gIBAAKCAYEAroOogvsj/fZDZY8XFdkl6dJmky0lRvnWMmpeH41Bla6U1qLZ -AmZuyIF+mQC/cgojIsrBMzBxb1kKqzATF4+XwPwgKz7fmiddmHyYz2WDJfAjIveJ -ZjdMjM4+EytGlkkJ52T8V8ds0/L2qKexJ+NBLxkeQLfV8n1mIk7zX7jguwbCG1Pr -nEMdJ3Sew20vnje+RsngAzdPChoJpVsWi/K7cettX/tbnre1DL02GXc5qJoQYk7b -3zkmhz31TgFrd9VVtmUGyFXAysuSAb3EN+5VnHGr0xKkeg8utErea2FNtNIgua8H -ONfm9Eiyaav1SVKzPHlyqLtcdxH3I8Wg7yqMsaprZ1n5A1v/levxnL8+It02KseD -5HqV4rf/cImSlCt3lpRg8U5E1pyFQ2IVEC/XTDMiI3c+AR+w2jSRB3Bwn9zJtFlW -KHG3m1xGI4ck+Lci1JvWWLXQagQSPtZTsubxTQNx1gsgZhgv1JHVZMdbVlAbbRMC -1nSuJNl7KPAS/VfzAgEDAoIBgHRXxaynbVP5gkO0ug6Qw/E27wzIw4SmjsxG6Wpe -K7kfDeRskKxESdsA/xCrKkwGwhcx1iIgS5+Qscd1Yg+1D9X9asd/P7waPmWoZd+Z -AhlKwhdPsO7PiF3e1AzHhGQwsUTt/Y/aSI1MpHBvy2/s1h9mFCslOUxTmWw0oj/Q -ldIEgWeNR72CE2+jFIJIyml6ftnb6qzPiga8Bm48ubKh0kvySOqnkmnPzgh+JBD6 -JnBmtZbfPT97bwTT+N6rnPqOOApvfHPf15kWI8yDbprG1l4OCUaIUH1AszxLd826 -5IPM+8gINLRDP1MA6azECPjTyHXhtnSIBZCyWSVkc05vYmNXYUNiXWMajcxW9M02 -wKzFELO8NCEAkaTPxwo4SCyIjUxiK1LbQ9h8PSy4c1+gGP4LAMR8xqP4QKg6zdu9 -osUGG/xRe/uufgTBFkcjqBHtK5L5VI0jeNIUAgW/6iNbYXjBMJ0GfauLs+g1VsOm -WfdgXzsb9DYdMa0OXXHypmV4GwKBwQDUwQj8RKJ6c8cT4vcWCoJvJF00+RFL+P3i -Gx2DLERxRrDa8AVGfqaCjsR+3vLgG8V/py+z+dxZYSqeB80Qeo6PDITcRKoeAYh9 -xlT3LJOS+k1cJcEmlbbO2IjLkTmzSwa80fWexKu8/Xv6vv15gpqYl1ngYoqJM3pd -vzmTIOi7MKSZ0WmEQavrZj8zK4endE3v0eAEeQ55j1GImbypSf7Idh7wOXtjZ7WD -Dg6yWDrri+AP/L3gClMj8wsAxMV4ZR8CgcEA0fzDHkFa6raVOxWnObmRoDhAtE0a -cjUj976NM5yyfdf2MrKy4/RhdTiPZ6b08/lBC/+xRfV3xKVGzacm6QjqjZrUpgHC -0LKiZaMtccCJjLtPwQd0jGQEnKfMFaPsnhOc5y8qVkCzVOSthY5qhz0XNotHHFmJ -gffVgB0iqrMTvSL7IA2yqqpOqNRlhaYhNl8TiFP3gIeMtVa9rZy31JPgT2uJ+kfo -gV7sdTPEjPWZd7OshGxWpT6QfVDj/T9T7L6tAoHBAI3WBf2DFvxNL2KXT2QHAZ9t -k3imC4f7U+wSE6zILaDZyzygA4RUbwG0gv8/TJVn2P/Eynf76DuWHGlaiLWnCbSz -Az2DHBQBBaku409zDQym3j1ugMRjzzSQWzJg0SIyBH3hTmnYcn3+Uqcp/lEBvGW6 -O+rsXFt3pukqJmIV8HzLGGaLm62BHUeZf3dyWm+i3p/hQAL7Xvu04QW70xuGqdr5 -afV7p5eaeQIJXyGQJ0eylV/90+qxjMKiB1XYg6WYvwKBwQCL/ddpgOdHJGN8uRom -e7Zq0Csi3hGheMKlKbN3vcxT5U7MdyHtTZZOJbTvxKNNUNYH/8uD+PqDGNneb29G -BfGzvI3EASyLIcGZF3OhKwZd0jUrWk2y7Vhob91jwp2+t73vdMbkKyI4mHOuXvGv -fg95si9oO7EBT+Oqvhccd2J+F1IVXncccYnF4u5ZGWt5lLewN/pVr7MjjykeaHqN -t+rfnQam2psA6fL4zS2zTmZPzR2tnY8Y1GBTi0Ko1OKd1HMCgcAb5cB/7/AQlhP9 -yQa04PLH9ygQkKKptZp7dy5WcWRx0K/hAHRoi2aw1wZqfm7VBNu2SLcs90kCCCxp -6C5sfJi6b8NpNbIPC+sc9wsFr7pGo9SFzQ78UlcWYK2Gu2FxlMjonhka5hvo4zvg -WxlpXKEkaFt3gLd92m/dMqBrHfafH7VwOJY2zT3WIpjwuk0ZzmRg5p0pG/svVQEH -NZmwRwlopysbR69B/n1nefJ84UO50fLh5s5Zr3gBRwbWNZyzhXk= ------END RSA PRIVATE KEY----- diff --git a/SampleCode/TDQuoteVerificationSample/Makefile b/SampleCode/TDQuoteVerificationSample/Makefile deleted file mode 100644 index 3b7ba806..00000000 --- a/SampleCode/TDQuoteVerificationSample/Makefile +++ /dev/null @@ -1,267 +0,0 @@ -# -# 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. -# -# - -######## SGX SDK Settings ######## - -SGX_SDK ?= /opt/intel/sgxsdk -SGX_MODE ?= HW -SGX_ARCH ?= x64 -DEBUG ?= 0 -UNTRUSTED_VERIFY ?= 0 - -# Don't support 32bit in this sample -SGX_COMMON_FLAGS := -m64 -SGX_LIBRARY_PATH := $(SGX_SDK)/lib64 -SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign -SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r - -ifeq ($(DEBUG), 1) -ifeq ($(SGX_PRERELEASE), 1) -$(error Cannot set DEBUG and SGX_PRERELEASE at the same time!!) -endif -endif - -ifeq ($(DEBUG), 1) - SGX_COMMON_FLAGS += -O0 -g3 -ggdb -else - SGX_COMMON_FLAGS += -O2 -endif - -SGX_COMMON_FLAGS += -DSGX_TRUSTED -Wall -Wextra -Winit-self -Wpointer-arith -Wreturn-type \ - -Waddress -Wsequence-point -Wformat-security \ - -Wmissing-include-dirs -Wfloat-equal -Wundef -Wshadow \ - -Wcast-align -Wcast-qual -Wconversion -Wredundant-decls -SGX_COMMON_CFLAGS := $(SGX_COMMON_FLAGS) -Wjump-misses-init -Wstrict-prototypes -Wunsuffixed-float-constants -SGX_COMMON_CXXFLAGS := $(SGX_COMMON_FLAGS) -Wnon-virtual-dtor -std=c++11 - -######## App Settings ######## -ifneq ($(SGX_MODE), HW) - Urts_Library_Name := sgx_urts_sim -else - Urts_Library_Name := sgx_urts -endif - -App_Cpp_Files := App/App.cpp -App_Include_Paths := -IApp - -ifeq ($(UNTRUSTED_VERIFY), 0) -App_Include_Paths += -I$(SGX_SDK)/include -endif - - -App_C_Flags := -fPIC -Wno-attributes $(App_Include_Paths) - -# Three configuration modes - Debug, prerelease, release -# Debug - Macro DEBUG enabled. -# Prerelease - Macro NDEBUG and EDEBUG enabled. -# Release - Macro NDEBUG enabled. -ifeq ($(DEBUG), 1) - App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG -else ifeq ($(SGX_PRERELEASE), 1) - App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG -else - App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG -endif - -App_Cpp_Flags := $(App_C_Flags) -App_Link_Flags := -L$(SGX_LIBRARY_PATH) -lsgx_dcap_quoteverify -l$(Urts_Library_Name) -lpthread -ldl - - -App_Cpp_Objects := $(App_Cpp_Files:.cpp=.o) - -App_Name := app - -######## Enclave Settings ######## - -ifneq ($(SGX_MODE), HW) - Trts_Library_Name := sgx_trts_sim - Service_Library_Name := sgx_tservice_sim -else - Trts_Library_Name := sgx_trts - Service_Library_Name := sgx_tservice -endif -Crypto_Library_Name := sgx_tcrypto -DCAP_DIR ?= ../../ -DCAP_QG_DIR ?= $(DCAP_DIR)/QuoteGeneration/ - -Enclave_Cpp_Files := Enclave/Enclave.cpp -Enclave_Include_Paths := -IEnclave -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/libcxx - -Enclave_C_Flags := $(Enclave_Include_Paths) -nostdinc -fvisibility=hidden -fpie -ffunction-sections -fdata-sections -CC_BELOW_4_9 := $(shell expr "`$(CC) -dumpversion`" \< "4.9") -ifeq ($(CC_BELOW_4_9), 1) - Enclave_C_Flags += -fstack-protector -else - Enclave_C_Flags += -fstack-protector-strong -endif - -Enclave_Cpp_Flags := $(Enclave_C_Flags) -nostdinc++ - -# Enable the security flags -Enclave_Security_Link_Flags := -Wl,-z,relro,-z,now,-z,noexecstack - -# To generate a proper enclave, it is recommended to follow below guideline to link the trusted libraries: -# 1. Link sgx_trts with the `--whole-archive' and `--no-whole-archive' options, -# so that the whole content of trts is included in the enclave. -# 2. For other libraries, you just need to pull the required symbols. -# Use `--start-group' and `--end-group' to link these libraries. -# Do NOT move the libraries linked with `--start-group' and `--end-group' within `--whole-archive' and `--no-whole-archive' options. -# Otherwise, you may get some undesirable errors. -Enclave_Link_Flags := $(Enclave_Security_Link_Flags) -fPIC \ - -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \ - -Wl,--whole-archive -lsgx_dcap_tvl -l$(Trts_Library_Name) -Wl,--no-whole-archive \ - -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \ - -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ - -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ - -Wl,--defsym,__ImageBase=0 -Wl,--gc-sections \ - -Wl,--version-script=Enclave/Enclave.lds - -Enclave_Cpp_Objects := $(sort $(Enclave_Cpp_Files:.cpp=.o)) - -Enclave_Name := enclave.so -Signed_Enclave_Name := enclave.signed.so -Enclave_Config_File := Enclave/Enclave.config.xml - -ifeq ($(SGX_MODE), HW) -ifeq ($(DEBUG), 1) - Build_Mode = HW_DEBUG -else ifeq ($(SGX_PRERELEASE), 1) - Build_Mode = HW_PRERELEASE -else - Build_Mode = HW_RELEASE -endif -else -ifeq ($(DEBUG), 1) - Build_Mode = SIM_DEBUG -else ifeq ($(SGX_PRERELEASE), 1) - Build_Mode = SIM_PRERELEASE -else - Build_Mode = SIM_RELEASE -endif -endif - - -.PHONY: all target -ifeq ($(UNTRUSTED_VERIFY), 0) -all: .config_$(Build_Mode)_$(SGX_ARCH) - @$(MAKE) target - -ifeq ($(Build_Mode), HW_RELEASE) -target: $(App_Name) $(Enclave_Name) - @echo "The project has been built in release hardware mode." - @echo "Please sign the $(Enclave_Name) first with your signing key before you run the $(App_Name) to launch and access the enclave." - @echo "To sign the enclave use the command:" - @echo " $(SGX_ENCLAVE_SIGNER) sign -key -enclave $(Enclave_Name) -out <$(Signed_Enclave_Name)> -config $(Enclave_Config_File)" - @echo "You can also sign the enclave using an external signing tool." - @echo "To build the project in simulation mode set SGX_MODE=SIM. To build the project in prerelease mode set SGX_PRERELEASE=1 and SGX_MODE=HW." - - -else -target: $(App_Name) $(Signed_Enclave_Name) -ifeq ($(Build_Mode), HW_DEBUG) - @echo "The project has been built in debug hardware mode." -else ifeq ($(Build_Mode), SIM_DEBUG) - @echo "The project has been built in debug simulation mode." -else ifeq ($(Build_Mode), HW_PRERELEASE) - @echo "The project has been built in pre-release hardware mode." -else ifeq ($(Build_Mode), SIM_PRERELEASE) - @echo "The project has been built in pre-release simulation mode." -else - @echo "The project has been built in release simulation mode." -endif - -endif - - -.config_$(Build_Mode)_$(SGX_ARCH): - @rm -f .config_* $(App_Name) $(Enclave_Name) $(Signed_Enclave_Name) $(App_Cpp_Objects) App/Enclave_u.* $(Enclave_Cpp_Objects) Enclave/Enclave_t.* - @touch .config_$(Build_Mode)_$(SGX_ARCH) - -######## App Objects ######## - -App/Enclave_u.h: $(SGX_EDGER8R) Enclave/Enclave.edl - @cd App && $(SGX_EDGER8R) --untrusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include - @echo "GEN => $@" - -App/Enclave_u.c: App/Enclave_u.h - -App/Enclave_u.o: App/Enclave_u.c - @$(CC) $(SGX_COMMON_CFLAGS) $(App_C_Flags) -c $< -o $@ - @echo "CC <= $<" - -App/%.o: App/%.cpp App/Enclave_u.h - @$(CXX) $(SGX_COMMON_CXXFLAGS) $(App_Cpp_Flags) -c $< -o $@ -DTRUSTED_VERIFY - @echo "CXX <= $<" - -$(App_Name): App/Enclave_u.o $(App_Cpp_Objects) - @$(CXX) $^ -o $@ $(App_Link_Flags) - @echo "LINK => $@" - -######## Enclave Objects ######## - -Enclave/Enclave_t.h: $(SGX_EDGER8R) Enclave/Enclave.edl - @cd Enclave && $(SGX_EDGER8R) --trusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include - @echo "GEN => $@" - -Enclave/Enclave_t.c: Enclave/Enclave_t.h - -Enclave/Enclave_t.o: Enclave/Enclave_t.c - @$(CC) $(SGX_COMMON_CFLAGS) $(Enclave_C_Flags) -c $< -o $@ - @echo "CC <= $<" - -Enclave/%.o: Enclave/%.cpp Enclave/Enclave_t.h - @$(CXX) $(SGX_COMMON_CXXFLAGS) $(Enclave_Cpp_Flags) -c $< -o $@ - @echo "CXX <= $<" - -$(Enclave_Name): Enclave/Enclave_t.o $(Enclave_Cpp_Objects) - $(CXX) $^ -o $@ $(Enclave_Link_Flags) - echo "LINK => $@" - -$(Signed_Enclave_Name): $(Enclave_Name) - @$(SGX_ENCLAVE_SIGNER) sign -key Enclave/Enclave_private_sample.pem -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File) - @echo "SIGN => $@" -else -all: - @$(MAKE) target -target: $(App_Name) -App/%.o: App/%.cpp - $(CXX) $(SGX_COMMON_CXXFLAGS) $(App_Cpp_Flags) -c $< -o $@ -UTRUSTED_VERIFY - @echo "CXX <= $<" - -$(App_Name): $(App_Cpp_Objects) - @$(CXX) $^ -o $@ $(App_Link_Flags) - @echo "LINK => $@" -endif - -.PHONY: clean - -clean: - @rm -f .config_* $(App_Name) $(Enclave_Name) $(Signed_Enclave_Name) $(App_Cpp_Objects) App/*_u.* $(Enclave_Cpp_Objects) Enclave/Enclave_t.* diff --git a/SampleCode/TDQuoteVerificationSample/README.md b/SampleCode/TDQuoteVerificationSample/README.md deleted file mode 100644 index baf0b873..00000000 --- a/SampleCode/TDQuoteVerificationSample/README.md +++ /dev/null @@ -1,44 +0,0 @@ -Intel(R) Software Guard Extensions Data Center Attestation Primitives (Intel(R) SGX DCAP) Quote Verification SampleCode -================================================ - -## Linux -Supported operating systems: -* CentOS 8.3 64bits - -Requirements: -* make -* gcc -* g++ -* bash shell - -Prerequisite: -* Installed Intel(R) TDX DCAP Verfication Packages -* Installed Intel(R) Quote Generation Service Packages -* Installed Intel(R) SGX DCAP PCCS (Provisioning Certificate Caching Service) -* Intel(R) SGX DCAP Packages(only needed in trusted mode of quote verification) -If want verified quote in trusted mode -* Intel(R) SGX SDK - -*Please refer to SGX DCAP Linux installation guide "https://download.01.org/intel-sgx/sgx-dcap/#version#/linux/docs/Intel_SGX_DCAP_Linux_SW_Installation_Guide.pdf" to install above dependencies*
-*Note that you need to change **\#version\#** to actual version number in URL, such as 1.11.* - - -1. Generate an ECDSA quote with certification data of type 5 using this Quote Generation Sample Code -``` - $ cd /opt/intel/tdx-quote-generation-sample - $ make - $ ./test_tdx_attest -``` - -2. Build and run TD-based Quote Verification Sample to verify a given quote -``` - Untrusted mode build: - $ make UNTRUSTED_VERIFY=1 - Trused & Untrusted mode debug build: - $ make DEBUG=1 - $ ./app -quote
[default=../tdx-quote-generation-sample/quote.dat]> - Trused & Untrusted mode Release build: - $ make `#You need to sign ISV enclave with your own key in this mode` - $ ./app -quote [default=../tdx-quote-generation-sample/quote.dat]> -``` -**Note**: Our libdcap_quoteprov.so is not built with Intel(R) Control Flow Enforcement Technology(CET) feature. If the sample is built with CET feature(it can be enabled by the compiler's default setting) and it is running on a CET enabled platform, you may encounter such an error message(or something similar): "Couldn't find the platform library. rebuild shared object with SHSTK support enabled". It means the system glibc enforces that a CET-enabled application can't load a non-CET shared library. You need to rebuild the sample by adding -fcf-protection=none option explicitly to disable CET. diff --git a/prebuilt/openssl/inc/openssl/opensslv.h b/prebuilt/openssl/inc/openssl/opensslv.h index bd9dc920..fec5f579 100644 --- a/prebuilt/openssl/inc/openssl/opensslv.h +++ b/prebuilt/openssl/inc/openssl/opensslv.h @@ -39,8 +39,8 @@ extern "C" { * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for * major minor fix final patch/beta) */ -# define OPENSSL_VERSION_NUMBER 0x101010ffL -# define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1o 3 May 2022" +# define OPENSSL_VERSION_NUMBER 0x1010111fL +# define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1q 5 Jul 2022" /*- * The macros below are to be used for shared library (.so, .dll, ...) diff --git a/prebuilt/openssl/inc/openssl/ssl.h b/prebuilt/openssl/inc/openssl/ssl.h index fd0c5a99..9af0c899 100644 --- a/prebuilt/openssl/inc/openssl/ssl.h +++ b/prebuilt/openssl/inc/openssl/ssl.h @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * Copyright 2005 Nokia. All rights reserved. * @@ -1305,6 +1305,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) # define SSL_CTRL_GET_MAX_PROTO_VERSION 131 # define SSL_CTRL_GET_SIGNATURE_NID 132 # define SSL_CTRL_GET_TMP_KEY 133 +# define SSL_CTRL_GET_VERIFY_CERT_STORE 137 +# define SSL_CTRL_GET_CHAIN_CERT_STORE 138 # define SSL_CERT_SET_FIRST 1 # define SSL_CERT_SET_NEXT 2 # define SSL_CERT_SET_SERVER 3 @@ -1360,10 +1362,14 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st)) # define SSL_CTX_set1_verify_cert_store(ctx,st) \ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st)) +# define SSL_CTX_get0_verify_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_VERIFY_CERT_STORE,0,(char *)(st)) # define SSL_CTX_set0_chain_cert_store(ctx,st) \ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st)) # define SSL_CTX_set1_chain_cert_store(ctx,st) \ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st)) +# define SSL_CTX_get0_chain_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERT_STORE,0,(char *)(st)) # define SSL_set0_chain(s,sk) \ SSL_ctrl(s,SSL_CTRL_CHAIN,0,(char *)(sk)) # define SSL_set1_chain(s,sk) \ @@ -1386,10 +1392,14 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st)) # define SSL_set1_verify_cert_store(s,st) \ SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st)) +#define SSL_get0_verify_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_GET_VERIFY_CERT_STORE,0,(char *)(st)) # define SSL_set0_chain_cert_store(s,st) \ SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st)) # define SSL_set1_chain_cert_store(s,st) \ SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st)) +#define SSL_get0_chain_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_GET_CHAIN_CERT_STORE,0,(char *)(st)) # define SSL_get1_groups(s, glist) \ SSL_ctrl(s,SSL_CTRL_GET_GROUPS,0,(int*)(glist)) # define SSL_CTX_set1_groups(ctx, glist, glistlen) \ diff --git a/prebuilt/openssl/lib/linux64/libcrypto.a b/prebuilt/openssl/lib/linux64/libcrypto.a index d8b79489..917eb3d2 100644 Binary files a/prebuilt/openssl/lib/linux64/libcrypto.a and b/prebuilt/openssl/lib/linux64/libcrypto.a differ diff --git a/prebuilt/openssl/lib/win64/libcrypto.lib b/prebuilt/openssl/lib/win64/libcrypto.lib index 0d274c0f..a3245b76 100644 Binary files a/prebuilt/openssl/lib/win64/libcrypto.lib and b/prebuilt/openssl/lib/win64/libcrypto.lib differ diff --git a/tools/PCKCertSelection/Makefile b/tools/PCKCertSelection/Makefile index 66dd4057..c1115feb 100644 --- a/tools/PCKCertSelection/Makefile +++ b/tools/PCKCertSelection/Makefile @@ -33,8 +33,8 @@ # main make file for PCK Cert Selection project # -ifndef $(VERBOSE) - VERBOSE:=@ +ifndef VERBOSE + PCKCERTSEL_VERBOSE:=@ endif # this is project root directory @@ -60,30 +60,30 @@ ZIPFILE := PCKCertSelectionLinux.zip .NOTPARALLEL: $(PROJECTS) $(ZIPFILE) all: $(PROJECTS) $(ZIPFILE) - $(VERBOSE)echo projects all: done + $(PCKCERTSEL_VERBOSE)echo projects all: done debug: - $(VERBOSE)$(MAKE) DEBUG=1 all + $(PCKCERTSEL_VERBOSE)$(MAKE) DEBUG=1 all release: - $(VERBOSE)$(MAKE) all + $(PCKCERTSEL_VERBOSE)$(MAKE) all clean: $(PROJECTS) - $(VERBOSE)rm -rf out/*.zip - $(VERBOSE)echo projects clean: done + $(PCKCERTSEL_VERBOSE)rm -rf out/*.zip + $(PCKCERTSEL_VERBOSE)echo projects clean: done PCKSelectionSample : PCKCertSelectionLib $(PROJECTS): $(BIN_DIR) - $(VERBOSE)$(MAKE) -C $@ $(MAKECMDGOALS) - $(VERBOSE)echo "$@ : done" - $(VERBOSE)echo + $(PCKCERTSEL_VERBOSE)$(MAKE) -C $@ $(MAKECMDGOALS) + $(PCKCERTSEL_VERBOSE)echo "$@ : done" + $(PCKCERTSEL_VERBOSE)echo $(BIN_DIR): - $(VERBOSE)mkdir -p $@ + $(PCKCERTSEL_VERBOSE)mkdir -p $@ $(ZIPFILE): bash pack.sh - $(VERBOSE)echo "$@ : done" - $(VERBOSE)echo + $(PCKCERTSEL_VERBOSE)echo "$@ : done" + $(PCKCERTSEL_VERBOSE)echo diff --git a/tools/PCKCertSelection/PCKCertSelectionLib/Makefile b/tools/PCKCertSelection/PCKCertSelectionLib/Makefile index 8730e619..3c20fd67 100644 --- a/tools/PCKCertSelection/PCKCertSelectionLib/Makefile +++ b/tools/PCKCertSelection/PCKCertSelectionLib/Makefile @@ -33,8 +33,8 @@ # main make file for PCK Cert Selection library project # -ifndef $(VERBOSE) - VERBOSE:=@ +ifndef VERBOSE + PCKCERTSEL_VERBOSE:=@ endif ######## Project Settings ######## @@ -159,60 +159,60 @@ all: $(BIN_DIR) $(LIB_NAME) # local source files compiling %.o: %.cpp - $(VERBOSE)echo "Compiling $<..." - $(VERBOSE)$(CXX) $(CPP_FLAGS) -c $< -o $@ - $(VERBOSE)echo "\t -> $@ done" + $(PCKCERTSEL_VERBOSE)echo "Compiling $<..." + $(PCKCERTSEL_VERBOSE)$(CXX) $(CPP_FLAGS) -c $< -o $@ + $(PCKCERTSEL_VERBOSE)echo "\t -> $@ done" # parser source files compiling %.o: $(PARSERS_DIR)/%.cpp - $(VERBOSE)echo "Compiling $<..." - $(VERBOSE)$(CXX) $(CPP_FLAGS) -c $< -o $@ - $(VERBOSE)echo "\t -> $@ done" + $(PCKCERTSEL_VERBOSE)echo "Compiling $<..." + $(PCKCERTSEL_VERBOSE)$(CXX) $(CPP_FLAGS) -c $< -o $@ + $(PCKCERTSEL_VERBOSE)echo "\t -> $@ done" # x509 source files compiling %.o: $(X509_DIR)/%.cpp - $(VERBOSE)echo "Compiling $<..." - $(VERBOSE)$(CXX) $(CPP_FLAGS) -c $< -o $@ - $(VERBOSE)echo "\t -> $@ done" + $(PCKCERTSEL_VERBOSE)echo "Compiling $<..." + $(PCKCERTSEL_VERBOSE)$(CXX) $(CPP_FLAGS) -c $< -o $@ + $(PCKCERTSEL_VERBOSE)echo "\t -> $@ done" # helpers source files compiling %.o: $(HELPERS_DIR)/%.cpp - $(VERBOSE)echo "Compiling $<..." - $(VERBOSE)$(CXX) $(CPP_FLAGS) -c $< -o $@ - $(VERBOSE)echo "\t -> $@ done" + $(PCKCERTSEL_VERBOSE)echo "Compiling $<..." + $(PCKCERTSEL_VERBOSE)$(CXX) $(CPP_FLAGS) -c $< -o $@ + $(PCKCERTSEL_VERBOSE)echo "\t -> $@ done" # json source files compiling %.o: $(JSON_DIR)/%.cpp - $(VERBOSE)echo "Compiling $<..." - $(VERBOSE)$(CXX) $(CPP_FLAGS) -c $< -o $@ - $(VERBOSE)echo "\t -> $@ done" + $(PCKCERTSEL_VERBOSE)echo "Compiling $<..." + $(PCKCERTSEL_VERBOSE)$(CXX) $(CPP_FLAGS) -c $< -o $@ + $(PCKCERTSEL_VERBOSE)echo "\t -> $@ done" # utils source files compiling %.o: $(UTILS_DIR)/%.cpp - $(VERBOSE)echo "Compiling $<..." - $(VERBOSE)$(CXX) $(CPP_FLAGS) -c $< -o $@ - $(VERBOSE)echo "\t -> $@ done" + $(PCKCERTSEL_VERBOSE)echo "Compiling $<..." + $(PCKCERTSEL_VERBOSE)$(CXX) $(CPP_FLAGS) -c $< -o $@ + $(PCKCERTSEL_VERBOSE)echo "\t -> $@ done" # build library - link into output dir $(LIB_NAME): $(LIB_CPP_OBJECTS) - $(VERBOSE)echo "Linking..." - $(VERBOSE)$(CXX) $^ -o $(BIN_DIR)/$@ $(LINK_FLAGS) - $(VERBOSE)cp $(BIN_DIR)/$@ $(BIN_DIR)/$(LIB_SYM) - $(VERBOSE)echo "Stripping..." - $(VERBOSE)$(STRIP_CMD) $(BIN_DIR)/$@ - $(VERBOSE)echo "\t -> $@ done" + $(PCKCERTSEL_VERBOSE)echo "Linking..." + $(PCKCERTSEL_VERBOSE)$(CXX) $^ -o $(BIN_DIR)/$@ $(LINK_FLAGS) + $(PCKCERTSEL_VERBOSE)cp $(BIN_DIR)/$@ $(BIN_DIR)/$(LIB_SYM) + $(PCKCERTSEL_VERBOSE)echo "Stripping..." + $(PCKCERTSEL_VERBOSE)$(STRIP_CMD) $(BIN_DIR)/$@ + $(PCKCERTSEL_VERBOSE)echo "\t -> $@ done" debug: - $(VERBOSE)$(MAKE) DEBUG=1 all + $(PCKCERTSEL_VERBOSE)$(MAKE) DEBUG=1 all release: - $(VERBOSE)$(MAKE) all + $(PCKCERTSEL_VERBOSE)$(MAKE) all clean: - $(VERBOSE)echo -n "Clean $(LIB_NAME)..." - $(VERBOSE)rm -f $(BIN_DIR)/$(LIB_NAME)* $(LIB_CPP_OBJECTS) - $(VERBOSE)echo done + $(PCKCERTSEL_VERBOSE)echo -n "Clean $(LIB_NAME)..." + $(PCKCERTSEL_VERBOSE)rm -f $(BIN_DIR)/$(LIB_NAME)* $(LIB_CPP_OBJECTS) + $(PCKCERTSEL_VERBOSE)echo done $(BIN_DIR): - $(VERBOSE)mkdir -p $@ + $(PCKCERTSEL_VERBOSE)mkdir -p $@ diff --git a/tools/PCKCertSelection/PCKSelectionSample/Makefile b/tools/PCKCertSelection/PCKSelectionSample/Makefile index 3749c519..19019f5e 100644 --- a/tools/PCKCertSelection/PCKSelectionSample/Makefile +++ b/tools/PCKCertSelection/PCKSelectionSample/Makefile @@ -33,8 +33,8 @@ # main make file for PCK Cert Selection sample project # -ifndef $(VERBOSE) - VERBOSE:=@ +ifndef VERBOSE + PCKCERTSEL_VERBOSE:=@ endif ######## Project Settings ######## @@ -102,28 +102,28 @@ all: $(BIN_DIR) $(APP_NAME) # local source files compiling %.o: %.cpp - $(VERBOSE)echo "Compiling $<..." - $(VERBOSE)$(CXX) $(CPP_FLAGS) -c $< -o $@ - $(VERBOSE)echo "\t -> $@ done" + $(PCKCERTSEL_VERBOSE)echo "Compiling $<..." + $(PCKCERTSEL_VERBOSE)$(CXX) $(CPP_FLAGS) -c $< -o $@ + $(PCKCERTSEL_VERBOSE)echo "\t -> $@ done" # build application - link into output dir $(APP_NAME): $(APP_CPP_OBJECTS) - $(VERBOSE)echo "Building..." - $(VERBOSE)$(CXX) $^ -o $(BIN_DIR)/$@ $(LINK_FLAGS) - $(VERBOSE)echo "\t -> $@ done" + $(PCKCERTSEL_VERBOSE)echo "Building..." + $(PCKCERTSEL_VERBOSE)$(CXX) $^ -o $(BIN_DIR)/$@ $(LINK_FLAGS) + $(PCKCERTSEL_VERBOSE)echo "\t -> $@ done" debug: - $(VERBOSE)$(MAKE) DEBUG=1 all + $(PCKCERTSEL_VERBOSE)$(MAKE) DEBUG=1 all release: - $(VERBOSE)$(MAKE) all + $(PCKCERTSEL_VERBOSE)$(MAKE) all clean: - $(VERBOSE)echo -n "Clean $(APP_NAME)..." - $(VERBOSE)rm -f $(BIN_DIR)/$(APP_NAME) $(APP_CPP_OBJECTS) - $(VERBOSE)echo done + $(PCKCERTSEL_VERBOSE)echo -n "Clean $(APP_NAME)..." + $(PCKCERTSEL_VERBOSE)rm -f $(BIN_DIR)/$(APP_NAME) $(APP_CPP_OBJECTS) + $(PCKCERTSEL_VERBOSE)echo done # make sure output dir exist $(BIN_DIR): - $(VERBOSE)mkdir -p $@ + $(PCKCERTSEL_VERBOSE)mkdir -p $@ diff --git a/tools/PCKRetrievalTool/App/App.cpp b/tools/PCKRetrievalTool/App/App.cpp index 2f567982..09dbdf18 100644 --- a/tools/PCKRetrievalTool/App/App.cpp +++ b/tools/PCKRetrievalTool/App/App.cpp @@ -226,7 +226,7 @@ int parse_arg(int argc, const char *argv[]) else if (strncmp(argv[i], "-platform_id", 12) == 0) { non_enclave_mode = true; if (i == argc - 1 || argv[i + 1][0] == '-') { - fprintf(stdout, "Please input the platform ID, and the platform ID's length should not more than 260 bytes: \n"); + fprintf(stdout, "Please input the platform ID, and the platform ID's length should not be more than 260 bytes: \n"); char platform_id[MAX_PATH] = {0}; if (NULL == fgets(platform_id, MAX_PATH, stdin)) { fprintf(stderr, "No platform id is provided for -platform_id\n"); @@ -234,7 +234,7 @@ int parse_arg(int argc, const char *argv[]) } platform_id_string = platform_id; if (platform_id_string.length() > MAX_PATH) { - fprintf(stderr, "Error: the platform ID's length should not more than 260 bytes.\n"); + fprintf(stderr, "Error: the platform ID's length should not be more than 260 bytes.\n"); return -1; } i++; @@ -243,7 +243,7 @@ int parse_arg(int argc, const char *argv[]) else { platform_id_string = argv[i+1]; if (platform_id_string.length() > MAX_PATH) { - fprintf(stderr, "Error: the platform ID's length should not more than 260 bytes.\n"); + fprintf(stderr, "Error: the platform ID's length should not be more than 260 bytes.\n"); return -1; } i++; @@ -414,7 +414,7 @@ cache_server_delivery_status_t send_collected_data_to_server(uint8_t* p_data_buf delivery_status = DELIVERY_FAIL; } else { - fprintf(stderr, "Error: unexpected error happend during sending data to cache server.\n"); + fprintf(stderr, "Error: unexpected error occurred while sending data to cache server.\n"); delivery_status = DELIVERY_FAIL; } diff --git a/tools/PCKRetrievalTool/App/linux/network_wrapper.cpp b/tools/PCKRetrievalTool/App/linux/network_wrapper.cpp index c730a795..17e9edb5 100644 --- a/tools/PCKRetrievalTool/App/linux/network_wrapper.cpp +++ b/tools/PCKRetrievalTool/App/linux/network_wrapper.cpp @@ -366,7 +366,7 @@ network_post_error_t network_https_post(const uint8_t* raw_data, const uint32_t string strJson(""); ret = generate_json_message_body(raw_data, raw_data_size, platform_id_length, non_enclave_mode, strJson); if (ret != POST_SUCCESS) { - printf("Error: unexpected error happens during generate json message body.\n"); + printf("Error: unexpected error occurred while generating json message body.\n"); return ret; } CURL *curl = NULL; diff --git a/tools/PCKRetrievalTool/App/utility.cpp b/tools/PCKRetrievalTool/App/utility.cpp index a4033263..a39106a2 100644 --- a/tools/PCKRetrievalTool/App/utility.cpp +++ b/tools/PCKRetrievalTool/App/utility.cpp @@ -83,7 +83,7 @@ typedef sgx_status_t (SGXAPI *sgx_create_enclave_func_t)(const LPCSTR file_name, #else #define PCE_ENCLAVE_NAME "libsgx_pce.signed.so.1" #define ID_ENCLAVE_NAME "libsgx_id_enclave.signed.so.1" -#define SGX_URTS_LIBRARY "libsgx_urts.so.1" +#define SGX_URTS_LIBRARY "libsgx_urts.so" #define SGX_MULTI_PACKAGE_AGENT_UEFI_LIBRARY "libmpa_uefi.so.1" #define FINDFUNCTIONSYM dlsym #define CLOSELIBRARYHANDLE dlclose @@ -380,7 +380,7 @@ uefi_status_t get_platform_manifest(uint8_t ** buffer, uint16_t &out_buffer_size p_mp_uefi_get_request == NULL || p_mp_uefi_get_registration_status == NULL || p_mp_uefi_terminate == NULL) { - printf("Error: cound't find uefi function interface(s) in the UEFI shared library.\n"); + printf("Error: coulnd't find uefi function interface(s) in the UEFI shared library.\n"); CLOSELIBRARYHANDLE(uefi_lib_handle); return ret; } @@ -418,7 +418,7 @@ uefi_status_t get_platform_manifest(uint8_t ** buffer, uint16_t &out_buffer_size MpRegistrationStatus status; MpResult mpResult_registration_status = p_mp_uefi_get_registration_status(&status); if (mpResult != MP_SUCCESS) { - printf("Warning: error happens when get registration status, the error code is: %d \n", mpResult_registration_status); + printf("Warning: error occurred while getting registration status, the error code is: %d \n", mpResult_registration_status); break; } if(status.registrationStatus == MP_TASK_COMPLETED){ @@ -495,7 +495,7 @@ uefi_status_t set_registration_status() status.errorCode = MPA_SUCCESS; mpResult = p_mp_uefi_set_registration_status(&status); if (mpResult != MP_SUCCESS) { - printf("Warning: error happens when set registration status, the error code is: %d \n", mpResult); + printf("Warning: error occurred while setting registration status, the error code is: %d \n", mpResult); } else { ret = UEFI_OPERATION_SUCCESS; @@ -721,7 +721,7 @@ int collect_data(uint8_t **pp_data_buffer) } if (encrypted_ppid_ret_size != ENCRYPTED_PPID_LENGTH) { - fprintf(stderr, "PCE returned unexpected returned encrypted PPID size.\n"); + fprintf(stderr, "PCE returned incorrect encrypted PPID size.\n"); ret = -1; goto CLEANUP; } diff --git a/tools/PCKRetrievalTool/App/win/network_wrapper.cpp b/tools/PCKRetrievalTool/App/win/network_wrapper.cpp index 4bea6c42..812a3cdc 100644 --- a/tools/PCKRetrievalTool/App/win/network_wrapper.cpp +++ b/tools/PCKRetrievalTool/App/win/network_wrapper.cpp @@ -359,7 +359,7 @@ network_post_error_t network_https_post(const uint8_t* raw_data, const uint32_t string strJson(""); ret = generate_json_message_body(raw_data, raw_data_size, platform_id_length, non_enclave_mode, strJson); if (ret != POST_SUCCESS) { - printf("Error: unexpected error happens during generate json message body.\n"); + printf("Error: unexpected error occurred while generating json message body.\n"); return ret; } diff --git a/tools/PCKRetrievalTool/gen_release.sh b/tools/PCKRetrievalTool/gen_release.sh index a5bc16d3..b76fd893 100755 --- a/tools/PCKRetrievalTool/gen_release.sh +++ b/tools/PCKRetrievalTool/gen_release.sh @@ -53,9 +53,6 @@ cp ../../../../build/linux/libsgx_enclave_common.so $rel_dir_name/libsgx_enclave cp ../../../../build/linux/libsgx_urts.so $rel_dir_name/libsgx_urts.so cp README_standalone.txt $rel_dir_name/README.txt cp License.txt $rel_dir_name -cd $rel_dir_name -ln -s libsgx_urts.so libsgx_urts.so.1 -cd .. tar cvpzf $rel_dir_name.tar.gz $rel_dir_name diff --git a/tools/PCKRetrievalTool/installer/deb/sgx-pck-id-retrieval-tool/sgx-pck-id-retrieval-tool-1.0/debian/control b/tools/PCKRetrievalTool/installer/deb/sgx-pck-id-retrieval-tool/sgx-pck-id-retrieval-tool-1.0/debian/control index b3e2fe86..9527a580 100644 --- a/tools/PCKRetrievalTool/installer/deb/sgx-pck-id-retrieval-tool/sgx-pck-id-retrieval-tool-1.0/debian/control +++ b/tools/PCKRetrievalTool/installer/deb/sgx-pck-id-retrieval-tool/sgx-pck-id-retrieval-tool-1.0/debian/control @@ -9,6 +9,6 @@ Homepage: https://github.com/intel/SGXDataCenterAttestationPrimitives Package: sgx-pck-id-retrieval-tool Architecture: amd64 Depends: ${shlibs:Depends}, ${misc:Depends} -Recommends: libsgx-urts (>= 2.17), libsgx-ae-pce (>= @dep_version@),libsgx-ae-id-enclave (>=@dep_version@), libsgx-ra-uefi (>= @dep_version@) +Recommends: libsgx-urts (>= 2.18), libsgx-ae-pce (>= @dep_version@),libsgx-ae-id-enclave (>=@dep_version@), libsgx-ra-uefi (>= @dep_version@) Description: Intel(R) Software Guard Extensions: this tool is used to collect the platform information to retrieve the PCK certs from PCS(Provisioning Certification Server) diff --git a/tools/PCKRetrievalTool/installer/rpm/sgx-pck-id-retrieval-tool/sgx-pck-id-retrieval-tool.spec b/tools/PCKRetrievalTool/installer/rpm/sgx-pck-id-retrieval-tool/sgx-pck-id-retrieval-tool.spec index fd2c6d2d..6203fd5e 100644 --- a/tools/PCKRetrievalTool/installer/rpm/sgx-pck-id-retrieval-tool/sgx-pck-id-retrieval-tool.spec +++ b/tools/PCKRetrievalTool/installer/rpm/sgx-pck-id-retrieval-tool/sgx-pck-id-retrieval-tool.spec @@ -37,7 +37,7 @@ Version: @version@ Release: 1%{?dist} Summary: Intel(R) Software Guard Extensions:this tool is used to collect the platform information to retrieve the PCK certs from PCS(Provisioning Certification Server) Group: Development/System -Recommends: libsgx-urts >= 2.17, libsgx-ae-pce >= %{version}-%{release}, libsgx-ae-id-enclave >= %{version}-%{release},libsgx-ra-uefi >= %{version}-%{release} +Recommends: libsgx-urts >= 2.18, libsgx-ae-pce >= %{version}-%{release}, libsgx-ae-id-enclave >= %{version}-%{release},libsgx-ra-uefi >= %{version}-%{release} License: BSD License URL: https://github.com/intel/SGXDataCenterAttestationPrimitives diff --git a/tools/PccsAdminTool/README.txt b/tools/PccsAdminTool/README.txt index 799305dc..36040b32 100644 --- a/tools/PccsAdminTool/README.txt +++ b/tools/PccsAdminTool/README.txt @@ -19,7 +19,7 @@ optional arguments: optional arguments: -h, --help show this help message and exit - -u URL, --url URL The URL of the PCCS's GET platforms API; default: https://localhost:8081/sgx/certification/v3/platforms + -u URL, --url URL The URL of the PCCS's GET platforms API; default: https://localhost:8081/sgx/certification/v4/platforms -o OUTPUT_FILE, --output_file OUTPUT_FILE The output file name for platform list; default: platform_list.json -s SOURCE, --source SOURCE @@ -36,14 +36,14 @@ optional arguments: The input file name for platform list; default: platform_list.json -o OUTPUT_FILE, --output_file OUTPUT_FILE The output file name for platform collaterals; default: platform_collaterals.json - -u URL, --url URL The URL of the Intel PCS service; default: https://api.trustedservices.intel.com/sgx/certification/v3/ + -u URL, --url URL The URL of the Intel PCS service; default: https://api.trustedservices.intel.com/sgx/certification/v4/ 3. Put platform collateral data to PCCS cache db ./pccsadmin.py put [-h] [-u URL] [-i INPUT_FILE] optional arguments: -h, --help show this help message and exit - -u URL, --url URL The URL of the PCCS's PUT collateral API; default: https://localhost:8081/sgx/certification/v3/platformcollateral + -u URL, --url URL The URL of the PCCS's PUT collateral API; default: https://localhost:8081/sgx/certification/v4/platformcollateral -i INPUT_FILE, --input_file INPUT_FILE The input file name for platform collaterals; default: platform_collaterals.json @@ -62,7 +62,7 @@ optional arguments: optional arguments: -h, --help show this help message and exit - -u URL, --url URL The URL of the PCCS's refresh API; default: https://localhost:8081/sgx/certification/v3/refresh + -u URL, --url URL The URL of the PCCS's refresh API; default: https://localhost:8081/sgx/certification/v4/refresh -f FMSPCs, --fmspc FMSPCs If this argument is not provided, then it will require PCCS to refresh quote verification collateral. all - Refresh all cached certificates. diff --git a/tools/PccsAdminTool/pccsadmin.py b/tools/PccsAdminTool/pccsadmin.py index d31b5afc..72942c06 100755 --- a/tools/PccsAdminTool/pccsadmin.py +++ b/tools/PccsAdminTool/pccsadmin.py @@ -337,6 +337,7 @@ def pcs_fetch(args): root_cert = qe_identity[1][spos:] cdp = sgxext.get_root_ca_crl(unquote(root_cert).encode('utf-8')) rootcacrl = pcsclient.getFileFromUrl(cdp) + output_json["collaterals"]["rootcacrl_cdp"] = cdp output_json["collaterals"]["rootcacrl"] = rootcacrl with open(output_file, "w") as ofile: diff --git a/tools/SGXPlatformRegistration/inf/Tools/Installer_VersionSync.py b/tools/SGXPlatformRegistration/inf/Tools/Installer_VersionSync.py index 5e11fa81..8753025b 100644 --- a/tools/SGXPlatformRegistration/inf/Tools/Installer_VersionSync.py +++ b/tools/SGXPlatformRegistration/inf/Tools/Installer_VersionSync.py @@ -66,8 +66,8 @@ def SyncNuspecVersion(filename, version): Identity = Metadata[0].getElementsByTagName("version") Identity[0].firstChild.replaceWholeText(version) - print vsixmanifest.toxml() - f = open(filename, "wb") + print(vsixmanifest.toxml()) + f = open(filename, "w") vsixmanifest.writexml(f) f.close() diff --git a/tools/SGXPlatformRegistration/package/installer/deb/sgx-ra-service/sgx-ra-service-1.0/debian/control b/tools/SGXPlatformRegistration/package/installer/deb/sgx-ra-service/sgx-ra-service-1.0/debian/control index cfc7582a..fadcd86d 100644 --- a/tools/SGXPlatformRegistration/package/installer/deb/sgx-ra-service/sgx-ra-service-1.0/debian/control +++ b/tools/SGXPlatformRegistration/package/installer/deb/sgx-ra-service/sgx-ra-service-1.0/debian/control @@ -9,6 +9,5 @@ Homepage: https://github.com/intel/SGXDataCenterAttestationPrimitives Package: sgx-ra-service Architecture: amd64 Depends: ${shlibs:Depends}, ${misc:Depends},libsgx-ra-uefi (>= @dep_version@),libsgx-ra-network (>= @dep_version@) -Description: Intel(R) Software Guard Extensions Multi-Package Registration Agent Service - Enables SGX Remote attestation for Multi-Package platforms +Description: Intel(R) Software Guard Extensions Multi-Package Registration Agent Service: Enables SGX Remote Attestation for Multi-Package platforms