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 c74f1f3353f2e3c922b60e486155f7870e4822ad Author: jeffery.wsj <[email protected]> AuthorDate: Mon Aug 8 04:50:07 2022 +0800 [sdk] Support JavaEnclave benchmark metric tracing feature Summary: 1. Add metric tracing feature for JavaEnclave. 2. Add metric tracing unit test case. 3. Add sm2/sm3/sm4 test case based on bouncycastle. Test Plan: all tests pass Reviewers: lei.yul, cengfeng.lzy, sanhong.lsh Issue: https://aone.alibaba-inc.com/task/43916112 CR: https://code.aone.alibaba-inc.com/java-tee/JavaEnclave/codereview/9697539 --- build.sh | 4 + .../com/alibaba/samples/helloworld/host/Main.java | 5 +- .../common/EnclaveInvocationResult.java | 18 +++ .../enclave/InvocationWrapper.java | 2 + .../enclave/agent/EnclaveAgentServiceImpl.java | 44 +++---- .../enclave/framework/LoadServiceInvoker.java | 3 +- .../tee_sdk_svm/edge_routines/tee_sdk_symbol.c | 8 +- .../host/AbstractEnclave.java | 132 ++++++++++++--------- .../host/BaseEnclaveServicesRecycler.java | 6 +- .../host/EmbeddedLibOSEnclave.java | 10 +- .../host/EnclaveConfigure.java | 54 +++++---- .../confidentialcomputing/host/EnclaveInfo.java | 5 + .../host/EnclaveServicesRecycler.java | 9 +- .../confidentialcomputing/host/MetricTrace.java | 76 ++++++++++++ .../host/MetricTraceContext.java | 62 ++++++++++ .../host/MockEnclaveInfo.java | 7 ++ .../host/MockInJvmEnclave.java | 12 +- .../host/MockInSvmEnclave.java | 19 +-- .../host/ProxyEnclaveInvocationHandler.java | 20 ++-- .../host/ProxyMockJvmInvocationHandler.java | 48 ++++++++ .../confidentialcomputing/host/SGXEnclaveInfo.java | 7 ++ .../confidentialcomputing/host/TeeSdkEnclave.java | 21 ++-- .../exception/MetricTraceLogWriteException.java | 30 +++++ .../host/TestRemoteAttestation.java | 3 +- sdk/native/script/build_app/Makefile | 11 +- .../test/common/MetricTraceService.java | 8 ++ .../test/common/SM2Service.java | 8 ++ .../test/common/SM3Service.java | 8 ++ .../test/common/SM4Service.java | 8 ++ test/enclave/pom.xml | 25 ++++ .../test/enclave/MetricTraceServiceImpl.java | 17 +++ .../test/enclave/SM2ServiceImpl.java | 91 ++++++++++++++ .../test/enclave/SM3ServiceImpl.java | 19 +++ .../test/enclave/SM4ServiceImpl.java | 57 +++++++++ .../test/host/TestEnclaveMetricTrace.java | 67 +++++++++++ .../test/host/TestSMEnclave.java | 91 ++++++++++++++ test/pom.xml | 13 +- tools/cicd/Dockerfile | 4 +- tools/cicd/make.sh | 6 +- 39 files changed, 884 insertions(+), 154 deletions(-) diff --git a/build.sh b/build.sh index fc270bc..e6338da 100755 --- a/build.sh +++ b/build.sh @@ -21,5 +21,9 @@ cd "${WORKDIR}"/sdk && mvn $SETTING clean install # Install JavaEnclave SDK 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 +# Install JavaEnclave archetype +cd "${WORKDIR}"/archetype && mvn $SETTING clean install +# Install BouncyCastle Native Package +cd "${WORKDIR}"/third-party-libs/bouncycastle-native && mvn $SETTING clean install # Test unit test cases in JavaEnclave cd "${WORKDIR}"/test && OCCLUM_RELEASE_ENCLAVE=true mvn $SETTING -Pnative clean package diff --git a/samples/helloworld/host/src/main/java/com/alibaba/samples/helloworld/host/Main.java b/samples/helloworld/host/src/main/java/com/alibaba/samples/helloworld/host/Main.java index d531358..c8d3784 100644 --- a/samples/helloworld/host/src/main/java/com/alibaba/samples/helloworld/host/Main.java +++ b/samples/helloworld/host/src/main/java/com/alibaba/samples/helloworld/host/Main.java @@ -3,15 +3,12 @@ package com.alibaba.samples.helloworld.host; import com.alibaba.confidentialcomputing.host.Enclave; import com.alibaba.confidentialcomputing.host.EnclaveFactory; import com.alibaba.confidentialcomputing.host.EnclaveType; -import com.alibaba.confidentialcomputing.host.exception.EnclaveCreatingException; -import com.alibaba.confidentialcomputing.host.exception.EnclaveDestroyingException; -import com.alibaba.confidentialcomputing.host.exception.ServicesLoadingException; import com.alibaba.samples.helloworld.common.Service; import java.util.Iterator; public class Main { - public static void main(String[] args) throws EnclaveCreatingException, ServicesLoadingException, EnclaveDestroyingException { + public static void main(String[] args) throws Exception { EnclaveType[] enclaveTypes = { EnclaveType.MOCK_IN_JVM, EnclaveType.MOCK_IN_SVM, diff --git a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationResult.java b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationResult.java index b664304..aea12e1 100644 --- a/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationResult.java +++ b/sdk/common/src/main/java/com/alibaba/confidentialcomputing/common/EnclaveInvocationResult.java @@ -15,6 +15,7 @@ public final class EnclaveInvocationResult implements Serializable { private final Object resultedValue; private final Throwable exception; + private long cost; // ns. public EnclaveInvocationResult(Object result, Throwable exception) { this.resultedValue = result; @@ -38,4 +39,21 @@ public final class EnclaveInvocationResult implements Serializable { public Throwable getException() { return this.exception; } + + /** + * set method's overhead. + * + */ + public void setCost(long cost) { + this.cost = cost; + } + + /** + * get method's overhead. + * + * @return method's overhead(ns). + */ + public long getCost() { + return this.cost; + } } \ No newline at end of file diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/InvocationWrapper.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/InvocationWrapper.java index 98b5eb6..cb8ff24 100644 --- a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/InvocationWrapper.java +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/InvocationWrapper.java @@ -23,6 +23,7 @@ import java.io.IOException; public class InvocationWrapper { public static <T> void invoke(EncData input, EncData result, CallBacks callBacks, EnclaveMethodInvoker<T> invoker) throws IOException { + long start = System.nanoTime(); byte[] data = transformInput(input); EnclaveInvocationResult ret; try { @@ -31,6 +32,7 @@ public class InvocationWrapper { ret = new EnclaveInvocationResult(null, new ConfidentialComputingException(t)); } // Set method returned value to result parameter + ret.setCost(System.nanoTime() - start); wrapReturnValue(result, callBacks, ret); } 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 index b5e5716..f396873 100644 --- 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 @@ -6,6 +6,7 @@ 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.EnclaveMethodInvoker; import com.alibaba.confidentialcomputing.enclave.framework.LoadServiceInvoker; import com.alibaba.confidentialcomputing.enclave.framework.ServiceMethodInvoker; import com.alibaba.confidentialcomputing.enclave.framework.UnloadServiceInvoker; @@ -20,40 +21,32 @@ public class EnclaveAgentServiceImpl { protected EnclaveAgentServiceImpl() { } - public byte[] loadService(String serviceName) { + private <T> byte[] invoke(EnclaveMethodInvoker<T> invoker, T input) { + long start = System.nanoTime(); + EnclaveInvocationResult ret; try { - return SerializationHelper.serialize(loadServiceInstance.callMethod(serviceName)); - } catch (IOException e) { - try { - return SerializationHelper.serialize(new EnclaveInvocationResult(null, e)); - } catch (IOException ex) { - } + ret = invoker.callMethod(input); + } catch (Throwable t) { + ret = new EnclaveInvocationResult(null, new ConfidentialComputingException(t)); + } + ret.setCost(System.nanoTime() - start); + try { + return SerializationHelper.serialize(ret); + } catch (IOException ex) { } return null; } + public byte[] loadService(String serviceName) { + return invoke(loadServiceInstance, serviceName); + } + 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; + return invoke(unloadServiceInstance, handler); } 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; + return invoke(serviceInvokerInstance, context); } public byte[] generateAttestationReport(byte[] userDate) { @@ -64,6 +57,7 @@ public class EnclaveAgentServiceImpl { } catch (ConfidentialComputingException e) { exception = e; } + try { return SerializationHelper.serialize(new EnclaveInvocationResult(report, exception)); } catch (IOException e) { 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 a4b2dec..fe6f6b7 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 @@ -14,9 +14,8 @@ public final class LoadServiceInvoker implements EnclaveMethodInvoker<String> { */ @Override public EnclaveInvocationResult callMethod(String inputData) { - Class<?> service; try { - service = Class.forName(inputData); + Class<?> service = Class.forName(inputData); return new EnclaveInvocationResult(EnclaveContext.getInstance().loadService(service), null); } catch (ClassNotFoundException e) { return new EnclaveInvocationResult(null, e); diff --git a/sdk/enclave/src/main/native/cpp/platform/tee_sdk_svm/edge_routines/tee_sdk_symbol.c b/sdk/enclave/src/main/native/cpp/platform/tee_sdk_svm/edge_routines/tee_sdk_symbol.c index 0a74027..d5e7ce8 100644 --- a/sdk/enclave/src/main/native/cpp/platform/tee_sdk_svm/edge_routines/tee_sdk_symbol.c +++ b/sdk/enclave/src/main/native/cpp/platform/tee_sdk_svm/edge_routines/tee_sdk_symbol.c @@ -66,7 +66,7 @@ char* strcat(char* dest, const char* source) { return dest; } -char* strcpy(char* dest,const char* sourse) { +char* strcpy(char* dest, const char* sourse) { TRACE_SYMBOL_CALL(); if(dest==NULL || sourse==NULL) return NULL; char* res=dest; @@ -74,10 +74,10 @@ char* strcpy(char* dest,const char* sourse) { return res; } -char* stpcpy(char *dest, const char *src) { +char* stpcpy(char *dest, const char *sourse) { TRACE_SYMBOL_CALL(); - size_t len = strlen (src); - return memcpy(dest, src, len + 1) + len; + strcpy(dest, sourse); + return dest + strlen(sourse); } size_t __getdelim(char **lineptr, size_t *n, int delim, FILE *stream) { 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 87af3ed..30142a3 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 @@ -11,11 +11,7 @@ import com.alibaba.confidentialcomputing.common.EnclaveInvocationResult; import com.alibaba.confidentialcomputing.common.EnclaveInvocationContext; import com.alibaba.confidentialcomputing.common.SerializationHelper; import com.alibaba.confidentialcomputing.common.ServiceHandler; -import com.alibaba.confidentialcomputing.host.exception.EnclaveCreatingException; -import com.alibaba.confidentialcomputing.host.exception.EnclaveMethodInvokingException; -import com.alibaba.confidentialcomputing.host.exception.RemoteAttestationException; -import com.alibaba.confidentialcomputing.host.exception.ServicesLoadingException; -import com.alibaba.confidentialcomputing.host.exception.ServicesUnloadingException; +import com.alibaba.confidentialcomputing.host.exception.*; /** * AbstractEnclave implements all kinds of enclave platform's common operation. @@ -54,20 +50,48 @@ abstract class AbstractEnclave implements Enclave { abstract AttestationReport generateAttestationReportNative(byte[] userData) throws RemoteAttestationException; - // load service by interface name. - ServiceHandler[] loadService(Class<?> service) throws ServicesLoadingException { + // load service by interface name in mock_jvm mode. + // because mock_svm/tee_sdk/lib_os adopt serialization and deserialization between host and enclave, + // while mock_jvm will call enclave service directly. + <T> Iterator<T> loadProxyServiceMockJVM(Class<?> service) throws ServicesLoadingException { + try (MetricTraceContext trace = new MetricTraceContext( + this.getEnclaveInfo(), + MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_SERVICE_LOADING_PATTERN, + service.getName())) { + List<T> serviceProxies = new ArrayList<>(); + Class<?>[] serviceInterface = new Class[]{service}; + + ServiceLoader<T> innerProxyServices = (ServiceLoader<T>) ServiceLoader.load(service); + for (T innerProxyService : innerProxyServices) { + ProxyMockJvmInvocationHandler handler = new ProxyMockJvmInvocationHandler(this, innerProxyService); + T proxy = (T) Proxy.newProxyInstance(service.getClassLoader(), serviceInterface, handler); + serviceProxies.add(proxy); + // Register proxy handler for enclave's corresponding service gc recycling. + enclaveContext.getEnclaveServicesRecycler().registerProxyHandler(proxy, handler); + } + return serviceProxies.iterator(); + } catch (MetricTraceLogWriteException e) { + throw new ServicesLoadingException(e); + } + } + + // load service by interface name in mock_svm/tee_sdk/lib_os enclave mode. + <T> Iterator<T> loadProxyService(Class<?> service) throws ServicesLoadingException { if (!getEnclaveContext().getEnclaveToken().tryAcquireToken()) { throw new ServicesLoadingException("enclave was destroyed."); } - try { + try (MetricTraceContext trace = new MetricTraceContext( + this.getEnclaveInfo(), + MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_SERVICE_LOADING_PATTERN, + service.getName())) { + List<T> serviceProxies = new ArrayList<>(); + Class<?>[] serviceInterface = new Class[]{service}; + // Only need to provide service's interface name is enough to load service // in enclave. EnclaveInvocationResult resultWrapper; - try { - resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(loadServiceNative(service.getName())); - } catch (IOException | ClassNotFoundException e) { - throw new ServicesLoadingException("EnclaveInvokeResultWrapper deserialization failed.", e); - } + resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(loadServiceNative(service.getName())); + trace.setCostInnerEnclave(resultWrapper.getCost()); Throwable exception = resultWrapper.getException(); Object result = resultWrapper.getResult(); // this exception is transformed from enclave, so throw it and handle it in proxy handler. @@ -81,7 +105,19 @@ abstract class AbstractEnclave implements Enclave { if (!(result instanceof ServiceHandler[])) { throw new ServicesLoadingException("service load return type is not ServiceHandler[]."); } - return (ServiceHandler[]) result; + + for (ServiceHandler serviceHandler : (ServiceHandler[]) result) { + ProxyEnclaveInvocationHandler handler = new ProxyEnclaveInvocationHandler(this, serviceHandler); + T proxy = (T) Proxy.newProxyInstance(service.getClassLoader(), serviceInterface, handler); + serviceProxies.add(proxy); + // Register proxy handler for enclave's corresponding service gc recycling. + enclaveContext.getEnclaveServicesRecycler().registerProxyHandler(proxy, handler); + } + return serviceProxies.iterator(); + } catch (IOException | ClassNotFoundException e) { + throw new ServicesLoadingException("EnclaveInvokeResultWrapper deserialization failed.", e); + } catch (MetricTraceLogWriteException e) { + throw new ServicesLoadingException(e); } finally { getEnclaveContext().getEnclaveToken().restoreToken(); } @@ -93,41 +129,37 @@ abstract class AbstractEnclave implements Enclave { if (!getEnclaveContext().getEnclaveToken().tryAcquireToken()) { throw new ServicesUnloadingException("enclave was destroyed."); } - try { + try (MetricTraceContext trace = new MetricTraceContext( + this.getEnclaveInfo(), + MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_SERVICE_UNLOADING_PATTERN, + service.getServiceImplClassName())) { EnclaveInvocationResult resultWrapper; - try { - resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(unloadServiceNative(service)); - } catch (IOException | ClassNotFoundException e) { - throw new ServicesUnloadingException("EnclaveInvokeResultWrapper deserialization failed.", e); - } + resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(unloadServiceNative(service)); + trace.setCostInnerEnclave(resultWrapper.getCost()); Throwable exception = resultWrapper.getException(); if (exception != null) { throw new ServicesUnloadingException("service unload exception happened in enclave.", exception); } + } catch (IOException | ClassNotFoundException e) { + throw new ServicesUnloadingException("EnclaveInvokeResultWrapper deserialization failed.", e); + } catch (MetricTraceLogWriteException e) { + throw new ServicesUnloadingException(e); } finally { getEnclaveContext().getEnclaveToken().restoreToken(); } } // it was called in service's proxy handler. - Object InvokeEnclaveMethod(EnclaveInvocationContext input) throws EnclaveMethodInvokingException { + EnclaveInvocationResult InvokeEnclaveMethod(EnclaveInvocationContext input) throws EnclaveMethodInvokingException { if (!getEnclaveContext().getEnclaveToken().tryAcquireToken()) { throw new EnclaveMethodInvokingException("enclave was destroyed."); } try { EnclaveInvocationResult resultWrapper; - try { - resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(invokeMethodNative(input)); - } catch (IOException | ClassNotFoundException e) { - throw new EnclaveMethodInvokingException("EnclaveInvokeResultWrapper deserialization failed.", e); - } - Throwable exception = resultWrapper.getException(); - if (exception != null) { - EnclaveMethodInvokingException e = new EnclaveMethodInvokingException("method invoke exception happened in enclave."); - e.initCause(exception); - throw e; - } - return resultWrapper.getResult(); + resultWrapper = (EnclaveInvocationResult) SerializationHelper.deserialize(invokeMethodNative(input)); + return resultWrapper; + } catch (IOException | ClassNotFoundException e) { + throw new EnclaveMethodInvokingException("EnclaveInvokeResultWrapper deserialization failed.", e); } finally { getEnclaveContext().getEnclaveToken().restoreToken(); } @@ -151,26 +183,20 @@ abstract class AbstractEnclave implements Enclave { throw new ServicesLoadingException("service type: " + service.getTypeName() + " is not an interface type."); } - // If enclave type is MOCK_IN_JVM, loading services by JDK SPI mechanism directly. - if (enclaveContext.getEnclaveType() == EnclaveType.MOCK_IN_JVM) { - ServiceLoader<T> loader = ServiceLoader.load(service); - return loader.iterator(); - } - - // Loading services in enclave and creating proxy for them. - Class<?>[] serviceInterface = new Class[1]; - serviceInterface[0] = service; - - List<T> serviceProxies = new ArrayList<>(); - ServiceHandler[] services = loadService(service); - for (ServiceHandler serviceHandler : services) { - ProxyEnclaveInvocationHandler handler = new ProxyEnclaveInvocationHandler(this, serviceHandler); - T proxy = (T) Proxy.newProxyInstance(service.getClassLoader(), serviceInterface, handler); - serviceProxies.add(proxy); - // Register proxy handler for enclave's corresponding service gc recycling. - enclaveContext.getEnclaveServicesRecycler().registerProxyHandler(proxy, handler); - } - return serviceProxies.iterator(); + Iterator<T> serviceProxies; + switch (enclaveContext.getEnclaveType()) { + // If enclave type is MOCK_IN_JVM, loading services by JDK SPI mechanism directly. + case MOCK_IN_JVM: + serviceProxies = loadProxyServiceMockJVM(service); + break; + // Loading services in enclave and creating proxy for them. + case MOCK_IN_SVM: + case TEE_SDK: + case EMBEDDED_LIB_OS: + default: + serviceProxies = loadProxyService(service); + } + return serviceProxies; } /** diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/BaseEnclaveServicesRecycler.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/BaseEnclaveServicesRecycler.java index 957539e..e323c3d 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/BaseEnclaveServicesRecycler.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/BaseEnclaveServicesRecycler.java @@ -1,5 +1,7 @@ package com.alibaba.confidentialcomputing.host; +import java.lang.reflect.InvocationHandler; + /** * BaseEnclaveServicesRecycler an empty enclave services recycler for MOCK_IN_JVM enclave. */ @@ -7,10 +9,10 @@ class BaseEnclaveServicesRecycler { BaseEnclaveServicesRecycler() { } - void enqueueProxyHandler(ProxyEnclaveInvocationHandler handler) { + void enqueueProxyHandler(InvocationHandler handler) { } - void registerProxyHandler(Object obj, ProxyEnclaveInvocationHandler handler) { + void registerProxyHandler(Object obj, InvocationHandler handler) { } void interruptServiceRecycler() { 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 index c44b403..0c6a9c0 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclave.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclave.java @@ -15,8 +15,8 @@ import com.alibaba.confidentialcomputing.host.exception.*; * 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_CONNECT_TIMEOUT_MS = 800; // ms. + private static final int HTTP_READ_TIMEOUT_MS = 2000; // 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:"; @@ -241,6 +241,12 @@ public class EmbeddedLibOSEnclave extends AbstractEnclave { // 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. + try (MetricTraceContext trace = new MetricTraceContext( + this.getEnclaveInfo(), + MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_DESTROYING_PATTERN)) { + } catch (MetricTraceLogWriteException e) { + throw new EnclaveDestroyingException(e); + } } } 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 30086e8..00d4201 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 @@ -1,6 +1,9 @@ package com.alibaba.confidentialcomputing.host; import com.alibaba.confidentialcomputing.host.exception.EnclaveCreatingException; +import com.alibaba.confidentialcomputing.host.exception.MetricTraceLogWriteException; + +import java.io.IOException; /** * EnclaveConfigure decides a new created enclave's type and debug mode. @@ -73,29 +76,34 @@ class EnclaveConfigure { // create an enclave with specific enclave type. static Enclave create(EnclaveType type) throws EnclaveCreatingException { - Enclave enclave; - switch (type) { - case MOCK_IN_JVM: - enclave = new MockInJvmEnclave(); - break; - case MOCK_IN_SVM: - enclave = new MockInSvmEnclave(); - break; - case TEE_SDK: - // TEE_SDK only support hardware mode, not support simulate mode. - enclave = new TeeSdkEnclave(enclaveDebug); - break; - case EMBEDDED_LIB_OS: - // EMBEDDED_LIB_OS only support hardware mode, not support simulate mode. - enclave = EmbeddedLibOSEnclave.getEmbeddedLibOSEnclaveInstance( - EmbeddedLibOSEnclaveConfig.getEmbeddedLibOSEnclaveConfigInstance().getDebuggable(), - EnclaveSimulate.HARDWARE); - break; - case NONE: - default: - throw new EnclaveCreatingException("enclave type is not supported."); + try (MetricTraceContext trace = new MetricTraceContext(MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_CREATING_PATTERN)) { + Enclave enclave; + switch (type) { + case MOCK_IN_JVM: + enclave = new MockInJvmEnclave(); + break; + case MOCK_IN_SVM: + enclave = new MockInSvmEnclave(); + break; + case TEE_SDK: + // TEE_SDK only support hardware mode, not support simulate mode. + enclave = new TeeSdkEnclave(enclaveDebug); + break; + case EMBEDDED_LIB_OS: + // EMBEDDED_LIB_OS only support hardware mode, not support simulate mode. + enclave = EmbeddedLibOSEnclave.getEmbeddedLibOSEnclaveInstance( + EmbeddedLibOSEnclaveConfig.getEmbeddedLibOSEnclaveConfigInstance().getDebuggable(), + EnclaveSimulate.HARDWARE); + break; + case NONE: + default: + throw new EnclaveCreatingException("enclave type is not supported."); + } + trace.setEnclaveInfo(enclave.getEnclaveInfo()); + EnclaveInfoManager.getEnclaveInfoManagerInstance().addEnclave(enclave); + return enclave; + } catch (IOException | MetricTraceLogWriteException e) { + throw new EnclaveCreatingException(e); } - EnclaveInfoManager.getEnclaveInfoManagerInstance().addEnclave(enclave); - return enclave; } } diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveInfo.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveInfo.java index 1eaa9f5..a66d324 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveInfo.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveInfo.java @@ -9,6 +9,11 @@ public interface EnclaveInfo { */ EnclaveType getEnclaveType(); + /** + * the enclave's Hash ID. + */ + int getEnclaveID(); + /** * is the enclave debuggable or not. MOCK_IN_JVM and MOCK_IN_SVM are simulation mode, * so the two mock enclave type are debuggable. TEE_SDK and EMBEDDED_LIB_OS depend on diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveServicesRecycler.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveServicesRecycler.java index 711c0b7..7af0ad4 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveServicesRecycler.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveServicesRecycler.java @@ -3,6 +3,7 @@ package com.alibaba.confidentialcomputing.host; import com.alibaba.confidentialcomputing.host.exception.ServicesUnloadingException; import java.lang.ref.Cleaner; +import java.lang.reflect.InvocationHandler; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; @@ -39,9 +40,9 @@ class EnclaveServicesRecycler extends BaseEnclaveServicesRecycler { // enqueue the recycled proxy handler object of a service handler. @Override - void enqueueProxyHandler(ProxyEnclaveInvocationHandler handler) { + void enqueueProxyHandler(InvocationHandler handler) { try { - toBeReleasedEnclaveServices.add(handler); + toBeReleasedEnclaveServices.add((ProxyEnclaveInvocationHandler) handler); } catch (IllegalStateException | ClassCastException | NullPointerException | IllegalArgumentException e) { // Have to handle this exception locally. e.printStackTrace(); @@ -50,8 +51,8 @@ class EnclaveServicesRecycler extends BaseEnclaveServicesRecycler { // register service's proxy handler when it's created. @Override - void registerProxyHandler(Object obj, ProxyEnclaveInvocationHandler handler) { - cleaner.register(obj, handler); + void registerProxyHandler(Object obj, InvocationHandler handler) { + cleaner.register(obj, (ProxyEnclaveInvocationHandler)handler); } // interrupt enclave services' recycler thread exit. diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MetricTrace.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MetricTrace.java new file mode 100644 index 0000000..afb9ca2 --- /dev/null +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MetricTrace.java @@ -0,0 +1,76 @@ +package com.alibaba.confidentialcomputing.host; + +import com.alibaba.confidentialcomputing.host.exception.MetricTraceLogWriteException; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.text.DecimalFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.concurrent.TimeUnit; + +public abstract class MetricTrace implements AutoCloseable { + private final static String PRIORITY_METRIC_LOG_PATH = "com.alibaba.enclave.metric.path"; + private final static String PRIORITY_ENABLE_METRIC_LOG = "com.alibaba.enclave.metric.on"; + + private static boolean enableEnclaveMetricTrace = false; + private final static String DEFAULT_METRIC_LOG_PATH = + "JavaEnclave_Metric_Log_" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + ".log"; + private static volatile String logPath; + private static volatile BufferedWriter logFile; + private static DecimalFormat formatter = new DecimalFormat("###,###"); + + private final long start = System.nanoTime(); + + static { + String metricLogFlag = System.getProperty(PRIORITY_ENABLE_METRIC_LOG); + if ("true".equals(metricLogFlag) || "1".equals(metricLogFlag)) { + enableEnclaveMetricTrace = true; + } + String priorityLogPath = System.getProperty(PRIORITY_METRIC_LOG_PATH); + if (priorityLogPath != null) { + logPath = priorityLogPath; + } else { + logPath = DEFAULT_METRIC_LOG_PATH; + } + } + + public static void setEnclaveMetricTraceSwitch(boolean flag) { + enableEnclaveMetricTrace = flag; + } + + public static boolean isEnableEnclaveMetricTrace() { + return enableEnclaveMetricTrace; + } + + abstract EnclaveInfo getEnclaveInfo(); + + abstract String getMetricKeyName(); + + abstract long getCostInnerEnclave(); + + void metricTracing(EnclaveInfo enclaveInfo, String name, long costTotal, long costEnclave) throws IOException { + logFile.write(String.format("%s %s %s %s %s\r\n", + enclaveInfo.getEnclaveID(), + enclaveInfo.getEnclaveType(), + name, + formatter.format(TimeUnit.NANOSECONDS.toMicros(costTotal)), + formatter.format(TimeUnit.NANOSECONDS.toMicros(costEnclave)))); + logFile.flush(); + } + + @Override + public void close() throws MetricTraceLogWriteException { + try { + if (isEnableEnclaveMetricTrace()) { + if (logFile == null) { + logFile = new BufferedWriter(new FileWriter(this.logPath)); + } + metricTracing(getEnclaveInfo(), getMetricKeyName(), System.nanoTime() - start, getCostInnerEnclave()); + } + } catch (IOException e) { + throw new MetricTraceLogWriteException(e); + } + } +} diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MetricTraceContext.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MetricTraceContext.java new file mode 100644 index 0000000..0084e4e --- /dev/null +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MetricTraceContext.java @@ -0,0 +1,62 @@ +package com.alibaba.confidentialcomputing.host; + +final class MetricTraceContext extends MetricTrace { + private EnclaveInfo info; + private long costInnerEnclave = 0x0; + private String pattern; + + MetricTraceContext(EnclaveInfo info, LogPrefix prefix) { + this.info = info; + pattern = prefix.toString(); + } + + MetricTraceContext(EnclaveInfo info, LogPrefix prefix, String service) { + this.info = info; + pattern = new StringBuilder().append(prefix.toString()).append(":").append(service).toString(); + } + + MetricTraceContext(LogPrefix prefix) { + pattern = prefix.toString(); + } + + enum LogPrefix { + METRIC_LOG_ENCLAVE_CREATING_PATTERN("enclave_creating_cost(us)"), + METRIC_LOG_ENCLAVE_DESTROYING_PATTERN("enclave_destroying_cost(us)"), + METRIC_LOG_ENCLAVE_SERVICE_LOADING_PATTERN("enclave_service_loading(us)"), + METRIC_LOG_ENCLAVE_SERVICE_UNLOADING_PATTERN("enclave_service_unloading(us)"), + METRIC_LOG_ENCLAVE_SERVICE_INVOKING_PATTERN("enclave_service_invoking(us)"); + private final String prefix; + + LogPrefix(String prefix) { + this.prefix = prefix; + } + + @Override + public String toString() { + return this.prefix; + } + } + + void setCostInnerEnclave(long cost) { + costInnerEnclave = cost; + } + + void setEnclaveInfo(EnclaveInfo info) { + this.info = info; + } + + @Override + EnclaveInfo getEnclaveInfo() { + return this.info; + } + + @Override + String getMetricKeyName() { + return pattern; + } + + @Override + long getCostInnerEnclave() { + return this.costInnerEnclave; + } +} diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockEnclaveInfo.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockEnclaveInfo.java index 8e790f4..ef8a510 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockEnclaveInfo.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockEnclaveInfo.java @@ -7,6 +7,7 @@ class MockEnclaveInfo implements EnclaveInfo { private boolean isEnclaveDebuggable; private long enclaveEPCMemorySizeBytes; // Bytes. private int enclaveMaxThreadsNumber; + private int enclaveID; @ConstructorParameters({"enclaveType", "isEnclaveDebuggable", "enclaveEPCMemorySizeBytes", "enclaveMaxThreadsNumber"}) MockEnclaveInfo(EnclaveType enclaveType, boolean isEnclaveDebuggable, long enclaveEPCMemorySizeBytes, int enclaveMaxThreadsNumber) { @@ -14,6 +15,7 @@ class MockEnclaveInfo implements EnclaveInfo { this.isEnclaveDebuggable = isEnclaveDebuggable; this.enclaveEPCMemorySizeBytes = enclaveEPCMemorySizeBytes; this.enclaveMaxThreadsNumber = enclaveMaxThreadsNumber; + this.enclaveID = this.hashCode(); } @Override @@ -21,6 +23,11 @@ class MockEnclaveInfo implements EnclaveInfo { return this.enclaveType; } + @Override + public int getEnclaveID() { + return this.enclaveID; + } + @Override public boolean isEnclaveDebuggable() { return this.isEnclaveDebuggable; 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 7ba9da0..1f5fc14 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 @@ -4,6 +4,8 @@ import com.alibaba.confidentialcomputing.common.EnclaveInvocationContext; import com.alibaba.confidentialcomputing.common.ServiceHandler; import com.alibaba.confidentialcomputing.host.exception.*; +import java.io.IOException; + /** * MockInJvmEnclave is a mock jvm enclave. Both host and enclave codes run * in one jvm. It was used for test and debug. @@ -11,7 +13,7 @@ import com.alibaba.confidentialcomputing.host.exception.*; class MockInJvmEnclave extends AbstractEnclave { private final MockEnclaveInfo enclaveInfo; - MockInJvmEnclave() { + MockInJvmEnclave() throws IOException { // Set EnclaveContext for this enclave instance. super(EnclaveType.MOCK_IN_JVM, new BaseEnclaveServicesRecycler()); enclaveInfo = new MockEnclaveInfo(EnclaveType.MOCK_IN_JVM, true, -1, -1); @@ -48,6 +50,12 @@ class MockInJvmEnclave extends AbstractEnclave { @Override public void destroy() throws EnclaveDestroyingException { - EnclaveInfoManager.getEnclaveInfoManagerInstance().removeEnclave(this); + try (MetricTraceContext trace = new MetricTraceContext( + this.getEnclaveInfo(), + MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_DESTROYING_PATTERN)) { + EnclaveInfoManager.getEnclaveInfoManagerInstance().removeEnclave(this); + } catch (MetricTraceLogWriteException e) { + throw new EnclaveDestroyingException(e); + } } } 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 508b741..4dcf169 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 @@ -31,7 +31,6 @@ class MockInSvmEnclave extends AbstractEnclave { MockInSvmEnclave() throws EnclaveCreatingException { // Set EnclaveContext for this enclave instance. super(EnclaveType.MOCK_IN_SVM, new EnclaveServicesRecycler()); - // Extract jni .so and svm sdk .so from .jar file. if (extractTempPath == null) { synchronized (MockInSvmEnclave.class) { @@ -113,12 +112,18 @@ class MockInSvmEnclave extends AbstractEnclave { public void destroy() throws EnclaveDestroyingException { // destroyToken will wait for all ongoing enclave invocations finished. if (this.getEnclaveContext().getEnclaveToken().destroyToken()) { - // interrupt enclave services' recycler firstly. - this.getEnclaveContext().getEnclaveServicesRecycler().interruptServiceRecycler(); - // destroy svm isolate. - nativeSvmDetachIsolate(enclaveSvmSdkHandle, isolateThreadHandle); - nativeDestroyEnclave(enclaveSvmSdkHandle); - EnclaveInfoManager.getEnclaveInfoManagerInstance().removeEnclave(this); + try (MetricTraceContext trace = new MetricTraceContext( + this.getEnclaveInfo(), + MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_DESTROYING_PATTERN)) { + // interrupt enclave services' recycler firstly. + this.getEnclaveContext().getEnclaveServicesRecycler().interruptServiceRecycler(); + // destroy svm isolate. + nativeSvmDetachIsolate(enclaveSvmSdkHandle, isolateThreadHandle); + nativeDestroyEnclave(enclaveSvmSdkHandle); + EnclaveInfoManager.getEnclaveInfoManagerInstance().removeEnclave(this); + } catch (MetricTraceLogWriteException e) { + throw new EnclaveDestroyingException(e); + } } } 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 8666dcb..98a439d 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 @@ -1,9 +1,9 @@ package com.alibaba.confidentialcomputing.host; import com.alibaba.confidentialcomputing.common.EnclaveInvocationContext; +import com.alibaba.confidentialcomputing.common.EnclaveInvocationResult; import com.alibaba.confidentialcomputing.common.ServiceHandler; import com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingException; -import com.alibaba.confidentialcomputing.host.exception.EnclaveMethodInvokingException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationHandler; @@ -45,13 +45,14 @@ class ProxyEnclaveInvocationHandler implements InvocationHandler, Runnable { } // Handle service method invocation exception. - Object result; - try { - result = enclave.InvokeEnclaveMethod(methodInvokeMetaWrapper); - } catch (EnclaveMethodInvokingException e) { - // Get cause exception if it has one. - Throwable causeException = e.getCause(); - if (causeException instanceof ConfidentialComputingException) { + try (MetricTraceContext trace = new MetricTraceContext( + enclave.getEnclaveInfo(), + MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_SERVICE_INVOKING_PATTERN, + method.getName())) { + EnclaveInvocationResult result = enclave.InvokeEnclaveMethod(methodInvokeMetaWrapper); + trace.setCostInnerEnclave(result.getCost()); + Throwable causeException = result.getException(); + if (causeException != null && causeException instanceof ConfidentialComputingException) { Throwable enclaveCauseException = causeException.getCause(); Class<?>[] exceptionTypes = method.getExceptionTypes(); if (enclaveCauseException instanceof InvocationTargetException) { @@ -70,9 +71,8 @@ class ProxyEnclaveInvocationHandler implements InvocationHandler, Runnable { } } } - throw e; + return result.getResult(); } - return result; } AbstractEnclave getEnclave() { diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ProxyMockJvmInvocationHandler.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ProxyMockJvmInvocationHandler.java new file mode 100644 index 0000000..edfe877 --- /dev/null +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/ProxyMockJvmInvocationHandler.java @@ -0,0 +1,48 @@ +package com.alibaba.confidentialcomputing.host; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class ProxyMockJvmInvocationHandler<T> implements InvocationHandler, Runnable { + private final AbstractEnclave enclave; + private final T proxyService; + + ProxyMockJvmInvocationHandler(AbstractEnclave enclave, T proxyService) { + this.enclave = enclave; + this.proxyService = proxyService; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + Object result; + try (MetricTraceContext trace = new MetricTraceContext( + enclave.getEnclaveInfo(), + MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_SERVICE_INVOKING_PATTERN, + method.getName())) { + result = method.invoke(proxyService, args); + } catch (InvocationTargetException e) { + // 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. + Class<?>[] exceptionTypes = method.getExceptionTypes(); + Throwable rootCause = e.getCause(); + for (Class<?> exception : exceptionTypes) { + if (exception == rootCause.getClass()) { + throw rootCause; + } + } + throw e; + } + return result; + } + + @Override + public void run() { + enclave.getEnclaveContext().getEnclaveServicesRecycler().enqueueProxyHandler(this); + } +} diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXEnclaveInfo.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXEnclaveInfo.java index 8f61b73..1a1022d 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXEnclaveInfo.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXEnclaveInfo.java @@ -7,6 +7,7 @@ class SGXEnclaveInfo implements EnclaveInfo { private boolean isEnclaveDebuggable; private long enclaveEPCMemorySizeBytes; // Bytes. private int enclaveMaxThreadsNumber; + private int enclaveID; @ConstructorParameters({"enclaveType", "isEnclaveDebuggable", "enclaveEPCMemorySizeBytes", "enclaveMaxThreadsNumber"}) SGXEnclaveInfo(EnclaveType enclaveType, boolean isEnclaveDebuggable, long enclaveEPCMemorySizeBytes, int enclaveMaxThreadsNumber) { @@ -14,6 +15,7 @@ class SGXEnclaveInfo implements EnclaveInfo { this.isEnclaveDebuggable = isEnclaveDebuggable; this.enclaveEPCMemorySizeBytes = enclaveEPCMemorySizeBytes; this.enclaveMaxThreadsNumber = enclaveMaxThreadsNumber; + this.enclaveID = this.hashCode(); } @Override @@ -21,6 +23,11 @@ class SGXEnclaveInfo implements EnclaveInfo { return this.enclaveType; } + @Override + public int getEnclaveID() { + return this.enclaveID; + } + @Override public boolean isEnclaveDebuggable() { return this.isEnclaveDebuggable; 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 5bf0f1d..7179662 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 @@ -27,7 +27,6 @@ class TeeSdkEnclave extends AbstractEnclave { TeeSdkEnclave(EnclaveDebug mode) throws EnclaveCreatingException { // Set EnclaveContext for this enclave instance. super(EnclaveType.TEE_SDK, mode, new EnclaveServicesRecycler()); - // Extract jni .so and signed tee .so from .jar file. // Only once extract and load operation. if (extractTempPath == null) { @@ -135,13 +134,19 @@ class TeeSdkEnclave extends AbstractEnclave { public void destroy() throws EnclaveDestroyingException { // destroyToken will wait for all ongoing enclave invocations finished. if (this.getEnclaveContext().getEnclaveToken().destroyToken()) { - // interrupt enclave services' recycler firstly. - this.getEnclaveContext().getEnclaveServicesRecycler().interruptServiceRecycler(); - // destroy svm isolate. - nativeSvmDetachIsolate(enclaveHandle, isolateThreadHandle); - // destroy the enclave. - nativeDestroyEnclave(enclaveHandle); - EnclaveInfoManager.getEnclaveInfoManagerInstance().removeEnclave(this); + try (MetricTraceContext trace = new MetricTraceContext( + this.getEnclaveInfo(), + MetricTraceContext.LogPrefix.METRIC_LOG_ENCLAVE_DESTROYING_PATTERN)) { + // interrupt enclave services' recycler firstly. + this.getEnclaveContext().getEnclaveServicesRecycler().interruptServiceRecycler(); + // destroy svm isolate. + nativeSvmDetachIsolate(enclaveHandle, isolateThreadHandle); + // destroy the enclave. + nativeDestroyEnclave(enclaveHandle); + EnclaveInfoManager.getEnclaveInfoManagerInstance().removeEnclave(this); + } catch (MetricTraceLogWriteException e) { + throw new EnclaveDestroyingException(e); + } } } diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/MetricTraceLogWriteException.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/MetricTraceLogWriteException.java new file mode 100644 index 0000000..f244cb6 --- /dev/null +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/exception/MetricTraceLogWriteException.java @@ -0,0 +1,30 @@ +package com.alibaba.confidentialcomputing.host.exception; + +/** + * MetricTraceLogWriteException {@link MetricTraceLogWriteException} is thrown when an enclave metric trace + * write into log file. + * Programmers need to handle MetricTraceLogWriteException seriously. + */ +public class MetricTraceLogWriteException extends EnclaveCreatingException { + /** + * @param info exception information. + */ + public MetricTraceLogWriteException(String info) { + super(EnclaveNativeInvokingException.ENCLAVE_REMOTE_ATTESTATION_ERROR.buildExceptionMessage(info)); + } + + /** + * @param e exception. + */ + public MetricTraceLogWriteException(Throwable e) { + super(EnclaveNativeInvokingException.ENCLAVE_REMOTE_ATTESTATION_ERROR.toString(), e); + } + + /** + * @param info exception message. + * @param e exception. + */ + public MetricTraceLogWriteException(String info, Throwable e) { + super(EnclaveNativeInvokingException.ENCLAVE_REMOTE_ATTESTATION_ERROR.buildExceptionMessage(info), e); + } +} 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 e4e509b..997f3e1 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 @@ -3,6 +3,7 @@ package com.alibaba.confidentialcomputing.host; import com.alibaba.confidentialcomputing.host.exception.RemoteAttestationException; import org.junit.jupiter.api.Test; +import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -10,7 +11,7 @@ import static org.junit.jupiter.api.Assertions.*; class TestRemoteAttestation { @Test - void testRemoteAttestation() { + void testRemoteAttestation() throws IOException { Enclave mockInJvmEnclave = new MockInJvmEnclave(); assertThrows(RemoteAttestationException.class, () -> RemoteAttestation.generateAttestationReport(mockInJvmEnclave, null)); assertThrows(RemoteAttestationException.class, () -> RemoteAttestation.verifyAttestationReport(new AttestationReport(EnclaveType.MOCK_IN_JVM, null))); diff --git a/sdk/native/script/build_app/Makefile b/sdk/native/script/build_app/Makefile index ec3d6c0..9a6ce58 100644 --- a/sdk/native/script/build_app/Makefile +++ b/sdk/native/script/build_app/Makefile @@ -1,6 +1,8 @@ include /opt/javaenclave/config/config.mk include /opt/javaenclave/config/platform/tee_sdk_svm/jni/config.mk +LIB_SUNEC=sunec + .PHONY: all build clean all: @@ -17,11 +19,18 @@ ifeq ($(TEE_SDK), TRUE) cp ${JAVA_HOME}/lib/svm/builder/clibraries/linux-amd64/libjvm.a ${ENCLAVE_BASE_DIR}/target/enclave_workspace cp ${JAVA_HOME}/lib/svm/builder/clibraries/linux-amd64/liblibchelper.a ${ENCLAVE_BASE_DIR}/target/enclave_workspace + # copy libenc_sunec.a from svm-output to enclave_workspace if it exist. + cp ${ENCLAVE_BASE_DIR}/target/svm-output/libenc_sunec.a ${ENCLAVE_BASE_DIR}/target/enclave_workspace 2>/dev/null || : + + ifneq ($(wildcard ${ENCLAVE_BASE_DIR}/target/enclave_workspace/libenc_sunec.a),) + LIB_SUNEC=enc_sunec + endif + $(CC) -o ${ENCLAVE_BASE_DIR}/target/svm-output/lib_tee_sdk_svm_load \ /opt/javaenclave/bin/platform/tee_sdk_svm/*.o ${ENCLAVE_BASE_DIR}/target/svm-output/lib_tee_sdk_svm_load.o \ -L${JAVA_HOME}/lib/static/linux-amd64/glibc \ -L${ENCLAVE_BASE_DIR}/target/enclave_workspace \ - -fpie -ljava -lzip -lnio -lnet -ljvm -lfdlibm -llibchelper \ + -fpie -ljava -lzip -lnio -lnet -l$(LIB_SUNEC) -ljvm -lfdlibm -llibchelper \ $(TS_ENCLAVE_LDFLAGS) -Wl,--version-script=/opt/javaenclave/config/platform/tee_sdk_svm/edl/tee_sdk_enclave.lds ifeq ($(ENCLAVE_PRIVATE_PEM_PATH), ) diff --git a/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/MetricTraceService.java b/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/MetricTraceService.java new file mode 100644 index 0000000..f2e81b6 --- /dev/null +++ b/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/MetricTraceService.java @@ -0,0 +1,8 @@ +package com.alibaba.confidentialcomputing.test.common; + +import com.alibaba.confidentialcomputing.common.annotations.EnclaveService; + +@EnclaveService +public interface MetricTraceService { + String invertCharacter(String str); +} diff --git a/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM2Service.java b/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM2Service.java new file mode 100644 index 0000000..9233099 --- /dev/null +++ b/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM2Service.java @@ -0,0 +1,8 @@ +package com.alibaba.confidentialcomputing.test.common; + +import com.alibaba.confidentialcomputing.common.annotations.EnclaveService; + +@EnclaveService +public interface SM2Service { + String encryptAndDecryptWithPlaintext(String plaintext) throws Exception; +} diff --git a/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM3Service.java b/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM3Service.java new file mode 100644 index 0000000..5e64d3a --- /dev/null +++ b/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM3Service.java @@ -0,0 +1,8 @@ +package com.alibaba.confidentialcomputing.test.common; + +import com.alibaba.confidentialcomputing.common.annotations.EnclaveService; + +@EnclaveService +public interface SM3Service { + byte[] sm3Service(String plainText) throws Exception; +} diff --git a/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM4Service.java b/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM4Service.java new file mode 100644 index 0000000..bec5bb8 --- /dev/null +++ b/test/common/src/main/java/com/alibaba/confidentialcomputing/test/common/SM4Service.java @@ -0,0 +1,8 @@ +package com.alibaba.confidentialcomputing.test.common; + +import com.alibaba.confidentialcomputing.common.annotations.EnclaveService; + +@EnclaveService +public interface SM4Service { + String sm4Service(String plaintext) throws Exception; +} diff --git a/test/enclave/pom.xml b/test/enclave/pom.xml index 5bc5380..278d1e9 100644 --- a/test/enclave/pom.xml +++ b/test/enclave/pom.xml @@ -107,6 +107,23 @@ </profiles> <build> <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.1</version> + <configuration> + <source>11</source> + <target>11</target> + <compilerArgs> + <arg>--add-modules</arg> + <arg>jdk.internal.vm.compiler,jdk.crypto.ec</arg> + <arg>--add-exports</arg> + <arg>jdk.crypto.ec/sun.security.ec=ALL-UNNAMED</arg> + <arg>--add-exports</arg> + <arg>jdk.internal.vm.compiler/org.graalvm.compiler.options=ALL-UNNAMED</arg> + </compilerArgs> + </configuration> + </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> @@ -160,6 +177,14 @@ <scope>compile</scope> <optional>true</optional> </dependency> + <dependency> + <groupId>com.alibaba.confidentialcomputing</groupId> + <artifactId>bouncycastle-native</artifactId> + </dependency> + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcprov-jdk15on</artifactId> + </dependency> <dependency> <groupId>com.google.auto.service</groupId> <artifactId>auto-service-annotations</artifactId> diff --git a/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/MetricTraceServiceImpl.java b/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/MetricTraceServiceImpl.java new file mode 100644 index 0000000..b96b569 --- /dev/null +++ b/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/MetricTraceServiceImpl.java @@ -0,0 +1,17 @@ +package com.alibaba.confidentialcomputing.test.enclave; + +import com.alibaba.confidentialcomputing.test.common.MetricTraceService; +import com.google.auto.service.AutoService; + +@AutoService(MetricTraceService.class) +public class MetricTraceServiceImpl implements MetricTraceService { + @Override + public String invertCharacter(String str) { + byte[] content = new byte[str.length()]; + byte[] initial = str.getBytes(); + for (int i = 0x0; i < initial.length; i++) { + content[i] = initial[initial.length - i -1]; + } + return new String(content); + } +} diff --git a/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM2ServiceImpl.java b/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM2ServiceImpl.java new file mode 100644 index 0000000..68e3366 --- /dev/null +++ b/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM2ServiceImpl.java @@ -0,0 +1,91 @@ +package com.alibaba.confidentialcomputing.test.enclave; + +import org.bouncycastle.asn1.gm.GMNamedCurves; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey; +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.jce.spec.ECParameterSpec; +import org.bouncycastle.jce.spec.ECPrivateKeySpec; +import org.bouncycastle.jce.spec.ECPublicKeySpec; +import org.bouncycastle.math.ec.ECPoint; +import org.bouncycastle.util.encoders.Hex; + +import javax.crypto.Cipher; +import java.math.BigInteger; +import java.security.*; +import java.security.spec.ECGenParameterSpec; +import java.util.Base64; + +import com.alibaba.confidentialcomputing.test.common.SM2Service; +import com.google.auto.service.AutoService; + +@AutoService(SM2Service.class) +public class SM2ServiceImpl implements SM2Service { + private BouncyCastleProvider provider; + private ECParameterSpec ecParameterSpec; + private KeyFactory keyFactory; + private String publicKey; + private String privateKey; + + public SM2ServiceImpl() { + try { + provider = (BouncyCastleProvider) Security.getProvider("BC"); + if (provider == null) { + provider = new BouncyCastleProvider(); + } + X9ECParameters parameters = GMNamedCurves.getByName("sm2p256v1"); + ecParameterSpec = new ECParameterSpec(parameters.getCurve(), parameters.getG(), parameters.getN(), parameters.getH()); + keyFactory = KeyFactory.getInstance("EC", provider); + generateSm2KeyPair(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void generateSm2KeyPair() throws Exception { + final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1"); + final KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", provider); + SecureRandom random = new SecureRandom(); + kpg.initialize(sm2Spec, random); + KeyPair keyPair = kpg.generateKeyPair(); + BCECPrivateKey privateKey = (BCECPrivateKey) keyPair.getPrivate(); + BCECPublicKey publicKey = (BCECPublicKey) keyPair.getPublic(); + this.publicKey = new String(Hex.encode(publicKey.getQ().getEncoded(true))); + this.privateKey = privateKey.getD().toString(16); + } + + private String encode(String input, String pubKey) { + try { + X9ECParameters parameters = GMNamedCurves.getByName("sm2p256v1"); + ECParameterSpec ecParameterSpec = new ECParameterSpec(parameters.getCurve(), parameters.getG(), parameters.getN(), parameters.getH()); + ECPoint ecPoint = parameters.getCurve().decodePoint(Hex.decode(pubKey)); + KeyFactory keyFactory = KeyFactory.getInstance("EC", provider); + BCECPublicKey key = (BCECPublicKey) keyFactory.generatePublic(new ECPublicKeySpec(ecPoint, ecParameterSpec)); + Cipher cipher = Cipher.getInstance("SM2", provider); + cipher.init(Cipher.ENCRYPT_MODE, key); + return Base64.getEncoder().encodeToString(cipher.doFinal(input.getBytes())); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + private byte[] decoder(String input, String prvKey) { + try { + Cipher cipher = Cipher.getInstance("SM2", provider); + BigInteger bigInteger = new BigInteger(prvKey, 16); + BCECPrivateKey privateKey = (BCECPrivateKey) keyFactory.generatePrivate(new ECPrivateKeySpec(bigInteger, ecParameterSpec)); + cipher.init(Cipher.DECRYPT_MODE, privateKey); + return cipher.doFinal(Base64.getDecoder().decode(input)); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @Override + public String encryptAndDecryptWithPlaintext(String plaintext) throws Exception { + return new String(decoder(encode(plaintext, publicKey), privateKey)); + } +} diff --git a/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM3ServiceImpl.java b/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM3ServiceImpl.java new file mode 100644 index 0000000..dcb1bf8 --- /dev/null +++ b/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM3ServiceImpl.java @@ -0,0 +1,19 @@ +package com.alibaba.confidentialcomputing.test.enclave; + +import com.alibaba.confidentialcomputing.test.common.SM3Service; +import com.google.auto.service.AutoService; +import org.bouncycastle.crypto.Digest; +import org.bouncycastle.crypto.digests.SM3Digest; + +@AutoService(SM3Service.class) +public class SM3ServiceImpl implements SM3Service { + @Override + public byte[] sm3Service(String plainText) throws Exception { + byte[] messages = plainText.getBytes(); + Digest md = new SM3Digest(); + md.update(messages, 0, messages.length); + byte[] digest = new byte[md.getDigestSize()]; + md.doFinal(digest, 0); + return digest; + } +} diff --git a/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM4ServiceImpl.java b/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM4ServiceImpl.java new file mode 100644 index 0000000..bab25b2 --- /dev/null +++ b/test/enclave/src/main/java/com/alibaba/confidentialcomputing/test/enclave/SM4ServiceImpl.java @@ -0,0 +1,57 @@ +package com.alibaba.confidentialcomputing.test.enclave; + +import com.alibaba.confidentialcomputing.test.common.SM4Service; +import com.google.auto.service.AutoService; +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.Provider; +import java.security.SecureRandom; +import java.security.Security; + +@AutoService(SM4Service.class) +public class SM4ServiceImpl implements SM4Service { + private static final String ALGORITHM_NAME = "SM4"; + private static final String ALGORITHM_ECB_PKCS5PADDING = "SM4/ECB/PKCS5Padding"; + private static final int DEFAULT_KEY_SIZE = 128; + + static { + Provider provider = Security.getProvider("BC"); + if (provider == null) { + provider = new BouncyCastleProvider(); + } + Security.addProvider(provider); + } + + private byte[] generateKey() throws Exception { + KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME); + kg.init(DEFAULT_KEY_SIZE, new SecureRandom()); + return kg.generateKey().getEncoded(); + } + + private byte[] sm4EncryptAndDecrypt(byte[] data, byte[] key, String sm4mode, byte[] iv, int mode) throws Exception { + IvParameterSpec ivParameterSpec = null; + if (null != iv) { + ivParameterSpec = new IvParameterSpec(iv); + } + SecretKeySpec sm4Key = new SecretKeySpec(key, ALGORITHM_NAME); + Cipher cipher = Cipher.getInstance(sm4mode, BouncyCastleProvider.PROVIDER_NAME); + if (null == ivParameterSpec) { + cipher.init(mode, sm4Key); + } else { + cipher.init(mode, sm4Key, ivParameterSpec); + } + return cipher.doFinal(data); + } + + @Override + public String sm4Service(String plaintext) throws Exception { + byte[] key = generateKey(); + byte[] encryptResult = sm4EncryptAndDecrypt(plaintext.getBytes(StandardCharsets.UTF_8), key, ALGORITHM_ECB_PKCS5PADDING, null, Cipher.ENCRYPT_MODE); + return new String(sm4EncryptAndDecrypt(encryptResult, key, ALGORITHM_ECB_PKCS5PADDING, null, Cipher.DECRYPT_MODE), StandardCharsets.UTF_8); + } +} diff --git a/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestEnclaveMetricTrace.java b/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestEnclaveMetricTrace.java new file mode 100644 index 0000000..3bba0f3 --- /dev/null +++ b/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestEnclaveMetricTrace.java @@ -0,0 +1,67 @@ +package com.alibaba.confidentialcomputing.test.host; + +import com.alibaba.confidentialcomputing.host.Enclave; +import com.alibaba.confidentialcomputing.host.EnclaveFactory; +import com.alibaba.confidentialcomputing.host.EnclaveType; +import com.alibaba.confidentialcomputing.host.MetricTrace; +import com.alibaba.confidentialcomputing.test.common.MetricTraceService; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.util.Iterator; + +import static org.junit.jupiter.api.Assertions.*; + +public class TestEnclaveMetricTrace { + private String invertCharacter(String str) { + byte[] content = new byte[str.length()]; + byte[] initial = str.getBytes(); + for (int i = 0x0; i < initial.length; i++) { + content[i] = initial[initial.length - i - 1]; + } + return new String(content); + } + + @Test + public void testEnclaveMetricTrace() throws Exception { + MetricTrace.setEnclaveMetricTraceSwitch(true); + String plaintext = "ABC_DEF_GHI_JKL_MNO_PQR_STU_VWX_YZ"; + EnclaveType[] types = new EnclaveType[] { + EnclaveType.MOCK_IN_JVM, + EnclaveType.MOCK_IN_SVM, + EnclaveType.TEE_SDK, + EnclaveType.EMBEDDED_LIB_OS}; + for (EnclaveType type : types) { + Enclave enclave = EnclaveFactory.create(type); + assertNotNull(enclave); + Iterator<MetricTraceService> userServices = enclave.load(MetricTraceService.class); + assertNotNull(userServices); + assertTrue(userServices.hasNext()); + MetricTraceService service = userServices.next(); + String result = service.invertCharacter(plaintext); + assertEquals(result, invertCharacter(plaintext)); + enclave.destroy(); + } + MetricTrace.setEnclaveMetricTraceSwitch(false); + + Field flog = MetricTrace.class.getDeclaredField("logPath"); + flog.setAccessible(true); + String logPath = (String) flog.get(null); + assertNotNull(logPath); + File file = new File(logPath); + assertTrue(file.exists()); + InputStream in = new FileInputStream(logPath); + byte[] buffer = new byte[in.available()]; + in.read(buffer); + String str = new String(buffer); + assertTrue(str.contains("enclave_creating_cost")); + assertTrue(str.contains("enclave_destroying_cost")); + assertTrue(str.contains("enclave_service_loading")); + assertTrue(str.contains("TEE_SDK")); + assertTrue(str.contains("EMBEDDED_LIB_OS")); + assertTrue(file.delete()); + } +} diff --git a/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestSMEnclave.java b/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestSMEnclave.java new file mode 100644 index 0000000..aa12f33 --- /dev/null +++ b/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestSMEnclave.java @@ -0,0 +1,91 @@ +package com.alibaba.confidentialcomputing.test.host; + +import com.alibaba.confidentialcomputing.host.Enclave; +import com.alibaba.confidentialcomputing.host.EnclaveFactory; +import com.alibaba.confidentialcomputing.host.EnclaveType; +import com.alibaba.confidentialcomputing.test.common.SM2Service; +import com.alibaba.confidentialcomputing.test.common.SM3Service; +import com.alibaba.confidentialcomputing.test.common.SM4Service; +import org.bouncycastle.crypto.Digest; +import org.bouncycastle.crypto.digests.SM3Digest; +import org.junit.jupiter.api.Test; + +import java.util.Iterator; + +import static org.junit.jupiter.api.Assertions.*; + +public class TestSMEnclave { + private byte[] sm3Digest(String plaintext) { + byte[] messages = plaintext.getBytes(); + Digest md = new SM3Digest(); + md.update(messages, 0, messages.length); + byte[] digest = new byte[md.getDigestSize()]; + md.doFinal(digest, 0); + return digest; + } + + @Test + public void testSM2Enclave() throws Exception { + String plaintext = "Hello World!!!"; + EnclaveType[] types = new EnclaveType[]{ + EnclaveType.MOCK_IN_JVM, + EnclaveType.MOCK_IN_SVM, + EnclaveType.TEE_SDK, + EnclaveType.EMBEDDED_LIB_OS}; + + for (EnclaveType type : types) { + Enclave enclave = EnclaveFactory.create(type); + assertNotNull(enclave); + Iterator<SM2Service> userServices = enclave.load(SM2Service.class); + assertNotNull(userServices); + assertTrue(userServices.hasNext()); + SM2Service service = userServices.next(); + String result = service.encryptAndDecryptWithPlaintext(plaintext); + assertEquals(plaintext, result); + enclave.destroy(); + } + } + + @Test + public void testSM3Enclave() throws Exception { + String plaintext = "Hello World!!!"; + EnclaveType[] types = new EnclaveType[]{ + EnclaveType.MOCK_IN_JVM, + EnclaveType.MOCK_IN_SVM, + EnclaveType.TEE_SDK, + EnclaveType.EMBEDDED_LIB_OS}; + + for (EnclaveType type : types) { + Enclave enclave = EnclaveFactory.create(type); + assertNotNull(enclave); + Iterator<SM3Service> userServices = enclave.load(SM3Service.class); + assertNotNull(userServices); + assertTrue(userServices.hasNext()); + SM3Service service = userServices.next(); + byte[] result = service.sm3Service(plaintext); + assertArrayEquals(sm3Digest(plaintext), result); + enclave.destroy(); + } + } + + @Test + public void testSM4Enclave() throws Exception { + String plaintext = "Hello World!!!"; + EnclaveType[] types = new EnclaveType[]{ + EnclaveType.MOCK_IN_JVM, + EnclaveType.MOCK_IN_SVM, + EnclaveType.TEE_SDK, + EnclaveType.EMBEDDED_LIB_OS}; + + for (EnclaveType type : types) { + Enclave enclave = EnclaveFactory.create(type); + assertNotNull(enclave); + Iterator<SM4Service> userServices = enclave.load(SM4Service.class); + assertNotNull(userServices); + assertTrue(userServices.hasNext()); + SM4Service service = userServices.next(); + assertEquals(service.sm4Service(plaintext), plaintext); + enclave.destroy(); + } + } +} diff --git a/test/pom.xml b/test/pom.xml index 97e1d9b..a5e79dd 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -12,6 +12,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <graal.version>22.2.0</graal.version> <com.alibaba.enclave.platform>MOCK_IN_SVM:TEE_SDK:EMBEDDED_LIB_OS</com.alibaba.enclave.platform> </properties> <dependencyManagement> @@ -46,6 +47,16 @@ <artifactId>host</artifactId> <version>0.1.0</version> </dependency> + <dependency> + <groupId>com.alibaba.confidentialcomputing</groupId> + <artifactId>bouncycastle-native</artifactId> + <version>1.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcprov-jdk15on</artifactId> + <version>1.66</version> + </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> @@ -83,4 +94,4 @@ <module>enclave</module> <module>host</module> </modules> -</project> +</project> \ No newline at end of file diff --git a/tools/cicd/Dockerfile b/tools/cicd/Dockerfile index e010d98..cdac972 100644 --- a/tools/cicd/Dockerfile +++ b/tools/cicd/Dockerfile @@ -10,7 +10,7 @@ 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/"] +ADD ["sgx_linux_x64_sdk_2.17.100.1.bin", "/root/tools/"] ENV GRAALVM_HOME "/root/tools/graalvm-ce-java11-22.2.0" ENV JAVA_HOME "/root/tools/graalvm-ce-java11-22.2.0" ENV PATH="/opt/occlum/build/bin:/usr/local/occlum/bin:$PATH" @@ -39,7 +39,7 @@ RUN apt-get update && apt-get install -y gdb gnupg wget aptitude libfuse-dev lib 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=/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 + cd /root/tools && chmod 777 sgx_linux_x64_sdk_2.17.100.1.bin && echo -e 'no\n/opt/teesdk\n' | ./sgx_linux_x64_sdk_2.17.100.1.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 diff --git a/tools/cicd/make.sh b/tools/cicd/make.sh index 971b8b7..c05d6f3 100755 --- a/tools/cicd/make.sh +++ b/tools/cicd/make.sh @@ -3,7 +3,7 @@ MODE=$1 BUILD_IMAGE=javaenclave_build -BUILD_TAG=v0.1.11 +BUILD_TAG=v0.1.12 SHELL_FOLDER=$(cd "$(dirname "$0")";pwd) @@ -17,13 +17,13 @@ if [[ "$(docker images -q ${BUILD_IMAGE}:${BUILD_TAG} 2> /dev/null)" == "" ]]; t wget http://graal.oss-cn-beijing.aliyuncs.com/graal-enclave/JDK11-22.2.0/graalvm-ce-java11-22.2.0.tar 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/tee_java/dependency/sgx_linux_x64_sdk_2.17.100.1.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-ce-java11-22.2.0.tar rm -f settings.xml rm -f zlib-1.2.11.tar.gz - rm -f sgx_linux_x64_sdk_2.17.100.0.bin + rm -f sgx_linux_x64_sdk_2.17.100.1.bin rm -f Alibaba_Dragonwell_11.0.15.11.9_x64_alpine-linux.tar.gz fi --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
