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:17:59 UTC

[incubator-teaclave-java-tee-sdk] 19/48: [Enc] Provide C only libenc_sunec.a on demand

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 263a6776cb14cabfd518e33748c796a55f314ae4
Author: cengfeng.lzy <ce...@alibaba-inc.com>
AuthorDate: Thu Apr 7 11:33:14 2022 +0800

    [Enc] Provide C only libenc_sunec.a on demand
    
    Summary: The library libsunec.a provided by Graal VM has C++ symbols which
    are not supported by OE SDK. So we compile a C symbol only
    libenc_sunec.a library for Enclave usages on demand.
    
    Test Plan: all tests pass
    
    Reviewers: lei.yul, jeffery.wsj, sanhong.lsh
    
    Issue: https://aone.alibaba-inc.com/task/41832504
    
    CR:
    https://code.aone.alibaba-inc.com/java-tee/JavaEnclave/codereview/8856699
---
 build.sh                                           |   5 +-
 sdk/enclave/pom.xml                                |   8 +-
 .../enclave/NativeCommandUtil.java                 |  49 ++
 .../enclave/SUNECReplaceFeature.java               | 175 +++++++
 .../enclave/substitutes/NativeSunECMethods.java    |  21 +
 .../enclave/substitutes/SUNECSubstitutions.java    |  53 ++
 .../src/main/resources/native/sunec/ECC_JNI.c      | 524 ++++++++++++++++++++
 ...puting_enclave_substitutes_NativeSunECMethods.h |  53 ++
 .../src/main/resources/native/sunec/ecc_impl.h     | 271 +++++++++++
 .../src/main/resources/native/sunec/ecl-exp.h      | 201 ++++++++
 .../src/main/resources/native/sunec/jlong.h        |  31 ++
 .../src/main/resources/native/sunec/jlong_md.h     | 100 ++++
 .../src/main/resources/native/sunec/jni_util.h     | 534 +++++++++++++++++++++
 .../enclave/NativeImageTest.java                   |  50 +-
 .../enclave/ReplaceSunECTest.java                  |  78 +++
 .../enclave/testservice/EncryptionService.java     |  10 +
 .../enclave/testservice/SunECOperations.java       |  12 +
 ...computing.enclave.testservice.EncryptionService |   1 +
 tools/cicd/make.sh                                 |   2 +-
 19 files changed, 2131 insertions(+), 47 deletions(-)

diff --git a/build.sh b/build.sh
old mode 100644
new mode 100755
index bed423b..44288a0
--- a/build.sh
+++ b/build.sh
@@ -7,11 +7,12 @@ cd "${SHELL_FOLDER}"
 
 # workspace dir is the same as build.sh path location.
 WORKDIR="$PWD"
+SETTING="--settings /root/tools/settings.xml"
 
 # Build JavaEnclave SDK
-cd "${WORKDIR}"/sdk && mvn --settings /root/tools/settings.xml clean install
+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
 # Test unit test cases in JavaEnclave
-cd "${WORKDIR}"/test && mvn -X --settings /root/tools/settings.xml -Pnative -e clean package
+cd "${WORKDIR}"/test && mvn -X $SETTING -Pnative -e clean package
diff --git a/sdk/enclave/pom.xml b/sdk/enclave/pom.xml
index e586e83..3875579 100644
--- a/sdk/enclave/pom.xml
+++ b/sdk/enclave/pom.xml
@@ -96,7 +96,7 @@
                     <target>11</target>
                     <compilerArgs>
                         <arg>--add-modules</arg>
-                        <arg>jdk.internal.vm.ci,jdk.internal.vm.compiler</arg>
+                        <arg>jdk.internal.vm.ci,jdk.internal.vm.compiler,jdk.crypto.ec</arg>
                         <arg>--add-exports</arg>
                         <arg>jdk.internal.vm.ci/jdk.vm.ci.meta=ALL-UNNAMED</arg>
                         <arg>--add-exports</arg>
@@ -105,6 +105,8 @@
                         <arg>jdk.internal.vm.compiler/org.graalvm.compiler.options=ALL-UNNAMED</arg>
                         <arg>--add-exports</arg>
                         <arg>jdk.internal.vm.compiler/org.graalvm.compiler.word=ALL-UNNAMED</arg>
+                        <arg>--add-exports</arg>
+                        <arg>jdk.crypto.ec/sun.security.ec=ALL-UNNAMED</arg>
                     </compilerArgs>
                     <!--OptionProcessor can automatically generate OptionDescriptor classes at javac time-->
                     <annotationProcessorPaths>
@@ -143,7 +145,7 @@
                     <doclint>none</doclint>
                     <additionalJOptions>
                         <additionalJOption>--add-modules</additionalJOption>
-                        <additionalJOption>jdk.internal.vm.ci,jdk.internal.vm.compiler</additionalJOption>
+                        <additionalJOption>jdk.internal.vm.ci,jdk.internal.vm.compiler,jdk.crypto.ec</additionalJOption>
                         <additionalJOption>--add-exports</additionalJOption>
                         <additionalJOption>jdk.internal.vm.ci/jdk.vm.ci.meta=ALL-UNNAMED</additionalJOption>
                         <additionalJOption>--add-exports</additionalJOption>
@@ -152,6 +154,8 @@
                         <additionalJOption>jdk.internal.vm.compiler/org.graalvm.compiler.options=ALL-UNNAMED</additionalJOption>
                         <additionalJOption>--add-exports</additionalJOption>
                         <additionalJOption>jdk.internal.vm.compiler/org.graalvm.compiler.word=ALL-UNNAMED</additionalJOption>
+                        <additionalJOption>--add-exports</additionalJOption>
+                        <additionalJOption>jdk.crypto.ec/sun.security.ec=ALL-UNNAMED</additionalJOption>
                     </additionalJOptions>
                 </configuration>
                 <version>3.2.0</version>
diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/NativeCommandUtil.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/NativeCommandUtil.java
new file mode 100644
index 0000000..9966a30
--- /dev/null
+++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/NativeCommandUtil.java
@@ -0,0 +1,49 @@
+package com.alibaba.confidentialcomputing.enclave;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.SequenceInputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class NativeCommandUtil {
+    public static final Path GRAALVM_HOME = Paths.get(System.getenv("GRAALVM_HOME"));
+
+    public static int executeNewProcess(List<String> command, Path workDir) {
+        if (command == null || command.isEmpty()) {
+            throw new RuntimeException("Didn't provide any execution command.");
+        }
+        ProcessBuilder pb = new ProcessBuilder(command).directory(workDir.toFile());
+        pb.redirectErrorStream(true);
+        String oneLineCommand = command.stream().collect(Collectors.joining(" "));
+        System.out.println(oneLineCommand);
+        Process p = null;
+        try {
+            p = pb.start();
+            InputStreamReader inst = new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8);
+            try (BufferedReader br = new BufferedReader(inst)) {
+                String res;
+                while ((res = br.readLine()) != null) {
+                    System.out.println(res);
+                }
+            }
+            int exitCode = p.waitFor();
+            if (exitCode != 0) {
+                throw new RuntimeException("Failed to execute command:\n " + oneLineCommand +
+                        "\n Working directory is :" + workDir.toString() + "\n The exit code is " + exitCode+
+                        "\n");
+            }
+            return 0;
+        } catch (IOException | InterruptedException e) {
+            throw new RuntimeException("Failed to execute command:\n " + oneLineCommand, e);
+        } finally {
+            if (p != null) {
+                p.destroy();
+            }
+        }
+    }
+}
diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/SUNECReplaceFeature.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/SUNECReplaceFeature.java
new file mode 100644
index 0000000..aa365d5
--- /dev/null
+++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/SUNECReplaceFeature.java
@@ -0,0 +1,175 @@
+package com.alibaba.confidentialcomputing.enclave;
+
+import com.oracle.svm.core.SubstrateOptions;
+import com.oracle.svm.core.annotate.AutomaticFeature;
+import com.oracle.svm.core.c.libc.LibCBase;
+import com.oracle.svm.core.c.libc.TemporaryBuildDirectoryProvider;
+import com.oracle.svm.core.jdk.JNIRegistrationUtil;
+import com.oracle.svm.core.util.VMError;
+import com.oracle.svm.hosted.FeatureImpl;
+import com.oracle.svm.hosted.ImageClassLoader;
+import com.oracle.svm.hosted.NativeImageGenerator;
+import org.graalvm.nativeimage.ImageSingletons;
+import org.graalvm.nativeimage.Platform;
+import org.graalvm.nativeimage.Platforms;
+import org.graalvm.nativeimage.hosted.Feature;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.alibaba.confidentialcomputing.enclave.NativeCommandUtil.GRAALVM_HOME;
+
+/**
+ * THe original {@code libsunec.a} library provided by GraalVM (which is copied from OpenJDK) has C++ operations which
+ * are not supported by some Enclave SDKs (e.g. OpenEnclave and Tee SDK), therefore, a substituted library that replies
+ * only on C symbols is required.
+ * <p>
+ * This class compiles the new C only {@code libsunec.a} and outputs it into the path specified by {@link SubstrateOptions#Path}
+ * options along with other SVM artifacts on demand.
+ */
+@AutomaticFeature
+public class SUNECReplaceFeature extends JNIRegistrationUtil implements Feature {
+
+    public static final String LIBENC_SUNEC_A = "libenc_sunec.a";
+    private Path sunecTmpDir = null;
+
+    @Override
+    public void beforeAnalysis(BeforeAnalysisAccess access) {
+        access.registerReachabilityHandler(this::prepareEncSunEC,
+                method(access, "com.alibaba.confidentialcomputing.enclave.substitutes.NativeSunECMethods", "signDigest", byte[].class, byte[].class, byte[].class, byte[].class, int.class),
+                method(access, "com.alibaba.confidentialcomputing.enclave.substitutes.NativeSunECMethods", "verifySignedDigest", byte[].class, byte[].class, byte[].class, byte[].class),
+                method(access, "com.alibaba.confidentialcomputing.enclave.substitutes.NativeSunECMethods", "isCurveSupported", byte[].class),
+                method(access, "com.alibaba.confidentialcomputing.enclave.substitutes.NativeSunECMethods", "generateECKeyPair", int.class, byte[].class, byte[].class),
+                method(access, "com.alibaba.confidentialcomputing.enclave.substitutes.NativeSunECMethods", "deriveKey", byte[].class, byte[].class, byte[].class));
+    }
+
+    @Platforms(Platform.LINUX.class)
+    private void prepareEncSunEC(BeforeAnalysisAccess a) {
+        if (Files.notExists(GRAALVM_HOME)) {
+            VMError.shouldNotReachHere("System environment variable GRAALVM_HOME is set to " + GRAALVM_HOME
+                    + ", but the directory does not exist!");
+        }
+        Path tempDirectory = ImageSingletons.lookup(TemporaryBuildDirectoryProvider.class).getTemporaryBuildDirectory();
+        try {
+            sunecTmpDir = tempDirectory.resolve("sunec");
+            if (Files.notExists(sunecTmpDir)) {
+                Files.createDirectory(sunecTmpDir);
+            }
+        } catch (IOException e) {
+            VMError.shouldNotReachHere("Can't create sunec directory in tmp directory.", e);
+        }
+
+        prepareCFiles((FeatureImpl.BeforeAnalysisAccessImpl) a, sunecTmpDir);
+
+        Path originalSunEC = GRAALVM_HOME.resolve("lib/static/linux-amd64/" + LibCBase.singleton().getName() + "/libsunec.a");
+        if (Files.notExists(originalSunEC)) {
+            VMError.shouldNotReachHere("Can't find original libsunec.a from $GRAALVM_HOME.");
+        }
+        List<String> command = new ArrayList<>();
+        // 1. Compile the C symbol only ECC_JNI.c into ENC_ECC_JNI.o
+        // LibCBase instance has been set in LibCFeature#afterRegistration, so it's safe to get it now.
+        command.add(LibCBase.singleton().getTargetCompiler());
+        command.add("-fPIC");
+        command.add("-I" + GRAALVM_HOME.resolve("include").toAbsolutePath().toString());
+        command.add("-I" + GRAALVM_HOME.resolve("include/linux").toAbsolutePath().toString());
+        command.add("-I.");
+        command.add("-L.");
+        command.add("ECC_JNI.c");
+        command.add("-c");
+        command.add("-o");
+        command.add("ENC_ECC_JNI.o");
+        NativeCommandUtil.executeNewProcess(command, sunecTmpDir);
+
+        // 2. Extract the original libsunec.a
+        command.clear();
+        command.add("ar");
+        command.add("-x");
+        command.add(originalSunEC.toAbsolutePath().toString());
+        NativeCommandUtil.executeNewProcess(command, sunecTmpDir);
+
+        // 3. Archive the ENC_ECC_JNI.o generated in step 1 and other original .o files into the new static library.
+        command.clear();
+        // Must in the form of "/bin/bash -c", otherwise the *.o is not recognized by ProcessBuilder.
+        command.add("/bin/bash");
+        command.add("-c");
+        command.add("ar rcs " + LIBENC_SUNEC_A + " *.o");
+        NativeCommandUtil.executeNewProcess(command, sunecTmpDir);
+
+        // 4. Delete the intermediate results and only keep the static library generated by step 3.
+        try {
+            Files.walkFileTree(sunecTmpDir, new SimpleFileVisitor<>() {
+                @Override
+                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                    if (!file.getFileName().toString().endsWith(".a")) {
+                        Files.delete(file);
+                    }
+                    return FileVisitResult.CONTINUE;
+                }
+            });
+        } catch (IOException e) {
+            VMError.shouldNotReachHere("Fail to delete temporary file for generating substituted libsunec.a", e);
+        }
+    }
+
+    private static void prepareCFiles(FeatureImpl.BeforeAnalysisAccessImpl access, Path sunecTmpDir) {
+        ImageClassLoader imageClassLoader = access.getImageClassLoader();
+
+        String dir = "native/sunec/";
+        List<String> cSources = new ArrayList<>();
+        cSources.add("com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods.h");
+        cSources.add("ecc_impl.h");
+        cSources.add("ECC_JNI.c");
+        cSources.add("ecl-exp.h");
+        cSources.add("jlong.h");
+        cSources.add("jlong_md.h");
+        cSources.add("jni_util.h");
+
+        for (String cSource : cSources) {
+            File file = sunecTmpDir.resolve(cSource).toFile();
+
+            try (InputStream inputStream = imageClassLoader.getClassLoader().getResourceAsStream(dir + cSource);
+                 FileOutputStream outputStream = new FileOutputStream(file)) {
+                if (inputStream == null) {
+                    VMError.shouldNotReachHere("Source file " + cSource
+                            + " doesn't exist. It is required to compile the enclave compatible libsunec.a.");
+                }
+                inputStream.transferTo(outputStream);
+                outputStream.flush();
+            } catch (IOException e) {
+                VMError.shouldNotReachHere("Can't store resource file to tmp directory", e);
+            }
+        }
+    }
+
+    /**
+     * Copy the new static library from temporary directory to the output directory.
+     */
+    @Override
+    public void afterImageWrite(AfterImageWriteAccess access) {
+        // The sunec methods are not reachable, so the new library doesn't exist
+        if (sunecTmpDir == null) {
+            return;
+        }
+        FeatureImpl.AfterImageWriteAccessImpl a = (FeatureImpl.AfterImageWriteAccessImpl) access;
+        Path outputDirectory = NativeImageGenerator.generatedFiles(a.getUniverse().getBigBang().getOptions());
+
+        Path sunecLibrary = sunecTmpDir.resolve(LIBENC_SUNEC_A);
+        if (Files.exists(sunecLibrary)) {
+            try {
+                Files.copy(sunecLibrary, outputDirectory.resolve(LIBENC_SUNEC_A), StandardCopyOption.REPLACE_EXISTING);
+            } catch (IOException e) {
+                VMError.shouldNotReachHere("Fail to copy file from temporary directory", e);
+            }
+        }
+    }
+}
diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/substitutes/NativeSunECMethods.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/substitutes/NativeSunECMethods.java
new file mode 100644
index 0000000..9b64e82
--- /dev/null
+++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/substitutes/NativeSunECMethods.java
@@ -0,0 +1,21 @@
+package com.alibaba.confidentialcomputing.enclave.substitutes;
+
+import java.security.GeneralSecurityException;
+
+public class NativeSunECMethods {
+    public static native boolean isCurveSupported(byte[] encodedParams);
+
+    public static native Object[] generateECKeyPair(int keySize,
+                    byte[] encodedParams, byte[] seed) throws GeneralSecurityException;
+
+    public static native byte[] signDigest(byte[] digest, byte[] s,
+                    byte[] encodedParams, byte[] seed, int timing)
+                    throws GeneralSecurityException;
+
+    public static native boolean verifySignedDigest(byte[] signature,
+                    byte[] digest, byte[] w, byte[] encodedParams)
+                    throws GeneralSecurityException;
+
+    public static native byte[] deriveKey(byte[] s, byte[] w,
+                    byte[] encodedParams) throws GeneralSecurityException;
+}
diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/substitutes/SUNECSubstitutions.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/substitutes/SUNECSubstitutions.java
new file mode 100644
index 0000000..6eee323
--- /dev/null
+++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/substitutes/SUNECSubstitutions.java
@@ -0,0 +1,53 @@
+package com.alibaba.confidentialcomputing.enclave.substitutes;
+
+import com.oracle.svm.core.annotate.Substitute;
+import com.oracle.svm.core.annotate.TargetClass;
+import sun.security.ec.ECDHKeyAgreement;
+import sun.security.ec.ECKeyPairGenerator;
+
+import java.security.GeneralSecurityException;
+
+public class SUNECSubstitutions {
+
+    @TargetClass(ECKeyPairGenerator.class)
+    public static final class Target_sun_security_ec_ECKeyPairGenerator {
+        @Substitute
+        static Object[] generateECKeyPair(int keySize,
+                        byte[] encodedParams, byte[] seed) throws GeneralSecurityException {
+            return NativeSunECMethods.generateECKeyPair(keySize, encodedParams, seed);
+        }
+
+        @Substitute
+        static boolean isCurveSupported(byte[] encodedParams) {
+            return NativeSunECMethods.isCurveSupported(encodedParams);
+        }
+    }
+
+    @TargetClass(className = "sun.security.ec.ECDSASignature")
+    public static final class Target_sun_security_ec_ECDSASignature {
+
+        @Substitute
+        static byte[] signDigest(byte[] digest, byte[] s,
+                        byte[] encodedParams, byte[] seed, int timing)
+                        throws GeneralSecurityException {
+            return NativeSunECMethods.signDigest(digest, s, encodedParams, seed, timing);
+        }
+
+        @Substitute
+        static boolean verifySignedDigest(byte[] signature,
+                        byte[] digest, byte[] w, byte[] encodedParams)
+                        throws GeneralSecurityException {
+            return NativeSunECMethods.verifySignedDigest(signature, digest, w, encodedParams);
+        }
+    }
+
+    @TargetClass(ECDHKeyAgreement.class)
+    public static final class Target_sun_security_ec_ECDHKeyAgreement {
+        @Substitute
+        static byte[] deriveKey(byte[] s, byte[] w,
+                        byte[] encodedParams) throws GeneralSecurityException {
+            return NativeSunECMethods.deriveKey(s, w, encodedParams);
+        }
+    }
+
+}
diff --git a/sdk/enclave/src/main/resources/native/sunec/ECC_JNI.c b/sdk/enclave/src/main/resources/native/sunec/ECC_JNI.c
new file mode 100755
index 0000000..5b65696
--- /dev/null
+++ b/sdk/enclave/src/main/resources/native/sunec/ECC_JNI.c
@@ -0,0 +1,524 @@
+/*
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <jni.h>
+#include "jni_util.h"
+#include "ecc_impl.h"
+#include "com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods.h"
+
+#define ILLEGAL_STATE_EXCEPTION "java/lang/IllegalStateException"
+#define INVALID_ALGORITHM_PARAMETER_EXCEPTION \
+        "java/security/InvalidAlgorithmParameterException"
+#define INVALID_PARAMETER_EXCEPTION \
+        "java/security/InvalidParameterException"
+#define KEY_EXCEPTION   "java/security/KeyException"
+
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+JNIEXPORT jint JNICALL JNI_OnLoad_sunec(JavaVM *vm, void *reserved) {
+    return JNI_VERSION_1_8;
+}
+
+/*
+ * Throws an arbitrary Java exception.
+ */
+void ThrowException_C(JNIEnv *env, const char *exceptionName)
+{
+    jclass exceptionClazz = (*env)->FindClass(env, exceptionName);
+    if (exceptionClazz != NULL) {
+        (*env)->ThrowNew(env, exceptionClazz, NULL);
+    }
+}
+
+/*
+ * Deep free of the ECParams struct
+ */
+void FreeECParams_C(ECParams *ecparams, jboolean freeStruct)
+{
+    // Use B_FALSE to free the SECItem->data element, but not the SECItem itself
+    // Use B_TRUE to free both
+
+    SECITEM_FreeItem(&ecparams->fieldID.u.prime, B_FALSE);
+    SECITEM_FreeItem(&ecparams->curve.a, B_FALSE);
+    SECITEM_FreeItem(&ecparams->curve.b, B_FALSE);
+    SECITEM_FreeItem(&ecparams->curve.seed, B_FALSE);
+    SECITEM_FreeItem(&ecparams->base, B_FALSE);
+    SECITEM_FreeItem(&ecparams->order, B_FALSE);
+    SECITEM_FreeItem(&ecparams->DEREncoding, B_FALSE);
+    SECITEM_FreeItem(&ecparams->curveOID, B_FALSE);
+    if (freeStruct)
+        free(ecparams);
+}
+
+jbyteArray getEncodedBytes_C(JNIEnv *env, SECItem *hSECItem)
+{
+    SECItem *s = (SECItem *)hSECItem;
+
+    jbyteArray jEncodedBytes = (*env)->NewByteArray(env, s->len);
+    if (jEncodedBytes == NULL) {
+        return NULL;
+    }
+    // Copy bytes from a native SECItem buffer to Java byte array
+    (*env)->SetByteArrayRegion(env, jEncodedBytes, 0, s->len, (jbyte *)s->data);
+    if ((*env)->ExceptionCheck(env)) { // should never happen
+        return NULL;
+    }
+    return jEncodedBytes;
+}
+
+/*
+ * Class:     sun_security_ec_ECKeyPairGenerator
+ * Method:    isCurveSupported
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean
+JNICALL Java_com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods_isCurveSupported
+  (JNIEnv *env, jclass clazz, jbyteArray encodedParams)
+{
+    SECKEYECParams params_item;
+    ECParams *ecparams = NULL;
+    jboolean result = JNI_FALSE;
+
+    // The curve is supported if we can get parameters for it
+    params_item.len = (*env)->GetArrayLength(env, encodedParams);
+    params_item.data =
+        (unsigned char *) (*env)->GetByteArrayElements(env, encodedParams, 0);
+    if (params_item.data == NULL) {
+        goto cleanup;
+    }
+
+    // Fill a new ECParams using the supplied OID
+    if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
+        /* bad curve OID */
+        goto cleanup;
+    }
+
+    // If we make it to here, then the curve is supported
+    result = JNI_TRUE;
+
+cleanup:
+    {
+        if (params_item.data) {
+            (*env)->ReleaseByteArrayElements(env, encodedParams,
+                (jbyte *) params_item.data, JNI_ABORT);
+        }
+        if (ecparams) {
+            FreeECParams_C(ecparams, TRUE);
+        }
+    }
+
+    return result;
+}
+
+/*
+ * Class:     sun_security_ec_ECKeyPairGenerator
+ * Method:    generateECKeyPair
+ * Signature: (I[B[B)[[B
+ */
+JNIEXPORT jobjectArray
+JNICALL Java_com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods_generateECKeyPair
+  (JNIEnv *env, jclass clazz, jint keySize, jbyteArray encodedParams, jbyteArray seed)
+{
+    ECPrivateKey *privKey = NULL; // contains both public and private values
+    ECParams *ecparams = NULL;
+    SECKEYECParams params_item;
+    jint jSeedLength;
+    jbyte* pSeedBuffer = NULL;
+    jobjectArray result = NULL;
+    jclass baCls = NULL;
+    jbyteArray jba;
+
+    // Initialize the ECParams struct
+    params_item.len = (*env)->GetArrayLength(env, encodedParams);
+    params_item.data =
+        (unsigned char *) (*env)->GetByteArrayElements(env, encodedParams, 0);
+    if (params_item.data == NULL) {
+        goto cleanup;
+    }
+
+    // Fill a new ECParams using the supplied OID
+    if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
+        /* bad curve OID */
+        ThrowException_C(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
+        goto cleanup;
+    }
+
+    // Copy seed from Java to native buffer
+    jSeedLength = (*env)->GetArrayLength(env, seed);
+    pSeedBuffer = (jbyte*)malloc(jSeedLength * sizeof(jbyte));
+
+    (*env)->GetByteArrayRegion(env, seed, 0, jSeedLength, pSeedBuffer);
+
+    // Generate the new keypair (using the supplied seed)
+    if (EC_NewKey(ecparams, &privKey, (unsigned char *) pSeedBuffer,
+        jSeedLength, 0) != SECSuccess) {
+        ThrowException_C(env, KEY_EXCEPTION);
+        goto cleanup;
+    }
+
+    jboolean isCopy;
+    baCls = (*env)->FindClass(env, "[B");
+    if (baCls == NULL) {
+        goto cleanup;
+    }
+    result = (*env)->NewObjectArray(env, 2, baCls, NULL);
+    if (result == NULL) {
+        goto cleanup;
+    }
+    jba = getEncodedBytes_C(env, &(privKey->privateValue));
+    if (jba == NULL) {
+        result = NULL;
+        goto cleanup;
+    }
+    (*env)->SetObjectArrayElement(env, result, 0, jba); // big integer
+    if ((*env)->ExceptionCheck(env)) { // should never happen
+        result = NULL;
+        goto cleanup;
+    }
+
+    jba = getEncodedBytes_C(env, &(privKey->publicValue));
+    if (jba == NULL) {
+        result = NULL;
+        goto cleanup;
+    }
+    (*env)->SetObjectArrayElement(env, result, 1, jba); // encoded ec point
+    if ((*env)->ExceptionCheck(env)) { // should never happen
+        result = NULL;
+        goto cleanup;
+    }
+
+cleanup:
+    {
+        if (params_item.data) {
+            (*env)->ReleaseByteArrayElements(env, encodedParams,
+                (jbyte *) params_item.data, JNI_ABORT);
+        }
+        if (ecparams) {
+            FreeECParams_C(ecparams, TRUE);
+        }
+        if (privKey) {
+            FreeECParams_C(&privKey->ecParams, FALSE);
+            SECITEM_FreeItem(&privKey->version, B_FALSE);
+            SECITEM_FreeItem(&privKey->privateValue, B_FALSE);
+            SECITEM_FreeItem(&privKey->publicValue, B_FALSE);
+            free(privKey);
+        }
+
+        if (pSeedBuffer) {
+            free(pSeedBuffer);
+        }
+    }
+
+    return result;
+}
+
+/*
+ * Class:     sun_security_ec_ECDSASignature
+ * Method:    signDigest
+ * Signature: ([B[B[B[B)[B
+ */
+JNIEXPORT jbyteArray
+JNICALL Java_com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods_signDigest
+  (JNIEnv *env, jclass clazz, jbyteArray digest, jbyteArray privateKey, jbyteArray encodedParams, jbyteArray seed, jint timing)
+{
+    jbyte* pDigestBuffer = NULL;
+    jint jDigestLength = (*env)->GetArrayLength(env, digest);
+    jbyteArray jSignedDigest = NULL;
+
+    SECItem signature_item;
+    jbyte* pSignedDigestBuffer = NULL;
+    jbyteArray temp;
+
+    jint jSeedLength = (*env)->GetArrayLength(env, seed);
+    jbyte* pSeedBuffer = NULL;
+
+    // Copy digest from Java to native buffer
+    pDigestBuffer = (jbyte *)malloc(jDigestLength*sizeof(jbyte));
+    (*env)->GetByteArrayRegion(env, digest, 0, jDigestLength, pDigestBuffer);
+    SECItem digest_item;
+    digest_item.data = (unsigned char *) pDigestBuffer;
+    digest_item.len = jDigestLength;
+
+    ECPrivateKey privKey;
+    privKey.privateValue.data = NULL;
+
+    // Initialize the ECParams struct
+    ECParams *ecparams = NULL;
+    SECKEYECParams params_item;
+    params_item.len = (*env)->GetArrayLength(env, encodedParams);
+    params_item.data =
+        (unsigned char *) (*env)->GetByteArrayElements(env, encodedParams, 0);
+    if (params_item.data == NULL) {
+        goto cleanup;
+    }
+
+    // Fill a new ECParams using the supplied OID
+    if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
+        /* bad curve OID */
+        ThrowException_C(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
+        goto cleanup;
+    }
+
+    // Extract private key data
+    privKey.ecParams = *ecparams; // struct assignment
+    privKey.privateValue.len = (*env)->GetArrayLength(env, privateKey);
+    privKey.privateValue.data =
+        (unsigned char *) (*env)->GetByteArrayElements(env, privateKey, 0);
+    if (privKey.privateValue.data == NULL) {
+        goto cleanup;
+    }
+
+    // Prepare a buffer for the signature (twice the key length)
+    pSignedDigestBuffer = (jbyte *)malloc(ecparams->order.len * 2 * sizeof(jbyte));
+    signature_item.data = (unsigned char *) pSignedDigestBuffer;
+    signature_item.len = ecparams->order.len * 2;
+
+    // Copy seed from Java to native buffer
+    pSeedBuffer = (jbyte *)malloc(jSeedLength*sizeof(jbyte));
+    (*env)->GetByteArrayRegion(env, seed, 0, jSeedLength, pSeedBuffer);
+
+    // Sign the digest (using the supplied seed)
+    if (ECDSA_SignDigest(&privKey, &signature_item, &digest_item,
+        (unsigned char *) pSeedBuffer, jSeedLength, 0, timing) != SECSuccess) {
+        ThrowException_C(env, KEY_EXCEPTION);
+        goto cleanup;
+    }
+
+    // Create new byte array
+    temp = (*env)->NewByteArray(env, signature_item.len);
+    if (temp == NULL) {
+        goto cleanup;
+    }
+
+    // Copy data from native buffer
+    (*env)->SetByteArrayRegion(env, temp, 0, signature_item.len, pSignedDigestBuffer);
+    jSignedDigest = temp;
+
+cleanup:
+    {
+        if (params_item.data) {
+            (*env)->ReleaseByteArrayElements(env, encodedParams,
+                (jbyte *) params_item.data, JNI_ABORT);
+        }
+        if (privKey.privateValue.data) {
+            (*env)->ReleaseByteArrayElements(env, privateKey,
+                (jbyte *) privKey.privateValue.data, JNI_ABORT);
+        }
+        if (pDigestBuffer) {
+            free(pDigestBuffer);
+        }
+        if (pSignedDigestBuffer) {
+            free(pSignedDigestBuffer);
+        }
+        if (pSeedBuffer) {
+            free(pSeedBuffer);
+        }
+        if (ecparams) {
+            FreeECParams_C(ecparams, TRUE);
+        }
+    }
+
+    return jSignedDigest;
+}
+
+/*
+ * Class:     sun_security_ec_ECDSASignature
+ * Method:    verifySignedDigest
+ * Signature: ([B[B[B[B)Z
+ */
+JNIEXPORT jboolean
+JNICALL Java_com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods_verifySignedDigest
+  (JNIEnv *env, jclass clazz, jbyteArray signedDigest, jbyteArray digest, jbyteArray publicKey, jbyteArray encodedParams)
+{
+    jboolean isValid = FALSE;
+
+    // Copy signedDigest from Java to native buffer
+    jbyte* pSignedDigestBuffer = NULL;
+    jint jSignedDigestLength = (*env)->GetArrayLength(env, signedDigest);
+    pSignedDigestBuffer = (jbyte *)malloc(jSignedDigestLength*sizeof(jbyte));
+    (*env)->GetByteArrayRegion(env, signedDigest, 0, jSignedDigestLength,
+        pSignedDigestBuffer);
+    SECItem signature_item;
+    signature_item.data = (unsigned char *) pSignedDigestBuffer;
+    signature_item.len = jSignedDigestLength;
+
+    // Copy digest from Java to native buffer
+    jbyte* pDigestBuffer = NULL;
+    jint jDigestLength = (*env)->GetArrayLength(env, digest);
+    pDigestBuffer = (jbyte *)malloc(jDigestLength*sizeof(jbyte));
+    (*env)->GetByteArrayRegion(env, digest, 0, jDigestLength, pDigestBuffer);
+    SECItem digest_item;
+    digest_item.data = (unsigned char *) pDigestBuffer;
+    digest_item.len = jDigestLength;
+
+    // Extract public key data
+    ECPublicKey pubKey;
+    pubKey.publicValue.data = NULL;
+    ECParams *ecparams = NULL;
+    SECKEYECParams params_item;
+
+    // Initialize the ECParams struct
+    params_item.len = (*env)->GetArrayLength(env, encodedParams);
+    params_item.data =
+        (unsigned char *) (*env)->GetByteArrayElements(env, encodedParams, 0);
+    if (params_item.data == NULL) {
+        goto cleanup;
+    }
+
+    // Fill a new ECParams using the supplied OID
+    if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
+        /* bad curve OID */
+        ThrowException_C(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
+        goto cleanup;
+    }
+    pubKey.ecParams = *ecparams; // struct assignment
+    pubKey.publicValue.len = (*env)->GetArrayLength(env, publicKey);
+    pubKey.publicValue.data =
+        (unsigned char *) (*env)->GetByteArrayElements(env, publicKey, 0);
+
+    if (ECDSA_VerifyDigest(&pubKey, &signature_item, &digest_item, 0)
+            != SECSuccess) {
+        goto cleanup;
+    }
+
+    isValid = TRUE;
+
+cleanup:
+    {
+        if (params_item.data)
+            (*env)->ReleaseByteArrayElements(env, encodedParams,
+                (jbyte *) params_item.data, JNI_ABORT);
+
+        if (pubKey.publicValue.data)
+            (*env)->ReleaseByteArrayElements(env, publicKey,
+                (jbyte *) pubKey.publicValue.data, JNI_ABORT);
+
+        if (ecparams)
+            FreeECParams_C(ecparams, TRUE);
+
+        if (pSignedDigestBuffer)
+            free(pSignedDigestBuffer);
+
+        if (pDigestBuffer)
+            free(pDigestBuffer);
+    }
+
+    return isValid;
+}
+
+/*
+ * Class:     sun_security_ec_ECDHKeyAgreement
+ * Method:    deriveKey
+ * Signature: ([B[B[B)[B
+ */
+JNIEXPORT jbyteArray
+JNICALL Java_com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods_deriveKey
+  (JNIEnv *env, jclass clazz, jbyteArray privateKey, jbyteArray publicKey, jbyteArray encodedParams)
+{
+    jbyteArray jSecret = NULL;
+    ECParams *ecparams = NULL;
+    SECItem privateValue_item;
+    privateValue_item.data = NULL;
+    SECItem publicValue_item;
+    publicValue_item.data = NULL;
+    SECKEYECParams params_item;
+    params_item.data = NULL;
+
+    // Extract private key value
+    privateValue_item.len = (*env)->GetArrayLength(env, privateKey);
+    privateValue_item.data =
+            (unsigned char *) (*env)->GetByteArrayElements(env, privateKey, 0);
+    if (privateValue_item.data == NULL) {
+        goto cleanup;
+    }
+
+    // Extract public key value
+    publicValue_item.len = (*env)->GetArrayLength(env, publicKey);
+    publicValue_item.data =
+        (unsigned char *) (*env)->GetByteArrayElements(env, publicKey, 0);
+    if (publicValue_item.data == NULL) {
+        goto cleanup;
+    }
+
+    // Initialize the ECParams struct
+    params_item.len = (*env)->GetArrayLength(env, encodedParams);
+    params_item.data =
+        (unsigned char *) (*env)->GetByteArrayElements(env, encodedParams, 0);
+    if (params_item.data == NULL) {
+        goto cleanup;
+    }
+
+    // Fill a new ECParams using the supplied OID
+    if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
+        /* bad curve OID */
+        ThrowException_C(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
+        goto cleanup;
+    }
+
+    // Prepare a buffer for the secret
+    SECItem secret_item;
+    secret_item.data = NULL;
+    secret_item.len = ecparams->order.len * 2;
+
+    if (ECDH_Derive(&publicValue_item, ecparams, &privateValue_item, B_FALSE,
+        &secret_item, 0) != SECSuccess) {
+        ThrowException_C(env, ILLEGAL_STATE_EXCEPTION);
+        goto cleanup;
+    }
+
+    // Create new byte array
+    jSecret = (*env)->NewByteArray(env, secret_item.len);
+    if (jSecret == NULL) {
+        goto cleanup;
+    }
+
+    // Copy bytes from the SECItem buffer to a Java byte array
+    (*env)->SetByteArrayRegion(env, jSecret, 0, secret_item.len,
+        (jbyte *)secret_item.data);
+
+    // Free the SECItem data buffer
+    SECITEM_FreeItem(&secret_item, B_FALSE);
+
+cleanup:
+    {
+        if (privateValue_item.data)
+            (*env)->ReleaseByteArrayElements(env, privateKey,
+                (jbyte *) privateValue_item.data, JNI_ABORT);
+
+        if (publicValue_item.data)
+            (*env)->ReleaseByteArrayElements(env, publicKey,
+                (jbyte *) publicValue_item.data, JNI_ABORT);
+
+        if (params_item.data)
+            (*env)->ReleaseByteArrayElements(env, encodedParams,
+                (jbyte *) params_item.data, JNI_ABORT);
+
+        if (ecparams)
+            FreeECParams_C(ecparams, TRUE);
+    }
+
+    return jSecret;
+}
diff --git a/sdk/enclave/src/main/resources/native/sunec/com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods.h b/sdk/enclave/src/main/resources/native/sunec/com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods.h
new file mode 100644
index 0000000..2586ad3
--- /dev/null
+++ b/sdk/enclave/src/main/resources/native/sunec/com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods.h
@@ -0,0 +1,53 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods */
+
+#ifndef _Included_com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods
+#define _Included_com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods
+ * Method:    isCurveSupported
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods_isCurveSupported
+  (JNIEnv *, jclass, jbyteArray);
+
+/*
+ * Class:     com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods
+ * Method:    generateECKeyPair
+ * Signature: (I[B[B)[Ljava/lang/Object;
+ */
+JNIEXPORT jobjectArray JNICALL Java_com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods_generateECKeyPair
+  (JNIEnv *, jclass, jint, jbyteArray, jbyteArray);
+
+/*
+ * Class:     com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods
+ * Method:    signDigest
+ * Signature: ([B[B[B[BI)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods_signDigest
+  (JNIEnv *, jclass, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jint);
+
+/*
+ * Class:     com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods
+ * Method:    verifySignedDigest
+ * Signature: ([B[B[B[B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods_verifySignedDigest
+  (JNIEnv *, jclass, jbyteArray, jbyteArray, jbyteArray, jbyteArray);
+
+/*
+ * Class:     com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods
+ * Method:    deriveKey
+ * Signature: ([B[B[B)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_com_alibaba_confidentialcomputing_enclave_substitutes_NativeSunECMethods_deriveKey
+  (JNIEnv *, jclass, jbyteArray, jbyteArray, jbyteArray);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/sdk/enclave/src/main/resources/native/sunec/ecc_impl.h b/sdk/enclave/src/main/resources/native/sunec/ecc_impl.h
new file mode 100755
index 0000000..48aa13a
--- /dev/null
+++ b/sdk/enclave/src/main/resources/native/sunec/ecc_impl.h
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* *********************************************************************
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Dr Vipul Gupta <vi...@sun.com> and
+ *   Douglas Stebila <do...@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Last Modified Date from the Original Code: May 2017
+ *********************************************************************** */
+
+#ifndef _ECC_IMPL_H
+#define _ECC_IMPL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include "ecl-exp.h"
+
+/*
+ * Multi-platform definitions
+ */
+#ifdef __linux__
+#define B_FALSE FALSE
+#define B_TRUE TRUE
+typedef unsigned char uint8_t;
+typedef unsigned long ulong_t;
+typedef enum { B_FALSE, B_TRUE } boolean_t;
+#endif /* __linux__ */
+
+#ifdef _ALLBSD_SOURCE
+#include <stdint.h>
+#define B_FALSE FALSE
+#define B_TRUE TRUE
+typedef unsigned long ulong_t;
+typedef enum boolean { B_FALSE, B_TRUE } boolean_t;
+#endif /* _ALLBSD_SOURCE */
+
+#ifdef AIX
+#define B_FALSE FALSE
+#define B_TRUE TRUE
+typedef unsigned char uint8_t;
+typedef unsigned long ulong_t;
+#endif /* AIX */
+
+#ifdef _WIN32
+typedef unsigned char uint8_t;
+typedef unsigned long ulong_t;
+typedef enum boolean { B_FALSE, B_TRUE } boolean_t;
+#define strdup _strdup          /* Replace POSIX name with ISO C++ name */
+#endif /* _WIN32 */
+
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif  /* _KERNEL */
+
+#define EC_MAX_DIGEST_LEN 1024  /* max digest that can be signed */
+#define EC_MAX_POINT_LEN 145    /* max len of DER encoded Q */
+#define EC_MAX_VALUE_LEN 72     /* max len of ANSI X9.62 private value d */
+#define EC_MAX_SIG_LEN 144      /* max signature len for supported curves */
+#define EC_MIN_KEY_LEN  112     /* min key length in bits */
+#define EC_MAX_KEY_LEN  571     /* max key length in bits */
+#define EC_MAX_OID_LEN 10       /* max length of OID buffer */
+
+/*
+ * Various structures and definitions from NSS are here.
+ */
+
+#ifdef _KERNEL
+#define PORT_ArenaAlloc(a, n, f)        kmem_alloc((n), (f))
+#define PORT_ArenaZAlloc(a, n, f)       kmem_zalloc((n), (f))
+#define PORT_ArenaGrow(a, b, c, d)      NULL
+#define PORT_ZAlloc(n, f)               kmem_zalloc((n), (f))
+#define PORT_Alloc(n, f)                kmem_alloc((n), (f))
+#else
+#define PORT_ArenaAlloc(a, n, f)        malloc((n))
+#define PORT_ArenaZAlloc(a, n, f)       calloc(1, (n))
+#define PORT_ArenaGrow(a, b, c, d)      NULL
+#define PORT_ZAlloc(n, f)               calloc(1, (n))
+#define PORT_Alloc(n, f)                malloc((n))
+#endif
+
+#define PORT_NewArena(b)                (char *)12345
+#define PORT_ArenaMark(a)               NULL
+#define PORT_ArenaUnmark(a, b)
+#define PORT_ArenaRelease(a, m)
+#define PORT_FreeArena(a, b)
+#define PORT_Strlen(s)                  strlen((s))
+#define PORT_SetError(e)
+
+#define PRBool                          boolean_t
+#define PR_TRUE                         B_TRUE
+#define PR_FALSE                        B_FALSE
+
+#ifdef _KERNEL
+#define PORT_Assert                     ASSERT
+#define PORT_Memcpy(t, f, l)            bcopy((f), (t), (l))
+#else
+#define PORT_Assert                     assert
+#define PORT_Memcpy(t, f, l)            memcpy((t), (f), (l))
+#endif
+
+#define CHECK_OK(func) if (func == NULL) goto cleanup
+#define CHECK_SEC_OK(func) if (SECSuccess != (rv = func)) goto cleanup
+
+typedef enum {
+        siBuffer = 0,
+        siClearDataBuffer = 1,
+        siCipherDataBuffer = 2,
+        siDERCertBuffer = 3,
+        siEncodedCertBuffer = 4,
+        siDERNameBuffer = 5,
+        siEncodedNameBuffer = 6,
+        siAsciiNameString = 7,
+        siAsciiString = 8,
+        siDEROID = 9,
+        siUnsignedInteger = 10,
+        siUTCTime = 11,
+        siGeneralizedTime = 12
+} SECItemType;
+
+typedef struct SECItemStr SECItem;
+
+struct SECItemStr {
+        SECItemType type;
+        unsigned char *data;
+        unsigned int len;
+};
+
+typedef SECItem SECKEYECParams;
+
+typedef enum { ec_params_explicit,
+               ec_params_named
+} ECParamsType;
+
+typedef enum { ec_field_GFp = 1,
+               ec_field_GF2m
+} ECFieldType;
+
+struct ECFieldIDStr {
+    int         size;   /* field size in bits */
+    ECFieldType type;
+    union {
+        SECItem  prime; /* prime p for (GFp) */
+        SECItem  poly;  /* irreducible binary polynomial for (GF2m) */
+    } u;
+    int         k1;     /* first coefficient of pentanomial or
+                         * the only coefficient of trinomial
+                         */
+    int         k2;     /* two remaining coefficients of pentanomial */
+    int         k3;
+};
+typedef struct ECFieldIDStr ECFieldID;
+
+struct ECCurveStr {
+        SECItem a;      /* contains octet stream encoding of
+                         * field element (X9.62 section 4.3.3)
+                         */
+        SECItem b;
+        SECItem seed;
+};
+typedef struct ECCurveStr ECCurve;
+
+typedef void PRArenaPool;
+
+struct ECParamsStr {
+    PRArenaPool * arena;
+    ECParamsType  type;
+    ECFieldID     fieldID;
+    ECCurve       curve;
+    SECItem       base;
+    SECItem       order;
+    int           cofactor;
+    SECItem       DEREncoding;
+    ECCurveName   name;
+    SECItem       curveOID;
+};
+typedef struct ECParamsStr ECParams;
+
+struct ECPublicKeyStr {
+    ECParams ecParams;
+    SECItem publicValue;   /* elliptic curve point encoded as
+                            * octet stream.
+                            */
+};
+typedef struct ECPublicKeyStr ECPublicKey;
+
+struct ECPrivateKeyStr {
+    ECParams ecParams;
+    SECItem publicValue;   /* encoded ec point */
+    SECItem privateValue;  /* private big integer */
+    SECItem version;       /* As per SEC 1, Appendix C, Section C.4 */
+};
+typedef struct ECPrivateKeyStr ECPrivateKey;
+
+typedef enum _SECStatus {
+        SECBufferTooSmall = -3,
+        SECWouldBlock = -2,
+        SECFailure = -1,
+        SECSuccess = 0
+} SECStatus;
+
+#ifdef _KERNEL
+#define RNG_GenerateGlobalRandomBytes(p,l) ecc_knzero_random_generator((p), (l))
+#else
+/*
+ This function is no longer required because the random bytes are now
+ supplied by the caller. Force a failure.
+*/
+#define RNG_GenerateGlobalRandomBytes(p,l) SECFailure
+#endif
+#define CHECK_MPI_OK(func) if (MP_OKAY > (err = func)) goto cleanup
+#define MP_TO_SEC_ERROR(err)
+
+#define SECITEM_TO_MPINT(it, mp)                                        \
+        CHECK_MPI_OK(mp_read_unsigned_octets((mp), (it).data, (it).len))
+
+extern int ecc_knzero_random_generator(uint8_t *, size_t);
+extern ulong_t soft_nzero_random_generator(uint8_t *, ulong_t);
+
+extern SECStatus EC_DecodeParams(const SECItem *, ECParams **, int);
+extern SECItem * SECITEM_AllocItem(PRArenaPool *, SECItem *, unsigned int, int);
+extern SECStatus SECITEM_CopyItem(PRArenaPool *, SECItem *, const SECItem *,
+    int);
+extern void SECITEM_FreeItem(SECItem *, boolean_t);
+/* This function has been modified to accept an array of random bytes */
+extern SECStatus EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
+    const unsigned char* random, int randomlen, int);
+/* This function has been modified to accept an array of random bytes */
+extern SECStatus ECDSA_SignDigest(ECPrivateKey *, SECItem *, const SECItem *,
+    const unsigned char* random, int randomlen, int, int timing);
+extern SECStatus ECDSA_VerifyDigest(ECPublicKey *, const SECItem *,
+    const SECItem *, int);
+extern SECStatus ECDH_Derive(SECItem *, ECParams *, SECItem *, boolean_t,
+    SECItem *, int);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* _ECC_IMPL_H */
diff --git a/sdk/enclave/src/main/resources/native/sunec/ecl-exp.h b/sdk/enclave/src/main/resources/native/sunec/ecl-exp.h
new file mode 100755
index 0000000..8b442c6
--- /dev/null
+++ b/sdk/enclave/src/main/resources/native/sunec/ecl-exp.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* *********************************************************************
+ *
+ * The Original Code is the elliptic curve math library.
+ *
+ * The Initial Developer of the Original Code is
+ * Sun Microsystems, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Douglas Stebila <do...@stebila.ca>, Sun Microsystems Laboratories
+ *
+ *********************************************************************** */
+
+#ifndef _ECL_EXP_H
+#define _ECL_EXP_H
+
+/* Curve field type */
+typedef enum {
+        ECField_GFp,
+        ECField_GF2m
+} ECField;
+
+/* Hexadecimal encoding of curve parameters */
+struct ECCurveParamsStr {
+        char *text;
+        ECField field;
+        unsigned int size;
+        char *irr;
+        char *curvea;
+        char *curveb;
+        char *genx;
+        char *geny;
+        char *order;
+        int cofactor;
+};
+typedef struct ECCurveParamsStr ECCurveParams;
+
+/* Named curve parameters */
+typedef enum {
+
+        ECCurve_noName = 0,
+
+        /* NIST prime curves */
+        ECCurve_NIST_P192,
+        ECCurve_NIST_P224,
+        ECCurve_NIST_P256,
+        ECCurve_NIST_P384,
+        ECCurve_NIST_P521,
+
+        /* NIST binary curves */
+        ECCurve_NIST_K163,
+        ECCurve_NIST_B163,
+        ECCurve_NIST_K233,
+        ECCurve_NIST_B233,
+        ECCurve_NIST_K283,
+        ECCurve_NIST_B283,
+        ECCurve_NIST_K409,
+        ECCurve_NIST_B409,
+        ECCurve_NIST_K571,
+        ECCurve_NIST_B571,
+
+        /* ANSI X9.62 prime curves */
+        /* ECCurve_X9_62_PRIME_192V1 == ECCurve_NIST_P192 */
+        ECCurve_X9_62_PRIME_192V2,
+        ECCurve_X9_62_PRIME_192V3,
+        ECCurve_X9_62_PRIME_239V1,
+        ECCurve_X9_62_PRIME_239V2,
+        ECCurve_X9_62_PRIME_239V3,
+        /* ECCurve_X9_62_PRIME_256V1 == ECCurve_NIST_P256 */
+
+        /* ANSI X9.62 binary curves */
+        ECCurve_X9_62_CHAR2_PNB163V1,
+        ECCurve_X9_62_CHAR2_PNB163V2,
+        ECCurve_X9_62_CHAR2_PNB163V3,
+        ECCurve_X9_62_CHAR2_PNB176V1,
+        ECCurve_X9_62_CHAR2_TNB191V1,
+        ECCurve_X9_62_CHAR2_TNB191V2,
+        ECCurve_X9_62_CHAR2_TNB191V3,
+        ECCurve_X9_62_CHAR2_PNB208W1,
+        ECCurve_X9_62_CHAR2_TNB239V1,
+        ECCurve_X9_62_CHAR2_TNB239V2,
+        ECCurve_X9_62_CHAR2_TNB239V3,
+        ECCurve_X9_62_CHAR2_PNB272W1,
+        ECCurve_X9_62_CHAR2_PNB304W1,
+        ECCurve_X9_62_CHAR2_TNB359V1,
+        ECCurve_X9_62_CHAR2_PNB368W1,
+        ECCurve_X9_62_CHAR2_TNB431R1,
+
+        /* SEC2 prime curves */
+        ECCurve_SECG_PRIME_112R1,
+        ECCurve_SECG_PRIME_112R2,
+        ECCurve_SECG_PRIME_128R1,
+        ECCurve_SECG_PRIME_128R2,
+        ECCurve_SECG_PRIME_160K1,
+        ECCurve_SECG_PRIME_160R1,
+        ECCurve_SECG_PRIME_160R2,
+        ECCurve_SECG_PRIME_192K1,
+        /* ECCurve_SECG_PRIME_192R1 == ECCurve_NIST_P192 */
+        ECCurve_SECG_PRIME_224K1,
+        /* ECCurve_SECG_PRIME_224R1 == ECCurve_NIST_P224 */
+        ECCurve_SECG_PRIME_256K1,
+        /* ECCurve_SECG_PRIME_256R1 == ECCurve_NIST_P256 */
+        /* ECCurve_SECG_PRIME_384R1 == ECCurve_NIST_P384 */
+        /* ECCurve_SECG_PRIME_521R1 == ECCurve_NIST_P521 */
+
+        /* SEC2 binary curves */
+        ECCurve_SECG_CHAR2_113R1,
+        ECCurve_SECG_CHAR2_113R2,
+        ECCurve_SECG_CHAR2_131R1,
+        ECCurve_SECG_CHAR2_131R2,
+        /* ECCurve_SECG_CHAR2_163K1 == ECCurve_NIST_K163 */
+        ECCurve_SECG_CHAR2_163R1,
+        /* ECCurve_SECG_CHAR2_163R2 == ECCurve_NIST_B163 */
+        ECCurve_SECG_CHAR2_193R1,
+        ECCurve_SECG_CHAR2_193R2,
+        /* ECCurve_SECG_CHAR2_233K1 == ECCurve_NIST_K233 */
+        /* ECCurve_SECG_CHAR2_233R1 == ECCurve_NIST_B233 */
+        ECCurve_SECG_CHAR2_239K1,
+        /* ECCurve_SECG_CHAR2_283K1 == ECCurve_NIST_K283 */
+        /* ECCurve_SECG_CHAR2_283R1 == ECCurve_NIST_B283 */
+        /* ECCurve_SECG_CHAR2_409K1 == ECCurve_NIST_K409 */
+        /* ECCurve_SECG_CHAR2_409R1 == ECCurve_NIST_B409 */
+        /* ECCurve_SECG_CHAR2_571K1 == ECCurve_NIST_K571 */
+        /* ECCurve_SECG_CHAR2_571R1 == ECCurve_NIST_B571 */
+
+        /* WTLS curves */
+        ECCurve_WTLS_1,
+        /* there is no WTLS 2 curve */
+        /* ECCurve_WTLS_3 == ECCurve_NIST_K163 */
+        /* ECCurve_WTLS_4 == ECCurve_SECG_CHAR2_113R1 */
+        /* ECCurve_WTLS_5 == ECCurve_X9_62_CHAR2_PNB163V1 */
+        /* ECCurve_WTLS_6 == ECCurve_SECG_PRIME_112R1 */
+        /* ECCurve_WTLS_7 == ECCurve_SECG_PRIME_160R1 */
+        ECCurve_WTLS_8,
+        ECCurve_WTLS_9,
+        /* ECCurve_WTLS_10 == ECCurve_NIST_K233 */
+        /* ECCurve_WTLS_11 == ECCurve_NIST_B233 */
+        /* ECCurve_WTLS_12 == ECCurve_NIST_P224 */
+
+        /* ECC Brainpool prime curves in RFC 5639*/
+        ECCurve_BrainpoolP256r1,
+        ECCurve_BrainpoolP320r1,
+        ECCurve_BrainpoolP384r1,
+        ECCurve_BrainpoolP512r1,
+
+        ECCurve_pastLastCurve
+} ECCurveName;
+
+/* Aliased named curves */
+
+#define ECCurve_X9_62_PRIME_192V1 ECCurve_NIST_P192
+#define ECCurve_X9_62_PRIME_256V1 ECCurve_NIST_P256
+#define ECCurve_SECG_PRIME_192R1 ECCurve_NIST_P192
+#define ECCurve_SECG_PRIME_224R1 ECCurve_NIST_P224
+#define ECCurve_SECG_PRIME_256R1 ECCurve_NIST_P256
+#define ECCurve_SECG_PRIME_384R1 ECCurve_NIST_P384
+#define ECCurve_SECG_PRIME_521R1 ECCurve_NIST_P521
+#define ECCurve_SECG_CHAR2_163K1 ECCurve_NIST_K163
+#define ECCurve_SECG_CHAR2_163R2 ECCurve_NIST_B163
+#define ECCurve_SECG_CHAR2_233K1 ECCurve_NIST_K233
+#define ECCurve_SECG_CHAR2_233R1 ECCurve_NIST_B233
+#define ECCurve_SECG_CHAR2_283K1 ECCurve_NIST_K283
+#define ECCurve_SECG_CHAR2_283R1 ECCurve_NIST_B283
+#define ECCurve_SECG_CHAR2_409K1 ECCurve_NIST_K409
+#define ECCurve_SECG_CHAR2_409R1 ECCurve_NIST_B409
+#define ECCurve_SECG_CHAR2_571K1 ECCurve_NIST_K571
+#define ECCurve_SECG_CHAR2_571R1 ECCurve_NIST_B571
+#define ECCurve_WTLS_3 ECCurve_NIST_K163
+#define ECCurve_WTLS_4 ECCurve_SECG_CHAR2_113R1
+#define ECCurve_WTLS_5 ECCurve_X9_62_CHAR2_PNB163V1
+#define ECCurve_WTLS_6 ECCurve_SECG_PRIME_112R1
+#define ECCurve_WTLS_7 ECCurve_SECG_PRIME_160R1
+#define ECCurve_WTLS_10 ECCurve_NIST_K233
+#define ECCurve_WTLS_11 ECCurve_NIST_B233
+#define ECCurve_WTLS_12 ECCurve_NIST_P224
+
+#endif /* _ECL_EXP_H */
diff --git a/sdk/enclave/src/main/resources/native/sunec/jlong.h b/sdk/enclave/src/main/resources/native/sunec/jlong.h
new file mode 100755
index 0000000..40fd9f1
--- /dev/null
+++ b/sdk/enclave/src/main/resources/native/sunec/jlong.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef _JLONG_H_
+#define _JLONG_H_
+
+#include "jlong_md.h"
+
+#endif
diff --git a/sdk/enclave/src/main/resources/native/sunec/jlong_md.h b/sdk/enclave/src/main/resources/native/sunec/jlong_md.h
new file mode 100755
index 0000000..40fb0af
--- /dev/null
+++ b/sdk/enclave/src/main/resources/native/sunec/jlong_md.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef _SOLARIS_JLONG_MD_H_
+#define _SOLARIS_JLONG_MD_H_
+
+/* Make sure ptrdiff_t is defined */
+#include <stddef.h>
+#include <stdint.h>  /* For uintptr_t */
+
+#define jlong_high(a)   ((jint)((a)>>32))
+#define jlong_low(a)    ((jint)(a))
+#define jlong_add(a, b) ((a) + (b))
+#define jlong_and(a, b) ((a) & (b))
+#define jlong_div(a, b) ((a) / (b))
+#define jlong_mul(a, b) ((a) * (b))
+#define jlong_neg(a)    (-(a))
+#define jlong_not(a)    (~(a))
+#define jlong_or(a, b)  ((a) | (b))
+#define jlong_shl(a, n) ((a) << (n))
+#define jlong_shr(a, n) ((a) >> (n))
+#define jlong_sub(a, b) ((a) - (b))
+#define jlong_xor(a, b) ((a) ^ (b))
+#define jlong_rem(a,b)  ((a) % (b))
+
+/* comparison operators */
+#define jlong_ltz(ll)   ((ll)<0)
+#define jlong_gez(ll)   ((ll)>=0)
+#define jlong_gtz(ll)   ((ll)>0)
+#define jlong_eqz(a)    ((a) == 0)
+#define jlong_eq(a, b)  ((a) == (b))
+#define jlong_ne(a,b)   ((a) != (b))
+#define jlong_ge(a,b)   ((a) >= (b))
+#define jlong_le(a,b)   ((a) <= (b))
+#define jlong_lt(a,b)   ((a) < (b))
+#define jlong_gt(a,b)   ((a) > (b))
+
+#define jlong_zero      ((jlong) 0)
+#define jlong_one       ((jlong) 1)
+#define jlong_minus_one ((jlong) -1)
+
+/* For static variables initialized to zero */
+#define jlong_zero_init  ((jlong) 0L)
+
+#ifdef _LP64
+  #ifndef jlong_to_ptr
+    #define jlong_to_ptr(a) ((void*)(a))
+  #endif
+  #ifndef ptr_to_jlong
+    #define ptr_to_jlong(a) ((jlong)(a))
+  #endif
+#else
+  #ifndef jlong_to_ptr
+    #define jlong_to_ptr(a) ((void*)(int)(a))
+  #endif
+  #ifndef ptr_to_jlong
+    #define ptr_to_jlong(a) ((jlong)(int)(a))
+  #endif
+#endif
+
+#define jint_to_jlong(a)        ((jlong)(a))
+#define jlong_to_jint(a)        ((jint)(a))
+
+/* Useful on machines where jlong and jdouble have different endianness. */
+#define jlong_to_jdouble_bits(a)
+#define jdouble_to_jlong_bits(a)
+
+#define jlong_to_int(a)     ((int)(a))
+#define int_to_jlong(a)     ((jlong)(a))
+#define jlong_to_uint(a)    ((unsigned int)(a))
+#define uint_to_jlong(a)    ((jlong)(a))
+#define jlong_to_ptrdiff(a) ((ptrdiff_t)(a))
+#define ptrdiff_to_jlong(a) ((jlong)(a))
+#define jlong_to_size(a)    ((size_t)(a))
+#define size_to_jlong(a)    ((jlong)(a))
+#define long_to_jlong(a)    ((jlong)(a))
+
+#endif /* !_SOLARIS_JLONG_MD_H_ */
diff --git a/sdk/enclave/src/main/resources/native/sunec/jni_util.h b/sdk/enclave/src/main/resources/native/sunec/jni_util.h
new file mode 100755
index 0000000..baeb10d
--- /dev/null
+++ b/sdk/enclave/src/main/resources/native/sunec/jni_util.h
@@ -0,0 +1,534 @@
+/*
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef JNI_UTIL_H
+#define JNI_UTIL_H
+
+#include "jni.h"
+#include "jlong.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file contains utility functions that can be implemented in pure JNI.
+ *
+ * Caution: Callers of functions declared in this file should be
+ * particularly aware of the fact that these functions are convenience
+ * functions, and as such are often compound operations, each one of
+ * which may throw an exception. Therefore, the functions this file
+ * will often return silently if an exception has occurred, and callers
+ * must check for exception themselves.
+ */
+
+/* Throw a Java exception by name. Similar to SignalError. */
+JNIEXPORT void JNICALL
+JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg);
+
+/* Throw common exceptions */
+JNIEXPORT void JNICALL
+JNU_ThrowNullPointerException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowArrayIndexOutOfBoundsException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowOutOfMemoryError(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowIllegalArgumentException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowIllegalAccessError(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowIllegalAccessException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowInternalError(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowIOException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowNoSuchFieldException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowNoSuchMethodException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowClassNotFoundException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowNumberFormatException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowNoSuchFieldError(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowNoSuchMethodError(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowStringIndexOutOfBoundsException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowInstantiationException(JNIEnv *env, const char *msg);
+
+/* Throw an exception by name, using the string returned by
+ * getLastErrorString for the detail string. If the last-error
+ * string is NULL, use the given default detail string.
+ */
+JNIEXPORT void JNICALL
+JNU_ThrowByNameWithLastError(JNIEnv *env, const char *name,
+                             const char *defaultDetail);
+
+/* Throw an exception by name, using a given message and the string
+ * returned by getLastErrorString to construct the detail string.
+ */
+JNIEXPORT void JNICALL
+JNU_ThrowByNameWithMessageAndLastError
+  (JNIEnv *env, const char *name, const char *message);
+
+/* Throw an IOException, using the last-error string for the detail
+ * string. If the last-error string is NULL, use the given default
+ * detail string.
+ */
+JNIEXPORT void JNICALL
+JNU_ThrowIOExceptionWithLastError(JNIEnv *env, const char *defaultDetail);
+
+/* Convert between Java strings and i18n C strings */
+JNIEXPORT jstring
+NewStringPlatform(JNIEnv *env, const char *str);
+
+JNIEXPORT const char *
+GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy);
+
+JNIEXPORT jstring JNICALL
+JNU_NewStringPlatform(JNIEnv *env, const char *str);
+
+JNIEXPORT const char * JNICALL
+JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy);
+
+JNIEXPORT void JNICALL
+JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str);
+
+/* Class constants */
+JNIEXPORT jclass JNICALL
+JNU_ClassString(JNIEnv *env);
+
+JNIEXPORT jclass JNICALL
+JNU_ClassClass(JNIEnv *env);
+
+JNIEXPORT jclass JNICALL
+JNU_ClassObject(JNIEnv *env);
+
+JNIEXPORT jclass JNICALL
+JNU_ClassThrowable(JNIEnv *env);
+
+/* Copy count number of arguments from src to dst. Array bounds
+ * and ArrayStoreException are checked.
+ */
+JNIEXPORT jint JNICALL
+JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src,
+                    jint count);
+
+/* Invoke a object-returning static method, based on class name,
+ * method name, and signature string.
+ *
+ * The caller should check for exceptions by setting hasException
+ * argument. If the caller is not interested in whether an exception
+ * has occurred, pass in NULL.
+ */
+JNIEXPORT jvalue JNICALL
+JNU_CallStaticMethodByName(JNIEnv *env,
+                           jboolean *hasException,
+                           const char *class_name,
+                           const char *name,
+                           const char *signature,
+                           ...);
+
+/* Invoke an instance method by name.
+ */
+JNIEXPORT jvalue JNICALL
+JNU_CallMethodByName(JNIEnv *env,
+                     jboolean *hasException,
+                     jobject obj,
+                     const char *name,
+                     const char *signature,
+                     ...);
+
+JNIEXPORT jvalue JNICALL
+JNU_CallMethodByNameV(JNIEnv *env,
+                      jboolean *hasException,
+                      jobject obj,
+                      const char *name,
+                      const char *signature,
+                      va_list args);
+
+/* Construct a new object of class, specifying the class by name,
+ * and specififying which constructor to run and what arguments to
+ * pass to it.
+ *
+ * The method will return an initialized instance if successful.
+ * It will return NULL if an error has occurred (for example if
+ * it ran out of memory) and the appropriate Java exception will
+ * have been thrown.
+ */
+JNIEXPORT jobject JNICALL
+JNU_NewObjectByName(JNIEnv *env, const char *class_name,
+                    const char *constructor_sig, ...);
+
+/* returns:
+ * 0: object is not an instance of the class named by classname.
+ * 1: object is an instance of the class named by classname.
+ * -1: the class named by classname cannot be found. An exception
+ * has been thrown.
+ */
+JNIEXPORT jint JNICALL
+JNU_IsInstanceOfByName(JNIEnv *env, jobject object, char *classname);
+
+
+/* Get or set class and instance fields.
+ * Note that set functions take a variable number of arguments,
+ * but only one argument of the appropriate type can be passed.
+ * For example, to set an integer field i to 100:
+ *
+ * JNU_SetFieldByName(env, &exc, obj, "i", "I", 100);
+ *
+ * To set a float field f to 12.3:
+ *
+ * JNU_SetFieldByName(env, &exc, obj, "f", "F", 12.3);
+ *
+ * The caller should check for exceptions by setting hasException
+ * argument. If the caller is not interested in whether an exception
+ * has occurred, pass in NULL.
+ */
+JNIEXPORT jvalue JNICALL
+JNU_GetFieldByName(JNIEnv *env,
+                   jboolean *hasException,
+                   jobject obj,
+                   const char *name,
+                   const char *sig);
+JNIEXPORT void JNICALL
+JNU_SetFieldByName(JNIEnv *env,
+                   jboolean *hasException,
+                   jobject obj,
+                   const char *name,
+                   const char *sig,
+                   ...);
+
+JNIEXPORT jvalue JNICALL
+JNU_GetStaticFieldByName(JNIEnv *env,
+                         jboolean *hasException,
+                         const char *classname,
+                         const char *name,
+                         const char *sig);
+JNIEXPORT void JNICALL
+JNU_SetStaticFieldByName(JNIEnv *env,
+                         jboolean *hasException,
+                         const char *classname,
+                         const char *name,
+                         const char *sig,
+                         ...);
+
+
+/*
+ * Calls the .equals method.
+ */
+JNIEXPORT jboolean JNICALL
+JNU_Equals(JNIEnv *env, jobject object1, jobject object2);
+
+
+/************************************************************************
+ * Thread calls
+ *
+ * Convenience thread-related calls on the java.lang.Object class.
+ */
+
+JNIEXPORT void JNICALL
+JNU_MonitorWait(JNIEnv *env, jobject object, jlong timeout);
+
+JNIEXPORT void JNICALL
+JNU_Notify(JNIEnv *env, jobject object);
+
+JNIEXPORT void JNICALL
+JNU_NotifyAll(JNIEnv *env, jobject object);
+
+
+/************************************************************************
+ * Miscellaneous utilities used by the class libraries
+ */
+
+#define IS_NULL(obj) ((obj) == NULL)
+#define JNU_IsNull(env,obj) ((obj) == NULL)
+
+/************************************************************************
+ * Miscellaneous utilities used by the class libraries to return from
+ * a function if a value is NULL or an exception is pending.
+ */
+
+#define CHECK_NULL(x)                           \
+    do {                                        \
+        if ((x) == NULL) {                      \
+            return;                             \
+        }                                       \
+    } while (0)                                 \
+
+#define CHECK_NULL_THROW_NPE(env, x, msg)         \
+    do {                                        \
+        if ((x) == NULL) {                      \
+           JNU_ThrowNullPointerException((env), (msg));\
+           return;                              \
+        }                                       \
+    } while(0)                                  \
+
+#define CHECK_NULL_THROW_NPE_RETURN(env, x, msg, z)\
+    do {                                        \
+        if ((x) == NULL) {                      \
+           JNU_ThrowNullPointerException((env), (msg));\
+           return (z);                          \
+        }                                       \
+    } while(0)                                  \
+
+#define CHECK_NULL_RETURN(x, y)                 \
+    do {                                        \
+        if ((x) == NULL) {                      \
+            return (y);                         \
+        }                                       \
+    } while (0)                                 \
+
+#ifdef __cplusplus
+#define JNU_CHECK_EXCEPTION(env)                \
+    do {                                        \
+        if ((env)->ExceptionCheck()) {          \
+            return;                             \
+        }                                       \
+    } while (0)                                 \
+
+#define JNU_CHECK_EXCEPTION_RETURN(env, y)      \
+    do {                                        \
+        if ((env)->ExceptionCheck()) {          \
+            return (y);                         \
+        }                                       \
+    } while (0)
+#else
+#define JNU_CHECK_EXCEPTION(env)                \
+    do {                                        \
+        if ((*env)->ExceptionCheck(env)) {      \
+            return;                             \
+        }                                       \
+    } while (0)                                 \
+
+#define JNU_CHECK_EXCEPTION_RETURN(env, y)      \
+    do {                                        \
+        if ((*env)->ExceptionCheck(env)) {      \
+            return (y);                         \
+        }                                       \
+    } while (0)
+#endif /* __cplusplus */
+/************************************************************************
+ * Debugging utilities
+ */
+
+JNIEXPORT void JNICALL
+JNU_PrintString(JNIEnv *env, char *hdr, jstring string);
+
+JNIEXPORT void JNICALL
+JNU_PrintClass(JNIEnv *env, char *hdr, jobject object);
+
+JNIEXPORT jstring JNICALL
+JNU_ToString(JNIEnv *env, jobject object);
+
+/*
+ * Package shorthand for use by native libraries
+ */
+#define JNU_JAVAPKG         "java/lang/"
+#define JNU_JAVAIOPKG       "java/io/"
+#define JNU_JAVANETPKG      "java/net/"
+
+/*
+ * Check if the current thread is attached to the VM, and returns
+ * the JNIEnv of the specified version if the thread is attached.
+ *
+ * If the current thread is not attached, this function returns 0.
+ *
+ * If the current thread is attached, this function returns the
+ * JNI environment, or returns (void *)JNI_ERR if the specified
+ * version is not supported.
+ */
+JNIEXPORT void * JNICALL
+JNU_GetEnv(JavaVM *vm, jint version);
+
+/*
+ * Warning free access to pointers stored in Java long fields.
+ */
+#define JNU_GetLongFieldAsPtr(env,obj,id) \
+    (jlong_to_ptr((*(env))->GetLongField((env),(obj),(id))))
+#define JNU_SetLongFieldFromPtr(env,obj,id,val) \
+    (*(env))->SetLongField((env),(obj),(id),ptr_to_jlong(val))
+
+/*
+ * Internal use only.
+ */
+enum {
+    NO_ENCODING_YET = 0,        /* "sun.jnu.encoding" not yet set */
+    NO_FAST_ENCODING,           /* Platform encoding is not fast */
+    FAST_8859_1,                /* ISO-8859-1 */
+    FAST_CP1252,                /* MS-DOS Cp1252 */
+    FAST_646_US,                /* US-ASCII : ISO646-US */
+    FAST_UTF_8
+};
+
+int getFastEncoding();
+
+JNIEXPORT void InitializeEncoding(JNIEnv *env, const char *name);
+
+void* getProcessHandle();
+
+void buildJniFunctionName(const char *sym, const char *cname,
+                          char *jniEntryName);
+
+JNIEXPORT size_t JNICALL
+getLastErrorString(char *buf, size_t len);
+
+JNIEXPORT int JNICALL
+getErrorString(int err, char *buf, size_t len);
+
+#ifdef STATIC_BUILD
+/* Macros for handling declaration of static/dynamic
+ * JNI library Load/Unload functions
+ *
+ * Use DEF_JNI_On{Un}Load when you want a static and non-static entry points.
+ * Use DEF_STATIC_JNI_On{Un}Load when you only want a static one.
+ *
+ * LIBRARY_NAME must be set to the name of the library
+ */
+
+/* These three macros are needed to get proper concatenation of
+ * the LIBRARY_NAME
+ *
+ * NOTE: LIBRARY_NAME must be set for static builds.
+ */
+#define ADD_LIB_NAME3(name, lib) name ## lib
+#define ADD_LIB_NAME2(name, lib) ADD_LIB_NAME3(name, lib)
+#define ADD_LIB_NAME(entry) ADD_LIB_NAME2(entry, LIBRARY_NAME)
+
+#define DEF_JNI_OnLoad \
+ADD_LIB_NAME(JNI_OnLoad_)(JavaVM *vm, void *reserved) \
+{ \
+  jint JNICALL ADD_LIB_NAME(JNI_OnLoad_dynamic_)(JavaVM *vm, void *reserved); \
+  ADD_LIB_NAME(JNI_OnLoad_dynamic_)(vm, reserved); \
+  return JNI_VERSION_1_8; \
+} \
+jint JNICALL ADD_LIB_NAME(JNI_OnLoad_dynamic_)
+
+#define DEF_STATIC_JNI_OnLoad \
+JNIEXPORT jint JNICALL ADD_LIB_NAME(JNI_OnLoad_)(JavaVM *vm, void *reserved) { \
+    return JNI_VERSION_1_8; \
+}
+
+#define DEF_JNI_OnUnload \
+ADD_LIB_NAME(JNI_OnUnload_)(JavaVM *vm, void *reserved) \
+{ \
+  void JNICALL ADD_LIB_NAME(JNI_OnUnload_dynamic_)(JavaVM *vm, void *reserved); \
+  ADD_LIB_NAME(JNI_OnUnload_dynamic_)(vm, reserved); \
+} \
+void JNICALL ADD_LIB_NAME(JNI_OnUnload_dynamic_)
+
+#define DEF_STATIC_JNI_OnUnload \
+ADD_LIB_NAME(JNI_OnUnload_)
+
+#else
+
+#define DEF_JNI_OnLoad JNI_OnLoad
+#define DEF_STATIC_JNI_OnLoad
+#define DEF_JNI_OnUnload JNI_OnUnload
+#define DEF_STATIC_JNI_OnUnload
+#endif
+
+#ifdef STATIC_BUILD
+/* Macros for handling declaration of static/dynamic
+ * Agent library Load/Attach/Unload functions
+ *
+ * Use DEF_Agent_OnLoad, DEF_Agent_OnAttach or DEF_Agent_OnUnload
+ *     when you want both static and non-static entry points.
+ * Use DEF_STATIC_Agent_OnLoad, DEF_STATIC_Agent_OnAttach or
+ *     DEF_STATIC_Agent_OnUnload when you only want a static one.
+ *
+ * LIBRARY_NAME must be set to the name of the library for static builds.
+ */
+
+#define DEF_Agent_OnLoad \
+ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) \
+{ \
+  jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)(JavaVM *vm, char *options, void *reserved); \
+  return ADD_LIB_NAME(Agent_OnLoad_dynamic_)(vm, options, reserved); \
+} \
+jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)
+
+#define DEF_STATIC_Agent_OnLoad \
+JNIEXPORT jint JNICALL ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) { \
+    return JNI_FALSE; \
+}
+
+#define DEF_Agent_OnAttach \
+ADD_LIB_NAME(Agent_OnAttach_)(JavaVM *vm, char *options, void *reserved) \
+{ \
+  jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)(JavaVM *vm, char *options, void *reserved); \
+  return ADD_LIB_NAME(Agent_OnAttach_dynamic_)(vm, options, reserved); \
+} \
+jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)
+
+#define DEF_STATIC_Agent_OnAttach \
+JNIEXPORT jint JNICALL ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) { \
+    return JNI_FALSE; \
+}
+
+#define DEF_Agent_OnUnload \
+ADD_LIB_NAME(Agent_OnUnload_)(JavaVM *vm) \
+{ \
+  void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)(JavaVM *vm); \
+  ADD_LIB_NAME(Agent_OnUnload_dynamic_)(vm); \
+} \
+void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)
+
+#define DEF_STATIC_Agent_OnUnload \
+ADD_LIB_NAME(Agent_OnUnload_)
+
+#else
+#define DEF_Agent_OnLoad Agent_OnLoad
+#define DEF_Agent_OnAttach Agent_OnAttach
+#define DEF_Agent_OnUnload Agent_OnUnload
+#define DEF_STATIC_Agent_OnLoad
+#define DEF_STATIC_Agent_OnAttach
+#define DEF_STATIC_Agent_OnUnload
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* JNI_UTIL_H */
diff --git a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/NativeImageTest.java b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/NativeImageTest.java
index 43e5e37..99296d9 100644
--- a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/NativeImageTest.java
+++ b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/NativeImageTest.java
@@ -1,11 +1,7 @@
 package com.alibaba.confidentialcomputing.enclave;
 
-import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.SequenceInputStream;
-import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -16,9 +12,11 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
+import static com.alibaba.confidentialcomputing.enclave.NativeCommandUtil.GRAALVM_HOME;
+import static com.alibaba.confidentialcomputing.enclave.SUNECReplaceFeature.LIBENC_SUNEC_A;
+
 public abstract class NativeImageTest implements NativeImageTestable {
     private static final String JNI_LIB_NAME = "encinvokeentrytest";
-    public static final Path GRAALVM_HOME = Paths.get(System.getenv("GRAALVM_HOME"));
     public static final Path MVN_BUILD_DIR = Paths.get("target");
     private static final String SVM_OUT = "svm-out";
     private static final String SVM_ENCLAVE_LIB = "svm_enclave_sdk";
@@ -179,7 +177,7 @@ public abstract class NativeImageTest implements NativeImageTestable {
         if (extraOptions != null && !extraOptions.isEmpty()) {
             command.addAll(extraOptions);
         }
-        NativeImageTest.executeNewProcess(command, workingDir);
+        NativeCommandUtil.executeNewProcess(command, workingDir);
     }
 
     private void compileJNILibrary() {
@@ -204,7 +202,7 @@ public abstract class NativeImageTest implements NativeImageTestable {
             prepareDynamicLinkingCommand(command);
         }
         command.addAll(addMacros());
-        executeNewProcess(command, workingDir);
+        NativeCommandUtil.executeNewProcess(command, workingDir);
     }
 
     protected Collection<String> addMacros(){
@@ -229,7 +227,9 @@ public abstract class NativeImageTest implements NativeImageTestable {
         command.add(graalvmHome.resolve("lib/static/linux-amd64/musl/libzip.a").toString());
         command.add(graalvmHome.resolve("lib/static/linux-amd64/musl/libnet.a").toString());
         command.add(graalvmHome.resolve("lib/static/linux-amd64/musl/libjava.a").toString());
-        command.add(graalvmHome.resolve("lib/static/linux-amd64/musl/libsunec.a").toString());
+        if (Files.exists(svmOutputDir.toAbsolutePath().resolve(LIBENC_SUNEC_A))) {
+            command.add(svmOutputDir.toAbsolutePath().resolve(LIBENC_SUNEC_A).toString());
+        }
         command.add(graalvmHome.resolve("lib/static/linux-amd64/musl/libfdlibm.a").toString());
         command.add("-std=c99");
         command.add("-lc");
@@ -254,40 +254,6 @@ public abstract class NativeImageTest implements NativeImageTestable {
         command.add("lib" + JNI_LIB_NAME + ".so");
     }
 
-    public static int executeNewProcess(List<String> command, Path workDir) {
-        if (command == null || command.isEmpty()) {
-            throw new RuntimeException("Didn't provide any execution command.");
-        }
-        ProcessBuilder pb = new ProcessBuilder(command).directory(workDir.toFile());
-        String oneLineCommand = command.stream().reduce((e1, e2) -> e1 + " " + e2).orElse("");
-        System.out.println(oneLineCommand);
-        Process p = null;
-        try {
-            p = pb.start();
-            SequenceInputStream sis = new SequenceInputStream(p.getInputStream(), p.getErrorStream());
-            InputStreamReader inst = new InputStreamReader(sis, StandardCharsets.UTF_8);
-            StringBuilder sb = new StringBuilder();
-            try (BufferedReader br = new BufferedReader(inst)) {
-                String res;
-                while ((res = br.readLine()) != null) {
-                    sb.append(res).append("\n");
-                }
-            }
-            System.out.println(sb);
-            int exitCode = p.waitFor();
-            if (exitCode != 0) {
-                throw new RuntimeException("Failed to execute command:\n " + oneLineCommand +
-                        "\n Working directory is :" + workDir.toString() + "\n The exit code is " + exitCode);
-            }
-            return 0;
-        } catch (IOException | InterruptedException e) {
-            throw new RuntimeException("Failed to execute command:\n " + oneLineCommand, e);
-        } finally {
-            if (p != null) {
-                p.destroy();
-            }
-        }
-    }
 
     public static void copyFile(Path source, Path dest, String errMSg) {
         try {
diff --git a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/ReplaceSunECTest.java b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/ReplaceSunECTest.java
new file mode 100644
index 0000000..8034352
--- /dev/null
+++ b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/ReplaceSunECTest.java
@@ -0,0 +1,78 @@
+package com.alibaba.confidentialcomputing.enclave;
+
+import com.alibaba.confidentialcomputing.enclave.testservice.EncryptionService;
+import com.alibaba.confidentialcomputing.enclave.testservice.SunECOperations;
+import com.oracle.svm.core.annotate.AutomaticFeature;
+import com.oracle.svm.hosted.FeatureImpl;
+import org.graalvm.nativeimage.hosted.Feature;
+import org.graalvm.nativeimage.hosted.RuntimeSerialization;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import sun.security.ec.ECKeyPairGenerator;
+
+import java.security.KeyPair;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class ReplaceSunECTest {
+
+    private static final String ENCRYPT_SERVICE = "com.alibaba.confidentialcomputing.enclave.testservice.EncryptionService";
+    private static final String SUNEC_OP = "com.alibaba.confidentialcomputing.enclave.testservice.SunECOperations";
+    @TestTarget(ReplaceSunECTest.class)
+    static class ReplaceSunECPreparation extends NativeImageTest{
+
+        @Override
+        SVMCompileElements specifyTestClasses() {
+            SVMCompileElements ret = new SVMCompileElements();
+            // Specify the service file
+            ret.addServices("META-INF/services/"+ENCRYPT_SERVICE);
+            ret.addClasses(EncryptionService.class, SunECOperations.class, UTFeature.class);
+            return ret;
+        }
+
+/*        @Override
+        public List<String> extraSVMOptions() {
+            return List.of("--debug-attach:5005");
+        }*/
+    }
+
+    @BeforeAll
+    public static void prepareLibraries(){
+        new ReplaceSunECPreparation().prepareNativeLibraries();
+    }
+
+    @BeforeEach
+    public void setup() {
+        EnclaveTestHelper.createIsolate();
+    }
+
+    @AfterEach
+    public void teardown() {
+        EnclaveTestHelper.destroyIsolate();
+    }
+
+    @Test
+    public void test(){
+        String id = EnclaveTestHelper.loadAndGetService(ENCRYPT_SERVICE, SUNEC_OP, 1);
+        KeyPair remoteRet = (KeyPair)EnclaveTestHelper.call(id, ENCRYPT_SERVICE, SUNEC_OP, "generateKeyPair", EnclaveTestHelper.EMPTY_STRING_ARRAY, EnclaveTestHelper.EMPTY_OBJECT_ARRAY);
+        assertNotNull(remoteRet);
+    }
+
+    @AutomaticFeature
+    static class UTFeature implements Feature {
+
+        @Override
+        public void beforeAnalysis(BeforeAnalysisAccess access) {
+            FeatureImpl.BeforeAnalysisAccessImpl a = (FeatureImpl.BeforeAnalysisAccessImpl)access;
+            Class<?> PKCS8KeyClass = a.getImageClassLoader().findClass("sun.security.pkcs.PKCS8Key").get();
+            Class<?> X509KeyClass = a.getImageClassLoader().findClass("sun.security.x509.X509Key").get();
+            RuntimeSerialization.register(PKCS8KeyClass, X509KeyClass);
+            RuntimeSerialization.registerAllAssociatedClasses(java.security.KeyRep.class);
+            RuntimeSerialization.registerAllAssociatedClasses(sun.security.ec.ECPrivateKeyImpl.class);
+            RuntimeSerialization.registerAllAssociatedClasses(sun.security.ec.ECPublicKeyImpl.class);
+        }
+    }
+}
diff --git a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/EncryptionService.java b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/EncryptionService.java
new file mode 100644
index 0000000..9c5b770
--- /dev/null
+++ b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/EncryptionService.java
@@ -0,0 +1,10 @@
+package com.alibaba.confidentialcomputing.enclave.testservice;
+
+import com.alibaba.confidentialcomputing.common.annotations.EnclaveService;
+
+import java.security.KeyPair;
+
+@EnclaveService
+public interface EncryptionService {
+    KeyPair generateKeyPair();
+}
diff --git a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/SunECOperations.java b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/SunECOperations.java
new file mode 100644
index 0000000..dfbdab9
--- /dev/null
+++ b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/testservice/SunECOperations.java
@@ -0,0 +1,12 @@
+package com.alibaba.confidentialcomputing.enclave.testservice;
+
+import java.security.KeyPair;
+import sun.security.ec.ECKeyPairGenerator;
+
+public class SunECOperations implements EncryptionService{
+    @Override
+    public KeyPair generateKeyPair() {
+        ECKeyPairGenerator pairGenerator = new ECKeyPairGenerator();
+        return pairGenerator.generateKeyPair();
+    }
+}
diff --git a/sdk/enclave/src/test/resources/META-INF/services/com.alibaba.confidentialcomputing.enclave.testservice.EncryptionService b/sdk/enclave/src/test/resources/META-INF/services/com.alibaba.confidentialcomputing.enclave.testservice.EncryptionService
new file mode 100644
index 0000000..86f677c
--- /dev/null
+++ b/sdk/enclave/src/test/resources/META-INF/services/com.alibaba.confidentialcomputing.enclave.testservice.EncryptionService
@@ -0,0 +1 @@
+com.alibaba.confidentialcomputing.enclave.testservice.SunECOperations
\ No newline at end of file
diff --git a/tools/cicd/make.sh b/tools/cicd/make.sh
index fd768b7..6da95c9 100755
--- a/tools/cicd/make.sh
+++ b/tools/cicd/make.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 
 BUILD_IMAGE=javaenclave_build
-BUILD_TAG=v0.1.3
+BUILD_TAG=v0.1.6
 
 SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org