diff --git a/Dockerfile.build b/Dockerfile.build deleted file mode 100644 index 19255aa..0000000 --- a/Dockerfile.build +++ /dev/null @@ -1,8 +0,0 @@ -FROM occlum/occlum:0.22.0-ubuntu18.04 -COPY files/aesmd.conf /etc/aesmd.conf -COPY files/msprod.list /etc/apt/sources.list.d/msprod.list -RUN wget -qO - https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add - -COPY files/setup-build.sh / -RUN bash /setup-build.sh -ENV LC_ALL=C.UTF-8 -ENV LANG=C.UTF-8 diff --git a/README.md b/README.md index 20a7568..658b7bf 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,16 @@ -# Azure SGX Attestation Support for UID2 Services +# UID2 Attestation Azure -The repo provides helper facilities for obtaining an attestation request on Azure/SGX platform. +The repo provides helper facilities for obtaining an attestation request on Microsoft Azure. -# Building +## How to Install -The build is only possible on Azure confidential computing virtual machines. It has been tested with a Standard_DC8_v2 instance. -Only Ubuntu 18.04 LTS (server) is supported at this stage. +For maven projects: -Once you get a build VM, make sure it has all the necessary software by running: - -``` -./setup_build_vm.sh -``` - -Before running the build, make sure you obtain a GitHub personal access token with permissions to clone UID2 repos. - -To build the project: - -``` -export GITHUB_ACCESS_TOKEN= -./setup_dependencies.sh -./build.sh ``` - -# Testing - -Running `./test.sh` will build and execute the example inside an SGX container. - -# Example - -You can verify that the build worked successfully by trying out the basic example: - -``` -cd example -./build.sh + + + com.uid2 + attestation-azure + 1.4.0-2195ee834a + ``` - -If all goes well this should print out base64-encoded attestation quote similar to what would be required -to pass attestation with the UID2 Core service. diff --git a/build.sh b/build.sh deleted file mode 100755 index bcc2063..0000000 --- a/build.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash - -set -ex - -version=1.0.0 -container_name=dev.docker.adsrvr.org/uid2/occlum-build -container_version=${version}.1 -work_dir="${PWD}" -tty_arg= -if [[ -t 0 ]]; then - tty_arg="-it" -fi - -docker_run() -{ - docker run ${tty_arg} -w "${PWD}" -v "${work_dir}:${work_dir}" -u $(id -u ${USER}):$(id -g ${USER}) $container_name:dev "$@" -} - -build_openssl() -{ - pushd target - rm -rf openssl - wget -O openssl.tar.gz https://github.com/openssl/openssl/archive/OpenSSL_1_1_1k.tar.gz - tar xzf openssl.tar.gz - mv openssl-OpenSSL_* openssl - pushd openssl - CC=occlum-gcc ./config \ - --prefix=${PWD}/target \ - --openssldir=${PWD}/target \ - --with-rand-seed=rdcpu \ - no-zlib no-async no-tests no-ssl2 no-ssl3 no-comp no-idea no-psk no-srp no-ec2m no-weak-ssl-ciphers no-dtls no-dtls1 no-shared - docker_run make -j - docker_run make install - popd - popd -} - -# Container with build environment as required by occlum -docker build -f Dockerfile.build -t ${container_name}:dev -t ${container_name}:${container_version} . - -mvn package -mvn deploy:deploy-file -Durl=file://$PWD/example/repo -DgroupId='com.uid2' -DartifactId='attestation-azure' -Dpackaging=jar -Dfile="./target/attestation-azure-${version}.jar" -Dversion=${version} - -test -f target/openssl/target/lib/libcrypto.a || build_openssl - -rm -rf target/bin -mkdir -p target/bin -CXXFLAGS="-ggdb -std=c++17 -I/opt/intel/sgxsdk/include -Itarget/openssl/target/include" -JNI_CXXFLAGS="-fPIC -Itarget/headers -I/usr/lib/jvm/java-11-openjdk-amd64/include -I/usr/lib/jvm/java-11-openjdk-amd64/include/linux" -LDFLAGS="-Ltarget/openssl/target/lib" -docker_run occlum-g++ ./src/cpp/{quote,quote_app}.cc -o target/bin/sgx_quote $CXXFLAGS $LDFLAGS -lcrypto -docker_run occlum-g++ ./src/cpp/{quote,quote_jni}.cc -shared -o target/bin/libazure-attestation.so $CXXFLAGS $JNI_CXXFLAGS $LDFLAGS -lcrypto -z noexecstack diff --git a/example/Occlum.json b/example/Occlum.json deleted file mode 100644 index 5a092eb..0000000 --- a/example/Occlum.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "resource_limits": { - "kernel_space_heap_size": "64MB", - "kernel_space_stack_size": "1MB", - "user_space_size": "3000MB", - "max_num_of_threads": 128 - }, - "process": { - "default_stack_size": "2MB", - "default_heap_size": "256MB", - "default_mmap_size": "2500MB" - }, - "entry_points": [ - "/bin", - "/usr/lib/jvm/bin/java" - ], - "env": { - "default": [ - "LD_LIBRARY_PATH=/usr/lib/jvm/lib/server:/usr/lib/jvm/lib:/usr/lib:/lib", - "OCCLUM=yes", - "HOME=/root" - ], - "untrusted": [ - ] - }, - "metadata": { - "product_id": 111, - "version_number": 1, - "debuggable": false - }, - "mount": [ - { - "target": "/", - "type": "unionfs", - "options": { - "layers": [ - { - "target": "/", - "type": "sefs", - "source": "./build/mount/__ROOT", - "options": { - "MAC": "" - } - }, - { - "target": "/", - "type": "sefs", - "source": "./run/mount/__ROOT" - } - ] - } - }, - { - "target": "/tmp", - "type": "sefs", - "source": "./run/mount/tmp", - "options": { - "temporary": true - } - }, - { - "target": "/proc", - "type": "procfs" - }, - { - "target": "/dev", - "type": "devfs" - } - ] -} diff --git a/example/build.sh b/example/build.sh deleted file mode 100755 index 9e19c21..0000000 --- a/example/build.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash - -set -ex - -container_name=dev.docker.adsrvr.org/uid2/occlum-build:dev -occlum_glibc=/opt/occlum/glibc/lib -work_dir="${PWD}" -tty_arg= -if [[ -t 0 ]]; then - tty_arg="-it" -fi - -docker_run() -{ - docker run ${tty_arg} -w "${PWD}" -v "${work_dir}:${work_dir}" -u $(id -u ${USER}):$(id -g ${USER}) $container_name "$@" -} - -docker_run_root() -{ - docker run ${tty_arg} -w "${PWD}" -v "${work_dir}:${work_dir}" --device /dev/sgx/enclave --device /dev/sgx/provision $container_name "$@" -} - -mvn package - -docker_run_root rm -rf target/occlum -mkdir -p target/occlum -pushd target/occlum - -docker_run occlum init -mkdir -p image/usr/lib -mkdir -p image/app -mkdir -p image/$occlum_glibc - -cp $work_dir/target/example-*-jar-with-dependencies.jar image/app/example.jar -cp $work_dir/../target/bin/libazure-attestation.so image/usr/lib -cp $work_dir/../target/bin/sgx_quote image/bin - -docker_run cp $occlum_glibc/libdl.so.2 image/$occlum_glibc -docker_run cp $occlum_glibc/librt.so.1 image/$occlum_glibc -docker_run cp $occlum_glibc/libm.so.6 image/$occlum_glibc -docker_run cp -r /etc/java-11-openjdk image/etc -docker_run cp -r /usr/lib/jvm/java-11-openjdk-amd64 image/usr/lib/jvm -docker_run cp /lib/x86_64-linux-gnu/libz.so.1 image/lib - -cp $work_dir/Occlum.json . - -docker_run_root occlum build -docker_run_root bash -c "export AZDCAP_DEBUG_LOG_LEVEL=FATAL; /opt/occlum/start_aesm.sh; occlum run /bin/sgx_quote" -docker_run_root bash -c "export AZDCAP_DEBUG_LOG_LEVEL=FATAL; /opt/occlum/start_aesm.sh; occlum run /usr/lib/jvm/bin/java -XX:MaxHeapSize=512m -XX:InitialHeapSize=512m -XX:CompressedClassSpaceSize=256m -XX:MaxMetaspaceSize=256m -jar /app/example.jar" - -popd diff --git a/example/pom.xml b/example/pom.xml deleted file mode 100644 index 5c0f7e5..0000000 --- a/example/pom.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - 4.0.0 - - com.uid2 - example - 1.0.0 - - ${project.groupId}:${project.artifactId} - Azure SGX Enclave attestation example application - jar - - - 1.0.0 - - - - - - project.local - project - file:${project.basedir}/repo - - - - - - com.uid2 - uid2-attestation-api - 1.0.0 - - - com.uid2 - attestation-azure - 1.0.0 - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 11 - 11 - - - - - maven-assembly-plugin - - - - com.uid2.example.Main - - - - jar-with-dependencies - - - - - make-assembly - package - - single - - - - - - - diff --git a/example/src/main/java/com/uid2/example/Main.java b/example/src/main/java/com/uid2/example/Main.java deleted file mode 100644 index 583cb54..0000000 --- a/example/src/main/java/com/uid2/example/Main.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.uid2.example; - -import java.util.Base64; -import com.uid2.attestation.azure.AzureAttestationProvider; - -public class Main { - public static void main(String[] args) { - try { - AzureAttestationProvider provider = new AzureAttestationProvider(); - byte[] nonce = {0, 1, 2, 3, 4, 5, 6, 7}; - byte[] request = provider.getAttestationRequest(nonce); - System.out.println("Quote Data (base64): " + Base64.getEncoder().encodeToString(request)); - System.out.println("Enclave Held Data (base64): " + Base64.getEncoder().encodeToString(nonce)); - } catch (Exception e) { - System.out.println(e.getMessage()); - } - } -} diff --git a/files/aesmd.conf b/files/aesmd.conf deleted file mode 100644 index 9b42daf..0000000 --- a/files/aesmd.conf +++ /dev/null @@ -1 +0,0 @@ -default quoting type = ecdsa_256 diff --git a/files/msprod.list b/files/msprod.list deleted file mode 100644 index 213c873..0000000 --- a/files/msprod.list +++ /dev/null @@ -1 +0,0 @@ -deb [arch=amd64] https://packages.microsoft.com/ubuntu/18.04/prod bionic main diff --git a/files/setup-build.sh b/files/setup-build.sh deleted file mode 100644 index 83db0ab..0000000 --- a/files/setup-build.sh +++ /dev/null @@ -1,8 +0,0 @@ -set -ex - -apt-get update -apt-get remove -y libsgx-dcap-default-qpl -apt-get install -y dkms linux-headers-$(uname -r) less az-dcap-client wget openjdk-11-jdk-headless net-tools telnet -wget https://download.01.org/intel-sgx/sgx-dcap/1.10/linux/distro/ubuntu18.04-server/sgx_linux_x64_driver_1.41.bin -O sgx_linux_x64_driver.bin -chmod a+x sgx_linux_x64_driver.bin -./sgx_linux_x64_driver.bin diff --git a/pom.xml b/pom.xml index c483856..b8ca5e4 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ 1.4.0-2195ee834a ${project.groupId}:${project.artifactId} - Azure SGX Enclave attestation + Azure Enclave attestation https://github.com/IABTechLab/uid2docs jar diff --git a/setup_build_vm.sh b/setup_build_vm.sh deleted file mode 100755 index ebb3835..0000000 --- a/setup_build_vm.sh +++ /dev/null @@ -1,3 +0,0 @@ -sudo apt-get update -sudo apt-get install -y docker.io openjdk-11-jdk-headless maven unzip -sudo usermod -aG docker $USER diff --git a/src/cpp/quote.cc b/src/cpp/quote.cc deleted file mode 100644 index f64c9a0..0000000 --- a/src/cpp/quote.cc +++ /dev/null @@ -1,173 +0,0 @@ -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "quote.h" - -using namespace std::chrono_literals; - -static std::stringstream gLogger; - -template -void LOG(const Ts&... args) -{ - (gLogger << ... << args) << std::endl; -} - -#define SGXIOC_GET_DCAP_QUOTE_SIZE _IOR('s', 7, uint32_t) -#define SGXIOC_GEN_QUOTE _IOWR('s', 8, EnclaveQuoteArgs) - -const char* const kSgxDeviceName = "/dev/sgx"; - -struct EnclaveQuoteArgs -{ - sgx_report_data_t* mReportData; // input - uint32_t* mQuoteSize; // input/output - union - { - uint8_t* mAsBuf; - sgx_quote_t* mAsQuote; - sgx_quote3_t* mAsQuote3; - } mQuote; // output -}; - -static std::string GetErrorString(int err) -{ - char buf[1024]; - strerror_r(err, buf, sizeof(buf)); - return buf; -} - -static int SgxDeviceIoctl(unsigned long request, void* data) -{ - const int fd = open(kSgxDeviceName, O_RDONLY); - if(fd < 0) - { - LOG("Failed to open ", kSgxDeviceName, ": ", errno, ", ", GetErrorString(errno)); - return -1; - } - - int ret = 0; - int count = 3; - while(count--) - { - if(ioctl(fd, request, data) == 0) - { - break; - } - else if (errno != EAGAIN) - { - LOG("ioctl() failed for ", kSgxDeviceName, ": ", errno, ", ", GetErrorString(errno)); - ret = -1; - break; - } - else - { - LOG(kSgxDeviceName, " is temporarily busy. Try again after 1s."); - std::this_thread::sleep_for(1000ms); - } - } - - close(fd); - return ret; -} - -static int SgxDeviceGetQuote(EnclaveQuoteArgs* args) -{ - if(!args->mQuote.mAsBuf || (args->mQuoteSize == nullptr) || (*args->mQuoteSize == 0)) - { - LOG("Invalid quote buffer or len"); - return -1; - } - - return SgxDeviceIoctl(SGXIOC_GEN_QUOTE, args); -} - -static int SgxDeviceGetQuoteSize(uint32_t* quoteSize) -{ - return SgxDeviceIoctl(SGXIOC_GET_DCAP_QUOTE_SIZE, quoteSize); -} - -static const char* FormatHex(char* out, const uint8_t* data, size_t size) -{ - for(size_t i = 0; i < size; ++i) - { - sprintf(&out[i*2], "%02X", data[i]); - } - out[size*2+1] = '\0'; - return out; -} - -static void Sha256(uint8_t* out, const uint8_t* data, uint32_t size) -{ - SHA256_CTX sha256; - SHA256_Init(&sha256); - SHA256_Update(&sha256, data, size); - SHA256_Final(out, &sha256); -} - -static bool GetSgxQuoteImpl(const std::vector& nonce, EnclaveQuote& out) -{ - EnclaveQuoteArgs quoteArgs; - bzero("eArgs, sizeof(quoteArgs)); - - uint32_t quoteSize = 0; - if(SgxDeviceGetQuoteSize("eSize) != 0) - { - LOG("Failed to get quote size"); - return false; - } - - out.mQuoteData.resize(quoteSize); - quoteArgs.mQuote.mAsBuf = out.mQuoteData.data(); - quoteArgs.mQuoteSize = "eSize; - - sgx_report_data_t hash; - bzero(&hash, sizeof(hash)); - Sha256(hash.d, nonce.data(), nonce.size()); - quoteArgs.mReportData = &hash; - - if(SgxDeviceGetQuote("eArgs) != 0) - { - LOG("Failed to get quote"); - return false; - } - - sgx_quote_t* quote = quoteArgs.mQuote.mAsQuote; - sgx_report_body_t& report_body = quote->report_body; - - char hexBuffer[1024*64]; - out.mMrEnclaveHex = FormatHex(hexBuffer, report_body.mr_enclave.m, SGX_HASH_SIZE); - out.mMrSignerHex = FormatHex(hexBuffer, report_body.mr_signer.m, SGX_HASH_SIZE); - out.mProductId = (uint16_t)report_body.isv_prod_id; - out.mSecurityVersion = (uint16_t)report_body.isv_svn; - - return true; -} - -bool GetSgxQuote(const std::vector& nonce, EnclaveQuote& out, std::string& errorDetails) -{ - gLogger = std::stringstream(); - - const bool res = GetSgxQuoteImpl(nonce, out); - if(!res) - { - errorDetails = gLogger.str(); - } - - return res; -} diff --git a/src/cpp/quote.h b/src/cpp/quote.h deleted file mode 100644 index d060528..0000000 --- a/src/cpp/quote.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include -#include - -struct EnclaveQuote -{ - std::string mMrEnclaveHex; - std::string mMrSignerHex; - std::uint16_t mProductId; - std::uint16_t mSecurityVersion; - std::vector mQuoteData; -}; - -extern bool GetSgxQuote(const std::vector& nonce, EnclaveQuote& out, std::string& errorDetails); diff --git a/src/cpp/quote_app.cc b/src/cpp/quote_app.cc deleted file mode 100644 index 98d9170..0000000 --- a/src/cpp/quote_app.cc +++ /dev/null @@ -1,23 +0,0 @@ -#include "quote.h" - -#include - -int main() -{ - std::vector nonce{0, 1, 2, 3}; - std::string errors; - EnclaveQuote quote; - if(!GetSgxQuote(nonce, quote, errors)) - { - std::cerr << "Failed to get SGX quote. Errors:\n" << errors << std::endl; - return 1; - } - - std::cout << "MRENCLAVE = " << quote.mMrEnclaveHex << "\n"; - std::cout << "MRSIGNER = " << quote.mMrSignerHex << "\n"; - std::cout << "PRODUCT ID = " << quote.mProductId << "\n"; - std::cout << "SEC VERSION = " << quote.mSecurityVersion << "\n"; - std::cout << "QUOTE SIZE = " << quote.mQuoteData.size() << "\n"; - - return 0; -} diff --git a/src/cpp/quote_jni.cc b/src/cpp/quote_jni.cc deleted file mode 100644 index eba0188..0000000 --- a/src/cpp/quote_jni.cc +++ /dev/null @@ -1,53 +0,0 @@ -#include "quote.h" - -#include "com_uid2_attestation_azure_AzureAttestation.h" - -#include -#include - -JNIEXPORT jobject JNICALL Java_com_uid2_attestation_azure_AzureAttestation_generateAttestationQuote(JNIEnv* env, jclass thisObject, jbyteArray nonce) -{ - jboolean isCopy = JNI_FALSE; - const int nonceSize = env->GetArrayLength(nonce); - jbyte* nonceData = env->GetByteArrayElements(nonce, &isCopy); - std::vector nonceVec((const std::uint8_t*)nonceData, (const std::uint8_t*)nonceData + nonceSize); - env->ReleaseByteArrayElements(nonce, nonceData, 0); - - EnclaveQuote quote; - std::string errorDetails; - if(!GetSgxQuote(nonceVec, quote, errorDetails)) - { - jclass exClass = env->FindClass("com/uid2/attestation/azure/EnclaveException"); - if(!exClass) - { - std::cerr << "Failed to find EnclaveException class" << std::endl; - abort(); - } - - env->ThrowNew(exClass, errorDetails.c_str()); - return nullptr; - } - - jclass resultClass = env->FindClass("com/uid2/attestation/azure/EnclaveQuoteResult"); - if(!resultClass) - { - std::cerr << "Failed to find EnclaveQuoteResult class" << std::endl; - abort(); - } - - jmethodID method = env->GetMethodID(resultClass, "", "(Ljava/lang/String;Ljava/lang/String;SS[B)V"); - if(!method) - { - std::cerr << "Failed to find EnclaveQuoteResult constructor" << std::endl; - abort(); - } - - jbyteArray quoteData = env->NewByteArray(quote.mQuoteData.size()); - env->SetByteArrayRegion(quoteData, 0, quote.mQuoteData.size(), (const jbyte*)quote.mQuoteData.data()); - - return env->NewObject(resultClass, method, - env->NewStringUTF(quote.mMrEnclaveHex.c_str()), - env->NewStringUTF(quote.mMrSignerHex.c_str()), - quote.mProductId, quote.mSecurityVersion, - quoteData); -} diff --git a/src/main/java/com/uid2/attestation/azure/AzureAttestation.java b/src/main/java/com/uid2/attestation/azure/AzureAttestation.java deleted file mode 100644 index 8be9e53..0000000 --- a/src/main/java/com/uid2/attestation/azure/AzureAttestation.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.uid2.attestation.azure; - -class AzureAttestation { - static { - System.loadLibrary("azure-attestation"); - } - - public static native EnclaveQuoteResult generateAttestationQuote(byte[] nonce) throws EnclaveException; -} diff --git a/src/main/java/com/uid2/attestation/azure/AzureAttestationProvider.java b/src/main/java/com/uid2/attestation/azure/AzureAttestationProvider.java deleted file mode 100644 index d64016b..0000000 --- a/src/main/java/com/uid2/attestation/azure/AzureAttestationProvider.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.uid2.attestation.azure; - -import com.uid2.enclave.AttestationException; -import com.uid2.enclave.IAttestationProvider; -import java.util.Arrays; - -public class AzureAttestationProvider implements IAttestationProvider { - @Override - public byte[] getAttestationRequest(byte[] publicKey) throws AttestationException { - try { - byte nonce[] = publicKey; - EnclaveQuoteResult result = AzureAttestation.generateAttestationQuote(nonce); - return result.quote; - } catch (EnclaveException e) { - throw new AttestationException(e); - } - } -} diff --git a/src/main/java/com/uid2/attestation/azure/EnclaveQuoteResult.java b/src/main/java/com/uid2/attestation/azure/EnclaveQuoteResult.java deleted file mode 100644 index 35c9f69..0000000 --- a/src/main/java/com/uid2/attestation/azure/EnclaveQuoteResult.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.uid2.attestation.azure; - -class EnclaveQuoteResult { - public String mrEnclave; - public String mrSigner; - public short productId; - public short securityVersion; - public byte[] quote; - - public EnclaveQuoteResult(String mrEnclave, String mrSigner, short productId, short securityVersion, byte[] quote) { - this.mrEnclave = mrEnclave; - this.mrSigner = mrSigner; - this.productId = productId; - this.securityVersion = securityVersion; - this.quote = quote; - } -} diff --git a/test.sh b/test.sh deleted file mode 100755 index fab8812..0000000 --- a/test.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -set -ex - -cd example -./build.sh