This is an automated email from the ASF dual-hosted git repository. shaojunwang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-teaclave-java-tee-sdk.git
commit f2ebac3b8abeae9be73c6118bd6b066b8082ee77 Author: jeffery.wsj <[email protected]> AuthorDate: Tue Jun 28 10:48:51 2022 +0800 [sdk] Add Embedded Libos tee enclave occlum for JavaEnclave Summary: 1. Add occlum enclave for JavaEnclave as embedded mode 2. Implement remote attestation generation and verification for Embedded LibOS enclave Test Plan: all tests pass Reviewers: lei.yul, cengfeng.lzy, sanhong.lsh Issue: https://aone.alibaba-inc.com/task/43348805 CR: https://code.aone.alibaba-inc.com/java-tee/JavaEnclave/codereview/9413169 --- build.sh | 5 +- sdk/common/pom.xml | 4 + .../EmbeddedLibOSInnerAttestationReport.java | 40 ++++ .../common/EnclaveInvocationContext.java | 9 +- .../common/SocketEnclaveInvocationContext.java | 51 +++++ .../exception/ConfidentialComputingException.java | 2 + .../enclave/NativeCommandUtil.java | 1 - .../enclave/agent/EnclaveAgent.java | 102 +++++++++ .../enclave/agent/EnclaveAgentServiceImpl.java | 86 +++++++ .../enclave/agent/EnclaveShutDown.java | 49 ++++ .../enclave/agent/RemoteAttestation.java | 21 ++ .../enclave/framework/LoadServiceInvoker.java | 4 +- .../enclave/framework/ServiceMethodInvoker.java | 1 - .../enclave/framework/UnloadServiceInvoker.java | 1 - .../enclave/system/EnclavePhysicalMemory.java | 1 - .../remote_attestation_generate/Makefile | 14 ++ .../jni_occlum_attestation_generate.c | 83 +++++++ .../jni_occlum_attestation_generate.h | 47 ++++ .../platform/tee_sdk_svm/wrapper/tee_sdk_wrapper.c | 1 - sdk/host/pom.xml | 4 + .../host/AbstractEnclave.java | 34 +-- .../host/AttestationReport.java | 3 + .../host/EmbeddedLibOSAttestationReport.java | 10 + .../host/EmbeddedLibOSEnclave.java | 248 +++++++++++++++++++++ .../host/EmbeddedLibOSEnclaveConfig.java | 83 +++++++ .../host/EnclaveConfigure.java | 5 + .../confidentialcomputing/host/EnclaveDebug.java | 2 +- .../{EnclaveDebug.java => EnclaveSimulate.java} | 14 +- .../confidentialcomputing/host/EnclaveType.java | 7 + .../confidentialcomputing/host/ExtractLibrary.java | 79 ++++++- .../host/MockInJvmEnclave.java | 8 +- .../host/MockInSvmEnclave.java | 28 ++- .../host/ProxyEnclaveInvocationHandler.java | 32 +-- .../host/RemoteAttestation.java | 6 +- ...tationReport.java => SGXAttestationReport.java} | 20 +- .../host/SGXRemoteAttestationVerify.java | 1 - .../host/TeeSdkAttestationReport.java | 31 +-- .../confidentialcomputing/host/TeeSdkEnclave.java | 27 ++- .../host/exception/EnclaveCreatingException.java | 1 + .../native/cpp/attestation_verify/sgx/jni/Makefile | 1 + .../sgx/jni/jni_remote_attestation_verify.c | 1 - .../cpp/platform/libos_occlum_enclave/jni/Makefile | 13 ++ .../libos_occlum_enclave/jni/jni_occlum_enclave.c | 206 +++++++++++++++++ .../libos_occlum_enclave/jni/jni_occlum_enclave.h | 60 +++++ .../cpp/platform/mock_in_svm/jni/jni_mock_in_svm.c | 7 +- .../cpp/platform/mock_in_svm/jni/jni_mock_in_svm.h | 6 +- .../cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.c | 17 +- .../cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.h | 6 +- .../host/MockTestEnclave.java | 24 +- .../host/TestRemoteAttestation.java | 12 +- .../bin/platform/libos_occlum_enclave/jni/.gitkeep | 0 .../libos_occlum_enclave_attestation/.gitkeep | 0 .../libos_occlum_enclave/enclave/config.mk | 5 + .../platform/libos_occlum_enclave/jni/config.mk | 17 ++ .../config/platform/tee_sdk_svm/jni/config.mk | 4 +- .../config/remote_attestation_verify/sgx/config.mk | 2 +- sdk/native/script/build_app/Makefile | 5 +- .../script/build_app/libos_occlum_enclave_build.sh | 87 ++++++++ sdk/native/script/build_app/make.sh | 1 - sdk/native/script/build_enclave_sdk/Makefile | 8 + sdk/native/script/build_host_sdk/Makefile | 19 ++ sdk/native/script/build_host_sdk/make.sh | 7 + sdk/pom.xml | 12 +- test/enclave/pom.xml | 21 +- .../src/main/resources/embedded_libos_enclave.json | 11 + test/host/pom.xml | 4 + .../test/host/TestJavaEnclaveService.java | 92 ++++++-- test/pom.xml | 2 +- tools/cicd/Dockerfile | 19 +- tools/cicd/make.sh | 6 +- 70 files changed, 1662 insertions(+), 178 deletions(-) diff --git a/build.sh b/build.sh index 5d096d2..fc270bc 100755 --- a/build.sh +++ b/build.sh @@ -9,6 +9,9 @@ SHELL_FOLDER=$(cd "$(dirname "$0")";pwd) cd "${SHELL_FOLDER}" +# fix occlum aesm service issue. +sed -i '128,129s/.*//g' /opt/occlum/build/bin/occlum + # workspace dir is the same as build.sh path location. WORKDIR="$PWD" SETTING="--settings /root/tools/settings.xml" @@ -19,4 +22,4 @@ cd "${WORKDIR}"/sdk && mvn $SETTING clean install rm -rf /opt/javaenclave && mkdir -p /opt/javaenclave && cp -r ${SHELL_FOLDER}/sdk/native/bin /opt/javaenclave \ && cp -r ${SHELL_FOLDER}/sdk/native/config /opt/javaenclave && cp -r ${SHELL_FOLDER}/sdk/native/script/build_app /opt/javaenclave # Test unit test cases in JavaEnclave -cd "${WORKDIR}"/test && mvn $SETTING -Pnative clean package +cd "${WORKDIR}"/test && OCCLUM_RELEASE_ENCLAVE=true mvn $SETTING -Pnative clean package diff --git a/sdk/common/pom.xml b/sdk/common/pom.xml index b039d49..efe3fa5 100644 --- a/sdk/common/pom.xml +++ b/sdk/common/pom.xml @@ -80,6 +80,10 @@ </plugins> </build> <dependencies> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-compress</artifactId> + </dependency> <dependency> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> diff --git a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EmbeddedLibOSInnerAttestationReport.java b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EmbeddedLibOSInnerAttestationReport.java new file mode 100644 index 0000000..29e2c9f --- /dev/null +++ b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EmbeddedLibOSInnerAttestationReport.java @@ -0,0 +1,40 @@ +package com.alibaba.confidentialcomputing.common; + +import java.io.Serializable; + +/** + * This class is used to transfer embedded lib os attestation report between JavaEnclave's + * host and enclave module. + */ +public final class EmbeddedLibOSInnerAttestationReport implements Serializable { + private static final long serialVersionUID = -6944029051086666440L; + + private final byte[] quote; + private final byte[] mrSigner; + private final byte[] mrEnclave; + private final byte[] userData; + + + public EmbeddedLibOSInnerAttestationReport(byte[] quote, byte[] mrSigner, byte[] mrEnclave, byte[] userData) { + this.quote = quote; + this.mrSigner = mrSigner; + this.mrEnclave = mrEnclave; + this.userData = userData; + } + + public byte[] getQuote() { + return this.quote; + } + + public byte[] getMrSigner() { + return this.mrSigner; + } + + public byte[] getMrEnclave() { + return this.mrEnclave; + } + + public byte[] getUserData() { + return this.userData; + } +} diff --git a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationContext.java b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationContext.java index c0325a0..de7244f 100644 --- a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationContext.java +++ b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationContext.java @@ -7,7 +7,7 @@ import java.io.Serializable; * call, including the service instance's unique instanceIdentity, interface name, class name, * method name and its parameters. */ -public final class EnclaveInvocationContext implements Serializable { +public class EnclaveInvocationContext implements Serializable { private static final long serialVersionUID = 6878585714134748604L; private final ServiceHandler serviceHandler; @@ -15,6 +15,13 @@ public final class EnclaveInvocationContext implements Serializable { private final String[] parameterTypes; private final Object[] arguments; + public EnclaveInvocationContext() { + this.serviceHandler = null; + this.methodName = null; + this.parameterTypes = null; + this.arguments = null; + } + public EnclaveInvocationContext(ServiceHandler serviceHandler, String methodName, String[] parameterTypes, diff --git a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/SocketEnclaveInvocationContext.java b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/SocketEnclaveInvocationContext.java new file mode 100644 index 0000000..93926b5 --- /dev/null +++ b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/SocketEnclaveInvocationContext.java @@ -0,0 +1,51 @@ +package com.alibaba.confidentialcomputing.common; + +/** + * This class stores a method's necessary information for reflection + * call by socket http, including the service instance's unique instanceIdentity, + * interface name, class name, method name and its parameters. + * It's used for embedded lib os inner service invocation. + */ +public final class SocketEnclaveInvocationContext extends EnclaveInvocationContext { + private static final long serialVersionUID = 6202620980098144988L; + public static final String SERVICE_LOADING = "service_loading"; + public static final String SERVICE_UNLOADING = "service_unloading"; + public static final String METHOD_INVOCATION = "method_invocation"; + public static final String REMOTE_ATTESTATION_GENERATE = "remote_attestation_generate"; + public static final String ENCLAVE_DESTROY = "enclave_destroy"; + + private final String agentServiceName; + private final byte[] userData; + + public SocketEnclaveInvocationContext( + String agentServiceName, + EnclaveInvocationContext context) { + super(context.getServiceHandler(), context.getMethodName(), context.getParameterTypes(), context.getArguments()); + this.agentServiceName = agentServiceName; + this.userData = null; + } + + public SocketEnclaveInvocationContext(String agentServiceName, ServiceHandler serviceHandler) { + super(serviceHandler); + this.agentServiceName = agentServiceName; + this.userData = null; + } + + public SocketEnclaveInvocationContext(String agentServiceName, byte[] userData) { + this.agentServiceName = agentServiceName; + this.userData = userData; + } + + public SocketEnclaveInvocationContext(String agentServiceName) { + this.agentServiceName = agentServiceName; + this.userData = null; + } + + public String getAgentServiceName() { + return agentServiceName; + } + + public byte[] getUserData() { + return userData; + } +} diff --git a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/exception/ConfidentialComputingException.java b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/exception/ConfidentialComputingException.java index 43c3b25..eaaba57 100644 --- a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/exception/ConfidentialComputingException.java +++ b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/exception/ConfidentialComputingException.java @@ -9,6 +9,8 @@ public class ConfidentialComputingException extends Exception { private static final long serialVersionUID = 5964126736764332957L; + public ConfidentialComputingException() {super();} + /** * @param info exception information. */ diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/NativeCommandUtil.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/NativeCommandUtil.java index 9966a30..a5afe9f 100644 --- a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/NativeCommandUtil.java +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/NativeCommandUtil.java @@ -3,7 +3,6 @@ package com.alibaba.confidentialcomputing.enclave; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; -import java.io.SequenceInputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveAgent.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveAgent.java new file mode 100644 index 0000000..3cf96df --- /dev/null +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveAgent.java @@ -0,0 +1,102 @@ +package com.alibaba.confidentialcomputing.enclave.agent; + +import com.alibaba.confidentialcomputing.common.SerializationHelper; +import com.alibaba.confidentialcomputing.common.SocketEnclaveInvocationContext; +import com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingException; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; + +class EnclaveAgent { + private static final String HTTP_EXECUTE_THREAD_NAME = "enclave_http_remote_invoking_thread"; + private static final String HTTP_SERVER_NAME = "/enclaveAgent"; + private static volatile EnclaveAgentServiceImpl service = new EnclaveAgentServiceImpl(); + private static volatile HttpServer httpServer = null; + + // socket service port is from host side. + public static void main(String[] args) throws ConfidentialComputingException, IOException { + if (args.length != 3) { + throw new ConfidentialComputingException("lib os enclave agent service's port resource is not available."); + } + int portHost = Integer.parseInt(args[0]); + int portEnclave = Integer.parseInt(args[1]); + int httpThreadPoolSize = Integer.parseInt(args[2]); + + notifyHostAndCreateHttpConnect(portHost, portEnclave, httpThreadPoolSize); + + // wait for enclave shut down notification. + EnclaveShutDown.shutDownWait(); + } + + private static void notifyHostAndCreateHttpConnect(int portHost, int portEnclave, int threadPoolSize) throws IOException { + // create http connection and wait for request from host. + httpServer = HttpServer.create(new InetSocketAddress(portEnclave), 0); + httpServer.createContext(HTTP_SERVER_NAME, new EnclaveHttpHandler()); + httpServer.setExecutor(Executors.newScheduledThreadPool(threadPoolSize, new ThreadFactory() { + public Thread newThread(Runnable r) { + Thread thread = new Thread(r); + thread.setName(HTTP_EXECUTE_THREAD_NAME); + thread.setDaemon(true); + return thread; + } + })); + httpServer.start(); + // notify host that enclave jvm had started up. + new Socket("localhost", portHost); + } + + static void closeHttpService() { + httpServer.stop(0); + } + + private static void writeBackResponse(HttpExchange exchange, byte[] response) throws IOException { + exchange.sendResponseHeaders(200, response.length); + OutputStream outputStream = exchange.getResponseBody(); + outputStream.write(response); + outputStream.flush(); + outputStream.close(); + } + + static class EnclaveHttpHandler implements HttpHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + InputStream inputStream = exchange.getRequestBody(); + byte[] payload = inputStream.readAllBytes(); + inputStream.close(); + SocketEnclaveInvocationContext context = null; + + try { + context = (SocketEnclaveInvocationContext) SerializationHelper.deserialize(payload); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + + switch (context.getAgentServiceName()) { + case SocketEnclaveInvocationContext.SERVICE_LOADING: + writeBackResponse(exchange, service.loadService(context.getServiceHandler().getServiceInterfaceName())); + break; + case SocketEnclaveInvocationContext.SERVICE_UNLOADING: + writeBackResponse(exchange, service.unloadService(context.getServiceHandler())); + break; + case SocketEnclaveInvocationContext.METHOD_INVOCATION: + writeBackResponse(exchange, service.invokeMethod(context)); + break; + case SocketEnclaveInvocationContext.REMOTE_ATTESTATION_GENERATE: + writeBackResponse(exchange, service.generateAttestationReport(context.getUserData())); + break; + case SocketEnclaveInvocationContext.ENCLAVE_DESTROY: + writeBackResponse(exchange, service.destroy()); + break; + default: + } + } + } +} diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveAgentServiceImpl.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveAgentServiceImpl.java new file mode 100644 index 0000000..b5e5716 --- /dev/null +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveAgentServiceImpl.java @@ -0,0 +1,86 @@ +package com.alibaba.confidentialcomputing.enclave.agent; + +import com.alibaba.confidentialcomputing.common.EnclaveInvocationContext; +import com.alibaba.confidentialcomputing.common.EnclaveInvocationResult; +import com.alibaba.confidentialcomputing.common.SerializationHelper; +import com.alibaba.confidentialcomputing.common.ServiceHandler; +import com.alibaba.confidentialcomputing.common.EmbeddedLibOSInnerAttestationReport; +import com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingException; +import com.alibaba.confidentialcomputing.enclave.framework.LoadServiceInvoker; +import com.alibaba.confidentialcomputing.enclave.framework.ServiceMethodInvoker; +import com.alibaba.confidentialcomputing.enclave.framework.UnloadServiceInvoker; + +import java.io.IOException; + +public class EnclaveAgentServiceImpl { + private static final LoadServiceInvoker loadServiceInstance = new LoadServiceInvoker(); + private static final ServiceMethodInvoker serviceInvokerInstance = new ServiceMethodInvoker(); + private static final UnloadServiceInvoker unloadServiceInstance = new UnloadServiceInvoker(); + + protected EnclaveAgentServiceImpl() { + } + + public byte[] loadService(String serviceName) { + try { + return SerializationHelper.serialize(loadServiceInstance.callMethod(serviceName)); + } catch (IOException e) { + try { + return SerializationHelper.serialize(new EnclaveInvocationResult(null, e)); + } catch (IOException ex) { + } + } + return null; + } + + public byte[] unloadService(ServiceHandler handler) { + try { + return SerializationHelper.serialize(unloadServiceInstance.callMethod(handler)); + } catch (IOException e) { + try { + return SerializationHelper.serialize(new EnclaveInvocationResult(null, e)); + } catch (IOException ex) { + } + } + return null; + } + + public byte[] invokeMethod(EnclaveInvocationContext context) { + try { + return SerializationHelper.serialize(serviceInvokerInstance.callMethod(context)); + } catch (IOException e) { + try { + return SerializationHelper.serialize(new EnclaveInvocationResult(null, e)); + } catch (IOException ex) { + } + } + return null; + } + + public byte[] generateAttestationReport(byte[] userDate) { + EmbeddedLibOSInnerAttestationReport report = null; + Throwable exception = null; + try { + report = RemoteAttestation.generateAttestationReport(userDate); + } catch (ConfidentialComputingException e) { + exception = e; + } + try { + return SerializationHelper.serialize(new EnclaveInvocationResult(report, exception)); + } catch (IOException e) { + try { + return SerializationHelper.serialize(new EnclaveInvocationResult(null, e)); + } catch (IOException ex) { + } + } + return null; + } + + public byte[] destroy() { + EnclaveShutDown.shutDownNotify(); + try { + return SerializationHelper.serialize(new EnclaveInvocationResult(true, null)); + } catch (IOException e) { + } + return null; + } +} diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveShutDown.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveShutDown.java new file mode 100644 index 0000000..b448c9f --- /dev/null +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/EnclaveShutDown.java @@ -0,0 +1,49 @@ +package com.alibaba.confidentialcomputing.enclave.agent; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +class EnclaveShutDown { + private static final int SHUTDOWN_DELAY_DURATION = 1000; // TimeUnit.MilliSecond + private static BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(); + + static void shutDownNotify() { + boolean interrupted = false; + try { + while (true) { + try { + queue.put(0); + return; + } catch (InterruptedException e) { + interrupted = true; + } + } + } finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + static void shutDownWait() { + boolean interrupted = false; + try { + while (true) { + try { + queue.take(); + // wait for destroy localhost remote destroy invocation return. + Thread.sleep(SHUTDOWN_DELAY_DURATION); + // close cached socket resources and socket service. + EnclaveAgent.closeHttpService(); + return; + } catch (InterruptedException e) { + interrupted = true; + } + } + } finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } +} diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/RemoteAttestation.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/RemoteAttestation.java new file mode 100644 index 0000000..557058c --- /dev/null +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/agent/RemoteAttestation.java @@ -0,0 +1,21 @@ +package com.alibaba.confidentialcomputing.enclave.agent; + +import com.alibaba.confidentialcomputing.common.EmbeddedLibOSInnerAttestationReport; +import com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingException; + +public class RemoteAttestation { + // lib os embedded enclave remote attestation jni.so path in occlum image. + private final static String JNI_EXTRACTED_PACKAGE_PATH = "/usr/lib/libos_occlum_enclave_attestation/lib_occlum_attestation_generate.so"; + + private static native void registerNatives(); + private static native EmbeddedLibOSInnerAttestationReport generateAttestationReportNative(byte[] userDate) throws ConfidentialComputingException; + + static { + System.load(JNI_EXTRACTED_PACKAGE_PATH); + registerNatives(); + } + + public static EmbeddedLibOSInnerAttestationReport generateAttestationReport(byte[] userDate) throws ConfidentialComputingException { + return generateAttestationReportNative(userDate); + } +} diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/LoadServiceInvoker.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/LoadServiceInvoker.java index d0c03ae..a4b2dec 100644 --- a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/LoadServiceInvoker.java +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/LoadServiceInvoker.java @@ -17,9 +17,9 @@ public final class LoadServiceInvoker implements EnclaveMethodInvoker<String> { Class<?> service; try { service = Class.forName(inputData); + return new EnclaveInvocationResult(EnclaveContext.getInstance().loadService(service), null); } catch (ClassNotFoundException e) { - throw new RuntimeException("Can't find the service interface class.", e); + return new EnclaveInvocationResult(null, e); } - return new EnclaveInvocationResult(EnclaveContext.getInstance().loadService(service), null); } } diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/ServiceMethodInvoker.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/ServiceMethodInvoker.java index 8387804..7f12b9f 100644 --- a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/ServiceMethodInvoker.java +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/ServiceMethodInvoker.java @@ -6,7 +6,6 @@ import com.alibaba.confidentialcomputing.common.ServiceHandler; import com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingException; import jdk.vm.ci.meta.MetaUtil; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/UnloadServiceInvoker.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/UnloadServiceInvoker.java index 5f5fb6b..0b82737 100644 --- a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/UnloadServiceInvoker.java +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/framework/UnloadServiceInvoker.java @@ -1,6 +1,5 @@ package com.alibaba.confidentialcomputing.enclave.framework; - import com.alibaba.confidentialcomputing.common.EnclaveInvocationResult; import com.alibaba.confidentialcomputing.common.ServiceHandler; import com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingException; diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclavePhysicalMemory.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclavePhysicalMemory.java index 35521b5..cdab91d 100644 --- a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclavePhysicalMemory.java +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclavePhysicalMemory.java @@ -6,7 +6,6 @@ import com.oracle.svm.core.util.VMError; import org.graalvm.word.UnsignedWord; import org.graalvm.word.WordFactory; -import java.util.Properties; /** * Physical memory implementation for Enclave environment. The sysconf(_SC_PAGESIZE()) and diff --git a/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/Makefile b/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/Makefile new file mode 100644 index 0000000..cdf38d9 --- /dev/null +++ b/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/Makefile @@ -0,0 +1,14 @@ +include $(NATIVE_BASE_DIR)/config/config.mk +include $(NATIVE_BASE_DIR)/config/platform/libos_occlum_enclave/enclave/config.mk + +.PHONY: all build clean + +all: build + +build: + $(CC) jni_occlum_attestation_generate.c -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/$(shell uname -s | tr A-Z a-z) \ + -I$(INCPATH) -I$(TEE_SDK_PATH)/include -L$(LIBPATH) -locclum_dcap -fPIC -shared \ + -o $(BIN)/platform/libos_occlum_enclave/libos_occlum_enclave_attestation/lib_occlum_attestation_generate.so + +clean: + rm -rf $(BIN)/platform/libos_occlum_enclave/libos_occlum_enclave_attestation/lib_occlum_attestation_generate.so \ No newline at end of file diff --git a/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/jni_occlum_attestation_generate.c b/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/jni_occlum_attestation_generate.c new file mode 100644 index 0000000..a9b689e --- /dev/null +++ b/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/jni_occlum_attestation_generate.c @@ -0,0 +1,83 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "sgx_quote_3.h" +#include "sgx_urts.h" +#include "sgx_pce.h" +#include "sgx_error.h" + +#include <occlum_dcap.h> + +#include "jni_occlum_attestation_generate.h" + +static JNINativeMethod embedded_libos_occlum_enclave_methods[] = { + {"generateAttestationReportNative", LIBOS_OCCLUM_ENCLAVE_REMOTE_ATTESTATION_GENERATION_SIGNATURE, (void *)&JavaEnclave_TeeLibOSNativeRemoteAttestationGenerate}, +}; + +JNIEXPORT void JNICALL Java_com_alibaba_confidentialcomputing_enclave_agent_RemoteAttestation_registerNatives(JNIEnv *env, jclass cls) { + (*env)->RegisterNatives(env, cls, embedded_libos_occlum_enclave_methods, sizeof(embedded_libos_occlum_enclave_methods)/sizeof(embedded_libos_occlum_enclave_methods[0])); +} + +JNIEXPORT jobject JNICALL JavaEnclave_TeeLibOSNativeRemoteAttestationGenerate(JNIEnv *env, jclass cls, jbyteArray userData) { + + void *handle = dcap_quote_open(); + if (handle == NULL) { + THROW_EXCEPTION(env, LIBOS_OCCLUM_ENCLAVE_REMOTE_ATTESTATION_EXCEPTION, "libos enclave occlum remote attestation generate: dcap_quote_open failed.") + } + + uint32_t quote_size = dcap_get_quote_size(handle); + uint8_t *p_quote_buffer = (uint8_t*)malloc(quote_size); + if (p_quote_buffer == NULL) { + dcap_quote_close(handle); + THROW_EXCEPTION(env, LIBOS_OCCLUM_ENCLAVE_REMOTE_ATTESTATION_EXCEPTION, "libos enclave occlum remote attestation generate: malloc p_quote_buffer failed.") + } + memset(p_quote_buffer, 0, quote_size); + + sgx_report_data_t report_data = {0}; + jbyte *userData_copy = (*env)->GetByteArrayElements(env, userData, NULL); + int userData_copy_length = (*env)->GetArrayLength(env, userData); + memcpy(report_data.d, userData_copy, userData_copy_length); + + int32_t ret = dcap_generate_quote(handle, p_quote_buffer, &report_data); + if (ret != 0x0) { + (*env)->ReleaseByteArrayElements(env, userData, userData_copy, 0); + free(p_quote_buffer); + dcap_quote_close(handle); + THROW_EXCEPTION(env, LIBOS_OCCLUM_ENCLAVE_REMOTE_ATTESTATION_EXCEPTION, "libos enclave occlum remote attestation generate: dcap_generate_quote failed.") + } + + sgx_quote3_t *p_quote = (sgx_quote3_t *)p_quote_buffer; + sgx_report_body_t *p_rep_body = (sgx_report_body_t *)(&p_quote->report_body); + + jbyteArray quote_array = (*env)->NewByteArray(env, quote_size); + jbyte *quote_array_ptr = (*env)->GetByteArrayElements(env, quote_array, NULL); + memcpy(quote_array_ptr, p_quote_buffer, quote_size); + + // create mr enclave byte array. + jbyteArray mr_enclave = (*env)->NewByteArray(env, SGX_HASH_SIZE); + jbyte *mr_enclave_buf = (*env)->GetByteArrayElements(env, mr_enclave, NULL); + memcpy(mr_enclave_buf, p_quote->report_body.mr_enclave.m, SGX_HASH_SIZE); + + // create mr signer byte array. + jbyteArray mr_signer = (*env)->NewByteArray(env, SGX_HASH_SIZE); + jbyte *mr_signer_buf = (*env)->GetByteArrayElements(env, mr_signer, NULL); + memcpy(mr_signer_buf, p_quote->report_body.mr_signer.m, SGX_HASH_SIZE); + + // create user data byte array. + jbyteArray user_data = (*env)->NewByteArray(env, SGX_REPORT_DATA_SIZE); + jbyte *user_data_buf = (*env)->GetByteArrayElements(env, user_data, NULL); + memcpy(user_data_buf, p_quote->report_body.report_data.d, SGX_REPORT_DATA_SIZE); + + (*env)->ReleaseByteArrayElements(env, userData, userData_copy, 0); + (*env)->ReleaseByteArrayElements(env, quote_array, quote_array_ptr, 0); + (*env)->ReleaseByteArrayElements(env, mr_enclave, mr_enclave_buf, 0); + (*env)->ReleaseByteArrayElements(env, mr_signer, mr_signer_buf, 0); + (*env)->ReleaseByteArrayElements(env, user_data, user_data_buf, 0); + free(p_quote_buffer); + dcap_quote_close(handle); + + jclass libos_inner_ra_report_clazz = (*env)->FindClass(env, LIBOS_OCCLUM_INNER_ATTESTATION_REPORT); + jmethodID construct = (*env)->GetMethodID(env, libos_inner_ra_report_clazz, "<init>", "([B[B[B[B)V"); + return (*env)->NewObject(env, libos_inner_ra_report_clazz, construct, quote_array, mr_signer, mr_enclave, user_data); +} diff --git a/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/jni_occlum_attestation_generate.h b/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/jni_occlum_attestation_generate.h new file mode 100644 index 0000000..c88e9ed --- /dev/null +++ b/sdk/enclave/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate/jni_occlum_attestation_generate.h @@ -0,0 +1,47 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include <jni.h> +/* Header for class com_alibaba_confidentialcomputing_enclave_agent_RemoteAttestation */ + +#ifndef _Included_com_alibaba_confidentialcomputing_enclave_agent_RemoteAttestation +#define _Included_com_alibaba_confidentialcomputing_enclave_agent_RemoteAttestation +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBOS_OCCLUM_ENCLAVE_REMOTE_ATTESTATION_GENERATION_SIGNATURE "([B)Lcom/alibaba/confidentialcomputing/common/EmbeddedLibOSInnerAttestationReport;" +#define LIBOS_OCCLUM_INNER_ATTESTATION_REPORT "com/alibaba/confidentialcomputing/common/EmbeddedLibOSInnerAttestationReport" +#define LIBOS_OCCLUM_ENCLAVE_REMOTE_ATTESTATION_EXCEPTION "com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingException" + +#define THROW_EXCEPTION(env, exception, info) \ +{ \ + jclass ra_class = (*env)->FindClass(env, exception); \ + if (ra_class == NULL) { \ + fprintf(stderr, "JavaEnclave Error: "); \ + fprintf(stderr, exception); \ + fprintf(stderr, " class loading failed.\n"); \ + return; \ + } \ + (*env)->ThrowNew(env, ra_class, info); \ + return; \ +} + +/* + * Class: com_alibaba_confidentialcomputing_enclave_agent_RemoteAttestation + * Method: registerNatives + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_alibaba_confidentialcomputing_enclave_agent_RemoteAttestation_registerNatives + (JNIEnv *, jclass); + +/* + * Class: com_alibaba_confidentialcomputing_enclave_agent_RemoteAttestation + * Method: generateAttestationReportNative + * Signature: ([B)Lcom/alibaba/confidentialcomputing/common/agent/EmbeddedLibOSInnerAttestationReport; + */ +JNIEXPORT jobject JNICALL JavaEnclave_TeeLibOSNativeRemoteAttestationGenerate + (JNIEnv *, jclass, jbyteArray); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/sdk/enclave/src/main/native/cpp/platform/tee_sdk_svm/wrapper/tee_sdk_wrapper.c b/sdk/enclave/src/main/native/cpp/platform/tee_sdk_svm/wrapper/tee_sdk_wrapper.c index 95255d4..6d651ea 100644 --- a/sdk/enclave/src/main/native/cpp/platform/tee_sdk_svm/wrapper/tee_sdk_wrapper.c +++ b/sdk/enclave/src/main/native/cpp/platform/tee_sdk_svm/wrapper/tee_sdk_wrapper.c @@ -33,7 +33,6 @@ int tee_sdk_random(void* data, long size) { } int enclave_svm_isolate_create(void* isolate, void* isolateThread) { - // printf("JavaEnclave Warning: %s is called in enclave svm.\n", __FUNCTION__); graal_isolate_t* isolate_t; graal_isolatethread_t* thread_t; diff --git a/sdk/host/pom.xml b/sdk/host/pom.xml index 1a60a7a..c65e281 100644 --- a/sdk/host/pom.xml +++ b/sdk/host/pom.xml @@ -107,6 +107,10 @@ <groupId>com.alibaba.confidentialcomputing</groupId> <artifactId>common</artifactId> </dependency> + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + </dependency> <dependency> <groupId>com.google.auto.service</groupId> <artifactId>auto-service-annotations</artifactId> diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AbstractEnclave.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AbstractEnclave.java index 486a59d..8b7bfe8 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AbstractEnclave.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AbstractEnclave.java @@ -17,7 +17,6 @@ import com.alibaba.confidentialcomputing.host.exception.RemoteAttestationExcepti import com.alibaba.confidentialcomputing.host.exception.ServicesLoadingException; import com.alibaba.confidentialcomputing.host.exception.ServicesUnloadingException; - /** * AbstractEnclave implements all kinds of enclave platform's common operation. * Such as service loadingăunloading and service method invocation. @@ -33,6 +32,9 @@ abstract class AbstractEnclave implements Enclave { if (type == EnclaveType.TEE_SDK && mode == EnclaveDebug.NONE) { throw new EnclaveCreatingException("TEE SDK enclave's debug mode must be RELEASE or DEBUG."); } + if (type == EnclaveType.EMBEDDED_LIB_OS && mode == EnclaveDebug.NONE) { + throw new EnclaveCreatingException("EMBEDDED_LIB_OS enclave's debug mode must be RELEASE or DEBUG."); + } enclaveContext = new EnclaveContext(type, mode, recycler); } @@ -44,11 +46,11 @@ abstract class AbstractEnclave implements Enclave { return enclaveContext; } - abstract byte[] loadServiceNative(byte[] payload) throws ServicesLoadingException; + abstract byte[] loadServiceNative(String service) throws ServicesLoadingException; - abstract byte[] unloadServiceNative(byte[] payload) throws ServicesUnloadingException; + abstract byte[] unloadServiceNative(ServiceHandler handler) throws ServicesUnloadingException; - abstract byte[] invokeMethodNative(byte[] payload) throws EnclaveMethodInvokingException; + abstract byte[] invokeMethodNative(EnclaveInvocationContext context) throws EnclaveMethodInvokingException; abstract AttestationReport generateAttestationReportNative(byte[] userData) throws RemoteAttestationException; @@ -60,15 +62,9 @@ abstract class AbstractEnclave implements Enclave { try { // Only need to provide service's interface name is enough to load service // in enclave. - byte[] payload; - try { - payload = SerializationHelper.serialize(service.getName()); - } catch (IOException e) { - throw new ServicesLoadingException("service name serialization failed.", e); - } EnclaveInvocationResult resultWrapper; try { - resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(loadServiceNative(payload)); + resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(loadServiceNative(service.getName())); } catch (IOException | ClassNotFoundException e) { throw new ServicesLoadingException("EnclaveInvokeResultWrapper deserialization failed.", e); } @@ -98,15 +94,9 @@ abstract class AbstractEnclave implements Enclave { throw new ServicesUnloadingException("enclave was destroyed."); } try { - byte[] payload; - try { - payload = SerializationHelper.serialize(service); - } catch (IOException e) { - throw new ServicesUnloadingException("unload service serialization failed.", e); - } EnclaveInvocationResult resultWrapper; try { - resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(unloadServiceNative(payload)); + resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(unloadServiceNative(service)); } catch (IOException | ClassNotFoundException e) { throw new ServicesUnloadingException("EnclaveInvokeResultWrapper deserialization failed.", e); } @@ -125,15 +115,9 @@ abstract class AbstractEnclave implements Enclave { throw new EnclaveMethodInvokingException("enclave was destroyed."); } try { - byte[] payload; - try { - payload = SerializationHelper.serialize(input); - } catch (IOException e) { - throw new EnclaveMethodInvokingException("EnclaveInvokeMetaWrapper serialization failed.", e); - } EnclaveInvocationResult resultWrapper; try { - resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(invokeMethodNative(payload)); + resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(invokeMethodNative(input)); } catch (IOException | ClassNotFoundException e) { throw new EnclaveMethodInvokingException("EnclaveInvokeResultWrapper deserialization failed.", e); } diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AttestationReport.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AttestationReport.java index dd8bcf9..9847907 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AttestationReport.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/AttestationReport.java @@ -71,6 +71,9 @@ public class AttestationReport implements Serializable { case 3: enclaveType = EnclaveType.TEE_SDK; break; + case 4: + enclaveType = EnclaveType.EMBEDDED_LIB_OS; + break; } System.arraycopy(attestationReport, 1, report, 0, report.length); return new AttestationReport(enclaveType, report); diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSAttestationReport.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSAttestationReport.java new file mode 100644 index 0000000..1913119 --- /dev/null +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSAttestationReport.java @@ -0,0 +1,10 @@ +package com.alibaba.confidentialcomputing.host; + +/** + * EmbeddedLibOSAttestationReport parse more details information from a lib os embedded type enclave's remote attestation report. + */ +public final class EmbeddedLibOSAttestationReport extends SGXAttestationReport { + EmbeddedLibOSAttestationReport(byte[] quote, byte[] mrSigner, byte[] mrEnclave, byte[] userData) { + super(EnclaveType.EMBEDDED_LIB_OS, quote, mrSigner, mrEnclave, userData); + } +} diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclave.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclave.java new file mode 100644 index 0000000..a0c7ff2 --- /dev/null +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclave.java @@ -0,0 +1,248 @@ +package com.alibaba.confidentialcomputing.host; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.*; +import java.util.concurrent.*; + +import com.alibaba.confidentialcomputing.common.*; +import com.alibaba.confidentialcomputing.host.exception.*; + +/** + * EmbeddedLibOSEnclave is a sgx2 enclave based on Ant's Occlum libos. + * EmbeddedLibOSEnclave is a singleton object module, there is only one + * EmbeddedLibOSEnclave object in a process. + */ +public class EmbeddedLibOSEnclave extends AbstractEnclave { + private static final int HTTP_CONNECT_TIMEOUT_MS = 50; // ms. + private static final int HTTP_READ_TIMEOUT_MS = 200; // ms. + private static final int HTTP_READ_REMOTE_ATTESTATION_TIMEOUT_MS = HTTP_READ_TIMEOUT_MS * 10; // ms. + private static final String EMBEDDED_LIB_OS_ENCLAVE_STARTUP_THREAD_NAME = "async_lib_os_enclave_startup_thread"; + private static final String HTTP_SERVER_PREFIX = "http://localhost:"; + private static final String HTTP_SERVER_NAME = "/enclaveAgent"; + private final static String JNI_EXTRACTED_PACKAGE_PATH = "jni/lib_jni_embedded_lib_os_enclave.so"; + private final static String EMBEDDED_LIB_OS_ENCLAVE_SIGNED_PACKAGE_PATH = "lib_embedded_lib_os_enclave_load.tgz"; + private final static String EMBEDDED_LIB_OS_ENCLAVE_SIGNED_PACKAGE_PATH_TAIL = "occlum_instance"; + private static volatile LibOSExtractTempPath extractTempPath; + private static volatile EmbeddedLibOSEnclave singleInstance; + + // enclaveHandle stores created enclave's handle id. + private long enclaveHandle; + private int portHost; + private int portEnclave; + private URL url; + private String httpURL; + + static EmbeddedLibOSEnclave getEmbeddedLibOSEnclaveInstance(EnclaveDebug mode, EnclaveSimulate sim) throws EnclaveCreatingException { + synchronized (EmbeddedLibOSEnclave.class) { + if (singleInstance == null) { + singleInstance = new EmbeddedLibOSEnclave(mode, sim); + } + return singleInstance; + } + } + + private EmbeddedLibOSEnclave(EnclaveDebug mode, EnclaveSimulate sim) throws EnclaveCreatingException { + // Set EnclaveContext for this enclave instance. + super(EnclaveType.EMBEDDED_LIB_OS, mode, new EnclaveServicesRecycler()); + // Extract jni .so and signed tee .so from .jar file. + // Only once extract and load operation. + if (extractTempPath == null) { + synchronized (EmbeddedLibOSEnclave.class) { + if (extractTempPath == null) { + try { + String jniTempFilePath = ExtractLibrary.extractLibrary( + EmbeddedLibOSEnclave.class.getClassLoader(), + JNI_EXTRACTED_PACKAGE_PATH); + String embeddedLibOsSignedFilePath = ExtractLibrary.extractAndDeCompressTgz( + EmbeddedLibOSEnclave.class.getClassLoader(), + EMBEDDED_LIB_OS_ENCLAVE_SIGNED_PACKAGE_PATH) + "/" + EMBEDDED_LIB_OS_ENCLAVE_SIGNED_PACKAGE_PATH_TAIL; + extractTempPath = new EmbeddedLibOSEnclave.LibOSExtractTempPath(jniTempFilePath, embeddedLibOsSignedFilePath); + System.load(extractTempPath.getJniTempFilePath()); + registerNatives(); + } catch (IOException e) { + throw new EnclaveCreatingException("extracting embedded lib os enclave jni .so or signed .so failed.", e); + } + } + } + } + + try { + portHost = getFreePort(); + portEnclave = getFreePort(); + httpURL = HTTP_SERVER_PREFIX + portEnclave + HTTP_SERVER_NAME; + url = new URL(httpURL); + // Attach to target enclave service by rmi. + attachToEnclaveAgent(mode, sim); + } catch (IOException e) { + throw new EnclaveCreatingException(e); + } + } + + // apply a free port for localhost communication between host and enclave. + private int getFreePort() throws IOException { + try (ServerSocket serverSocket = new ServerSocket(0)) { + return serverSocket.getLocalPort(); + } + } + + private Future<EnclaveCreatingException> startupLibOSEnclaveAsync(EnclaveDebug mode, EnclaveSimulate sim) { + // Create embedded lib os enclave by native call asynchronously. + // Occlum embedded start up interface is occlum_pal_exec, it blocks until progress exit in enclave. + return Executors.newFixedThreadPool(1, new ThreadFactory() { + public Thread newThread(Runnable r) { + Thread thread = new Thread(r); + thread.setName(EMBEDDED_LIB_OS_ENCLAVE_STARTUP_THREAD_NAME); + thread.setDaemon(true); + return thread; + } + }).submit(() -> { + EnclaveCreatingException exception = null; + try { + nativeCreateEnclave( + mode.getValue(), + sim.getValue(), + portHost, + portEnclave, + EmbeddedLibOSEnclaveConfig.getEmbeddedLibOSEnclaveConfigInstance(), + extractTempPath.getLibOSSignedFilePath()); + } catch (EnclaveCreatingException e) { + exception = e; + } + return exception; + }); + } + + // wait for enclave jvm start up and notify host. + private void waitForEnclaveStartup() throws IOException { + try (ServerSocket server = new ServerSocket(this.portHost)) { + server.setSoTimeout(EmbeddedLibOSEnclaveConfig.getEmbeddedLibOSEnclaveConfigInstance().getEmbeddedLibOSEnclaveStartupDuration()); + server.accept(); + } + } + + // attach to enclave embedded lib os java service. + private void attachToEnclaveAgent(EnclaveDebug mode, EnclaveSimulate sim) throws EnclaveCreatingException { + startupLibOSEnclaveAsync(mode, sim); + try { + waitForEnclaveStartup(); + } catch (IOException e) { + throw new EnclaveCreatingException(e); + } + } + + private static native void registerNatives(); + + private native int nativeCreateEnclave(int mode, int sim, int portHost, int portEnclave, EmbeddedLibOSEnclaveConfig config, String path) throws EnclaveCreatingException; + + private native int nativeDestroyEnclave(long enclaveHandler) throws EnclaveDestroyingException; + + private byte[] remoteRequest(byte[] request, int connectTimeout, int inTimeout) throws IOException, InterruptedException { + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + conn.setRequestProperty("Connection", "Keep-Alive"); + conn.setDoOutput(true); + conn.setDoInput(true); + conn.setConnectTimeout(connectTimeout); + conn.setReadTimeout(inTimeout); + conn.connect(); + + try (OutputStream outputStream = conn.getOutputStream()) { + outputStream.write(request); + outputStream.flush(); + } + + try (InputStream inputStream = conn.getInputStream()) { + return inputStream.readAllBytes(); + } + } + + @Override + byte[] loadServiceNative(String service) throws ServicesLoadingException { + try { + SocketEnclaveInvocationContext context = + new SocketEnclaveInvocationContext(SocketEnclaveInvocationContext.SERVICE_LOADING, new ServiceHandler(service)); + return remoteRequest(SerializationHelper.serialize(context), HTTP_CONNECT_TIMEOUT_MS, HTTP_READ_TIMEOUT_MS); + } catch (InterruptedException | IOException e) { + throw new ServicesLoadingException(e); + } + } + + @Override + byte[] unloadServiceNative(ServiceHandler handler) throws ServicesUnloadingException { + try { + SocketEnclaveInvocationContext context = + new SocketEnclaveInvocationContext(SocketEnclaveInvocationContext.SERVICE_UNLOADING, handler); + return remoteRequest(SerializationHelper.serialize(context), HTTP_CONNECT_TIMEOUT_MS, HTTP_READ_TIMEOUT_MS); + } catch (InterruptedException | IOException e) { + throw new ServicesUnloadingException(e); + } + } + + @Override + byte[] invokeMethodNative(EnclaveInvocationContext service) throws EnclaveMethodInvokingException { + try { + SocketEnclaveInvocationContext context = + new SocketEnclaveInvocationContext(SocketEnclaveInvocationContext.METHOD_INVOCATION, service); + // Should not set http timeout parameter in method invoke, the duration is deeply depends on user service. + return remoteRequest(SerializationHelper.serialize(context), HTTP_CONNECT_TIMEOUT_MS, 0x0); + } catch (InterruptedException | IOException e) { + throw new EnclaveMethodInvokingException(e); + } + } + + @Override + AttestationReport generateAttestationReportNative(byte[] userData) throws RemoteAttestationException { + try { + SocketEnclaveInvocationContext context = + new SocketEnclaveInvocationContext(SocketEnclaveInvocationContext.REMOTE_ATTESTATION_GENERATE, userData); + EnclaveInvocationResult resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize( + remoteRequest(SerializationHelper.serialize(context), HTTP_CONNECT_TIMEOUT_MS, HTTP_READ_REMOTE_ATTESTATION_TIMEOUT_MS)); + if (resultWrapper.getException() != null) { + throw resultWrapper.getException(); + } + EmbeddedLibOSInnerAttestationReport report = (EmbeddedLibOSInnerAttestationReport) resultWrapper.getResult(); + return new EmbeddedLibOSAttestationReport( + report.getQuote(), + report.getMrSigner(), + report.getMrEnclave(), + report.getUserData()); + } catch (InterruptedException | IOException | ClassNotFoundException e) { + throw new RemoteAttestationException(e); + } catch (Throwable e) { + throw new RemoteAttestationException(e); + } + } + + static int verifyAttestationReport(byte[] quote) throws RemoteAttestationException { + return SGXRemoteAttestationVerify.VerifyAttestationReport(quote); + } + + @Override + public void destroy() throws EnclaveDestroyingException { + synchronized (EmbeddedLibOSEnclave.class) { + // Because enclave libos occlum doesn't support creating a new occlum instance even + // destroy the pre-created occlum instance, Do nothing here. + // embedded lib os occlum instance in JavaEnclave is similar with a singleton instance. + } + } + + class LibOSExtractTempPath { + private final String jniTempFilePath; + private final String libOsSignedFilePath; + + LibOSExtractTempPath(String jniTempFilePath, String teeSdkSignedFilePath) { + this.jniTempFilePath = jniTempFilePath; + this.libOsSignedFilePath = teeSdkSignedFilePath; + } + + String getJniTempFilePath() { + return jniTempFilePath; + } + + String getLibOSSignedFilePath() { + return libOsSignedFilePath; + } + } +} diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclaveConfig.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclaveConfig.java new file mode 100644 index 0000000..8eecb71 --- /dev/null +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclaveConfig.java @@ -0,0 +1,83 @@ +package com.alibaba.confidentialcomputing.host; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.json.JSONArray; +import org.json.JSONObject; + +import static com.alibaba.confidentialcomputing.host.ExtractLibrary.extractLibrary; + +class EmbeddedLibOSEnclaveConfig { + private final static String EMBEDDED_LIB_OS_ENCLAVE_CONFIG_FILE = "embedded_libos_enclave.json"; + private static String configFilePath; + private static EmbeddedLibOSEnclaveConfig config; + + private boolean debuggable = false; + private int agentHttpHandlerThreadPoolSize = 5; + private int embeddedLibOSEnclaveStartupDuration = (int) TimeUnit.MINUTES.toMillis(1); + private String libOSLogLevel = "off"; + private String[] enclaveJVMArgs = null; + + static { + try { + configFilePath = extractLibrary(EmbeddedLibOSEnclave.class.getClassLoader(), EMBEDDED_LIB_OS_ENCLAVE_CONFIG_FILE); + File file = new File(configFilePath); + String content = Files.readString(file.toPath(), Charset.forName("UTF-8")); + JSONObject jsonObject = new JSONObject(content); + boolean debuggable = jsonObject.getBoolean("debuggable"); + int agentHttpHandlerThreadPoolSize = jsonObject.getInt("agent_http_handler_thread_pool_size"); + int embeddedLibOSEnclaveStartupDuration = jsonObject.getInt("enclave_startup_duration_ms"); + String libOSLogLevel = jsonObject.getString("log_level"); + JSONArray jvmArgs = jsonObject.getJSONArray("enclave_jvm_args"); + List<String> jvmArgsList = new ArrayList<>(); + for (int i = 0; i < jvmArgs.length(); i++) { + jvmArgsList.add(jvmArgs.getString(i)); + } + String[] enclaveJVMArgs = jvmArgsList.toArray(new String[jvmArgsList.size()]); + config = new EmbeddedLibOSEnclaveConfig(debuggable, agentHttpHandlerThreadPoolSize, embeddedLibOSEnclaveStartupDuration, libOSLogLevel, enclaveJVMArgs); + } catch (IOException e) { + e.printStackTrace(); + } + } + + static EmbeddedLibOSEnclaveConfig getEmbeddedLibOSEnclaveConfigInstance() { + return config; + } + + private EmbeddedLibOSEnclaveConfig(boolean debuggable, int agentHttpHandlerThreadPoolSize, int embeddedLibOSEnclaveStartupDuration, String libOSLogLevel, String[] jvmArgs) { + this.debuggable = debuggable; + this.agentHttpHandlerThreadPoolSize = agentHttpHandlerThreadPoolSize; + this.embeddedLibOSEnclaveStartupDuration = embeddedLibOSEnclaveStartupDuration; + this.libOSLogLevel = libOSLogLevel; + this.enclaveJVMArgs = jvmArgs; + } + + EnclaveDebug getDebuggable() { + if (this.debuggable) { + return EnclaveDebug.DEBUG; + } + return EnclaveDebug.RELEASE; + } + + int getAgentHttpHandlerThreadPoolSize() { + return this.agentHttpHandlerThreadPoolSize; + } + + int getEmbeddedLibOSEnclaveStartupDuration() { + return this.embeddedLibOSEnclaveStartupDuration; + } + + String getLibOSLogLevel() { + return this.libOSLogLevel; + } + + String[] getEnclaveJVMArgs() { + return this.enclaveJVMArgs; + } +} diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveConfigure.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveConfigure.java index 208e4de..c958b4c 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveConfigure.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveConfigure.java @@ -25,6 +25,9 @@ class EnclaveConfigure { case "TEE_SDK": enclaveType = EnclaveType.TEE_SDK; break; + case "EMBEDDED_LIB_OS": + enclaveType = EnclaveType.EMBEDDED_LIB_OS; + break; case "MOCK_IN_JVM": enclaveType = EnclaveType.MOCK_IN_JVM; break; @@ -77,6 +80,8 @@ class EnclaveConfigure { return new MockInSvmEnclave(); case TEE_SDK: return new TeeSdkEnclave(enclaveDebug); + case EMBEDDED_LIB_OS: + return EmbeddedLibOSEnclave.getEmbeddedLibOSEnclaveInstance(EmbeddedLibOSEnclaveConfig.getEmbeddedLibOSEnclaveConfigInstance().getDebuggable(), EnclaveSimulate.HARDWARE); case NONE: default: throw new EnclaveCreatingException("enclave type is not supported."); diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveDebug.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveDebug.java index bf8ab83..c0f2156 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveDebug.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveDebug.java @@ -3,7 +3,7 @@ package com.alibaba.confidentialcomputing.host; /** * An enumeration of enclave debug mode. */ -enum EnclaveDebug { +public enum EnclaveDebug { /** * For MOCK_IN_JVM and MOCK_IN_SVM, there is no real enclave environment. */ diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveDebug.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveSimulate.java similarity index 53% copy from sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveDebug.java copy to sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveSimulate.java index bf8ab83..ce8b180 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveDebug.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveSimulate.java @@ -1,25 +1,25 @@ package com.alibaba.confidentialcomputing.host; /** - * An enumeration of enclave debug mode. + * An enumeration of enclave simulate mode. */ -enum EnclaveDebug { +enum EnclaveSimulate { /** * For MOCK_IN_JVM and MOCK_IN_SVM, there is no real enclave environment. */ NONE(0), /** - * TEE_SDK could debug by gdb tool in this mode. + * TEE_SDK/EMBEDDED_LIB_OS could run in simulate mode without sgx. */ - DEBUG(1), + SIMULATE(1), /** - * TEE_SDK could not debug by gdb tool in this mode. + * TEE_SDK/EMBEDDED_LIB_OS could run in hardware mode with sgx. */ - RELEASE(2); + HARDWARE(2); private final int value; - EnclaveDebug(int value) { + EnclaveSimulate(int value) { this.value = value; } diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveType.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveType.java index 8e7f098..45155c8 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveType.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveType.java @@ -23,4 +23,11 @@ public enum EnclaveType { * host application runs in jvm environment, and enclave package were loaded by host. */ TEE_SDK, + /** + * An enclave based on Intel's SGX2, with OCCLUM Libos. Enclave application + * was compiled to .class files and packaged as a jar file, there is a jvm runs based + * on enclave's occlum libos. host application runs in jvm environment, and enclave + * package were loaded by host. + */ + EMBEDDED_LIB_OS, } \ No newline at end of file diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ExtractLibrary.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ExtractLibrary.java index 1ce65e0..890c624 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ExtractLibrary.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ExtractLibrary.java @@ -1,15 +1,19 @@ package com.alibaba.confidentialcomputing.host; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.utils.IOUtils; + +import java.io.*; +import java.util.zip.GZIPInputStream; /** - * JavaEnclave building tool will put native .so files into a java .jar file, - * ExtractLibrary will extracts tee sdk's jni .so and enclave signed .so into - * a temp path from the jar file. it's very convenient for deployment. + * JavaEnclave building tool will put native .so files or .tgz files into a java .jar file, + * ExtractLibrary will extract tee sdk's jni .so and enclave signed .so into a temp path + * from the jar file. + * extractAndDeCompressTgz will extract embedded lib os enclave's compressed .tgz image and + * decompress .tgz file into target temp path from the jar file. + * it's very convenient for deployment. */ public final class ExtractLibrary { /** @@ -35,4 +39,63 @@ public final class ExtractLibrary { } return fullPath; } + + /** + * get the temp file's full path. + * + * @param classLoader define the search scope for compressed fie .tgz. + * @param name lib.tgz name in the jar file. + * @return the temp decompression file's full path. + */ + public static String extractAndDeCompressTgz(ClassLoader classLoader, String name) throws IOException { + String fullPath = extractLibrary(classLoader, name); + String destDir = fullPath.replace(".tgz", ""); + deCompressTgz(fullPath, destDir); + return destDir; + } + + private static void deCompressTgz(String fullPath, String destDir) throws IOException { + TarArchiveEntry entry; + TarArchiveEntry[] subEntries; + File subEntryFile = null; + try (FileInputStream fis = new FileInputStream(fullPath); + GZIPInputStream gis = new GZIPInputStream(fis); + TarArchiveInputStream tis = new TarArchiveInputStream(gis)) { + while ((entry = tis.getNextTarEntry()) != null) { + StringBuilder entryFileName = new StringBuilder(); + entryFileName.append(destDir).append(File.separator).append(entry.getName()); + File entryFile = new File(entryFileName.toString()); + if (entry.isDirectory()) { + if (!entryFile.exists()) { + entryFile.mkdir(); + } + subEntries = entry.getDirectoryEntries(); + for (int i = 0; i < subEntries.length; i++) { + try (OutputStream out = new FileOutputStream(subEntryFile)) { + subEntryFile = new File(entryFileName + File.separator + subEntries[i].getName()); + IOUtils.copy(tis, out); + } + } + } else { + checkFileExists(entryFile); + OutputStream out = new FileOutputStream(entryFile); + IOUtils.copy(tis, out); + out.close(); + } + } + } + } + + private static void checkFileExists(File file) throws IOException { + if (file.isDirectory()) { + if (!file.exists()) { + file.mkdir(); + } + } else { + if (file.getParentFile() != null && !file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + file.createNewFile(); + } + } } diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInJvmEnclave.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInJvmEnclave.java index dc2e982..c25f114 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInJvmEnclave.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInJvmEnclave.java @@ -1,5 +1,7 @@ package com.alibaba.confidentialcomputing.host; +import com.alibaba.confidentialcomputing.common.EnclaveInvocationContext; +import com.alibaba.confidentialcomputing.common.ServiceHandler; import com.alibaba.confidentialcomputing.host.exception.*; /** @@ -22,17 +24,17 @@ class MockInJvmEnclave extends AbstractEnclave { } @Override - byte[] loadServiceNative(byte[] payload) throws ServicesLoadingException { + byte[] loadServiceNative(String service) throws ServicesLoadingException { return null; } @Override - byte[] unloadServiceNative(byte[] payload) throws ServicesUnloadingException { + byte[] unloadServiceNative(ServiceHandler handler) throws ServicesUnloadingException { return null; } @Override - byte[] invokeMethodNative(byte[] payload) throws EnclaveMethodInvokingException { + byte[] invokeMethodNative(EnclaveInvocationContext context) throws EnclaveMethodInvokingException { return null; } diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInSvmEnclave.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInSvmEnclave.java index d953afe..340553e 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInSvmEnclave.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockInSvmEnclave.java @@ -1,7 +1,9 @@ package com.alibaba.confidentialcomputing.host; +import com.alibaba.confidentialcomputing.common.EnclaveInvocationContext; +import com.alibaba.confidentialcomputing.common.SerializationHelper; +import com.alibaba.confidentialcomputing.common.ServiceHandler; import com.alibaba.confidentialcomputing.host.exception.*; -import com.alibaba.confidentialcomputing.host.exception.RemoteAttestationException; import java.io.IOException; @@ -68,17 +70,35 @@ class MockInSvmEnclave extends AbstractEnclave { } @Override - byte[] loadServiceNative(byte[] payload) throws ServicesLoadingException { + byte[] loadServiceNative(String service) throws ServicesLoadingException { + byte[] payload; + try { + payload = SerializationHelper.serialize(service); + } catch (IOException e) { + throw new ServicesLoadingException("service name serialization failed.", e); + } return nativeLoadService(enclaveSvmSdkHandle, isolateHandle, payload); } @Override - byte[] unloadServiceNative(byte[] payload) throws ServicesUnloadingException { + byte[] unloadServiceNative(ServiceHandler handler) throws ServicesUnloadingException { + byte[] payload; + try { + payload = SerializationHelper.serialize(handler); + } catch (IOException e) { + throw new ServicesUnloadingException("unload service serialization failed.", e); + } return nativeUnloadService(enclaveSvmSdkHandle, isolateHandle, payload); } @Override - byte[] invokeMethodNative(byte[] payload) throws EnclaveMethodInvokingException { + byte[] invokeMethodNative(EnclaveInvocationContext context) throws EnclaveMethodInvokingException { + byte[] payload; + try { + payload = SerializationHelper.serialize(context); + } catch (IOException e) { + throw new EnclaveMethodInvokingException("EnclaveInvokeMetaWrapper serialization failed.", e); + } return nativeInvokeMethod(enclaveSvmSdkHandle, isolateHandle, payload); } diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ProxyEnclaveInvocationHandler.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ProxyEnclaveInvocationHandler.java index db1a6be..8666dcb 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ProxyEnclaveInvocationHandler.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ProxyEnclaveInvocationHandler.java @@ -50,21 +50,23 @@ class ProxyEnclaveInvocationHandler implements InvocationHandler, Runnable { result = enclave.InvokeEnclaveMethod(methodInvokeMetaWrapper); } catch (EnclaveMethodInvokingException e) { // Get cause exception if it has one. - ConfidentialComputingException enclaveException = (ConfidentialComputingException) e.getCause(); - Throwable enclaveCauseException = enclaveException.getCause(); - Class<?>[] exceptionTypes = method.getExceptionTypes(); - if (enclaveCauseException instanceof InvocationTargetException) { - // Check whether cause exception matches one of the method's exception declaration. - // If it's true, it illustrates that an exception happened in enclave when the service - // method was invoked in enclave, we should throw this exception directly and user will - // handle it. - // If it's false, it illustrates that an exception happened in host side or enclave side, - // but the exception is not belong to the method's declaration. In the case we should throw - // EnclaveMethodInvokingException again. - Throwable rootCause = enclaveCauseException.getCause(); - for (Class<?> exception : exceptionTypes) { - if (exception == rootCause.getClass()) { - throw rootCause; + Throwable causeException = e.getCause(); + if (causeException instanceof ConfidentialComputingException) { + Throwable enclaveCauseException = causeException.getCause(); + Class<?>[] exceptionTypes = method.getExceptionTypes(); + if (enclaveCauseException instanceof InvocationTargetException) { + // Check whether cause exception matches one of the method's exception declaration. + // If it's true, it illustrates that an exception happened in enclave when the service + // method was invoked in enclave, we should throw this exception directly and user will + // handle it. + // If it's false, it illustrates that an exception happened in host side or enclave side, + // but the exception is not belong to the method's declaration. In the case we should throw + // EnclaveMethodInvokingException again. + Throwable rootCause = enclaveCauseException.getCause(); + for (Class<?> exception : exceptionTypes) { + if (exception == rootCause.getClass()) { + throw rootCause; + } } } } diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/RemoteAttestation.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/RemoteAttestation.java index 239a35d..20255e6 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/RemoteAttestation.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/RemoteAttestation.java @@ -19,6 +19,8 @@ public final class RemoteAttestation { System.arraycopy(userData, 0, result, 0, userData.length); } else if (userData.length > 64) { throw new RemoteAttestationException("enclave remote attestation user data length exceeds 64 bytes."); + } else { + result = userData; } return result; } @@ -59,8 +61,10 @@ public final class RemoteAttestation { switch (report.getEnclaveType()) { case TEE_SDK: return TeeSdkEnclave.verifyAttestationReport(report.getQuote()); + case EMBEDDED_LIB_OS: + return EmbeddedLibOSEnclave.verifyAttestationReport(report.getQuote()); default: - throw new RemoteAttestationException("enclaveType must be TEE_SDK."); + throw new RemoteAttestationException("enclaveType must be TEE_SDK or EMBEDDED_LIB_OS."); } } } diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkAttestationReport.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXAttestationReport.java similarity index 56% copy from sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkAttestationReport.java copy to sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXAttestationReport.java index 6ab0f44..3d66eae 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkAttestationReport.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXAttestationReport.java @@ -1,16 +1,28 @@ package com.alibaba.confidentialcomputing.host; /** - * TeeSdkAttestationReport parse more details information from a tee sdk type enclave's remote attestation report. + * SGX type enclave's remote attestation report. */ -public final class TeeSdkAttestationReport extends AttestationReport { +public class SGXAttestationReport extends AttestationReport { private final byte[] mrSigner; private final byte[] mrEnclave; + private final byte[] userData; - TeeSdkAttestationReport(byte[] quote, byte[] mrSigner, byte[] mrEnclave) { - super(EnclaveType.TEE_SDK, quote); + SGXAttestationReport(EnclaveType type, byte[] quote, byte[] mrSigner, byte[] mrEnclave, byte[] userData) { + super(type, quote); this.mrSigner = mrSigner; this.mrEnclave = mrEnclave; + this.userData = userData; + } + + /** + * Get enclave userData from an enclave's remote attestation report. + * <p> + * + * @return Remote attestation userData value which is from user. + */ + public byte[] getUserData() { + return this.userData; } /** diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXRemoteAttestationVerify.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXRemoteAttestationVerify.java index c8c0343..2db853d 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXRemoteAttestationVerify.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXRemoteAttestationVerify.java @@ -1,6 +1,5 @@ package com.alibaba.confidentialcomputing.host; -import com.alibaba.confidentialcomputing.host.ExtractLibrary; import com.alibaba.confidentialcomputing.host.exception.RemoteAttestationException; import java.io.IOException; diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkAttestationReport.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkAttestationReport.java index 6ab0f44..4f75a2c 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkAttestationReport.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkAttestationReport.java @@ -3,33 +3,8 @@ package com.alibaba.confidentialcomputing.host; /** * TeeSdkAttestationReport parse more details information from a tee sdk type enclave's remote attestation report. */ -public final class TeeSdkAttestationReport extends AttestationReport { - private final byte[] mrSigner; - private final byte[] mrEnclave; - - TeeSdkAttestationReport(byte[] quote, byte[] mrSigner, byte[] mrEnclave) { - super(EnclaveType.TEE_SDK, quote); - this.mrSigner = mrSigner; - this.mrEnclave = mrEnclave; - } - - /** - * Get enclave measurementEnclave from an enclave's remote attestation report. - * <p> - * - * @return Remote attestation measurementEnclave value. - */ - public byte[] getMeasurementEnclave() { - return this.mrEnclave; - } - - /** - * Get enclave measurementSigner from an enclave's remote attestation report. - * <p> - * - * @return Remote attestation measurementSigner value. - */ - public byte[] getMeasurementSigner() { - return this.mrSigner; +public final class TeeSdkAttestationReport extends SGXAttestationReport { + TeeSdkAttestationReport(byte[] quote, byte[] mrSigner, byte[] mrEnclave, byte[] userData) { + super(EnclaveType.TEE_SDK, quote, mrSigner, mrEnclave, userData); } } diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkEnclave.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkEnclave.java index 50bd225..36052b5 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkEnclave.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkEnclave.java @@ -1,5 +1,8 @@ package com.alibaba.confidentialcomputing.host; +import com.alibaba.confidentialcomputing.common.EnclaveInvocationContext; +import com.alibaba.confidentialcomputing.common.SerializationHelper; +import com.alibaba.confidentialcomputing.common.ServiceHandler; import com.alibaba.confidentialcomputing.host.exception.*; import java.io.IOException; @@ -75,17 +78,35 @@ class TeeSdkEnclave extends AbstractEnclave { } @Override - byte[] loadServiceNative(byte[] payload) throws ServicesLoadingException { + byte[] loadServiceNative(String service) throws ServicesLoadingException { + byte[] payload; + try { + payload = SerializationHelper.serialize(service); + } catch (IOException e) { + throw new ServicesLoadingException("service name serialization failed.", e); + } return nativeLoadService(enclaveHandle, isolateHandle, payload); } @Override - byte[] unloadServiceNative(byte[] payload) throws ServicesUnloadingException { + byte[] unloadServiceNative(ServiceHandler handler) throws ServicesUnloadingException { + byte[] payload; + try { + payload = SerializationHelper.serialize(handler); + } catch (IOException e) { + throw new ServicesUnloadingException("unload service serialization failed.", e); + } return nativeUnloadService(enclaveHandle, isolateHandle, payload); } @Override - byte[] invokeMethodNative(byte[] payload) throws EnclaveMethodInvokingException { + byte[] invokeMethodNative(EnclaveInvocationContext context) throws EnclaveMethodInvokingException { + byte[] payload; + try { + payload = SerializationHelper.serialize(context); + } catch (IOException e) { + throw new EnclaveMethodInvokingException("EnclaveInvokeMetaWrapper serialization failed.", e); + } return nativeInvokeMethod(enclaveHandle, isolateHandle, payload); } diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/EnclaveCreatingException.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/EnclaveCreatingException.java index 53307bd..44c4d6a 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/EnclaveCreatingException.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/EnclaveCreatingException.java @@ -8,6 +8,7 @@ import com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingE * Programmers need to handle EnclaveCreatingException seriously. */ public class EnclaveCreatingException extends ConfidentialComputingException { + /** * @param info exception information. */ diff --git a/sdk/host/src/main/native/cpp/attestation_verify/sgx/jni/Makefile b/sdk/host/src/main/native/cpp/attestation_verify/sgx/jni/Makefile index fda3ec9..a38e0b2 100644 --- a/sdk/host/src/main/native/cpp/attestation_verify/sgx/jni/Makefile +++ b/sdk/host/src/main/native/cpp/attestation_verify/sgx/jni/Makefile @@ -10,6 +10,7 @@ all: build build: $(CC) -g -c -Wno-unused-parameter $(RA_VERIFY_INCDIR) -I$(JAVA_HOME)/lib -I$(JAVA_HOME)/include \ -I$(JAVA_HOME)/include/$(shell uname -s | tr A-Z a-z) -fPIC jni_remote_attestation_verify.c + $(CC) jni_remote_attestation_verify.o $(RA_VERIFY_LDFLAGS) -fPIC -shared -o $(BIN)/remote_attestation/sgx/jni/lib_jni_sgx_remote_attestation_verify.so clean: diff --git a/sdk/host/src/main/native/cpp/attestation_verify/sgx/jni/jni_remote_attestation_verify.c b/sdk/host/src/main/native/cpp/attestation_verify/sgx/jni/jni_remote_attestation_verify.c index fa53006..22b9478 100644 --- a/sdk/host/src/main/native/cpp/attestation_verify/sgx/jni/jni_remote_attestation_verify.c +++ b/sdk/host/src/main/native/cpp/attestation_verify/sgx/jni/jni_remote_attestation_verify.c @@ -65,7 +65,6 @@ verify_result_wrapper ecdsa_quote_verification_qvl(const uint8_t* quote, uint32_ if (dcap_ret != SGX_QL_SUCCESS) { result.status = QUOTE_VERIFICATION_STATUS_QUOTE_VERIFY_FAILED; - // printf("JavaEnclave Remote Attestation Error: sgx_qv_verify_quote failed: 0x%04x\n", dcap_ret); return result; } diff --git a/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/Makefile b/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/Makefile new file mode 100644 index 0000000..cdd6548 --- /dev/null +++ b/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/Makefile @@ -0,0 +1,13 @@ +include $(NATIVE_BASE_DIR)/config/config.mk +include $(NATIVE_BASE_DIR)/config/platform/libos_occlum_enclave/jni/config.mk + +.PHONY: all build clean + +all: build + +build: + $(CC) $(C_FLAGS) -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/$(shell uname -s | tr A-Z a-z) -fPIC jni_occlum_enclave.c + $(CC) jni_occlum_enclave.o $(LINK_FLAGS) -fPIC -shared -o $(BIN)/platform/libos_occlum_enclave/jni/lib_jni_embedded_lib_os_enclave.so + +clean: + rm -rf *.o $(BIN)/platform/libos_occlum_enclave/jni/lib_jni_embedded_lib_os_enclave.so \ No newline at end of file diff --git a/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/jni_occlum_enclave.c b/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/jni_occlum_enclave.c new file mode 100644 index 0000000..8099c79 --- /dev/null +++ b/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/jni_occlum_enclave.c @@ -0,0 +1,206 @@ +#include <linux/limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <dlfcn.h> +#include <occlum_pal_api.h> + +#include "jni_occlum_enclave.h" + +#define OCCLUM_CMD_ARGS_MAX_LENGTH 50 +#define OCCLUM_HARDWARE_PAL_PATH "/opt/occlum/build/lib/libocclum-pal.so" +#define OCCLUM_SIMULATE_PAL_PATH "/opt/occlum/build/lib/libocclum-pal_sim.so" +#define OCCLUM_CMD_PATH "/usr/lib/dragonwell11/jre/bin/java" +#define OCCLUM_JVM_CMD_CP "-cp" +#define OCCLUM_JVM_CMD_JAR_PATH "/usr/app/*" +#define OCCLUM_JVM_CMD_MAIN_CLASS "com.alibaba.confidentialcomputing.enclave.agent.EnclaveAgent" + +void set_long_field_value(JNIEnv *env, jclass class_mirror, jobject obj, const char *field_name, jlong value) { + jfieldID field_id = (*env)->GetFieldID(env, class_mirror, field_name, "J"); + (*env)->SetLongField(env, obj, field_id, value); +} + +jint parse_http_handler_thread_pool_size(JNIEnv *env, jobject config) { + jclass config_class = (*env)->GetObjectClass(env, config); + jmethodID get_thread_pool_id = (*env)->GetMethodID(env, config_class, "getAgentHttpHandlerThreadPoolSize", "()I"); + return (*env)->CallObjectMethod(env, config, get_thread_pool_id); +} + +jstring parse_log_level(JNIEnv *env, jobject config) { + jclass config_class = (*env)->GetObjectClass(env, config); + jmethodID get_log_level_id = (*env)->GetMethodID(env, config_class, "getLibOSLogLevel", "()Ljava/lang/String;"); + return (*env)->CallObjectMethod(env, config, get_log_level_id); +} + +jobjectArray parse_jvm_cmd_args(JNIEnv *env, jobject config) { + jclass config_class = (*env)->GetObjectClass(env, config); + jmethodID get_jvm_args_id = (*env)->GetMethodID(env, config_class, "getEnclaveJVMArgs", "()[Ljava/lang/String;"); + return (*env)->CallObjectMethod(env, config, get_jvm_args_id); +} + +static JNINativeMethod tee_lib_os_methods[] = { + {"nativeCreateEnclave", ENCLAVE_CREATING_SIGNATURE, (void *)&JavaEnclave_TeeLibOSNativeCreateEnclave}, + {"nativeDestroyEnclave", "(J)I", (void *)&JavaEnclave_TeeLibOSNativeDestroyEnclave}, +}; + +JNIEXPORT void JNICALL +Java_com_alibaba_confidentialcomputing_host_EmbeddedLibOSEnclave_registerNatives(JNIEnv *env, jclass cls) { + (*env)->RegisterNatives(env, cls, tee_lib_os_methods, sizeof(tee_lib_os_methods)/sizeof(tee_lib_os_methods[0])); +} + +JNIEXPORT jint JNICALL JavaEnclave_TeeLibOSNativeCreateEnclave(JNIEnv *env, jobject obj, jint debug, jint sim, jint portHost, jint portEnclave, jobject config, jstring path) { + char* occlum_pal_path = OCCLUM_HARDWARE_PAL_PATH; + if (sim == 1) { + occlum_pal_path = OCCLUM_SIMULATE_PAL_PATH; + } + + void *lib_occlum_pal_handle = dlopen(occlum_pal_path, RTLD_LOCAL | RTLD_LAZY); + if (!lib_occlum_pal_handle) { + THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee lib os enclave: dlopen occlum_pal_path.so failed.") + } + + // set .so file handle back to java enclave object. + jclass class_enclave = (*env)->GetObjectClass(env, obj); + set_long_field_value(env, class_enclave, obj, "enclaveHandle", (jlong)lib_occlum_pal_handle); + + // lookup symbol occlum_pal_init in libocclum-pal.so + int (*occlum_pal_init)(const struct occlum_pal_attr *attr); + occlum_pal_init = (int (*)(const struct occlum_pal_attr *))dlsym((void *)lib_occlum_pal_handle, "occlum_pal_init"); + if (!occlum_pal_init) { + THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee lib os enclave: dlsym symbol occlum_pal_init failed.") + } + + /* lookup symbol occlum_pal_create_process in libocclum-pal.so */ + int (*occlum_pal_create_process)(struct occlum_pal_create_process_args *args); + occlum_pal_create_process = (int (*)(struct occlum_pal_create_process_args *))dlsym((void *)lib_occlum_pal_handle, "occlum_pal_create_process"); + if (!occlum_pal_create_process) { + THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee lib os enclave: dlsym symbol occlum_pal_create_process failed.") + } + + // lookup symbol occlum_pal_exec in libocclum-pal.so + int (*occlum_pal_exec)(struct occlum_pal_exec_args *args); + occlum_pal_exec = (int (*)(struct occlum_pal_exec_args *))dlsym((void *)lib_occlum_pal_handle, "occlum_pal_exec"); + if (!occlum_pal_exec) { + THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee lib os enclave: dlsym symbol occlum_pal_exec failed.") + } + + // parse occlum enclave log level. + jstring log_level = parse_log_level(env, config); + const char *log_level_str = (*env)->GetStringUTFChars(env, log_level, 0); + const char *path_str = (path == 0) ? 0 : (*env)->GetStringUTFChars(env, path, 0); + occlum_pal_attr_t pal_attr = OCCLUM_PAL_ATTR_INITVAL; + pal_attr.instance_dir = path_str; + pal_attr.log_level = log_level_str; + if (occlum_pal_init(&pal_attr) < 0) { + (*env)->ReleaseStringUTFChars(env, path, path_str); + (*env)->ReleaseStringUTFChars(env, log_level, log_level_str); + THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee lib os enclave: occlum_pal_init failed.") + } + + const char *cmd_path = OCCLUM_CMD_PATH; + char *cmd_args[OCCLUM_CMD_ARGS_MAX_LENGTH] = {NULL}; + t_jvm_args jvm_args_record[OCCLUM_CMD_ARGS_MAX_LENGTH] = {NULL}; + + // parse jvm args from user config file. + cmd_args[0] = cmd_path; + jobjectArray jvm_args = parse_jvm_cmd_args(env, config); + jsize length = (*env)->GetArrayLength(env, jvm_args); + if (length >= OCCLUM_CMD_ARGS_MAX_LENGTH) { + (*env)->ReleaseStringUTFChars(env, path, path_str); + (*env)->ReleaseStringUTFChars(env, log_level, log_level_str); + THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee lib os enclave: jvm args number exceeds max limitation 50.") + } + + // parse jvm args and cache them in jvm_args_record for later release. + int index = 0x0; + for (; index < length; index++) { + jvm_args_record[index].handler = (jstring)(*env)->GetObjectArrayElement(env, jvm_args, index); + jvm_args_record[index].handler_str = (char *)(*env)->GetStringUTFChars(env, jvm_args_record[index].handler, 0); + cmd_args[1+index] = jvm_args_record[index].handler_str; + } + // add cp path, main class name in cmd_args's tail. + cmd_args[1+index++] = OCCLUM_JVM_CMD_CP; + cmd_args[1+index++] = OCCLUM_JVM_CMD_JAR_PATH; + cmd_args[1+index++] = OCCLUM_JVM_CMD_MAIN_CLASS; + + // add portHost number as java args. + char port_host_buf[10]; + sprintf(port_host_buf, "%d", portHost); + cmd_args[1+index++] = port_host_buf; + + // add portEnclave number as java args. + char port_enclave_buf[10]; + sprintf(port_enclave_buf, "%d", portEnclave); + cmd_args[1+index++] = port_enclave_buf; + + // add http thread pool size as java args. + char thread_pool_size[10]; + sprintf(thread_pool_size, "%d", parse_http_handler_thread_pool_size(env, config)); + cmd_args[1+index] = thread_pool_size; + + struct occlum_stdio_fds io_fds = { + .stdin_fd = STDIN_FILENO, + .stdout_fd = STDOUT_FILENO, + .stderr_fd = STDERR_FILENO, + }; + + // Use Occlum PAL to create new process + int libos_tid = 0; + struct occlum_pal_create_process_args create_process_args = { + .path = cmd_path, + .argv = cmd_args, + .env = NULL, + .stdio = (const struct occlum_stdio_fds *) &io_fds, + .pid = &libos_tid, + }; + if (occlum_pal_create_process(&create_process_args) < 0) { + (*env)->ReleaseStringUTFChars(env, path, path_str); + (*env)->ReleaseStringUTFChars(env, log_level, log_level_str); + for (int i = 0x0; i < length; i++) { + (*env)->ReleaseStringUTFChars(env, jvm_args_record[i].handler, jvm_args_record[i].handler_str); + } + THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee lib os enclave: occlum_pal_create_process failed.") + } + + // Use Occlum PAL to execute the cmd + int exit_status = 0; + struct occlum_pal_exec_args exec_args = { + .pid = libos_tid, + .exit_value = &exit_status, + }; + // occlum_pal_exec will block until application run in occlum enclave exit. + if (occlum_pal_exec(&exec_args) < 0) { + (*env)->ReleaseStringUTFChars(env, path, path_str); + (*env)->ReleaseStringUTFChars(env, log_level, log_level_str); + for (int i = 0x0; i < length; i++) { + (*env)->ReleaseStringUTFChars(env, jvm_args_record[i].handler, jvm_args_record[i].handler_str); + } + THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee lib os enclave: occlum_pal_exec failed.") + } + + (*env)->ReleaseStringUTFChars(env, path, path_str); + (*env)->ReleaseStringUTFChars(env, log_level, log_level_str); + for (int i = 0x0; i < length; i++) { + (*env)->ReleaseStringUTFChars(env, jvm_args_record[i].handler, jvm_args_record[i].handler_str); + } + return 0; +} + +JNIEXPORT jint JNICALL JavaEnclave_TeeLibOSNativeDestroyEnclave(JNIEnv *env, jobject obj, jlong handler) { + // lookup symbol occlum_pal_destroy in libocclum-pal.so + int (*occlum_pal_destroy)(void); + occlum_pal_destroy = (int (*)(void))dlsym((void *)handler, "occlum_pal_destroy"); + + if (!occlum_pal_destroy) { + THROW_EXCEPTION(env, ENCLAVE_DESTROYING_EXCEPTION, "destroy tee lib os enclave: dlsym symbol occlum_pal_destroy failed.") + } + + if (occlum_pal_destroy() != 0x0) { + THROW_EXCEPTION(env, ENCLAVE_DESTROYING_EXCEPTION, "destroy tee lib os enclave: occlum_pal_destroy failed.") + } + + if (dlclose((void *)handler) != 0x0) { + THROW_EXCEPTION(env, ENCLAVE_DESTROYING_EXCEPTION, "destroy tee lib os enclave: close occlum_pal_path.so failed.") + } +} \ No newline at end of file diff --git a/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/jni_occlum_enclave.h b/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/jni_occlum_enclave.h new file mode 100644 index 0000000..c188536 --- /dev/null +++ b/sdk/host/src/main/native/cpp/platform/libos_occlum_enclave/jni/jni_occlum_enclave.h @@ -0,0 +1,60 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include <jni.h> +/* Header for class com_alibaba_confidentialcomputing_host_EmbeddedLibOSEnclave */ + +#ifndef _Included_com_alibaba_confidentialcomputing_host_EmbeddedLibOSEnclave +#define _Included_com_alibaba_confidentialcomputing_host_EmbeddedLibOSEnclave +#ifdef __cplusplus +extern "C" { +#endif + +#define ENCLAVE_CREATING_SIGNATURE "(IIIILcom/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclaveConfig;Ljava/lang/String;)I" +#define ENCLAVE_CREATING_EXCEPTION "com/alibaba/confidentialcomputing/host/exception/EnclaveCreatingException" +#define ENCLAVE_DESTROYING_EXCEPTION "com/alibaba/confidentialcomputing/host/exception/EnclaveDestroyingException" + +typedef struct { + jstring handler; + char* handler_str; +} t_jvm_args; + +#define THROW_EXCEPTION(env, exception, info) \ +{ \ + jclass ra_class = (*env)->FindClass(env, exception); \ + if (ra_class == NULL) { \ + fprintf(stderr, "JavaEnclave Error: "); \ + fprintf(stderr, exception); \ + fprintf(stderr, " class loading failed.\n"); \ + return; \ + } \ + (*env)->ThrowNew(env, ra_class, info); \ + return; \ +} + +/* + * Class: com_alibaba_confidentialcomputing_host_EmbeddedLibOSEnclave + * Method: registerNatives + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_alibaba_confidentialcomputing_host_EmbeddedLibOSEnclave_registerNatives + (JNIEnv *, jclass); + +/* + * Class: com_alibaba_confidentialcomputing_host_EmbeddedLibOSEnclave + * Method: nativeCreateEnclave + * Signature: (IIIILcom/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclaveConfig;Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL JavaEnclave_TeeLibOSNativeCreateEnclave + (JNIEnv *, jobject, jint, jint, jint, jint, jobject, jstring); + +/* + * Class: com_alibaba_confidentialcomputing_host_EmbeddedLibOSEnclave + * Method: nativeDestroyEnclave + * Signature: (J)I + */ +JNIEXPORT jint JNICALL JavaEnclave_TeeLibOSNativeDestroyEnclave + (JNIEnv *, jobject, jlong); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/sdk/host/src/main/native/cpp/platform/mock_in_svm/jni/jni_mock_in_svm.c b/sdk/host/src/main/native/cpp/platform/mock_in_svm/jni/jni_mock_in_svm.c index 32c189b..5510baa 100644 --- a/sdk/host/src/main/native/cpp/platform/mock_in_svm/jni/jni_mock_in_svm.c +++ b/sdk/host/src/main/native/cpp/platform/mock_in_svm/jni/jni_mock_in_svm.c @@ -134,7 +134,6 @@ JavaEnclave_MockSVMNativeSvmAttachIsolate(JNIEnv *env, jobject obj, jlong enclav } if (graal_create_isolate(NULL, &isolate_t, &isolate_thread_t) != 0) { - // fprintf(stderr, "graal_create_isolate create error:%s\n", dlerror()); THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "graal_create_isolate create error.") } @@ -145,7 +144,7 @@ JavaEnclave_MockSVMNativeSvmAttachIsolate(JNIEnv *env, jobject obj, jlong enclav return 0; } -JNIEXPORT jobject JNICALL +JNIEXPORT jbyteArray JNICALL JavaEnclave_MockSVMNativeLoadService(JNIEnv *env, jobject obj, jlong enclave_handler, jlong isolate_handler, jbyteArray load_service_payload) { enclave_calling_stub_result result_wrapper = mock_enclave_calling_entry(env, isolate_handler, load_service_payload, (mock_enclave_stub) mock_in_svm_load_service_symbol); if (result_wrapper.ret != 0) { @@ -154,7 +153,7 @@ JavaEnclave_MockSVMNativeLoadService(JNIEnv *env, jobject obj, jlong enclave_han return result_wrapper.result; } -JNIEXPORT jobject JNICALL +JNIEXPORT jbyteArray JNICALL JavaEnclave_MockSVMNativeInvokeMethod(JNIEnv *env, jobject obj, jlong enclave_handler, jlong isolate_handler, jbyteArray invoke_payload) { enclave_calling_stub_result result_wrapper = mock_enclave_calling_entry(env, isolate_handler, invoke_payload, (mock_enclave_stub) mock_in_svm_invoke_service_symbol); if (result_wrapper.ret != 0) { @@ -163,7 +162,7 @@ JavaEnclave_MockSVMNativeInvokeMethod(JNIEnv *env, jobject obj, jlong enclave_ha return result_wrapper.result; } -JNIEXPORT jobject JNICALL +JNIEXPORT jbyteArray JNICALL JavaEnclave_MockSVMNativeUnloadService(JNIEnv *env, jobject obj, jlong enclave_handler, jlong isolate_handler, jbyteArray unload_service_payload) { enclave_calling_stub_result result_wrapper = mock_enclave_calling_entry(env, isolate_handler, unload_service_payload, (mock_enclave_stub) mock_in_svm_unload_service_symbol); if (result_wrapper.ret != 0) { diff --git a/sdk/host/src/main/native/cpp/platform/mock_in_svm/jni/jni_mock_in_svm.h b/sdk/host/src/main/native/cpp/platform/mock_in_svm/jni/jni_mock_in_svm.h index 53db1a2..5449a51 100644 --- a/sdk/host/src/main/native/cpp/platform/mock_in_svm/jni/jni_mock_in_svm.h +++ b/sdk/host/src/main/native/cpp/platform/mock_in_svm/jni/jni_mock_in_svm.h @@ -21,9 +21,9 @@ typedef struct { { \ jclass ra_class = (*env)->FindClass(env, exception); \ if (ra_class == NULL) { \ - printf("JavaEnclave Error: "); \ - printf(exception); \ - printf(" class loading failed.\n"); \ + fprintf(stderr, "JavaEnclave Error: "); \ + fprintf(stderr, exception); \ + fprintf(stderr, " class loading failed.\n"); \ return; \ } \ (*env)->ThrowNew(env, ra_class, info); \ diff --git a/sdk/host/src/main/native/cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.c b/sdk/host/src/main/native/cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.c index 6a1870f..ad558d5 100644 --- a/sdk/host/src/main/native/cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.c +++ b/sdk/host/src/main/native/cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.c @@ -95,9 +95,7 @@ JavaEnclave_TeeSDKSVMNativeCreateEnclave(JNIEnv *env, jobject obj, jint mode, js const char *path_str = (path == 0) ? 0 : (*env)->GetStringUTFChars(env, path, 0); sgx_enclave_id_t enclave_id; int ret = sgx_create_enclave(path_str, enable_debug_mode, NULL, NULL, &enclave_id, NULL); - (*env)->ReleaseStringUTFChars(env, path, path_str); - if (ret != SGX_SUCCESS) { THROW_EXCEPTION(env, ENCLAVE_CREATING_EXCEPTION, "create tee sdk enclave by native calling failed.") } @@ -158,12 +156,12 @@ JavaEnclave_TeeSDKSVMNativeUnloadService(JNIEnv *env, jobject obj, jlong enclave JNIEXPORT jint JNICALL JavaEnclave_TeeSDKSVMNativeSvmDetachIsolate(JNIEnv *env, jobject obj, jlong enclave_handler, jlong isolate_thread_handler) { - int ret = 0x0; + int ret = 0; enclave_svm_isolate_destroy((sgx_enclave_id_t)enclave_handler, &ret, (uint64_t)isolate_thread_handler); if (ret != 0) { THROW_EXCEPTION(env, ENCLAVE_DESTROYING_EXCEPTION, "isolate destroy native call failed.") } - return 0; + return ret; } JNIEXPORT jint JNICALL @@ -177,7 +175,6 @@ JavaEnclave_TeeSDKSVMNativeDestroyEnclave(JNIEnv *env, jobject obj, jlong enclav JNIEXPORT jobject JNICALL JavaEnclave_TeeSDK_REMOTE_ATTESTATION_REPORT(JNIEnv *env, jobject obj, jlong enclave_handler, jbyteArray data) { int ret = 0; - quote3_error_t qe3_ret = SGX_QL_SUCCESS; // Step one, load remote attestation related .signed files. if (SGX_QL_SUCCESS != (qe3_ret = load_qe_signed_package())) { @@ -242,13 +239,19 @@ JavaEnclave_TeeSDK_REMOTE_ATTESTATION_REPORT(JNIEnv *env, jobject obj, jlong enc jbyte *mr_signer_buf = (*env)->GetByteArrayElements(env, mr_signer, NULL); memcpy(mr_signer_buf, ra_report.body.mr_signer.m, SGX_HASH_SIZE); + // create user data byte array. + jbyteArray user_data = (*env)->NewByteArray(env, SGX_REPORT_DATA_SIZE); + jbyte *user_data_buf = (*env)->GetByteArrayElements(env, user_data, NULL); + memcpy(user_data_buf, ra_report.body.report_data.d, SGX_REPORT_DATA_SIZE); + (*env)->ReleaseByteArrayElements(env, data, data_copy, 0); (*env)->ReleaseByteArrayElements(env, quote_array, quote_array_ptr, 0); (*env)->ReleaseByteArrayElements(env, mr_enclave, mr_enclave_buf, 0); (*env)->ReleaseByteArrayElements(env, mr_signer, mr_signer_buf, 0); + (*env)->ReleaseByteArrayElements(env, user_data, user_data_buf, 0); free(quote_buffer_ptr); jclass tee_sdk_ra_report_clazz = (*env)->FindClass(env, TEE_SDK_REMOTE_ATTESTATION_REPORT_CLASS_NAME); - jmethodID construct = (*env)->GetMethodID(env, tee_sdk_ra_report_clazz, "<init>", "([B[B[B)V"); - return (*env)->NewObject(env, tee_sdk_ra_report_clazz, construct, quote_array, mr_signer, mr_enclave); + jmethodID construct = (*env)->GetMethodID(env, tee_sdk_ra_report_clazz, "<init>", "([B[B[B[B)V"); + return (*env)->NewObject(env, tee_sdk_ra_report_clazz, construct, quote_array, mr_signer, mr_enclave, user_data); } \ No newline at end of file diff --git a/sdk/host/src/main/native/cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.h b/sdk/host/src/main/native/cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.h index 561b448..2dfced4 100644 --- a/sdk/host/src/main/native/cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.h +++ b/sdk/host/src/main/native/cpp/platform/tee_sdk_svm/jni/jni_tee_sdk_svm.h @@ -27,9 +27,9 @@ typedef struct { { \ jclass ra_class = (*env)->FindClass(env, exception); \ if (ra_class == NULL) { \ - printf("JavaEnclave Error: "); \ - printf(exception); \ - printf(" class loading failed.\n"); \ + fprintf(stderr, "JavaEnclave Error: "); \ + fprintf(stderr, exception); \ + fprintf(stderr, " class loading failed.\n"); \ return; \ } \ (*env)->ThrowNew(env, ra_class, info); \ diff --git a/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/MockTestEnclave.java b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/MockTestEnclave.java index 90df27e..e659c99 100644 --- a/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/MockTestEnclave.java +++ b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/MockTestEnclave.java @@ -12,7 +12,6 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; - class MockTestEnclave extends AbstractEnclave { private static final AtomicLong instanceIdentity = new AtomicLong(0); private static final Map<String, Object> instancesRegisterCenter = new ConcurrentHashMap<>(); @@ -73,12 +72,11 @@ class MockTestEnclave extends AbstractEnclave { } @Override - byte[] loadServiceNative(byte[] payload) throws ServicesLoadingException { + byte[] loadServiceNative(String interfaceName) throws ServicesLoadingException { List<ServiceHandler> handlers = new ArrayList<>(); Throwable exception = null; EnclaveInvocationResult result; try { - String interfaceName = (String) SerializationHelper.deserialize(payload); Class<?> service = Class.forName(interfaceName); Iterator<?> services = ServiceLoader.load(service).iterator(); while (services.hasNext()) { @@ -89,7 +87,7 @@ class MockTestEnclave extends AbstractEnclave { cacheServiceHandler.add(sm); instancesRegisterCenter.put(identity, instance); } - } catch (IOException | ClassNotFoundException e) { + } catch (ClassNotFoundException e) { exception = e; } finally { result = new EnclaveInvocationResult(handlers.toArray(new ServiceHandler[0]), exception); @@ -103,18 +101,12 @@ class MockTestEnclave extends AbstractEnclave { } @Override - byte[] unloadServiceNative(byte[] payload) throws ServicesUnloadingException { - ServiceHandler serviceHandler; + byte[] unloadServiceNative(ServiceHandler handler) throws ServicesUnloadingException { Throwable exception = null; EnclaveInvocationResult result; - try { - serviceHandler = (ServiceHandler) SerializationHelper.deserialize(payload); - instancesRegisterCenter.remove(serviceHandler.getInstanceIdentity()); - } catch (IOException | ClassNotFoundException e) { - exception = e; - } finally { - result = new EnclaveInvocationResult(null, exception); - } + + instancesRegisterCenter.remove(handler.getInstanceIdentity()); + result = new EnclaveInvocationResult(null, exception); try { return SerializationHelper.serialize(result); @@ -124,13 +116,11 @@ class MockTestEnclave extends AbstractEnclave { } @Override - byte[] invokeMethodNative(byte[] payload) throws EnclaveMethodInvokingException { - EnclaveInvocationContext invocationContext; + byte[] invokeMethodNative(EnclaveInvocationContext invocationContext) throws EnclaveMethodInvokingException { Throwable exception = null; Object invokeRet = null; EnclaveInvocationResult result; try { - invocationContext = (EnclaveInvocationContext) SerializationHelper.deserialize(payload); String className = invocationContext.getServiceHandler().getServiceImplClassName(); String[] parameterTypes = invocationContext.getParameterTypes(); String methodName = invocationContext.getMethodName(); diff --git a/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/TestRemoteAttestation.java b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/TestRemoteAttestation.java index d4b9a20..8f161c4 100644 --- a/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/TestRemoteAttestation.java +++ b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/TestRemoteAttestation.java @@ -11,7 +11,7 @@ import static org.junit.jupiter.api.Assertions.*; class TestRemoteAttestation { @Test - void testRemoteAttestation() throws EnclaveCreatingException { + void testRemoteAttestation() { Enclave mockInJvmEnclave = new MockInJvmEnclave(); assertThrows(RemoteAttestationException.class, () -> RemoteAttestation.generateAttestationReport(mockInJvmEnclave, null)); assertThrows(RemoteAttestationException.class, () -> RemoteAttestation.verifyAttestationReport(new AttestationReport(EnclaveType.MOCK_IN_JVM, null))); @@ -37,7 +37,7 @@ class TestRemoteAttestation { } @Test - void testAttestationReport() throws Exception { + void testAttestationReport() { byte[] quote = new byte[4]; for (int index = 0; index < quote.length; index++) { quote[index] = (byte) 0x5f; @@ -49,5 +49,13 @@ class TestRemoteAttestation { for (int index = 0; index < quote.length; index++) { assertEquals(quote[index], (deserializedReport.getQuote())[index]); } + + report = new AttestationReport(EnclaveType.EMBEDDED_LIB_OS, quote); + serializedReport = report.toByteArray(); + deserializedReport = AttestationReport.fromByteArray(serializedReport); + assertEquals(EnclaveType.EMBEDDED_LIB_OS, deserializedReport.getEnclaveType()); + for (int index = 0; index < quote.length; index++) { + assertEquals(quote[index], (deserializedReport.getQuote())[index]); + } } } diff --git a/sdk/native/bin/platform/libos_occlum_enclave/jni/.gitkeep b/sdk/native/bin/platform/libos_occlum_enclave/jni/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sdk/native/bin/platform/libos_occlum_enclave/libos_occlum_enclave_attestation/.gitkeep b/sdk/native/bin/platform/libos_occlum_enclave/libos_occlum_enclave_attestation/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sdk/native/config/platform/libos_occlum_enclave/enclave/config.mk b/sdk/native/config/platform/libos_occlum_enclave/enclave/config.mk new file mode 100644 index 0000000..941f478 --- /dev/null +++ b/sdk/native/config/platform/libos_occlum_enclave/enclave/config.mk @@ -0,0 +1,5 @@ +CC := /usr/local/occlum/bin/occlum-gcc + +TEE_SDK_PATH = /opt/teesdk/sgxsdk +LIBPATH ?= /opt/occlum/toolchains/dcap_lib/musl +INCPATH ?= /opt/occlum/toolchains/dcap_lib/inc diff --git a/sdk/native/config/platform/libos_occlum_enclave/jni/config.mk b/sdk/native/config/platform/libos_occlum_enclave/jni/config.mk new file mode 100644 index 0000000..c29f118 --- /dev/null +++ b/sdk/native/config/platform/libos_occlum_enclave/jni/config.mk @@ -0,0 +1,17 @@ +CC := gcc +OCCLUM_PREFIX ?= /opt/occlum +SGX_MODE ?= HW + +ifneq ($(SGX_MODE), HW) + URTS_LIBRARY_NAME := sgx_urts_sim + UAE_SERVICE_LIBRARY_NAME := sgx_uae_service_sim + OCCLUM_PAL_LIB := occlum-pal_sim +else + URTS_LIBRARY_NAME := sgx_urts + UAE_SERVICE_LIBRARY_NAME := sgx_uae_service + OCCLUM_PAL_LIB := occlum-pal +endif + +C_FLAGS := -Wl,-z,noexecstack -g -c -Wno-unused-parameter -I$(OCCLUM_PREFIX)/include + +LINK_FLAGS := -lpthread -L$(OCCLUM_PREFIX)/build/lib -L/opt/teesdk/sgxsdk/lib64 -l$(URTS_LIBRARY_NAME) -l$(UAE_SERVICE_LIBRARY_NAME) -lsgx_uprotected_fs \ No newline at end of file diff --git a/sdk/native/config/platform/tee_sdk_svm/jni/config.mk b/sdk/native/config/platform/tee_sdk_svm/jni/config.mk index f54e623..76bc3bc 100644 --- a/sdk/native/config/platform/tee_sdk_svm/jni/config.mk +++ b/sdk/native/config/platform/tee_sdk_svm/jni/config.mk @@ -4,9 +4,9 @@ CXX = g++ TEE_SDK_PATH = /opt/teesdk/sgxsdk UBUNTU_OS = $(shell if [ -d "/usr/lib/x86_64-linux-gnu" ]; then echo "yes"; else echo "no"; fi;) ifeq ("$(UBUNTU_OS)", "yes") - DCAP_LIB_PATH = /usr/lib/x86_64-linux-gnu + DCAP_LIB_PATH = /usr/lib/x86_64-linux-gnu else - DCAP_LIB_PATH = /usr/lib64 + DCAP_LIB_PATH = /usr/lib64 endif # SGX_MODE ?= SIM diff --git a/sdk/native/config/remote_attestation_verify/sgx/config.mk b/sdk/native/config/remote_attestation_verify/sgx/config.mk index 032c4fb..2783eff 100644 --- a/sdk/native/config/remote_attestation_verify/sgx/config.mk +++ b/sdk/native/config/remote_attestation_verify/sgx/config.mk @@ -10,4 +10,4 @@ else endif RA_VERIFY_INCDIR = -I$(TEE_SDK_PATH)/include -RA_VERIFY_LDFLAGS = -L$(DCAP_LIB_PATH) -lsgx_dcap_quoteverify -lsgx_dcap_ql \ No newline at end of file +RA_VERIFY_LDFLAGS = -L$(DCAP_LIB_PATH) -lsgx_dcap_quoteverify -lsgx_dcap_ql diff --git a/sdk/native/script/build_app/Makefile b/sdk/native/script/build_app/Makefile index 85d3a30..ec3d6c0 100644 --- a/sdk/native/script/build_app/Makefile +++ b/sdk/native/script/build_app/Makefile @@ -24,7 +24,6 @@ ifeq ($(TEE_SDK), TRUE) -fpie -ljava -lzip -lnio -lnet -ljvm -lfdlibm -llibchelper \ $(TS_ENCLAVE_LDFLAGS) -Wl,--version-script=/opt/javaenclave/config/platform/tee_sdk_svm/edl/tee_sdk_enclave.lds - # sign the enclave image ifeq ($(ENCLAVE_PRIVATE_PEM_PATH), ) openssl genrsa -out ${ENCLAVE_BASE_DIR}/target/enclave_workspace/private.pem -3 3072 $(SGX_ENCLAVE_SIGNER) sign -enclave ${ENCLAVE_BASE_DIR}/target/svm-output/lib_tee_sdk_svm_load \ @@ -36,3 +35,7 @@ ifeq ($(TEE_SDK), TRUE) -config ${ENCLAVE_BASE_DIR}/src/main/resources/tee_sdk_svm.conf -key $(ENCLAVE_PRIVATE_PEM_PATH) endif endif + +ifeq ($(EMBEDDED_LIB_OS), TRUE) + /bin/bash ${BUILD_SCRIPT_DIR}/libos_occlum_enclave_build.sh +endif diff --git a/sdk/native/script/build_app/libos_occlum_enclave_build.sh b/sdk/native/script/build_app/libos_occlum_enclave_build.sh new file mode 100644 index 0000000..3879514 --- /dev/null +++ b/sdk/native/script/build_app/libos_occlum_enclave_build.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +enclave_target_path=${ENCLAVE_BASE_DIR}/target +user_occlum_enclave_config_file=${ENCLAVE_BASE_DIR}/src/main/resources/embedded_libos_enclave.json + +# parse enclave with dependencies jar file name. +# shellcheck disable=SC2061 +# shellcheck disable=SC2185 +# shellcheck disable=SC2035 +pushd "${enclave_target_path}" +enclave_jar_name=$(find -name *-jar-with-dependencies.jar) +if [[ -z $enclave_jar_name ]]; +then + echo "enclave with dependencies jar file is empty." + exit 1 +fi +popd + +# create lib os enclave workspace. +mkdir -p "${ENCLAVE_BASE_DIR}"/target/enclave_workspace/occlum_instance +rm -rf "${ENCLAVE_BASE_DIR}"/target/enclave_workspace/occlum_instance/* + +pushd "${enclave_target_path}"/enclave_workspace/occlum_instance +# create occlum instance and build occlum image. +occlum init + +# update Occlum.json according to user's config file embedded_libos_enclave.json +debuggable=$(< "${user_occlum_enclave_config_file}" jq -r '.debuggable') +default_mmap_size=$(< "${user_occlum_enclave_config_file}" jq -r '.default_mmap_size') +occlum_kernel_heap_size=$(< "${user_occlum_enclave_config_file}" jq -r '.kernel_space_heap_size') +occlum_max_thread_num=$(< "${user_occlum_enclave_config_file}" jq -r '.max_num_of_threads') +user_space_size=$(< "${user_occlum_enclave_config_file}" jq -r '.user_space_size') + +new_json="$(jq --arg default_mmap_size "$default_mmap_size" \ + --arg user_space_size "$user_space_size" \ + --arg occlum_kernel_heap_size "$occlum_kernel_heap_size" \ + --argjson occlum_max_thread_num "$occlum_max_thread_num" \ + --argjson debuggable "$debuggable" \ + '.resource_limits.user_space_size = $user_space_size | + .resource_limits.kernel_space_heap_size = $occlum_kernel_heap_size | + .resource_limits.max_num_of_threads = $occlum_max_thread_num | + .process.default_heap_size = "150MB" | + .process.default_mmap_size = $default_mmap_size | + .metadata.debuggable = $debuggable | + .entry_points = [ "/usr/lib/dragonwell11/jre/bin" ] | + .env.default = [ "LD_LIBRARY_PATH=/usr/lib/dragonwell11/jre/lib/server:/usr/lib/dragonwell11/jre/lib:/usr/lib/dragonwell11/jre/../lib" ]' Occlum.json)" + +echo "${new_json}" > Occlum.json + +# prepare zlib for jvm in libos occlum enclave. +cp /opt/occlum/toolchains/gcc/x86_64-linux-musl/lib/libz.so.1.2.11 ./image/lib/libz.so.1 + +# prepare occlum_dcap for occlum remote attestation. +cp /opt/occlum/toolchains/dcap_lib/musl/libocclum_dcap.so.0.1.0 ./image/lib/libocclum_dcap.so.0.1.0 + +# prepare occlum remote attestation jni.so +mkdir -p ./image/usr/lib +cp -r /opt/javaenclave/bin/platform/libos_occlum_enclave/libos_occlum_enclave_attestation ./image/usr/lib + +# prepate musl-based jvm in libos occlum enclave. +mkdir -p ./image/usr/lib/dragonwell11/jre +cp -r /root/tools/dragonwell-11.0.15.11+9-GA/. ./image/usr/lib/dragonwell11/jre + +# prepare app jar with dependencies in libos occlum enclave. +mkdir -p ./image/usr/app +cp -r "${enclave_target_path}"/"${enclave_jar_name}" ./image/usr/app + +# prepare private.pem for image signing. +if [[ -z ${ENCLAVE_PRIVATE_PEM_PATH} ]]; +then + openssl genrsa -out private.pem -3 3072 + occlum build --sign-key private.pem +else + occlum build --sign-key "${ENCLAVE_PRIVATE_PEM_PATH}" +fi + +if [ $debuggable ] +then + # occlum package --debug > /dev/null + occlum package --debug > /dev/null 2>&1 +else + occlum package +fi + +mv ./occlum_instance.tar.gz "${ENCLAVE_BASE_DIR}"/target/svm-output/lib_embedded_lib_os_enclave_load.tgz + +popd \ No newline at end of file diff --git a/sdk/native/script/build_app/make.sh b/sdk/native/script/build_app/make.sh index cf8bfb4..1fb70f4 100644 --- a/sdk/native/script/build_app/make.sh +++ b/sdk/native/script/build_app/make.sh @@ -2,7 +2,6 @@ # shellcheck disable=SC2006 export BUILD_SCRIPT_DIR=`dirname "$0"` - # set enclave project's base dir path. export ENCLAVE_BASE_DIR="$1" # set enclave platform, such as mock_in_svm and tee_sdk. diff --git a/sdk/native/script/build_enclave_sdk/Makefile b/sdk/native/script/build_enclave_sdk/Makefile index 6098d52..64088c9 100644 --- a/sdk/native/script/build_enclave_sdk/Makefile +++ b/sdk/native/script/build_enclave_sdk/Makefile @@ -11,9 +11,17 @@ ifeq ($(TEE_SDK), TRUE) $(MAKE) -C $(ENCLAVE_BASE_DIR)/src/main/native/cpp/platform/tee_sdk_svm/remote_attestation_generate endif +ifeq ($(EMBEDDED_LIB_OS), TRUE) + $(MAKE) -C $(ENCLAVE_BASE_DIR)/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate +endif + clean: ifeq ($(TEE_SDK), TRUE) $(MAKE) -C $(ENCLAVE_BASE_DIR)/src/main/native/cpp/platform/tee_sdk_svm/wrapper clean $(MAKE) -C $(ENCLAVE_BASE_DIR)/src/main/native/cpp/platform/tee_sdk_svm/edge_routines clean $(MAKE) -C $(ENCLAVE_BASE_DIR)/src/main/native/cpp/platform/tee_sdk_svm/remote_attestation_generate clean +endif + +ifeq ($(EMBEDDED_LIB_OS), TRUE) + $(MAKE) -C $(ENCLAVE_BASE_DIR)/src/main/native/cpp/platform/libos_occlum_enclave/remote_attestation_generate clean endif \ No newline at end of file diff --git a/sdk/native/script/build_host_sdk/Makefile b/sdk/native/script/build_host_sdk/Makefile index ceff503..95e7b5b 100644 --- a/sdk/native/script/build_host_sdk/Makefile +++ b/sdk/native/script/build_host_sdk/Makefile @@ -11,6 +11,16 @@ endif ifeq ($(TEE_SDK), TRUE) $(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/platform/tee_sdk_svm + $(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/platform/libos_occlum_enclave/jni +endif + +ifeq ($(EMBEDDED_LIB_OS), TRUE) + $(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/platform/libos_occlum_enclave/jni +endif + +ifeq ($(TEE_SDK), TRUE) + $(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/attestation_verify/sgx/jni +else ifeq ($(EMBEDDED_LIB_OS), TRUE) $(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/attestation_verify/sgx/jni endif @@ -21,5 +31,14 @@ endif ifeq ($(TEE_SDK), TRUE) $(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/platform/tee_sdk_svm clean +endif + +ifeq ($(EMBEDDED_LIB_OS), TRUE) + $(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/platform/libos_occlum_enclave/jni clean +endif + +ifeq ($(TEE_SDK), TRUE) + $(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/attestation_verify/sgx/jni clean +else ifeq ($(EMBEDDED_LIB_OS), TRUE) $(MAKE) -C $(HOST_BASE_DIR)/src/main/native/cpp/attestation_verify/sgx/jni clean endif \ No newline at end of file diff --git a/sdk/native/script/build_host_sdk/make.sh b/sdk/native/script/build_host_sdk/make.sh index 70181db..26d72cd 100644 --- a/sdk/native/script/build_host_sdk/make.sh +++ b/sdk/native/script/build_host_sdk/make.sh @@ -48,6 +48,13 @@ then # copy jni.so to target/classes, which will be packed into a jar file. if [[ $TEE_SDK == TRUE ]]; then cp -r "$NATIVE_BASE_DIR"/bin/platform/tee_sdk_svm/jni "$HOST_BASE_DIR"/target/classes + fi + # copy jni.so to target/classes, which will be packed into a jar file. + if [[ $EMBEDDED_LIB_OS == TRUE ]]; then + cp -r "$NATIVE_BASE_DIR"/bin/platform/libos_occlum_enclave/jni "$HOST_BASE_DIR"/target/classes + fi + # copy sgx remote attestation verification jni.so to target/classes, which will be packed into a jar file. + if [ "$TEE_SDK" == TRUE ] || [ "$EMBEDDED_LIB_OS" == TRUE ]; then cp -r "$NATIVE_BASE_DIR"/bin/remote_attestation "$HOST_BASE_DIR"/target/classes fi else diff --git a/sdk/pom.xml b/sdk/pom.xml index 653eadc..bfe67d9 100644 --- a/sdk/pom.xml +++ b/sdk/pom.xml @@ -11,10 +11,20 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <com.alibaba.enclave.platform>MOCK_IN_SVM:TEE_SDK</com.alibaba.enclave.platform> + <com.alibaba.enclave.platform>MOCK_IN_SVM:TEE_SDK:EMBEDDED_LIB_OS</com.alibaba.enclave.platform> </properties> <dependencyManagement> <dependencies> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-compress</artifactId> + <version>1.19</version> + </dependency> + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + <version>20211205</version> + </dependency> <dependency> <groupId>com.alibaba.confidentialcomputing</groupId> <artifactId>common</artifactId> diff --git a/test/enclave/pom.xml b/test/enclave/pom.xml index 2bbb426..64e3d9f 100644 --- a/test/enclave/pom.xml +++ b/test/enclave/pom.xml @@ -123,6 +123,25 @@ </execution> </executions> </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <version>3.3.0</version> + <configuration> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + </configuration> + <executions> + <execution> + <id>make-assembly</id> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + </execution> + </executions> + </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> @@ -179,4 +198,4 @@ <scope>test</scope> </dependency> </dependencies> -</project> +</project> \ No newline at end of file diff --git a/test/enclave/src/main/resources/embedded_libos_enclave.json b/test/enclave/src/main/resources/embedded_libos_enclave.json new file mode 100644 index 0000000..655b56a --- /dev/null +++ b/test/enclave/src/main/resources/embedded_libos_enclave.json @@ -0,0 +1,11 @@ +{ + "debuggable": false, + "agent_http_handler_thread_pool_size": 6, + "enclave_startup_duration_ms": 60000, + "kernel_space_heap_size": "32MB", + "user_space_size": "1200MB", + "default_mmap_size": "800MB", + "max_num_of_threads": 48, + "log_level": "off", + "enclave_jvm_args": ["-XX:-UseCompressedOops", "-Xmx512m", "-Dos.name=Linux"] +} \ No newline at end of file diff --git a/test/host/pom.xml b/test/host/pom.xml index ceacc29..9073a33 100644 --- a/test/host/pom.xml +++ b/test/host/pom.xml @@ -19,6 +19,7 @@ <includes> <include>**/*.so</include> <include>**/*.signed</include> + <include>**/*.tgz</include> </includes> </resource> </resources> @@ -42,6 +43,9 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> + <!--configuration> + <forkCount>0</forkCount> + </configuration--> <version>3.0.0-M5</version> </plugin> </plugins> diff --git a/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestJavaEnclaveService.java b/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestJavaEnclaveService.java index 741bb3d..d589c65 100644 --- a/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestJavaEnclaveService.java +++ b/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestJavaEnclaveService.java @@ -2,6 +2,7 @@ package com.alibaba.confidentialcomputing.test.host; import java.io.IOException; import java.util.Iterator; +import java.util.Random; import com.alibaba.confidentialcomputing.host.*; import com.alibaba.confidentialcomputing.host.exception.EnclaveCreatingException; @@ -21,13 +22,28 @@ public class TestJavaEnclaveService { private String sayHelloService(EnclaveType type, String plain) throws EnclaveCreatingException, ServicesLoadingException, EnclaveDestroyingException, RemoteAttestationException, IOException { Enclave enclave = EnclaveFactory.create(type); + assertNotNull(enclave); + byte[] userData = new byte[64]; + new Random().nextBytes(userData); if (type == EnclaveType.TEE_SDK) { - TeeSdkAttestationReport report = (TeeSdkAttestationReport) RemoteAttestation.generateAttestationReport(enclave, null); + TeeSdkAttestationReport report = (TeeSdkAttestationReport) RemoteAttestation.generateAttestationReport(enclave, userData); assertEquals(report.getEnclaveType(), EnclaveType.TEE_SDK); assertNotNull(report.getQuote()); assertEquals(0, RemoteAttestation.verifyAttestationReport(report)); assertNotNull(report.getMeasurementEnclave()); assertNotNull(report.getMeasurementSigner()); + assertNotNull(report.getUserData()); + assertArrayEquals(userData, report.getUserData()); + } + if (type == EnclaveType.EMBEDDED_LIB_OS) { + EmbeddedLibOSAttestationReport report = (EmbeddedLibOSAttestationReport) RemoteAttestation.generateAttestationReport(enclave, userData); + assertEquals(report.getEnclaveType(), EnclaveType.EMBEDDED_LIB_OS); + assertNotNull(report.getQuote()); + assertEquals(0, RemoteAttestation.verifyAttestationReport(report)); + assertNotNull(report.getMeasurementEnclave()); + assertNotNull(report.getMeasurementSigner()); + assertNotNull(report.getUserData()); + assertArrayEquals(userData, report.getUserData()); } Iterator<SayHelloService> userServices = enclave.load(SayHelloService.class); assertNotNull(userServices); @@ -41,13 +57,28 @@ public class TestJavaEnclaveService { private void reflectionCallService(EnclaveType type) throws EnclaveCreatingException, ServicesLoadingException, EnclaveDestroyingException, RemoteAttestationException { Enclave enclave = EnclaveFactory.create(type); + assertNotNull(enclave); + byte[] userData = new byte[64]; + new Random().nextBytes(userData); if (type == EnclaveType.TEE_SDK) { - TeeSdkAttestationReport report = (TeeSdkAttestationReport) RemoteAttestation.generateAttestationReport(enclave, null); + TeeSdkAttestationReport report = (TeeSdkAttestationReport) RemoteAttestation.generateAttestationReport(enclave, userData); assertEquals(report.getEnclaveType(), EnclaveType.TEE_SDK); assertNotNull(report.getQuote()); assertEquals(0, RemoteAttestation.verifyAttestationReport(report)); assertNotNull(report.getMeasurementEnclave()); assertNotNull(report.getMeasurementSigner()); + assertNotNull(report.getUserData()); + assertArrayEquals(userData, report.getUserData()); + } + if (type == EnclaveType.EMBEDDED_LIB_OS) { + EmbeddedLibOSAttestationReport report = (EmbeddedLibOSAttestationReport) RemoteAttestation.generateAttestationReport(enclave, userData); + assertEquals(report.getEnclaveType(), EnclaveType.EMBEDDED_LIB_OS); + assertNotNull(report.getQuote()); + assertEquals(0, RemoteAttestation.verifyAttestationReport(report)); + assertNotNull(report.getMeasurementEnclave()); + assertNotNull(report.getMeasurementSigner()); + assertNotNull(report.getUserData()); + assertArrayEquals(userData, report.getUserData()); } Iterator<ReflectionCallService> userServices = enclave.load(ReflectionCallService.class); assertNotNull(userServices); @@ -60,13 +91,28 @@ public class TestJavaEnclaveService { private void javaEnclaveException(EnclaveType type) throws EnclaveCreatingException, ServicesLoadingException, EnclaveDestroyingException, RemoteAttestationException { Enclave enclave = EnclaveFactory.create(type); + assertNotNull(enclave); + byte[] userData = new byte[64]; + new Random().nextBytes(userData); if (type == EnclaveType.TEE_SDK) { - TeeSdkAttestationReport report = (TeeSdkAttestationReport) RemoteAttestation.generateAttestationReport(enclave, null); + TeeSdkAttestationReport report = (TeeSdkAttestationReport) RemoteAttestation.generateAttestationReport(enclave, userData); assertEquals(report.getEnclaveType(), EnclaveType.TEE_SDK); assertNotNull(report.getQuote()); assertEquals(0, RemoteAttestation.verifyAttestationReport(report)); assertNotNull(report.getMeasurementEnclave()); assertNotNull(report.getMeasurementSigner()); + assertNotNull(report.getUserData()); + assertArrayEquals(userData, report.getUserData()); + } + if (type == EnclaveType.EMBEDDED_LIB_OS) { + EmbeddedLibOSAttestationReport report = (EmbeddedLibOSAttestationReport) RemoteAttestation.generateAttestationReport(enclave, userData); + assertEquals(report.getEnclaveType(), EnclaveType.EMBEDDED_LIB_OS); + assertNotNull(report.getQuote()); + assertEquals(0, RemoteAttestation.verifyAttestationReport(report)); + assertNotNull(report.getMeasurementEnclave()); + assertNotNull(report.getMeasurementSigner()); + assertNotNull(report.getUserData()); + assertArrayEquals(userData, report.getUserData()); } Iterator<EnclaveException> userServices = enclave.load(EnclaveException.class); assertNotNull(userServices); @@ -77,24 +123,38 @@ public class TestJavaEnclaveService { } @Test - public void testSayHelloService() throws - EnclaveCreatingException, EnclaveDestroyingException, ServicesLoadingException, RemoteAttestationException, IOException { - assertEquals("Hello World", sayHelloService(EnclaveType.MOCK_IN_JVM, "Hello World")); - assertEquals("Hello World", sayHelloService(EnclaveType.MOCK_IN_SVM, "Hello World")); - assertEquals("Hello World", sayHelloService(EnclaveType.TEE_SDK, "Hello World")); + public void testSayHelloService() { + try { + assertEquals("Hello World", sayHelloService(EnclaveType.MOCK_IN_JVM, "Hello World")); + assertEquals("Hello World", sayHelloService(EnclaveType.MOCK_IN_SVM, "Hello World")); + assertEquals("Hello World", sayHelloService(EnclaveType.TEE_SDK, "Hello World")); + assertEquals("Hello World", sayHelloService(EnclaveType.EMBEDDED_LIB_OS, "Hello World")); + } catch (Exception e) { + e.printStackTrace(); + } } @Test - public void testReflectionCallService() throws ServicesLoadingException, EnclaveCreatingException, EnclaveDestroyingException, RemoteAttestationException { - reflectionCallService(EnclaveType.MOCK_IN_JVM); - reflectionCallService(EnclaveType.MOCK_IN_SVM); - reflectionCallService(EnclaveType.TEE_SDK); + public void testReflectionCallService() { + try { + reflectionCallService(EnclaveType.MOCK_IN_JVM); + reflectionCallService(EnclaveType.MOCK_IN_SVM); + reflectionCallService(EnclaveType.TEE_SDK); + reflectionCallService(EnclaveType.EMBEDDED_LIB_OS); + } catch (Exception e) { + e.printStackTrace(); + } } @Test - public void testJavaEnclaveException() throws ServicesLoadingException, EnclaveCreatingException, EnclaveDestroyingException, RemoteAttestationException { - javaEnclaveException(EnclaveType.MOCK_IN_JVM); - javaEnclaveException(EnclaveType.MOCK_IN_SVM); - javaEnclaveException(EnclaveType.TEE_SDK); + public void testJavaEnclaveException() { + try { + javaEnclaveException(EnclaveType.MOCK_IN_JVM); + javaEnclaveException(EnclaveType.MOCK_IN_SVM); + javaEnclaveException(EnclaveType.TEE_SDK); + javaEnclaveException(EnclaveType.EMBEDDED_LIB_OS); + } catch (Exception e) { + e.printStackTrace(); + } } } diff --git a/test/pom.xml b/test/pom.xml index 7c2f566..97e1d9b 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -12,7 +12,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <com.alibaba.enclave.platform>MOCK_IN_SVM:TEE_SDK</com.alibaba.enclave.platform> + <com.alibaba.enclave.platform>MOCK_IN_SVM:TEE_SDK:EMBEDDED_LIB_OS</com.alibaba.enclave.platform> </properties> <dependencyManagement> <dependencies> diff --git a/tools/cicd/Dockerfile b/tools/cicd/Dockerfile index a611185..544392d 100644 --- a/tools/cicd/Dockerfile +++ b/tools/cicd/Dockerfile @@ -6,23 +6,29 @@ ENV APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1 ENV DEBIAN_FRONTEND noninteractive ADD ["graalvm-enclave-22.1.0.tar", "/root/tools/"] -ADD ["x86_64-linux-musl-native.tgz", "/root/tools/"] ADD ["zlib-1.2.11.tar.gz", "/root/tools/"] ADD ["settings.xml", "/root/tools/"] +ADD ["zlib-1.2.11.tar.gz", "/root/tools/"] +ADD ["Alibaba_Dragonwell_11.0.15.11.9_x64_alpine-linux.tar.gz", "/root/tools"] ADD ["sgx_linux_x64_sdk_2.17.100.0.bin", "/root/tools/"] ENV GRAALVM_HOME "/root/tools/graalvm-enclave-22.1.0" ENV JAVA_HOME "/root/tools/graalvm-enclave-22.1.0" -ENV CC "/root/tools/x86_64-linux-musl-native/bin/gcc" -ENV PATH $PATH:"/root/tools/x86_64-linux-musl-native/bin" +ENV PATH="/opt/occlum/build/bin:/usr/local/occlum/bin:$PATH" +ENV CC=/usr/local/occlum/bin/occlum-gcc ARG PSW_VERSION=2.17.100.3 ARG DCAP_VERSION=1.14.100.3 # install necessary tools. -RUN apt-get update && apt-get install -y gdb gnupg wget aptitude && \ +RUN apt-get update && apt-get install -y gdb gnupg wget aptitude libfuse-dev libtool tzdata jq && \ + echo -e 'yes\n' | apt-get install -y maven && \ + echo -e 'yes\n' | apt-get install -y build-essential libz-dev zlib1g-dev && \ echo 'deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu bionic main' > /etc/apt/sources.list.d/intel-sgx.list && \ wget -qO - https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | apt-key add - && \ + echo 'deb [arch=amd64] https://occlum.io/occlum-package-repos/debian bionic main' | tee /etc/apt/sources.list.d/occlum.list && \ + wget -qO - https://occlum.io/occlum-package-repos/debian/public.key | apt-key add - && \ apt-get update && aptitude install -y \ + occlum \ libsgx-launch-dev=$PSW_VERSION-bionic1 \ libsgx-urts=$PSW_VERSION-bionic1 \ libsgx-urts-dbgsym=$PSW_VERSION-bionic1 \ @@ -32,5 +38,8 @@ RUN apt-get update && apt-get install -y gdb gnupg wget aptitude && \ libsgx-dcap-default-qpl=$DCAP_VERSION-bionic1 && \ echo -e 'yes\n' | apt-get install -y maven && \ echo -e 'yes\n' | apt-get install -y build-essential libz-dev zlib1g-dev && \ - cd /root/tools/zlib-1.2.11 && ./configure --prefix=/root/tools/x86_64-linux-musl-native --static && make && make install && \ + cd /root/tools/zlib-1.2.11 && ./configure --prefix=/opt/occlum/toolchains/gcc/x86_64-linux-musl && make && make install && \ cd /root/tools && chmod 777 sgx_linux_x64_sdk_2.17.100.0.bin && echo -e 'no\n/opt/teesdk\n' | ./sgx_linux_x64_sdk_2.17.100.0.bin + +# copy dcap_occlum lib from occlum docker image. +COPY --from=occlum/occlum:0.26.4-ubuntu18.04 /opt/occlum/toolchains/dcap_lib /opt/occlum/toolchains/dcap_lib \ No newline at end of file diff --git a/tools/cicd/make.sh b/tools/cicd/make.sh index f4667ea..5dc43d0 100755 --- a/tools/cicd/make.sh +++ b/tools/cicd/make.sh @@ -1,7 +1,7 @@ #!/bin/bash BUILD_IMAGE=javaenclave_build -BUILD_TAG=v0.1.9 +BUILD_TAG=v0.1.10 SHELL_FOLDER=$(cd "$(dirname "$0")";pwd) @@ -14,15 +14,15 @@ if [[ "$(docker images -q ${BUILD_IMAGE}:${BUILD_TAG} 2> /dev/null)" == "" ]]; t # Get the customized Graal VM from [email protected]:graal/SGXGraalVM.git # This should be replaced to the offical version when all patches are accepted by the Graal community wget https://graal.oss-cn-beijing.aliyuncs.com/graal-enclave/JDK11-22.1.0/graalvm-enclave-22.1.0.tar - wget http://graal.oss-cn-beijing.aliyuncs.com/graal-enclave/x86_64-linux-musl-native.tgz wget http://graal.oss-cn-beijing.aliyuncs.com/graal-enclave/zlib-1.2.11.tar.gz wget http://graal.oss-cn-beijing.aliyuncs.com/graal-enclave/settings_taobao.xml -O settings.xml wget https://dragonwell.oss-cn-shanghai.aliyuncs.com/11/tee_java/dependency/sgx_linux_x64_sdk_2.17.100.0.bin + wget https://dragonwell.oss-cn-shanghai.aliyuncs.com/11.0.15.11.9/Alibaba_Dragonwell_11.0.15.11.9_x64_alpine-linux.tar.gz docker build -t ${BUILD_IMAGE}:${BUILD_TAG} . rm -f graalvm-enclave-22.1.0.tar - rm -f x86_64-linux-musl-native.tgz rm -f zlib-1.2.11.tar.gz rm -f sgx_linux_x64_sdk_2.17.100.0.bin + rm -f Alibaba_Dragonwell_11.0.15.11.9_x64_alpine-linux.tar.gz fi # Set PCCS for DCAP Remote Attestation. --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
