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:13 UTC

[incubator-teaclave-java-tee-sdk] 33/48: [sdk] Add enclave information query feature for JavaEnclave

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 <je...@alibaba-inc.com>
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: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org