You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by sh...@apache.org on 2022/11/11 05:18:16 UTC
[incubator-teaclave-java-tee-sdk] 36/48: [sdk] Support JavaEnclave benchmark metric tracing feature
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 <je...@alibaba-inc.com>
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: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org