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(¶ms_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(¶ms_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(¶ms_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(¶ms_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(¶ms_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