From c406ea2dc08c30c2da7e5f683f319e99afc0ad57 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Wed, 21 Mar 2018 15:31:27 +0100 Subject: [PATCH] Added wrappers for ed25519, curve25519, chacha. Added maven pom.xml build file. --- build.xml | 3 + jni/include/com_wolfssl_wolfcrypt_Chacha.h | 63 +++ .../com_wolfssl_wolfcrypt_Curve25519.h | 111 ++++ jni/include/com_wolfssl_wolfcrypt_Ed25519.h | 119 ++++ jni/jni_chacha.c | 224 ++++++++ jni/jni_curve25519.c | 421 ++++++++++++++ jni/jni_ed25519.c | 532 ++++++++++++++++++ makefile | 3 +- makefile.linux | 3 +- makefile.macosx | 3 +- pom.xml | 45 ++ .../java/com/wolfssl/wolfcrypt/Chacha.java | 101 ++++ .../com/wolfssl/wolfcrypt/Curve25519.java | 172 ++++++ .../java/com/wolfssl/wolfcrypt/Ed25519.java | 183 ++++++ 14 files changed, 1980 insertions(+), 3 deletions(-) create mode 100644 jni/include/com_wolfssl_wolfcrypt_Chacha.h create mode 100644 jni/include/com_wolfssl_wolfcrypt_Curve25519.h create mode 100644 jni/include/com_wolfssl_wolfcrypt_Ed25519.h create mode 100644 jni/jni_chacha.c create mode 100644 jni/jni_curve25519.c create mode 100644 jni/jni_ed25519.c create mode 100644 pom.xml create mode 100644 src/main/java/com/wolfssl/wolfcrypt/Chacha.java create mode 100644 src/main/java/com/wolfssl/wolfcrypt/Curve25519.java create mode 100644 src/main/java/com/wolfssl/wolfcrypt/Ed25519.java diff --git a/build.xml b/build.xml index ec117c2..a0d8016 100644 --- a/build.xml +++ b/build.xml @@ -191,6 +191,9 @@ + + + diff --git a/jni/include/com_wolfssl_wolfcrypt_Chacha.h b/jni/include/com_wolfssl_wolfcrypt_Chacha.h new file mode 100644 index 0000000..5488033 --- /dev/null +++ b/jni/include/com_wolfssl_wolfcrypt_Chacha.h @@ -0,0 +1,63 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_wolfssl_wolfcrypt_Chacha */ + +#ifndef _Included_com_wolfssl_wolfcrypt_Chacha +#define _Included_com_wolfssl_wolfcrypt_Chacha +#ifdef __cplusplus +extern "C" { +#endif +#undef com_wolfssl_wolfcrypt_Chacha_NULL +#define com_wolfssl_wolfcrypt_Chacha_NULL 0LL +/* + * Class: com_wolfssl_wolfcrypt_Chacha + * Method: mallocNativeStruct + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Chacha_mallocNativeStruct + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Chacha + * Method: wc_Chacha_init + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1init + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Chacha + * Method: wc_Chacha_free + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1free + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Chacha + * Method: wc_Chacha_process + * Signature: ([B)[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1process + (JNIEnv *, jobject, jbyteArray); + +/* + * Class: com_wolfssl_wolfcrypt_Chacha + * Method: wc_Chacha_setKey + * Signature: ([B)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1setKey + (JNIEnv *, jobject, jbyteArray); + +/* + * Class: com_wolfssl_wolfcrypt_Chacha + * Method: wc_Chacha_setIV + * Signature: ([B)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1setIV + (JNIEnv *, jobject, jbyteArray); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/jni/include/com_wolfssl_wolfcrypt_Curve25519.h b/jni/include/com_wolfssl_wolfcrypt_Curve25519.h new file mode 100644 index 0000000..27b7d6d --- /dev/null +++ b/jni/include/com_wolfssl_wolfcrypt_Curve25519.h @@ -0,0 +1,111 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_wolfssl_wolfcrypt_Curve25519 */ + +#ifndef _Included_com_wolfssl_wolfcrypt_Curve25519 +#define _Included_com_wolfssl_wolfcrypt_Curve25519 +#ifdef __cplusplus +extern "C" { +#endif +#undef com_wolfssl_wolfcrypt_Curve25519_NULL +#define com_wolfssl_wolfcrypt_Curve25519_NULL 0LL +/* + * Class: com_wolfssl_wolfcrypt_Curve25519 + * Method: mallocNativeStruct + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Curve25519_mallocNativeStruct + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Curve25519 + * Method: wc_curve25519_init + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1init + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Curve25519 + * Method: wc_curve25519_free + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1free + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Curve25519 + * Method: wc_curve25519_make_key + * Signature: (Lcom/wolfssl/wolfcrypt/Rng;I)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1make_1key + (JNIEnv *, jobject, jobject, jint); + +/* + * Class: com_wolfssl_wolfcrypt_Curve25519 + * Method: wc_curve25519_make_key_ex + * Signature: (Lcom/wolfssl/wolfcrypt/Rng;II)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1make_1key_1ex + (JNIEnv *, jobject, jobject, jint, jint); + +/* + * Class: com_wolfssl_wolfcrypt_Curve25519 + * Method: wc_curve25519_check_key + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1check_1key + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Curve25519 + * Method: wc_curve25519_make_shared_secret + * Signature: (Lcom/wolfssl/wolfcrypt/Curve25519;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1make_1shared_1secret + (JNIEnv *, jobject, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Curve25519 + * Method: wc_curve25519_import_private + * Signature: ([B[B)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1import_1private + (JNIEnv *, jobject, jbyteArray, jbyteArray); + +/* + * Class: com_wolfssl_wolfcrypt_Curve25519 + * Method: wc_curve25519_import_private_only + * Signature: ([B)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1import_1private_1only + (JNIEnv *, jobject, jbyteArray); + +/* + * Class: com_wolfssl_wolfcrypt_Curve25519 + * Method: wc_curve25519_import_public + * Signature: ([B)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1import_1public + (JNIEnv *, jobject, jbyteArray); + +/* + * Class: com_wolfssl_wolfcrypt_Curve25519 + * Method: wc_curve25519_export_private + * Signature: ()[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1export_1private + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Curve25519 + * Method: wc_curve25519_export_public + * Signature: ()[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1export_1public + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/jni/include/com_wolfssl_wolfcrypt_Ed25519.h b/jni/include/com_wolfssl_wolfcrypt_Ed25519.h new file mode 100644 index 0000000..4d5d293 --- /dev/null +++ b/jni/include/com_wolfssl_wolfcrypt_Ed25519.h @@ -0,0 +1,119 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_wolfssl_wolfcrypt_Ed25519 */ + +#ifndef _Included_com_wolfssl_wolfcrypt_Ed25519 +#define _Included_com_wolfssl_wolfcrypt_Ed25519 +#ifdef __cplusplus +extern "C" { +#endif +#undef com_wolfssl_wolfcrypt_Ed25519_NULL +#define com_wolfssl_wolfcrypt_Ed25519_NULL 0LL +/* + * Class: com_wolfssl_wolfcrypt_Ed25519 + * Method: mallocNativeStruct + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_mallocNativeStruct + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Ed25519 + * Method: wc_ed25519_init + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1init + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Ed25519 + * Method: wc_ed25519_free + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1free + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Ed25519 + * Method: wc_ed25519_make_key + * Signature: (Lcom/wolfssl/wolfcrypt/Rng;I)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1make_1key + (JNIEnv *, jobject, jobject, jint); + +/* + * Class: com_wolfssl_wolfcrypt_Ed25519 + * Method: wc_ed25519_check_key + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1check_1key + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Ed25519 + * Method: wc_ed25519_import_private + * Signature: ([B[B)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1import_1private + (JNIEnv *, jobject, jbyteArray, jbyteArray); + +/* + * Class: com_wolfssl_wolfcrypt_Ed25519 + * Method: wc_ed25519_import_private_only + * Signature: ([B)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1import_1private_1only + (JNIEnv *, jobject, jbyteArray); + +/* + * Class: com_wolfssl_wolfcrypt_Ed25519 + * Method: wc_ed25519_import_public + * Signature: ([B)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1import_1public + (JNIEnv *, jobject, jbyteArray); + +/* + * Class: com_wolfssl_wolfcrypt_Ed25519 + * Method: wc_ed25519_sign_msg + * Signature: ([B)[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1sign_1msg + (JNIEnv *, jobject, jbyteArray); + +/* + * Class: com_wolfssl_wolfcrypt_Ed25519 + * Method: wc_ed25519_verify_msg + * Signature: ([B[B)Z + */ +JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1verify_1msg + (JNIEnv *, jobject, jbyteArray, jbyteArray); + +/* + * Class: com_wolfssl_wolfcrypt_Ed25519 + * Method: wc_ed25519_export_private + * Signature: ()[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1export_1private + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Ed25519 + * Method: wc_ed25519_export_private_only + * Signature: ()[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1export_1private_1only + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Ed25519 + * Method: wc_ed25519_export_public + * Signature: ()[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1export_1public + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/jni/jni_chacha.c b/jni/jni_chacha.c new file mode 100644 index 0000000..f874593 --- /dev/null +++ b/jni/jni_chacha.c @@ -0,0 +1,224 @@ +/* jni_Chacha.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __ANDROID__ + #include +#endif +#include +#include + +#include +#include +#include + +/* #define WOLFCRYPT_JNI_DEBUG_ON */ +#include + + +JNIEXPORT jlong JNICALL +Java_com_wolfssl_wolfcrypt_Chacha_mallocNativeStruct( + JNIEnv* env, jobject this) +{ + void* ret = 0; + +#ifdef HAVE_CHACHA + ret = XMALLOC(sizeof(ChaCha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (ret == NULL) + throwOutOfMemoryException(env, "Failed to allocate ChaCha object"); + + LogStr("new ChaCha() = %p\n", (void*)ret); +#else + throwNotCompiledInException(env); +#endif + + return (jlong) ret; +} + +JNIEXPORT void JNICALL +Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1init( + JNIEnv* env, jobject this) +{ +#ifdef HAVE_CHACHA + int ret = 0; + ChaCha* chacha = (ChaCha*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + ret = (!chacha) + ? BAD_FUNC_ARG + : 0; + + if (ret != 0) + throwWolfCryptExceptionFromError(env, ret); + + LogStr("Chacha_init(ChaCha=%p) = %d\n", chacha, ret); +#else + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL +Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1free( + JNIEnv* env, jobject this) +{ +#ifdef HAVE_CHACHA + ChaCha* chacha = (ChaCha*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception */ + return; + } + + if (chacha) + XFREE(chacha, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + LogStr("Chacha_free(chacha=%p)\n", chacha); +#else + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1setIV + (JNIEnv* env, jobject this, jbyteArray iv_object) +{ +#if defined(HAVE_CHACHA) + int ret = 0; + ChaCha* chacha = NULL; + byte* iv = NULL; + word32 ivSz = 0; + + chacha = (ChaCha*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + iv = getByteArray(env, iv_object); + ivSz = getByteArrayLength(env, iv_object); + + if (!chacha || !iv) { + ret = BAD_FUNC_ARG; + } else { + ret = wc_Chacha_SetIV(chacha, iv, ivSz); + } + + if (ret != 0) + throwWolfCryptExceptionFromError(env, ret); + + LogStr("wc_Chacha_SetIV(chacha=%p) = %d\n", chacha, ret); + + releaseByteArray(env, iv_object, iv, JNI_ABORT); +#else + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1setKey + (JNIEnv* env, jobject this, jbyteArray key_object) +{ +#if defined(HAVE_CHACHA) + int ret = 0; + ChaCha* chacha = NULL; + byte* key = NULL; + word32 keySz = 0; + + chacha = (ChaCha*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + key = getByteArray(env, key_object); + keySz = getByteArrayLength(env, key_object); + + if (!chacha || !key) { + ret = BAD_FUNC_ARG; + } else { + ret = wc_Chacha_SetKey(chacha, key, keySz); + } + + if (ret != 0) + throwWolfCryptExceptionFromError(env, ret); + + LogStr("wc_Chacha_SetKey(chacha=%p) = %d\n", chacha, ret); + + releaseByteArray(env, key_object, key, JNI_ABORT); +#else + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT jbyteArray JNICALL +Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1process( + JNIEnv* env, jobject this, jbyteArray input_obj) +{ + jbyteArray result = NULL; + +#ifdef HAVE_CHACHA + int ret = 0; + ChaCha* chacha = NULL; + byte* input = NULL; + int inputSz = 0; + byte* output = NULL; + + chacha = (ChaCha*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return NULL; + } + + input = getByteArray(env, input_obj); + inputSz = getByteArrayLength(env, input_obj); + + if (input == NULL) { + return NULL; + } + + output = XMALLOC(inputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (output == NULL) { + throwOutOfMemoryException(env, "Failed to allocate key buffer"); + return result; + } + + ret = (!chacha) + ? BAD_FUNC_ARG + : wc_Chacha_Process(chacha, output, input, inputSz); + + if (ret == 0) { + result = (*env)->NewByteArray(env, inputSz); + + if (result) { + (*env)->SetByteArrayRegion(env, result, 0, inputSz, + (const jbyte*) output); + } else { + throwWolfCryptException(env, "Failed to allocate memory for Chacha_process"); + } + } else { + throwWolfCryptExceptionFromError(env, ret); + } + + LogStr("wc_Chacha_Process() = %d\n", output, ret); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#else + throwNotCompiledInException(env); +#endif + return result; +} diff --git a/jni/jni_curve25519.c b/jni/jni_curve25519.c new file mode 100644 index 0000000..8f1f739 --- /dev/null +++ b/jni/jni_curve25519.c @@ -0,0 +1,421 @@ +/* jni_curve25519.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __ANDROID__ + #include +#endif +#include +#include + +#include +#include +#include + +/* #define WOLFCRYPT_JNI_DEBUG_ON */ +#include + +#define MAX_CURVE25519_PRIVATE_DER_SZ 128 + +JNIEXPORT jlong JNICALL +Java_com_wolfssl_wolfcrypt_Curve25519_mallocNativeStruct( + JNIEnv* env, jobject this) +{ + void* ret = 0; + +#ifdef HAVE_CURVE25519 + ret = XMALLOC(sizeof(curve25519_key), NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (ret == NULL) + throwOutOfMemoryException(env, "Failed to allocate Curve25519 object"); + + LogStr("new Curve25519() = %p\n", (void*)ret); +#else + throwNotCompiledInException(env); +#endif + + return (jlong) ret; +} + +JNIEXPORT void JNICALL +Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1init( + JNIEnv* env, jobject this) +{ +#ifdef HAVE_CURVE25519 + int ret = 0; + curve25519_key* curve25519 = (curve25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + ret = (!curve25519) + ? BAD_FUNC_ARG + : wc_curve25519_init(curve25519); + + if (ret != 0) + throwWolfCryptExceptionFromError(env, ret); + + LogStr("curve25519_init(curve25519=%p) = %d\n", curve25519, ret); +#else + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL +Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1free( + JNIEnv* env, jobject this) +{ +#ifdef HAVE_CURVE25519 + curve25519_key* curve25519 = (curve25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception */ + return; + } + + if (curve25519) + wc_curve25519_free(curve25519); + + LogStr("curve25519_free(curve25519=%p)\n", curve25519); +#else + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL +Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1make_1key( + JNIEnv* env, jobject this, jobject rng_object, jint size) +{ +#ifdef HAVE_CURVE25519 + int ret = 0; + curve25519_key* curve25519 = NULL; + RNG* rng = NULL; + + curve25519 = (curve25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + rng = (RNG*) getNativeStruct(env, rng_object); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + ret = (!curve25519 || !rng) + ? BAD_FUNC_ARG + : wc_curve25519_make_key(rng, size, curve25519); + + if (ret != 0) + throwWolfCryptExceptionFromError(env, ret); + + LogStr("curve25519_make_key(rng, size, curve25519=%p) = %d\n", curve25519, ret); +#else + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1import_1private + (JNIEnv* env, jobject this, jbyteArray priv_object, + jbyteArray pub_object) +{ +#if defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_IMPORT) + int ret = 0; + curve25519_key* curve25519 = NULL; + byte* priv = NULL; + byte* pub = NULL; + word32 privSz = 0, pubSz = 0; + + curve25519 = (curve25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + priv = getByteArray(env, priv_object); + privSz = getByteArrayLength(env, priv_object); + pub = getByteArray(env, pub_object); + pubSz = getByteArrayLength(env, pub_object); + + /* pub may be null if only importing private key */ + if (!curve25519 || !priv) { + ret = BAD_FUNC_ARG; + } else { + /* detect, and later skip, leading zero byte */ + ret = wc_curve25519_import_private_raw(priv, privSz, pub, + pubSz, curve25519); + } + + if (ret != 0) + throwWolfCryptExceptionFromError(env, ret); + + LogStr("wc_curve25519_import_private_key(curve25519=%p) = %d\n", curve25519, ret); + + releaseByteArray(env, priv_object, priv, JNI_ABORT); + releaseByteArray(env, pub_object, pub, JNI_ABORT); +#else + throwNotCompiledInException(env); +#endif +} + + JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1import_1private_1only + (JNIEnv* env, jobject this, jbyteArray priv_object) +{ +#if defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_IMPORT) + int ret = 0; + curve25519_key* curve25519 = NULL; + byte* priv = NULL; + word32 privSz = 0; + + curve25519 = (curve25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + priv = getByteArray(env, priv_object); + privSz = getByteArrayLength(env, priv_object); + + /* pub may be null if only importing private key */ + if (!curve25519 || !priv) { + ret = BAD_FUNC_ARG; + } else { + /* detect, and later skip, leading zero byte */ + ret = wc_curve25519_import_private(priv, privSz, curve25519); + } + + if (ret != 0) + throwWolfCryptExceptionFromError(env, ret); + + LogStr("wc_curve25519_import_private_key(curve25519=%p) = %d\n", curve25519, ret); + + releaseByteArray(env, priv_object, priv, JNI_ABORT); +#else + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1import_1public + (JNIEnv* env, jobject this, jbyteArray pub_object) +{ +#if defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_IMPORT) + int ret = 0; + curve25519_key* curve25519 = NULL; + byte* pub = NULL; + word32 pubSz = 0; + + curve25519 = (curve25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + pub = getByteArray(env, pub_object); + pubSz = getByteArrayLength(env, pub_object); + + if (!curve25519 || !pub) { + ret = BAD_FUNC_ARG; + } else { + /* detect, and later skip, leading zero byte */ + ret = wc_curve25519_import_public(pub, pubSz, curve25519); + } + + if (ret != 0) + throwWolfCryptExceptionFromError(env, ret); + + LogStr("wc_curve25519_import_public(curve25519=%p) = %d\n", curve25519, ret); + + releaseByteArray(env, pub_object, pub, JNI_ABORT); +#else + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT jbyteArray JNICALL +Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1export_1private( + JNIEnv* env, jobject this) +{ + jbyteArray result = NULL; + +#ifdef HAVE_CURVE25519_KEY_EXPORT + int ret = 0; + curve25519_key* curve25519 = NULL; + byte* output = NULL; + word32 outputSz = 0; + + curve25519 = (curve25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return NULL; + } + + outputSz = wc_curve25519_size(curve25519); + + output = XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (output == NULL) { + throwOutOfMemoryException(env, "Failed to allocate key buffer"); + return result; + } + + ret = (!curve25519) + ? BAD_FUNC_ARG + : wc_curve25519_export_private_raw(curve25519, output, &outputSz); + + if (ret == 0) { + result = (*env)->NewByteArray(env, outputSz); + + if (result) { + (*env)->SetByteArrayRegion(env, result, 0, outputSz, + (const jbyte*) output); + } else { + throwWolfCryptException(env, "Failed to allocate key"); + } + } else { + throwWolfCryptExceptionFromError(env, ret); + } + + LogStr("wc_curve25519_export_private(curve25519, output=%p, outputSz) = %d\n", output, ret); + LogStr("output[%u]: [%p]\n", (word32)outputSz, output); + LogHex((byte*) output, 0, outputSz); + + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#else + throwNotCompiledInException(env); +#endif + + return result; +} + +JNIEXPORT jbyteArray JNICALL +Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1export_1public ( + JNIEnv* env, jobject this) +{ + jbyteArray result = NULL; + +#ifdef HAVE_CURVE25519_KEY_EXPORT + int ret = 0; + curve25519_key* curve25519 = NULL; + byte* output = NULL; + word32 outputSz = 0; + + curve25519 = (curve25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return NULL; + } + + outputSz = wc_curve25519_size(curve25519); + + output = XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (output == NULL) { + throwOutOfMemoryException(env, "Failed to allocate key buffer"); + return result; + } + + ret = (!curve25519) + ? BAD_FUNC_ARG + : wc_curve25519_export_public(curve25519, output, &outputSz); + + if (ret == 0) { + result = (*env)->NewByteArray(env, outputSz); + + if (result) { + (*env)->SetByteArrayRegion(env, result, 0, outputSz, + (const jbyte*) output); + } else { + throwWolfCryptException(env, "Failed to allocate key"); + } + } else { + throwWolfCryptExceptionFromError(env, ret); + } + + LogStr("wc_curve25519_export_public(curve25519, output=%p, outputSz) = %d\n", output, ret); + LogStr("output[%u]: [%p]\n", (word32)outputSz, output); + LogHex((byte*) output, 0, outputSz); + + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#else + throwNotCompiledInException(env); +#endif + + return result; +} + +JNIEXPORT jbyteArray JNICALL +Java_com_wolfssl_wolfcrypt_Curve25519_wc_1curve25519_1make_1shared_1secret( + JNIEnv* env, jobject this, jobject pub_object) +{ + jbyteArray result = NULL; + +#ifdef HAVE_CURVE25519_SHARED_SECRET + int ret = 0; + curve25519_key* curve25519 = NULL; + curve25519_key* pub = NULL; + byte* output = NULL; + word32 outputSz = 0; + + curve25519 = (curve25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return NULL; + } + + pub = (curve25519_key*) getNativeStruct(env, pub_object); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return NULL; + } + + outputSz = wc_curve25519_size(curve25519); + output = XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (output == NULL) { + throwOutOfMemoryException(env, + "Failed to allocate shared secret buffer"); + return result; + } + + ret = (!curve25519 || !pub) + ? BAD_FUNC_ARG + : wc_curve25519_shared_secret(curve25519, pub, output, &outputSz); + + if (ret == 0) { + result = (*env)->NewByteArray(env, outputSz); + + if (result) { + (*env)->SetByteArrayRegion(env, result, 0, outputSz, + (const jbyte*) output); + } else { + throwWolfCryptException(env, "Failed to allocate shared secret"); + } + } else { + throwWolfCryptExceptionFromError(env, ret); + } + + LogStr("wc_curve25519_shared_secret(priv, pub, output=%p, outputSz) = %d\n", + output, ret); + LogStr("output[%u]: [%p]\n", (word32)outputSz, output); + LogHex((byte*) output, 0, outputSz); + + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#else + throwNotCompiledInException(env); +#endif + + return result; +} + diff --git a/jni/jni_ed25519.c b/jni/jni_ed25519.c new file mode 100644 index 0000000..4236103 --- /dev/null +++ b/jni/jni_ed25519.c @@ -0,0 +1,532 @@ +/* jni_ed25519.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __ANDROID__ + #include +#endif +#include +#include + +#include +#include +#include + +/* #define WOLFCRYPT_JNI_DEBUG_ON */ +#include + +#define MAX_ED25519_PRIVATE_DER_SZ 128 + +JNIEXPORT jlong JNICALL +Java_com_wolfssl_wolfcrypt_Ed25519_mallocNativeStruct( + JNIEnv* env, jobject this) +{ + void* ret = 0; + +#ifdef HAVE_ED25519 + ret = XMALLOC(sizeof(ed25519_key), NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (ret == NULL) + throwOutOfMemoryException(env, "Failed to allocate Ed25519 object"); + + LogStr("new Ed25519() = %p\n", (void*)ret); +#else + throwNotCompiledInException(env); +#endif + + return (jlong) ret; +} + +JNIEXPORT void JNICALL +Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1init( + JNIEnv* env, jobject this) +{ +#ifdef HAVE_ED25519 + int ret = 0; + ed25519_key* ed25519 = (ed25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + ret = (!ed25519) + ? BAD_FUNC_ARG + : wc_ed25519_init(ed25519); + + if (ret != 0) + throwWolfCryptExceptionFromError(env, ret); + + LogStr("ed25519_init(ed25519=%p) = %d\n", ed25519, ret); +#else + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL +Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1free( + JNIEnv* env, jobject this) +{ +#ifdef HAVE_ED25519 + ed25519_key* ed25519 = (ed25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception */ + return; + } + + if (ed25519) + wc_ed25519_free(ed25519); + + LogStr("ed25519_free(ed25519=%p)\n", ed25519); +#else + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL +Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1make_1key( + JNIEnv* env, jobject this, jobject rng_object, jint size) +{ +#ifdef HAVE_ED25519 + int ret = 0; + ed25519_key* ed25519 = NULL; + RNG* rng = NULL; + + ed25519 = (ed25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + rng = (RNG*) getNativeStruct(env, rng_object); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + ret = (!ed25519 || !rng) + ? BAD_FUNC_ARG + : wc_ed25519_make_key(rng, size, ed25519); + + if (ret != 0) + throwWolfCryptExceptionFromError(env, ret); + + LogStr("ed25519_make_key(rng, size, ed25519=%p) = %d\n", ed25519, ret); +#else + throwNotCompiledInException(env); +#endif +} + + +JNIEXPORT void JNICALL +Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1check_1key( + JNIEnv* env, jobject this) +{ +#ifdef HAVE_ED25519 + int ret = 0; + ed25519_key* ed25519 = (ed25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + ret = (!ed25519) + ? BAD_FUNC_ARG + : wc_ed25519_check_key(ed25519); + + if (ret != 0) + throwWolfCryptExceptionFromError(env, ret); + + LogStr("wc_ed25519_check_key(ed25519=%p) = %d\n", ed25519, ret); +#else + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1import_1private + (JNIEnv* env, jobject this, jbyteArray priv_object, jbyteArray pub_object) +{ +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) + int ret = 0; + ed25519_key* ed25519 = NULL; + byte* priv = NULL; + byte* pub = NULL; + word32 privSz = 0, pubSz = 0; + + ed25519 = (ed25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + priv = getByteArray(env, priv_object); + privSz = getByteArrayLength(env, priv_object); + pub = getByteArray(env, pub_object); + pubSz = getByteArrayLength(env, pub_object); + + /* pub may be null if only importing private key */ + if (!ed25519 || !priv) { + ret = BAD_FUNC_ARG; + } else { + /* detect, and later skip, leading zero byte */ + if (!pub) + ret = wc_ed25519_import_private_only(priv, privSz, ed25519); + else + ret = wc_ed25519_import_private_key(priv, privSz, pub, + pubSz, ed25519); + } + + if (ret != 0) + throwWolfCryptExceptionFromError(env, ret); + + LogStr("wc_ed25519_import_private_key(ed25519=%p) = %d\n", ed25519, ret); + + releaseByteArray(env, priv_object, priv, JNI_ABORT); + releaseByteArray(env, pub_object, pub, JNI_ABORT); +#else + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1import_1public + (JNIEnv* env, jobject this, jbyteArray pub_object) +{ +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) + int ret = 0; + ed25519_key* ed25519 = NULL; + byte* pub = NULL; + word32 pubSz = 0; + + ed25519 = (ed25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + pub = getByteArray(env, pub_object); + pubSz = getByteArrayLength(env, pub_object); + + if (!ed25519 || !pub) { + ret = BAD_FUNC_ARG; + } else { + ret = wc_ed25519_import_public(pub, pubSz, ed25519); + } + + if (ret != 0) + throwWolfCryptExceptionFromError(env, ret); + + LogStr("wc_ed25519_import_public(ed25519=%p) = %d\n", ed25519, ret); + + releaseByteArray(env, pub_object, pub, JNI_ABORT); +#else + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1import_1private_1only + (JNIEnv* env, jobject this, jbyteArray priv_object) +{ +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) + int ret = 0; + ed25519_key* ed25519 = NULL; + byte* priv = NULL; + word32 privSz = 0; + + ed25519 = (ed25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + priv = getByteArray(env, priv_object); + privSz = getByteArrayLength(env, priv_object); + + if (!ed25519 || !priv) { + ret = BAD_FUNC_ARG; + } else { + /* detect, and later skip, leading zero byte */ + ret = wc_ed25519_import_private_only(priv, privSz, ed25519); + } + + if (ret != 0) + throwWolfCryptExceptionFromError(env, ret); + + LogStr("wc_ed25519_import_private_key(ed25519=%p) = %d\n", ed25519, ret); + + releaseByteArray(env, priv_object, priv, JNI_ABORT); +#else + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT jbyteArray JNICALL +Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1export_1private( + JNIEnv* env, jobject this) +{ + jbyteArray result = NULL; + +#ifdef HAVE_ED25519_KEY_EXPORT + int ret = 0; + ed25519_key* ed25519 = NULL; + byte* output = NULL; + word32 outputSz = 0; + + ed25519 = (ed25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return NULL; + } + + outputSz = 2 * wc_ed25519_priv_size(ed25519); /* Export private + public */ + + output = XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (output == NULL) { + throwOutOfMemoryException(env, "Failed to allocate key buffer"); + return result; + } + + ret = (!ed25519) + ? BAD_FUNC_ARG + : wc_ed25519_export_private(ed25519, output, &outputSz); + + if (ret == 0) { + result = (*env)->NewByteArray(env, outputSz); + + if (result) { + (*env)->SetByteArrayRegion(env, result, 0, outputSz, + (const jbyte*) output); + } else { + throwWolfCryptException(env, "Failed to allocate key"); + } + } else { + throwWolfCryptExceptionFromError(env, ret); + } + + LogStr("wc_ed25519_export_x963(ed25519, output=%p, outputSz) = %d\n", output, ret); + LogStr("output[%u]: [%p]\n", (word32)outputSz, output); + LogHex((byte*) output, 0, outputSz); + + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#else + throwNotCompiledInException(env); +#endif + + return result; +} + +JNIEXPORT jbyteArray JNICALL +Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1export_1private_1only( + JNIEnv* env, jobject this) +{ + jbyteArray result = NULL; + +#ifdef HAVE_ED25519_KEY_EXPORT + int ret = 0; + ed25519_key* ed25519 = NULL; + byte* output = NULL; + word32 outputSz = 0; + + ed25519 = (ed25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return NULL; + } + + outputSz = wc_ed25519_size(ed25519); + + output = XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (output == NULL) { + throwOutOfMemoryException(env, "Failed to allocate key buffer"); + return result; + } + + ret = (!ed25519) + ? BAD_FUNC_ARG + : wc_ed25519_export_private_only(ed25519, output, &outputSz); + + if (ret == 0) { + result = (*env)->NewByteArray(env, outputSz); + + if (result) { + (*env)->SetByteArrayRegion(env, result, 0, outputSz, + (const jbyte*) output); + } else { + throwWolfCryptException(env, "Failed to allocate key"); + } + } else { + throwWolfCryptExceptionFromError(env, ret); + } + + LogStr("wc_ed25519_export_x963(ed25519, output=%p, outputSz) = %d\n", output, ret); + LogStr("output[%u]: [%p]\n", (word32)outputSz, output); + LogHex((byte*) output, 0, outputSz); + + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#else + throwNotCompiledInException(env); +#endif + + return result; +} + +JNIEXPORT jbyteArray JNICALL +Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1export_1public( + JNIEnv* env, jobject this) +{ + jbyteArray result = NULL; + +#ifdef HAVE_ED25519_KEY_EXPORT + int ret = 0; + ed25519_key* ed25519 = NULL; + byte* output = NULL; + word32 outputSz = 0; + + ed25519 = (ed25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return NULL; + } + + outputSz = wc_ed25519_size(ed25519); + + output = XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (output == NULL) { + throwOutOfMemoryException(env, "Failed to allocate key buffer"); + return result; + } + + ret = (!ed25519) + ? BAD_FUNC_ARG + : wc_ed25519_export_public(ed25519, output, &outputSz); + + if (ret == 0) { + result = (*env)->NewByteArray(env, outputSz); + + if (result) { + (*env)->SetByteArrayRegion(env, result, 0, outputSz, + (const jbyte*) output); + } else { + throwWolfCryptException(env, "Failed to allocate key"); + } + } else { + throwWolfCryptExceptionFromError(env, ret); + } + + LogStr("wc_ed25519_export_x963(ed25519, output=%p, outputSz) = %d\n", output, ret); + LogStr("output[%u]: [%p]\n", (word32)outputSz, output); + LogHex((byte*) output, 0, outputSz); + + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#else + throwNotCompiledInException(env); +#endif + + return result; +} + + +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1sign_1msg + (JNIEnv* env, jobject this, jbyteArray msg_in) +{ + jbyteArray result = NULL; +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_SIGN) + int ret = 0; + word32 len = 0, outlen = ED25519_SIG_SIZE; + ed25519_key* ed25519 = NULL; + byte* msg = NULL; + byte* output = NULL; + + ed25519 = (ed25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return NULL; + } + msg = getByteArray(env, msg_in); + len = getByteArrayLength(env, msg_in); + output = XMALLOC(outlen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (!ed25519) { + ret = BAD_FUNC_ARG; + } else { + ret = wc_ed25519_sign_msg(msg, len, output, &outlen, ed25519); + } + + if (ret == 0) { + result = (*env)->NewByteArray(env, outlen); + + if (result) { + (*env)->SetByteArrayRegion(env, result, 0, outlen, + (const jbyte*) output); + } else { + throwWolfCryptException(env, "Failed to allocate key"); + } + } else { + throwWolfCryptExceptionFromError(env, ret); + } + + LogStr("wc_ed25519_sign_msg(ed25519=%p) = %d\n", ed25519, ret); + printf("wc_ed25519_sign_msg(ed25519=%p) = %d\n", ed25519, ret); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + releaseByteArray(env, msg_in, msg, JNI_ABORT); +#else + throwNotCompiledInException(env); +#endif + return result; +} + + +JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_Ed25519_wc_1ed25519_1verify_1msg + (JNIEnv* env, jobject this, jbyteArray sig_in, jbyteArray msg_in) +{ + int result = -1; +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_SIGN) + int ret = 0; + word32 msglen, siglen; + ed25519_key* ed25519 = NULL; + byte* sig = NULL; + byte* msg = NULL; + + + ed25519 = (ed25519_key*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return result; + } + sig = getByteArray(env, sig_in); + msg = getByteArray(env, msg_in); + msglen = getByteArrayLength(env, msg_in); + siglen = getByteArrayLength(env, msg_in); + + if (!ed25519) { + ret = BAD_FUNC_ARG; + } else { + ret = wc_ed25519_verify_msg(sig, siglen, msg, msglen, &result, ed25519); + } + + if (ret != 0) + throwWolfCryptExceptionFromError(env, ret); + + LogStr("wc_ed25519_verify_msg(ed25519=%p) = %d\n", ed25519, ret); + + releaseByteArray(env, sig_in, sig, JNI_ABORT); + releaseByteArray(env, msg_in, msg, JNI_ABORT); +#else + throwNotCompiledInException(env); +#endif + return result; +} + diff --git a/makefile b/makefile index 66d1cfb..fbc2a99 100644 --- a/makefile +++ b/makefile @@ -4,7 +4,8 @@ INC_PATH = $(SRC_PATH)/include OBJ_LIST = jni_fips.o jni_native_struct.o jni_aes.o jni_des3.o jni_md5.o \ jni_sha.o jni_hmac.o jni_rng.o jni_rsa.o jni_dh.o jni_ecc.o \ - jni_error.o jni_asn.o jni_logging.o + jni_ed25519.o jni_curve25519.o jni_chacha.o jni_error.o jni_asn.o \ + jni_logging.o OBJS = $(patsubst %,$(OUT_PATH)/%,$(OBJ_LIST)) TARGET = $(OUT_PATH)/libwolfcryptjni.jnilib diff --git a/makefile.linux b/makefile.linux index 7672809..fe493ec 100644 --- a/makefile.linux +++ b/makefile.linux @@ -4,7 +4,8 @@ INC_PATH = $(SRC_PATH)/include OBJ_LIST = jni_fips.o jni_native_struct.o jni_aes.o jni_des3.o jni_md5.o \ jni_sha.o jni_hmac.o jni_rng.o jni_rsa.o jni_dh.o jni_ecc.o \ - jni_error.o jni_asn.o jni_logging.o + jni_ed25519.o jni_curve25519.o jni_chacha.o jni_error.o jni_asn.o \ + jni_logging.o OBJS = $(patsubst %,$(OUT_PATH)/%,$(OBJ_LIST)) TARGET = $(OUT_PATH)/libwolfcryptjni.so diff --git a/makefile.macosx b/makefile.macosx index 66d1cfb..fbc2a99 100644 --- a/makefile.macosx +++ b/makefile.macosx @@ -4,7 +4,8 @@ INC_PATH = $(SRC_PATH)/include OBJ_LIST = jni_fips.o jni_native_struct.o jni_aes.o jni_des3.o jni_md5.o \ jni_sha.o jni_hmac.o jni_rng.o jni_rsa.o jni_dh.o jni_ecc.o \ - jni_error.o jni_asn.o jni_logging.o + jni_ed25519.o jni_curve25519.o jni_chacha.o jni_error.o jni_asn.o \ + jni_logging.o OBJS = $(patsubst %,$(OUT_PATH)/%,$(OBJ_LIST)) TARGET = $(OUT_PATH)/libwolfcryptjni.jnilib diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..827423c --- /dev/null +++ b/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + wolfssl + wolfcrypt-jni + 1.0 + jar + wolfcrypt-jni + + + + + org.hamcrest + hamcrest-core + 1.3 + test + + + junit + junit + 4.12 + test + + + + + + + maven-compiler-plugin + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-surefire-plugin + + -Djava.library.path=/usr/lib/jni + + + + + diff --git a/src/main/java/com/wolfssl/wolfcrypt/Chacha.java b/src/main/java/com/wolfssl/wolfcrypt/Chacha.java new file mode 100644 index 0000000..e300e81 --- /dev/null +++ b/src/main/java/com/wolfssl/wolfcrypt/Chacha.java @@ -0,0 +1,101 @@ +/* Chacha.java + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +package com.wolfssl.wolfcrypt; + +import java.security.InvalidAlgorithmParameterException; + +/** + * Wrapper for the native WolfCrypt Chacha implementation. + * + * @author Daniele Lacamera + * @version 1.0, March 2018 + */ +public class Chacha extends NativeStruct { + + private WolfCryptState state = WolfCryptState.UNINITIALIZED; + + public Chacha() { + init(); + } + + @Override + public void releaseNativeStruct() { + free(); + + super.releaseNativeStruct(); + } + + protected native long mallocNativeStruct() throws OutOfMemoryError; + + private native void wc_Chacha_init(); + + private native void wc_Chacha_free(); + + private native byte[] wc_Chacha_process(byte in[]); + + private native void wc_Chacha_setKey(byte[] Key); + + private native void wc_Chacha_setIV(byte[] IV); + + + + + protected void init() { + if (state == WolfCryptState.UNINITIALIZED) { + wc_Chacha_init(); + state = WolfCryptState.INITIALIZED; + } else { + throw new IllegalStateException( + "Native resources already initialized."); + } + } + + protected void free() { + if (state != WolfCryptState.UNINITIALIZED) { + wc_Chacha_free(); + state = WolfCryptState.UNINITIALIZED; + } + } + + public void setKey(byte[] Key) { + if (state == WolfCryptState.INITIALIZED) { + wc_Chacha_setKey(Key); + state = WolfCryptState.READY; + } else { + throw new IllegalStateException("Object already has a key."); + } + } + + public void setIV(byte[] IV) { + wc_Chacha_setIV(IV); + } + + public byte[] process(byte[] in) { + if (state == WolfCryptState.READY) { + return wc_Chacha_process(in); + } else { + throw new IllegalStateException( + "No available key to perform the operation."); + } + } +} + diff --git a/src/main/java/com/wolfssl/wolfcrypt/Curve25519.java b/src/main/java/com/wolfssl/wolfcrypt/Curve25519.java new file mode 100644 index 0000000..d8ed18b --- /dev/null +++ b/src/main/java/com/wolfssl/wolfcrypt/Curve25519.java @@ -0,0 +1,172 @@ +/* Curve25519.java + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +package com.wolfssl.wolfcrypt; + +import java.security.InvalidAlgorithmParameterException; +import java.security.spec.EllipticCurve; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECFieldFp; + +/** + * Wrapper for the native WolfCrypt curve25519 implementation. + * + * @author Daniele Lacamera + * @version 1.0, March 2018 + */ +public class Curve25519 extends NativeStruct { + + private WolfCryptState state = WolfCryptState.UNINITIALIZED; + + public Curve25519() { + init(); + } + + @Override + public void releaseNativeStruct() { + free(); + + super.releaseNativeStruct(); + } + + protected native long mallocNativeStruct() throws OutOfMemoryError; + + private native void wc_curve25519_init(); + + private native void wc_curve25519_free(); + + private native void wc_curve25519_make_key(Rng rng, int size); + + private native void wc_curve25519_make_key_ex(Rng rng, int size, int endian); + + private native void wc_curve25519_check_key(); + + private native byte[] wc_curve25519_make_shared_secret(Curve25519 pubKey); + + private native void wc_curve25519_import_private(byte[] privKey, byte[] key); + private native void wc_curve25519_import_private_only(byte[] privKey); + private native void wc_curve25519_import_public(byte[] pubKey); + + + private native byte[] wc_curve25519_export_private(); + private native byte[] wc_curve25519_export_public(); + + + protected void init() { + if (state == WolfCryptState.UNINITIALIZED) { + wc_curve25519_init(); + state = WolfCryptState.INITIALIZED; + } else { + throw new IllegalStateException( + "Native resources already initialized."); + } + } + + protected void free() { + if (state != WolfCryptState.UNINITIALIZED) { + wc_curve25519_free(); + state = WolfCryptState.UNINITIALIZED; + } + } + + public void makeKey(Rng rng, int size) { + if (state == WolfCryptState.INITIALIZED) { + wc_curve25519_make_key(rng, size); + state = WolfCryptState.READY; + } else { + throw new IllegalStateException("Object already has a key."); + } + } + + public void makeKeyWithEndian(Rng rng, int size, int endian) { + if (state == WolfCryptState.INITIALIZED) { + wc_curve25519_make_key_ex(rng, size, endian); + state = WolfCryptState.READY; + } else { + throw new IllegalStateException("Object already has a key."); + } + } + + public void checkKey() { + if (state == WolfCryptState.READY) { + wc_curve25519_check_key(); + } else { + throw new IllegalStateException( + "No available key to perform the operation."); + } + } + + public void importPrivate(byte[] privKey, byte[] xKey) { + if (state == WolfCryptState.INITIALIZED) { + wc_curve25519_import_private(privKey, xKey); + state = WolfCryptState.READY; + } else { + throw new IllegalStateException("Object already has a key."); + } + } + + public void importPrivateOnly(byte[] privKey) { + if (state == WolfCryptState.INITIALIZED) { + wc_curve25519_import_private_only(privKey); + state = WolfCryptState.READY; + } else { + throw new IllegalStateException("Object already has a key."); + } + } + + public void importPublic(byte[] pubKey) { + if (state == WolfCryptState.INITIALIZED) { + wc_curve25519_import_public(pubKey); + state = WolfCryptState.READY; + } else { + throw new IllegalStateException("Object already has a key."); + } + } + + public byte[] exportPrivate() { + if (state == WolfCryptState.READY) { + return wc_curve25519_export_private(); + } else { + throw new IllegalStateException( + "No available key to perform the operation."); + } + } + + public byte[] exportPublic() { + if (state == WolfCryptState.READY) { + return wc_curve25519_export_private(); + } else { + throw new IllegalStateException( + "No available key to perform the operation."); + } + } + + public byte[] makeSharedSecret(Curve25519 pubKey) { + if (state == WolfCryptState.READY) { + return wc_curve25519_make_shared_secret(pubKey); + } else { + throw new IllegalStateException( + "No available key to perform the operation."); + } + } + +} + diff --git a/src/main/java/com/wolfssl/wolfcrypt/Ed25519.java b/src/main/java/com/wolfssl/wolfcrypt/Ed25519.java new file mode 100644 index 0000000..62bf75f --- /dev/null +++ b/src/main/java/com/wolfssl/wolfcrypt/Ed25519.java @@ -0,0 +1,183 @@ +/* Ed25519.java + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +package com.wolfssl.wolfcrypt; + +import java.security.InvalidAlgorithmParameterException; + +/** + * Wrapper for the native WolfCrypt ed25519 implementation. + * + * @author Daniele Lacamera + * @version 1.0, March 2018 + */ +public class Ed25519 extends NativeStruct { + + private WolfCryptState state = WolfCryptState.UNINITIALIZED; + + public Ed25519() { + init(); + } + + @Override + public void releaseNativeStruct() { + free(); + + super.releaseNativeStruct(); + } + + protected native long mallocNativeStruct() throws OutOfMemoryError; + + private native void wc_ed25519_init(); + + private native void wc_ed25519_free(); + + private native void wc_ed25519_make_key(Rng rng, int size); + + private native void wc_ed25519_check_key(); + + private native void wc_ed25519_import_private(byte[] privKey, byte[] key); + private native void wc_ed25519_import_private_only(byte[] privKey); + private native void wc_ed25519_import_public(byte[] privKey); + + private native byte[] wc_ed25519_sign_msg(byte[] msg); + private native boolean wc_ed25519_verify_msg(byte[] sig, byte[] msg); + + private native byte[] wc_ed25519_export_private(); + private native byte[] wc_ed25519_export_private_only(); + private native byte[] wc_ed25519_export_public(); + + protected void init() { + if (state == WolfCryptState.UNINITIALIZED) { + wc_ed25519_init(); + state = WolfCryptState.INITIALIZED; + } else { + throw new IllegalStateException( + "Native resources already initialized."); + } + } + + protected void free() { + if (state != WolfCryptState.UNINITIALIZED) { + wc_ed25519_free(); + state = WolfCryptState.UNINITIALIZED; + } + } + + public void makeKey(Rng rng, int size) { + if (state == WolfCryptState.INITIALIZED) { + wc_ed25519_make_key(rng, size); + state = WolfCryptState.READY; + } else { + throw new IllegalStateException("Object already has a key."); + } + } + + public void checkKey() { + if (state == WolfCryptState.READY) { + wc_ed25519_check_key(); + } else { + throw new IllegalStateException( + "No available key to perform the operation."); + } + } + + public void importPrivate(byte[] privKey, byte[] Key) { + if (state == WolfCryptState.INITIALIZED) { + wc_ed25519_import_private(privKey, Key); + state = WolfCryptState.READY; + } else { + throw new IllegalStateException("Object already has a key."); + } + } + + public void importPrivateOnly(byte[] privKey) { + if (state == WolfCryptState.INITIALIZED) { + wc_ed25519_import_private_only(privKey); + state = WolfCryptState.READY; + } else { + throw new IllegalStateException("Object already has a key."); + } + } + + public void importPublic(byte[] Key) { + if (state == WolfCryptState.INITIALIZED) { + wc_ed25519_import_public(Key); + state = WolfCryptState.READY; + } else { + throw new IllegalStateException("Object already has a key."); + } + } + + public byte[] exportPrivate() { + if (state == WolfCryptState.READY) { + return wc_ed25519_export_private(); + } else { + throw new IllegalStateException( + "No available key to perform the operation."); + } + } + + public byte[] exportPrivateOnly() { + if (state == WolfCryptState.READY) { + return wc_ed25519_export_private_only(); + } else { + throw new IllegalStateException( + "No available key to perform the operation."); + } + } + + public byte[] exportPublic() { + if (state == WolfCryptState.READY) { + return wc_ed25519_export_public(); + } else { + throw new IllegalStateException( + "No available key to perform the operation."); + } + } + + public byte[] sign_msg(byte[] msg_in) { + + byte[] msg_out = null; + if (state == WolfCryptState.READY) { + msg_out = wc_ed25519_sign_msg(msg_in); + } else { + throw new IllegalStateException( + "No available key to perform the operation."); + } + + return msg_out; + } + + public boolean verify_msg(byte[] msg, byte[] signature) { + boolean result = false; + + if (state == WolfCryptState.READY) { + result = wc_ed25519_verify_msg(signature, msg); + } else { + throw new IllegalStateException( + "No available key to perform the operation."); + } + + return result; + } +} +