104 lines
4.4 KiB
C
104 lines
4.4 KiB
C
/*
|
|
* Copyright (c) 2026 QPQ IaaS AG <info@qpq.swiss>. All rights reserved.
|
|
* Project: Gajumaru Core Java Libraries <gajumaru.io>
|
|
*
|
|
* This program is dual-licensed:
|
|
* 1) Under the GNU Affero General Public License as published by the Free
|
|
* Software Foundation, either version 3 of the License, or (at your option)
|
|
* any later version (AGPL-3.0-or-later).
|
|
*
|
|
* 2) Under a commercial/proprietary license available directly from QPQ IaaS AG.
|
|
* If you wish to use this software outside the strict constraints of the
|
|
* AGPLv3 (e.g. within a closed-source or proprietary product), you must
|
|
* purchase a commercial license from QPQ IaaS AG.
|
|
*
|
|
* Authors:
|
|
* - Craig Everett <craigeverett@qpq.swiss>
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later OR LicenseRef-QPQ-Commercial
|
|
*/
|
|
|
|
#include <jni.h>
|
|
#include <sodium.h>
|
|
#include <string.h>
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_swiss_qpq_gajumobile_security_GajuNative_memzero(JNIEnv *env, jclass clazz, jbyteArray array) {
|
|
if (array == NULL) return;
|
|
jsize len = (*env)->GetArrayLength(env, array);
|
|
jbyte *data = (*env)->GetByteArrayElements(env, array, NULL);
|
|
if (data != NULL) {
|
|
sodium_memzero(data, (size_t) len);
|
|
(*env)->ReleaseByteArrayElements(env, array, data, 0);
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL
|
|
Java_swiss_qpq_gajumobile_security_GajuNative_cryptoSignSeedKeypair(JNIEnv *env, jclass clazz, jbyteArray seed) {
|
|
if (seed == NULL || (*env)->GetArrayLength(env, seed) != crypto_sign_SEEDBYTES) return NULL;
|
|
|
|
unsigned char pk[crypto_sign_PUBLICKEYBYTES];
|
|
unsigned char sk[crypto_sign_SECRETKEYBYTES];
|
|
jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL);
|
|
|
|
crypto_sign_seed_keypair(pk, sk, (unsigned char *) seed_data);
|
|
(*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT);
|
|
|
|
jbyteArray result = (*env)->NewByteArray(env, crypto_sign_PUBLICKEYBYTES + crypto_sign_SECRETKEYBYTES);
|
|
(*env)->SetByteArrayRegion(env, result, 0, crypto_sign_PUBLICKEYBYTES, (jbyte *) pk);
|
|
(*env)->SetByteArrayRegion(env, result, crypto_sign_PUBLICKEYBYTES, crypto_sign_SECRETKEYBYTES, (jbyte *) sk);
|
|
|
|
sodium_memzero(pk, sizeof pk);
|
|
sodium_memzero(sk, sizeof sk);
|
|
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL
|
|
Java_swiss_qpq_gajumobile_security_GajuNative_cryptoSignDetached(JNIEnv *env, jclass clazz, jbyteArray message, jbyteArray secretKey) {
|
|
if (message == NULL || secretKey == NULL || (*env)->GetArrayLength(env, secretKey) != crypto_sign_SECRETKEYBYTES) return NULL;
|
|
|
|
jsize msg_len = (*env)->GetArrayLength(env, message);
|
|
unsigned char sig[crypto_sign_BYTES];
|
|
jbyte *msg_data = (*env)->GetByteArrayElements(env, message, NULL);
|
|
jbyte *sk_data = (*env)->GetByteArrayElements(env, secretKey, NULL);
|
|
|
|
crypto_sign_detached(sig, NULL, (unsigned char *) msg_data, (unsigned long long) msg_len, (unsigned char *) sk_data);
|
|
|
|
(*env)->ReleaseByteArrayElements(env, message, msg_data, JNI_ABORT);
|
|
(*env)->ReleaseByteArrayElements(env, secretKey, sk_data, JNI_ABORT);
|
|
|
|
jbyteArray result = (*env)->NewByteArray(env, crypto_sign_BYTES);
|
|
(*env)->SetByteArrayRegion(env, result, 0, crypto_sign_BYTES, (jbyte *) sig);
|
|
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT jboolean JNICALL
|
|
Java_swiss_qpq_gajumobile_security_GajuNative_cryptoSignVerifyDetached(JNIEnv *env, jclass clazz, jbyteArray signature, jbyteArray message, jbyteArray publicKey) {
|
|
if (signature == NULL || message == NULL || publicKey == NULL) return JNI_FALSE;
|
|
if ((*env)->GetArrayLength(env, signature) != crypto_sign_BYTES) return JNI_FALSE;
|
|
if ((*env)->GetArrayLength(env, publicKey) != crypto_sign_PUBLICKEYBYTES) return JNI_FALSE;
|
|
|
|
jsize msg_len = (*env)->GetArrayLength(env, message);
|
|
jbyte *sig_data = (*env)->GetByteArrayElements(env, signature, NULL);
|
|
jbyte *msg_data = (*env)->GetByteArrayElements(env, message, NULL);
|
|
jbyte *pk_data = (*env)->GetByteArrayElements(env, publicKey, NULL);
|
|
|
|
int res = crypto_sign_verify_detached((unsigned char *) sig_data, (unsigned char *) msg_data, (unsigned long long) msg_len, (unsigned char *) pk_data);
|
|
|
|
(*env)->ReleaseByteArrayElements(env, signature, sig_data, JNI_ABORT);
|
|
(*env)->ReleaseByteArrayElements(env, message, msg_data, JNI_ABORT);
|
|
(*env)->ReleaseByteArrayElements(env, publicKey, pk_data, JNI_ABORT);
|
|
|
|
return res == 0 ? JNI_TRUE : JNI_FALSE;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL
|
|
JNI_OnLoad(JavaVM* vm, void* reserved) {
|
|
if (sodium_init() == -1) {
|
|
return JNI_ERR;
|
|
}
|
|
return JNI_VERSION_1_6;
|
|
}
|