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 855cf637ce8c0eb29b731f2ac32d5a398d8122e0 Author: jeffery.wsj <[email protected]> AuthorDate: Wed Jul 27 18:32:40 2022 +0800 [sdk] Add enclave information query feature for JavaEnclave Summary: Add enclave information query feature for JavaEnclave Test Plan: all tests pass Reviewers: lei.yul, cengfeng.lzy, sanhong.lsh Issue: https://aone.alibaba-inc.com/task/43614236 CR: https://code.aone.alibaba-inc.com/java-tee/JavaEnclave/codereview/9542850 --- .../host/EmbeddedLibOSEnclave.java | 16 +++ .../host/EmbeddedLibOSEnclaveConfig.java | 47 ++++++- .../confidentialcomputing/host/Enclave.java | 8 ++ .../host/EnclaveConfigure.java | 21 +++- .../confidentialcomputing/host/EnclaveInfo.java | 29 +++++ .../host/EnclaveInfoMXBean.java | 24 ++++ .../host/EnclaveInfoManager.java | 36 ++++++ .../confidentialcomputing/host/EnclaveType.java | 6 +- .../host/MockEnclaveInfo.java | 38 ++++++ .../host/MockInJvmEnclave.java | 10 +- .../host/MockInSvmEnclave.java | 8 ++ .../confidentialcomputing/host/SGXEnclaveInfo.java | 38 ++++++ .../confidentialcomputing/host/TeeSdkEnclave.java | 17 +++ .../host/TeeSdkEnclaveConfig.java | 66 ++++++++++ .../host/MockTestEnclave.java | 5 + .../host/TestRemoteAttestation.java | 1 - test/enclave/pom.xml | 2 + test/host/pom.xml | 8 +- .../test/host/TestEnclaveInfo.java | 49 ++++++++ .../test/host/TestEnclaveInfoMXBean.java | 137 +++++++++++++++++++++ 20 files changed, 552 insertions(+), 14 deletions(-) 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 a0c7ff2..c44b403 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 @@ -33,6 +33,7 @@ public class EmbeddedLibOSEnclave extends AbstractEnclave { private int portEnclave; private URL url; private String httpURL; + private SGXEnclaveInfo enclaveInfo; static EmbeddedLibOSEnclave getEmbeddedLibOSEnclaveInstance(EnclaveDebug mode, EnclaveSimulate sim) throws EnclaveCreatingException { synchronized (EmbeddedLibOSEnclave.class) { @@ -75,6 +76,16 @@ public class EmbeddedLibOSEnclave extends AbstractEnclave { url = new URL(httpURL); // Attach to target enclave service by rmi. attachToEnclaveAgent(mode, sim); + // Create enclaveInfo. + boolean isDebuggable = true; + if (EmbeddedLibOSEnclaveConfig.getEmbeddedLibOSEnclaveConfigInstance().getDebuggable().getValue() == 0x2) { + isDebuggable = false; + } + enclaveInfo = new SGXEnclaveInfo( + EnclaveType.EMBEDDED_LIB_OS, + isDebuggable, + EmbeddedLibOSEnclaveConfig.getEmbeddedLibOSEnclaveConfigInstance().getMaxEPCHeapSizeBytes(), + EmbeddedLibOSEnclaveConfig.getEmbeddedLibOSEnclaveConfigInstance().getMaxNumOfThreads()); } catch (IOException e) { throw new EnclaveCreatingException(e); } @@ -219,6 +230,11 @@ public class EmbeddedLibOSEnclave extends AbstractEnclave { return SGXRemoteAttestationVerify.VerifyAttestationReport(quote); } + @Override + public EnclaveInfo getEnclaveInfo() { + return enclaveInfo; + } + @Override public void destroy() throws EnclaveDestroyingException { synchronized (EmbeddedLibOSEnclave.class) { diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclaveConfig.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclaveConfig.java index 8eecb71..ba176a4 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclaveConfig.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EmbeddedLibOSEnclaveConfig.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; +import com.alibaba.confidentialcomputing.common.exception.ConfidentialComputingException; import org.json.JSONArray; import org.json.JSONObject; @@ -21,6 +22,8 @@ class EmbeddedLibOSEnclaveConfig { private boolean debuggable = false; private int agentHttpHandlerThreadPoolSize = 5; private int embeddedLibOSEnclaveStartupDuration = (int) TimeUnit.MINUTES.toMillis(1); + private int maxNumOfThreads = 50; + private long maxEPCHeapSize = 1500; private String libOSLogLevel = "off"; private String[] enclaveJVMArgs = null; @@ -33,6 +36,8 @@ class EmbeddedLibOSEnclaveConfig { boolean debuggable = jsonObject.getBoolean("debuggable"); int agentHttpHandlerThreadPoolSize = jsonObject.getInt("agent_http_handler_thread_pool_size"); int embeddedLibOSEnclaveStartupDuration = jsonObject.getInt("enclave_startup_duration_ms"); + int maxNumOfThreads = jsonObject.getInt("max_num_of_threads"); + long maxEPCHeapSize = parseHeapSize(jsonObject.getString("user_space_size")) * 1024 * 1024; // convert MB to B. String libOSLogLevel = jsonObject.getString("log_level"); JSONArray jvmArgs = jsonObject.getJSONArray("enclave_jvm_args"); List<String> jvmArgsList = new ArrayList<>(); @@ -40,18 +45,46 @@ class EmbeddedLibOSEnclaveConfig { jvmArgsList.add(jvmArgs.getString(i)); } String[] enclaveJVMArgs = jvmArgsList.toArray(new String[jvmArgsList.size()]); - config = new EmbeddedLibOSEnclaveConfig(debuggable, agentHttpHandlerThreadPoolSize, embeddedLibOSEnclaveStartupDuration, libOSLogLevel, enclaveJVMArgs); - } catch (IOException e) { + config = new EmbeddedLibOSEnclaveConfig( + debuggable, + maxNumOfThreads, + maxEPCHeapSize, + agentHttpHandlerThreadPoolSize, + embeddedLibOSEnclaveStartupDuration, + libOSLogLevel, + enclaveJVMArgs); + } catch (IOException | ConfidentialComputingException e) { e.printStackTrace(); } } + private static long parseHeapSize(String value) throws ConfidentialComputingException { + // check heap size dimension must be MB or mb. + if (!(value.endsWith("MB") || value.endsWith("mb"))) { + throw new ConfidentialComputingException("Embedded lib os heap size dimension must be MB."); + } + String trimValue = value.replace("MB", ""); + if (trimValue.startsWith("0x") || trimValue.startsWith("0X")) { + return Long.parseLong(trimValue.substring(2), 16); + } + return Long.parseLong(trimValue); + } + static EmbeddedLibOSEnclaveConfig getEmbeddedLibOSEnclaveConfigInstance() { return config; } - private EmbeddedLibOSEnclaveConfig(boolean debuggable, int agentHttpHandlerThreadPoolSize, int embeddedLibOSEnclaveStartupDuration, String libOSLogLevel, String[] jvmArgs) { + private EmbeddedLibOSEnclaveConfig( + boolean debuggable, + int maxNumOfThreads, + long maxEPCHeapSize, + int agentHttpHandlerThreadPoolSize, + int embeddedLibOSEnclaveStartupDuration, + String libOSLogLevel, + String[] jvmArgs) { this.debuggable = debuggable; + this.maxNumOfThreads = maxNumOfThreads; + this.maxEPCHeapSize = maxEPCHeapSize; this.agentHttpHandlerThreadPoolSize = agentHttpHandlerThreadPoolSize; this.embeddedLibOSEnclaveStartupDuration = embeddedLibOSEnclaveStartupDuration; this.libOSLogLevel = libOSLogLevel; @@ -73,6 +106,14 @@ class EmbeddedLibOSEnclaveConfig { return this.embeddedLibOSEnclaveStartupDuration; } + int getMaxNumOfThreads() { + return this.maxNumOfThreads; + } + + long getMaxEPCHeapSizeBytes() { + return this.maxEPCHeapSize; + } + String getLibOSLogLevel() { return this.libOSLogLevel; } diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/Enclave.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/Enclave.java index f0a3b52..5eeef1f 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/Enclave.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/Enclave.java @@ -74,6 +74,14 @@ public interface Enclave { */ <T> Iterator<T> load(Class<T> service) throws ServicesLoadingException; + /** + * Returns enclave's enclave info. Such as enclave's type, is it debuggable and so on. + * <p> + * + * @return EnclaveInfo enclave information. + */ + EnclaveInfo getEnclaveInfo(); + /** * This method destroy the enclave instance, all the resources in the enclave will be released. * <p> 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 c958b4c..30086e8 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 @@ -12,7 +12,7 @@ import com.alibaba.confidentialcomputing.host.exception.EnclaveCreatingException */ class EnclaveConfigure { private static final String ENCLAVE_TYPE = "com.alibaba.enclave.type"; - private static final String ENCLAVE_DEBUG = "com.alibaba.enclave.debug"; + private static final String ENCLAVE_DEBUG = "com.alibaba.enclave.teesdk.debug"; private static final EnclaveType enclaveType; private static final EnclaveDebug enclaveDebug; @@ -73,18 +73,29 @@ class EnclaveConfigure { // create an enclave with specific enclave type. static Enclave create(EnclaveType type) throws EnclaveCreatingException { + Enclave enclave; switch (type) { case MOCK_IN_JVM: - return new MockInJvmEnclave(); + enclave = new MockInJvmEnclave(); + break; case MOCK_IN_SVM: - return new MockInSvmEnclave(); + enclave = new MockInSvmEnclave(); + break; case TEE_SDK: - return new TeeSdkEnclave(enclaveDebug); + // TEE_SDK only support hardware mode, not support simulate mode. + enclave = new TeeSdkEnclave(enclaveDebug); + break; case EMBEDDED_LIB_OS: - return EmbeddedLibOSEnclave.getEmbeddedLibOSEnclaveInstance(EmbeddedLibOSEnclaveConfig.getEmbeddedLibOSEnclaveConfigInstance().getDebuggable(), EnclaveSimulate.HARDWARE); + // 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."); } + 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 new file mode 100644 index 0000000..1eaa9f5 --- /dev/null +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveInfo.java @@ -0,0 +1,29 @@ +package com.alibaba.confidentialcomputing.host; + +/** + * an enclave's detail information. + */ +public interface EnclaveInfo { + /** + * the enclave's type, MOCK_IN_JVM、MOCK_IN_SVM、TEE_SDK or EMBEDDED_LIB_OS. + */ + EnclaveType getEnclaveType(); + + /** + * 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 + * user, if the enclave is not debuggable, we couldn't debug the code run in enclave by + * gdb or other debug tools. + */ + boolean isEnclaveDebuggable(); + + /** + * get enclave's usable epc memory size. + */ + long getEnclaveEPCMemorySizeBytes(); + + /** + * get enclave's usable max threads number. + */ + int getEnclaveMaxThreadsNumber(); +} diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveInfoMXBean.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveInfoMXBean.java new file mode 100644 index 0000000..357f27a --- /dev/null +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveInfoMXBean.java @@ -0,0 +1,24 @@ +package com.alibaba.confidentialcomputing.host; + +import java.util.List; + +/** + * EnclaveInfoMXBean help query created all existed enclave's detail information. + * Such as existed enclave instance number, every enclave's type info, is debuggable, + * and enclave's epc memory size and so on. + */ +public interface EnclaveInfoMXBean { + /** + * get all existed enclaves' number. + * + * @return int existed enclaves' number. + */ + int getEnclaveInstanceNumber(); + + /** + * get all existed enclaves' EnclaveInfo details. + * + * @return List<EnclaveInfo> all existed enclaves' EnclaveInfo details. + */ + List<EnclaveInfo> getEnclaveInstancesInfo(); +} diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveInfoManager.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveInfoManager.java new file mode 100644 index 0000000..24d04b2 --- /dev/null +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveInfoManager.java @@ -0,0 +1,36 @@ +package com.alibaba.confidentialcomputing.host; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class EnclaveInfoManager implements EnclaveInfoMXBean { + private final static EnclaveInfoManager instance = new EnclaveInfoManager(); + private HashMap<Enclave, Object> enclaveRecord = new HashMap<>(); + + public static EnclaveInfoManager getEnclaveInfoManagerInstance() { + return instance; + } + + synchronized void addEnclave(Enclave enclave) { + enclaveRecord.put(enclave, null); + } + + synchronized void removeEnclave(Enclave enclave) { + enclaveRecord.remove(enclave); + } + + @Override + public synchronized int getEnclaveInstanceNumber() { + return enclaveRecord.size(); + } + + @Override + public synchronized List<EnclaveInfo> getEnclaveInstancesInfo() { + List<EnclaveInfo> enclaveInfos = new ArrayList<>(); + for (Enclave enclave : enclaveRecord.keySet()) { + enclaveInfos.add(enclave.getEnclaveInfo()); + } + return enclaveInfos; + } +} diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveType.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveType.java index 45155c8..5a6705d 100644 --- a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveType.java +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/EnclaveType.java @@ -29,5 +29,9 @@ public enum EnclaveType { * on enclave's occlum libos. host application runs in jvm environment, and enclave * package were loaded by host. */ - EMBEDDED_LIB_OS, + EMBEDDED_LIB_OS; + + public String getEnclaveType() { + return this.toString(); + } } \ No newline at end of file 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 new file mode 100644 index 0000000..8e790f4 --- /dev/null +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/MockEnclaveInfo.java @@ -0,0 +1,38 @@ +package com.alibaba.confidentialcomputing.host; + +import javax.management.ConstructorParameters; + +class MockEnclaveInfo implements EnclaveInfo { + private final EnclaveType enclaveType; + private boolean isEnclaveDebuggable; + private long enclaveEPCMemorySizeBytes; // Bytes. + private int enclaveMaxThreadsNumber; + + @ConstructorParameters({"enclaveType", "isEnclaveDebuggable", "enclaveEPCMemorySizeBytes", "enclaveMaxThreadsNumber"}) + MockEnclaveInfo(EnclaveType enclaveType, boolean isEnclaveDebuggable, long enclaveEPCMemorySizeBytes, int enclaveMaxThreadsNumber) { + this.enclaveType = enclaveType; + this.isEnclaveDebuggable = isEnclaveDebuggable; + this.enclaveEPCMemorySizeBytes = enclaveEPCMemorySizeBytes; + this.enclaveMaxThreadsNumber = enclaveMaxThreadsNumber; + } + + @Override + public EnclaveType getEnclaveType() { + return this.enclaveType; + } + + @Override + public boolean isEnclaveDebuggable() { + return this.isEnclaveDebuggable; + } + + @Override + public long getEnclaveEPCMemorySizeBytes() { + return this.enclaveEPCMemorySizeBytes; + } + + @Override + public int getEnclaveMaxThreadsNumber() { + return this.enclaveMaxThreadsNumber; + } +} 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 c25f114..7ba9da0 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 @@ -9,9 +9,12 @@ import com.alibaba.confidentialcomputing.host.exception.*; * in one jvm. It was used for test and debug. */ class MockInJvmEnclave extends AbstractEnclave { + private final MockEnclaveInfo enclaveInfo; + MockInJvmEnclave() { // Set EnclaveContext for this enclave instance. super(EnclaveType.MOCK_IN_JVM, new BaseEnclaveServicesRecycler()); + enclaveInfo = new MockEnclaveInfo(EnclaveType.MOCK_IN_JVM, true, -1, -1); } @Override @@ -38,8 +41,13 @@ class MockInJvmEnclave extends AbstractEnclave { return null; } + @Override + public EnclaveInfo getEnclaveInfo() { + return enclaveInfo; + } + @Override public void destroy() throws EnclaveDestroyingException { - ; // Do nothing here. + EnclaveInfoManager.getEnclaveInfoManagerInstance().removeEnclave(this); } } 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 340553e..508b741 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 @@ -26,6 +26,7 @@ class MockInSvmEnclave extends AbstractEnclave { private long isolateHandle; // isolateThreadHandle stores the first attached isolateThread Handle. private long isolateThreadHandle; + private final MockEnclaveInfo enclaveInfo; MockInSvmEnclave() throws EnclaveCreatingException { // Set EnclaveContext for this enclave instance. @@ -58,6 +59,7 @@ class MockInSvmEnclave extends AbstractEnclave { nativeCreateEnclave(extractTempPath.getEnclaveSvmFilePath()); // Create svm attach isolate and isolateThread, and they are set in jni in nativeHandlerContext. nativeSvmAttachIsolate(enclaveSvmSdkHandle); + enclaveInfo = new MockEnclaveInfo(EnclaveType.MOCK_IN_SVM, true, -1, -1); } @Override @@ -102,6 +104,11 @@ class MockInSvmEnclave extends AbstractEnclave { return nativeInvokeMethod(enclaveSvmSdkHandle, isolateHandle, payload); } + @Override + public EnclaveInfo getEnclaveInfo() { + return enclaveInfo; + } + @Override public void destroy() throws EnclaveDestroyingException { // destroyToken will wait for all ongoing enclave invocations finished. @@ -111,6 +118,7 @@ class MockInSvmEnclave extends AbstractEnclave { // destroy svm isolate. nativeSvmDetachIsolate(enclaveSvmSdkHandle, isolateThreadHandle); nativeDestroyEnclave(enclaveSvmSdkHandle); + EnclaveInfoManager.getEnclaveInfoManagerInstance().removeEnclave(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 new file mode 100644 index 0000000..8f61b73 --- /dev/null +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/SGXEnclaveInfo.java @@ -0,0 +1,38 @@ +package com.alibaba.confidentialcomputing.host; + +import javax.management.ConstructorParameters; + +class SGXEnclaveInfo implements EnclaveInfo { + private final EnclaveType enclaveType; + private boolean isEnclaveDebuggable; + private long enclaveEPCMemorySizeBytes; // Bytes. + private int enclaveMaxThreadsNumber; + + @ConstructorParameters({"enclaveType", "isEnclaveDebuggable", "enclaveEPCMemorySizeBytes", "enclaveMaxThreadsNumber"}) + SGXEnclaveInfo(EnclaveType enclaveType, boolean isEnclaveDebuggable, long enclaveEPCMemorySizeBytes, int enclaveMaxThreadsNumber) { + this.enclaveType = enclaveType; + this.isEnclaveDebuggable = isEnclaveDebuggable; + this.enclaveEPCMemorySizeBytes = enclaveEPCMemorySizeBytes; + this.enclaveMaxThreadsNumber = enclaveMaxThreadsNumber; + } + + @Override + public EnclaveType getEnclaveType() { + return this.enclaveType; + } + + @Override + public boolean isEnclaveDebuggable() { + return this.isEnclaveDebuggable; + } + + @Override + public long getEnclaveEPCMemorySizeBytes() { + return this.enclaveEPCMemorySizeBytes; + } + + @Override + public int getEnclaveMaxThreadsNumber() { + return this.enclaveMaxThreadsNumber; + } +} 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 36052b5..5bf0f1d 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 @@ -22,6 +22,7 @@ class TeeSdkEnclave extends AbstractEnclave { private long isolateHandle; // isolateThreadHandle stores the first attached isolateThread Handle. private long isolateThreadHandle; + private SGXEnclaveInfo enclaveInfo; TeeSdkEnclave(EnclaveDebug mode) throws EnclaveCreatingException { // Set EnclaveContext for this enclave instance. @@ -53,6 +54,16 @@ class TeeSdkEnclave extends AbstractEnclave { nativeCreateEnclave(mode.getValue(), extractTempPath.getTeeSdkSignedFilePath()); // Create svm attach isolate and isolateThread, and they are set in jni in nativeHandlerContext. nativeSvmAttachIsolate(enclaveHandle); + // Create enclave info. + boolean isDebuggable = true; + if (mode.getValue() == 0x2) { + isDebuggable = false; + } + enclaveInfo = new SGXEnclaveInfo( + EnclaveType.TEE_SDK, + isDebuggable, + TeeSdkEnclaveConfig.getTeeSdkEnclaveConfigInstance().getHeapMaxSizeBytes(), + TeeSdkEnclaveConfig.getTeeSdkEnclaveConfigInstance().getThreadMaxNumber()); } private static native void registerNatives(); @@ -115,6 +126,11 @@ class TeeSdkEnclave extends AbstractEnclave { return nativeGenerateAttestationReport(enclaveHandle, userData); } + @Override + public EnclaveInfo getEnclaveInfo() { + return this.enclaveInfo; + } + @Override public void destroy() throws EnclaveDestroyingException { // destroyToken will wait for all ongoing enclave invocations finished. @@ -125,6 +141,7 @@ class TeeSdkEnclave extends AbstractEnclave { nativeSvmDetachIsolate(enclaveHandle, isolateThreadHandle); // destroy the enclave. nativeDestroyEnclave(enclaveHandle); + EnclaveInfoManager.getEnclaveInfoManagerInstance().removeEnclave(this); } } diff --git a/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkEnclaveConfig.java b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkEnclaveConfig.java new file mode 100644 index 0000000..5be6bd9 --- /dev/null +++ b/sdk/host/src/main/java/com/alibaba/confidentialcomputing/host/TeeSdkEnclaveConfig.java @@ -0,0 +1,66 @@ +package com.alibaba.confidentialcomputing.host; + +import org.xml.sax.InputSource; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import java.io.File; +import java.io.StringReader; +import java.nio.charset.Charset; +import java.nio.file.Files; + +import static com.alibaba.confidentialcomputing.host.ExtractLibrary.extractLibrary; + +class TeeSdkEnclaveConfig { + private final static String TEE_SDK_ENCLAVE_CONFIG_FILE = "tee_sdk_svm.conf"; + private long heapMaxSize; + private int threadMaxNumber; + + private static String configFilePath; + private static TeeSdkEnclaveConfig config; + + private TeeSdkEnclaveConfig(long heapMaxSize, int threadMaxNumber) { + this.heapMaxSize = heapMaxSize; + this.threadMaxNumber = threadMaxNumber; + } + + private static long hexToDecimal(String value) { + if (value.toLowerCase().startsWith("0x")) { + return Long.parseLong(value.substring(2), 16); + } + return Long.parseLong(value); + } + + private static String parseTeeSdkConfig(String path, String content) throws XPathExpressionException { + InputSource source = new InputSource(new StringReader(content)); + XPathFactory xpathFactory = XPathFactory.newInstance(); + XPath xpath = xpathFactory.newXPath(); + return xpath.evaluate(path, source); + } + + static { + try { + configFilePath = extractLibrary(TeeSdkEnclave.class.getClassLoader(), TEE_SDK_ENCLAVE_CONFIG_FILE); + File file = new File(configFilePath); + String content = Files.readString(file.toPath(), Charset.forName("UTF-8")); + String heapMaxSize = parseTeeSdkConfig("/EnclaveConfiguration/HeapMaxSize", content); + String threadMaxSize = parseTeeSdkConfig("/EnclaveConfiguration/TCSNum", content); + config = new TeeSdkEnclaveConfig(hexToDecimal(heapMaxSize), (int) hexToDecimal(threadMaxSize)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + static TeeSdkEnclaveConfig getTeeSdkEnclaveConfigInstance() { + return config; + } + + long getHeapMaxSizeBytes() { + return this.heapMaxSize; + } + + int getThreadMaxNumber() { + return this.threadMaxNumber; + } +} diff --git a/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/MockTestEnclave.java b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/MockTestEnclave.java index e659c99..acf94d1 100644 --- a/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/MockTestEnclave.java +++ b/sdk/host/src/test/java/com/alibaba/confidentialcomputing/host/MockTestEnclave.java @@ -145,6 +145,11 @@ class MockTestEnclave extends AbstractEnclave { } } + @Override + public EnclaveInfo getEnclaveInfo() { + return null; + } + @Override public void destroy() throws EnclaveDestroyingException { // destroyToken will wait for all ongoing enclave invocations finished. 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 8f161c4..e4e509b 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 @@ -1,6 +1,5 @@ package com.alibaba.confidentialcomputing.host; -import com.alibaba.confidentialcomputing.host.exception.EnclaveCreatingException; import com.alibaba.confidentialcomputing.host.exception.RemoteAttestationException; import org.junit.jupiter.api.Test; diff --git a/test/enclave/pom.xml b/test/enclave/pom.xml index 64e3d9f..e791ee7 100644 --- a/test/enclave/pom.xml +++ b/test/enclave/pom.xml @@ -157,6 +157,8 @@ <dependency> <groupId>com.alibaba.confidentialcomputing</groupId> <artifactId>enclave</artifactId> + <scope>compile</scope> + <optional>true</optional> </dependency> <dependency> <groupId>com.google.auto.service</groupId> diff --git a/test/host/pom.xml b/test/host/pom.xml index 9073a33..755b873 100644 --- a/test/host/pom.xml +++ b/test/host/pom.xml @@ -24,6 +24,11 @@ </resource> </resources> <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.1</version> + </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> @@ -43,9 +48,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <!--configuration> - <forkCount>0</forkCount> - </configuration--> <version>3.0.0-M5</version> </plugin> </plugins> diff --git a/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestEnclaveInfo.java b/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestEnclaveInfo.java new file mode 100644 index 0000000..7164035 --- /dev/null +++ b/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestEnclaveInfo.java @@ -0,0 +1,49 @@ +package com.alibaba.confidentialcomputing.test.host; + +import com.alibaba.confidentialcomputing.host.Enclave; +import com.alibaba.confidentialcomputing.host.EnclaveFactory; +import com.alibaba.confidentialcomputing.host.EnclaveInfo; +import com.alibaba.confidentialcomputing.host.EnclaveType; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class TestEnclaveInfo { + + @Test + public void testEnclaveInfo() throws Exception { + Enclave enclave = EnclaveFactory.create(EnclaveType.MOCK_IN_JVM); + EnclaveInfo enclaveInfo = enclave.getEnclaveInfo(); + assertEquals(enclaveInfo.getEnclaveType(), EnclaveType.MOCK_IN_JVM); + assertEquals(enclaveInfo.isEnclaveDebuggable(), true); + assertEquals(enclaveInfo.getEnclaveEPCMemorySizeBytes(), -1); + assertEquals(enclaveInfo.getEnclaveMaxThreadsNumber(), -1); + enclave.destroy(); + + enclave = EnclaveFactory.create(EnclaveType.MOCK_IN_SVM); + enclaveInfo = enclave.getEnclaveInfo(); + assertEquals(enclaveInfo.getEnclaveType(), EnclaveType.MOCK_IN_SVM); + assertEquals(enclaveInfo.isEnclaveDebuggable(), true); + assertEquals(enclaveInfo.getEnclaveEPCMemorySizeBytes(), -1); + assertEquals(enclaveInfo.getEnclaveMaxThreadsNumber(), -1); + enclave.destroy(); + + // it's related to config file in test project. + enclave = EnclaveFactory.create(EnclaveType.TEE_SDK); + enclaveInfo = enclave.getEnclaveInfo(); + assertEquals(enclaveInfo.getEnclaveType(), EnclaveType.TEE_SDK); + assertEquals(enclaveInfo.isEnclaveDebuggable(), false); + assertEquals(enclaveInfo.getEnclaveEPCMemorySizeBytes(), 0x20000000); + assertEquals(enclaveInfo.getEnclaveMaxThreadsNumber(), 15); + enclave.destroy(); + + // it's related to config file in test project. + enclave = EnclaveFactory.create(EnclaveType.EMBEDDED_LIB_OS); + enclaveInfo = enclave.getEnclaveInfo(); + assertEquals(enclaveInfo.getEnclaveType(), EnclaveType.EMBEDDED_LIB_OS); + assertEquals(enclaveInfo.isEnclaveDebuggable(), false); + assertEquals(enclaveInfo.getEnclaveEPCMemorySizeBytes(), 1200 * 1024 * 1024); + assertEquals(enclaveInfo.getEnclaveMaxThreadsNumber(), 60); + enclave.destroy(); + } +} diff --git a/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestEnclaveInfoMXBean.java b/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestEnclaveInfoMXBean.java new file mode 100644 index 0000000..ea3c092 --- /dev/null +++ b/test/host/src/test/java/com/alibaba/confidentialcomputing/test/host/TestEnclaveInfoMXBean.java @@ -0,0 +1,137 @@ +package com.alibaba.confidentialcomputing.test.host; + +import com.alibaba.confidentialcomputing.host.*; +import org.junit.jupiter.api.Test; + +import javax.management.MBeanServer; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.management.openmbean.CompositeData; +import javax.management.remote.*; + +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.net.ServerSocket; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.util.concurrent.CountDownLatch; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class TestEnclaveInfoMXBean { + private static final String DOMAIN_NAME = "EnclaveMXBean"; + private static final String ENCLAVE_MX_BEAN_STUB = "enclaveInfoMXBeanStub"; + + private CountDownLatch cl0 = new CountDownLatch(1); + private CountDownLatch cl1 = new CountDownLatch(1); + + private int rmiPort = getFreePort(); + ObjectName enclaveInfoMXBeanStub; + private Registry registry; + private MBeanServer mxBeanService; + private JMXConnectorServer jmxConnector; + + private int getFreePort() { + try (ServerSocket serverSocket = new ServerSocket(0)) { + return serverSocket.getLocalPort(); + } catch (IOException e) { + e.printStackTrace(); + } + return -1; + } + + private void service() throws Exception { + Enclave enclaveJVM = EnclaveFactory.create(EnclaveType.MOCK_IN_JVM); + EnclaveInfo enclaveInfoJVM = enclaveJVM.getEnclaveInfo(); + assertEquals(enclaveInfoJVM.getEnclaveType(), EnclaveType.MOCK_IN_JVM); + assertEquals(enclaveInfoJVM.isEnclaveDebuggable(), true); + assertEquals(enclaveInfoJVM.getEnclaveEPCMemorySizeBytes(), -1); + assertEquals(enclaveInfoJVM.getEnclaveMaxThreadsNumber(), -1); + + Enclave enclaveSVM = EnclaveFactory.create(EnclaveType.MOCK_IN_SVM); + EnclaveInfo enclaveInfoSVM = enclaveSVM.getEnclaveInfo(); + assertEquals(enclaveInfoSVM.getEnclaveType(), EnclaveType.MOCK_IN_SVM); + assertEquals(enclaveInfoSVM.isEnclaveDebuggable(), true); + assertEquals(enclaveInfoSVM.getEnclaveEPCMemorySizeBytes(), -1); + assertEquals(enclaveInfoSVM.getEnclaveMaxThreadsNumber(), -1); + + // it's related to config file in test project. + Enclave enclaveTEE = EnclaveFactory.create(EnclaveType.TEE_SDK); + EnclaveInfo enclaveInfoTEE = enclaveTEE.getEnclaveInfo(); + assertEquals(enclaveInfoTEE.getEnclaveType(), EnclaveType.TEE_SDK); + assertEquals(enclaveInfoTEE.isEnclaveDebuggable(), false); + assertEquals(enclaveInfoTEE.getEnclaveEPCMemorySizeBytes(), 0x20000000); + assertEquals(enclaveInfoTEE.getEnclaveMaxThreadsNumber(), 15); + + // it's related to config file in test project. + Enclave enclaveLIBOS = EnclaveFactory.create(EnclaveType.EMBEDDED_LIB_OS); + EnclaveInfo enclaveInfoLIBOS = enclaveLIBOS.getEnclaveInfo(); + assertEquals(enclaveInfoLIBOS.getEnclaveType(), EnclaveType.EMBEDDED_LIB_OS); + assertEquals(enclaveInfoLIBOS.isEnclaveDebuggable(), false); + assertEquals(enclaveInfoLIBOS.getEnclaveEPCMemorySizeBytes(), 1200 * 1024 * 1024); + assertEquals(enclaveInfoLIBOS.getEnclaveMaxThreadsNumber(), 60); + + enclaveInfoMXBeanStub = new ObjectName(DOMAIN_NAME + ":name=" + ENCLAVE_MX_BEAN_STUB); + mxBeanService = ManagementFactory.getPlatformMBeanServer(); + mxBeanService.registerMBean( + EnclaveInfoManager.getEnclaveInfoManagerInstance(), + enclaveInfoMXBeanStub); + + registry = LocateRegistry.createRegistry(rmiPort); + JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + rmiPort + "/" + DOMAIN_NAME); + jmxConnector = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mxBeanService); + jmxConnector.start(); + + cl0.countDown(); + cl1.await(); + + enclaveJVM.destroy(); + enclaveSVM.destroy(); + enclaveTEE.destroy(); + enclaveLIBOS.destroy(); + } + + @Test + public void testEnclaveInfo() throws Exception { + Thread serviceThread = new Thread(() -> { + try { + service(); + } catch (Exception e) { + assert (false); + } + }); + serviceThread.setDaemon(true); + serviceThread.start(); + // wait for mxbean service startup. + cl0.await(); + JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + rmiPort + "/" + DOMAIN_NAME); + JMXConnector jmxClient = JMXConnectorFactory.connect(url); + MBeanServerConnection mbsClient = jmxClient.getMBeanServerConnection(); + ObjectName mBeanName = new ObjectName(DOMAIN_NAME + ":name=" + ENCLAVE_MX_BEAN_STUB); + assertEquals(4, mbsClient.getAttribute(mBeanName, "EnclaveInstanceNumber")); + CompositeData[] enclaveInfos = (CompositeData[]) mbsClient.getAttribute(mBeanName, "EnclaveInstancesInfo"); + assertEquals(4, enclaveInfos.length); + for (CompositeData enclaveInfo : enclaveInfos) { + String enclaveType = (String) enclaveInfo.get("enclaveType"); + switch (enclaveType) { + case "MOCK_IN_JVM": + case "MOCK_IN_SVM": + assertEquals((long)enclaveInfo.get("enclaveEPCMemorySizeBytes"), -1); + assertEquals((int)enclaveInfo.get("enclaveMaxThreadsNumber"), -1); + break; + case "TEE_SDK": + assertEquals((long)enclaveInfo.get("enclaveEPCMemorySizeBytes"), 0x20000000); + assertEquals((int)enclaveInfo.get("enclaveMaxThreadsNumber"), 15); + break; + case "EMBEDDED_LIB_OS": + assertEquals((long)enclaveInfo.get("enclaveEPCMemorySizeBytes"), 1200 * 1024 * 1024); + assertEquals((int)enclaveInfo.get("enclaveMaxThreadsNumber"), 60); + break; + case "NONE": + assert (false); + } + } + // notify service exit. + cl1.countDown(); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
