1725 lines
45 KiB
C
1725 lines
45 KiB
C
/* jni_slhdsa.c
|
|
*
|
|
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfSSL.
|
|
*
|
|
* 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 3 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-1335, USA
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
|
|
#ifdef WOLFSSL_USER_SETTINGS
|
|
#include <wolfssl/wolfcrypt/settings.h>
|
|
#elif !defined(__ANDROID__)
|
|
#include <wolfssl/options.h>
|
|
#endif
|
|
|
|
#include <wolfssl/version.h>
|
|
#ifdef HAVE_FIPS
|
|
#include <wolfssl/wolfcrypt/fips.h>
|
|
#endif
|
|
#include <wolfssl/wolfcrypt/types.h>
|
|
|
|
#ifdef WOLFSSL_HAVE_SLHDSA
|
|
#include <wolfssl/wolfcrypt/wc_slhdsa.h>
|
|
#include <wolfssl/wolfcrypt/hash.h>
|
|
#include <wolfssl/wolfcrypt/sha256.h>
|
|
#include <wolfssl/wolfcrypt/sha512.h>
|
|
#include <wolfssl/wolfcrypt/sha3.h>
|
|
#endif
|
|
#include <wolfssl/wolfcrypt/error-crypt.h>
|
|
#include <wolfssl/wolfcrypt/memory.h>
|
|
|
|
#include <com_wolfssl_wolfcrypt_SlhDsa.h>
|
|
#include <wolfcrypt_jni_NativeStruct.h>
|
|
#include <wolfcrypt_jni_error.h>
|
|
|
|
/* #define WOLFCRYPT_JNI_DEBUG_ON */
|
|
#include <wolfcrypt_jni_debug.h>
|
|
|
|
#if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && !defined(WOLFSSL_NO_FORCE_ZERO)
|
|
#define SLHDSA_FORCE_ZERO(p, len) wc_ForceZero((p), (len))
|
|
#else
|
|
#define SLHDSA_FORCE_ZERO(p, len) XMEMSET((p), 0, (len))
|
|
#endif
|
|
|
|
/* A WOLFSSL_SLHDSA_VERIFY_ONLY build provides only public-key verify. DER
|
|
* encode (KeyToDer / PublicKeyToDer) additionally needs
|
|
* WC_ENABLE_ASYM_KEY_EXPORT. */
|
|
#ifdef WOLFSSL_HAVE_SLHDSA
|
|
|
|
#ifndef WOLFSSL_SLHDSA_VERIFY_ONLY
|
|
#define WC_JNI_SLHDSA_HAVE_MAKE_KEY
|
|
#define WC_JNI_SLHDSA_HAVE_SIGN
|
|
#define WC_JNI_SLHDSA_HAVE_PRIV_KEY
|
|
#endif
|
|
#ifdef WC_ENABLE_ASYM_KEY_EXPORT
|
|
#define WC_JNI_SLHDSA_HAVE_ASN1_EXPORT
|
|
#endif
|
|
|
|
#endif /* WOLFSSL_HAVE_SLHDSA */
|
|
|
|
#ifdef WOLFSSL_HAVE_SLHDSA
|
|
/* FIPS 205 Section 10.2.2 HashSLH-DSA pre-hash digest lengths for the SHAKE
|
|
* parameter sets: SHAKE128 produces a 256-bit (32-byte) output and SHAKE256 a
|
|
* 512-bit (64-byte) output. wolfSSL has no fixed-size constant for these XOFs,
|
|
* so name them explicitly here rather than borrowing the SHA-2 sizes. */
|
|
#define WC_JNI_SLHDSA_SHAKE128_PH_LEN 32
|
|
#define WC_JNI_SLHDSA_SHAKE256_PH_LEN 64
|
|
|
|
/* Maximum FIPS 205 pre-hash digest length across the PH functions
|
|
* (SHA-256 = 32, SHA-512 = 64, SHAKE128 = 32, SHAKE256 = 64), used to size
|
|
* local digest buffers. */
|
|
#ifdef WOLFSSL_SHA512
|
|
#define WC_JNI_SLHDSA_MAX_PH_LEN WC_SHA512_DIGEST_SIZE
|
|
#else
|
|
#define WC_JNI_SLHDSA_MAX_PH_LEN WC_JNI_SLHDSA_SHAKE256_PH_LEN
|
|
#endif
|
|
|
|
/* Compute the FIPS 205 Section 10.2.2 HashSLH-DSA pre-hash PH(msg) into the
|
|
* caller's 64-byte digest buffer, selecting the hash function and digest
|
|
* length from the key's parameter set per the standardized pre-hash OIDs:
|
|
* SHA2-128 -> SHA-256 (32 bytes)
|
|
* SHA2-192/256 -> SHA-512 (64 bytes)
|
|
* SHAKE-128 -> SHAKE128 (32 bytes)
|
|
* SHAKE-192/256 -> SHAKE256 (64 bytes)
|
|
* On success returns 0 and sets *digestLen and *hashType. */
|
|
static int slhdsa_prehash_msg(SlhDsaKey* key, const byte* msg, word32 msgLen,
|
|
byte* digest, word32* digestLen, enum wc_HashType* hashType)
|
|
{
|
|
int ret;
|
|
int param;
|
|
int category;
|
|
|
|
if (key == NULL || key->params == NULL || digest == NULL ||
|
|
digestLen == NULL || hashType == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
param = (int)key->params->param;
|
|
/* Category index: 0 = 128-bit, 1 = 192-bit, 2 = 256-bit. */
|
|
category = (param % 6) / 2;
|
|
|
|
if (SLHDSA_IS_SHA2(param)) {
|
|
if (category == 0) {
|
|
#ifndef NO_SHA256
|
|
ret = wc_Sha256Hash(msg, msgLen, digest);
|
|
*digestLen = WC_SHA256_DIGEST_SIZE;
|
|
*hashType = WC_HASH_TYPE_SHA256;
|
|
#else
|
|
ret = NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
else {
|
|
#ifdef WOLFSSL_SHA512
|
|
ret = wc_Sha512Hash(msg, msgLen, digest);
|
|
*digestLen = WC_SHA512_DIGEST_SIZE;
|
|
*hashType = WC_HASH_TYPE_SHA512;
|
|
#else
|
|
ret = NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
}
|
|
else {
|
|
if (category == 0) {
|
|
#ifdef WOLFSSL_SHAKE128
|
|
ret = wc_Shake128Hash(msg, msgLen, digest,
|
|
WC_JNI_SLHDSA_SHAKE128_PH_LEN);
|
|
*digestLen = WC_JNI_SLHDSA_SHAKE128_PH_LEN;
|
|
*hashType = WC_HASH_TYPE_SHAKE128;
|
|
#else
|
|
ret = NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
else {
|
|
#ifdef WOLFSSL_SHAKE256
|
|
ret = wc_Shake256Hash(msg, msgLen, digest,
|
|
WC_JNI_SLHDSA_SHAKE256_PH_LEN);
|
|
*digestLen = WC_JNI_SLHDSA_SHAKE256_PH_LEN;
|
|
*hashType = WC_HASH_TYPE_SHAKE256;
|
|
#else
|
|
ret = NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#endif /* WOLFSSL_HAVE_SLHDSA */
|
|
|
|
JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_mallocNativeStruct
|
|
(JNIEnv* env, jobject this)
|
|
{
|
|
#ifdef WOLFSSL_HAVE_SLHDSA
|
|
SlhDsaKey* key = NULL;
|
|
|
|
key = (SlhDsaKey*)XMALLOC(sizeof(SlhDsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (key == NULL) {
|
|
throwOutOfMemoryException(env, "Failed to allocate SlhDsa object");
|
|
}
|
|
else {
|
|
XMEMSET(key, 0, sizeof(SlhDsaKey));
|
|
}
|
|
|
|
LogStr("new SlhDsa() = %p\n", key);
|
|
|
|
return (jlong)(uintptr_t)key;
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
throwNotCompiledInException(env);
|
|
return (jlong)0;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1init
|
|
(JNIEnv* env, jobject this, jint param)
|
|
{
|
|
#ifdef WOLFSSL_HAVE_SLHDSA
|
|
int ret = 0;
|
|
SlhDsaKey* key = NULL;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return;
|
|
}
|
|
|
|
if (key == NULL) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
else {
|
|
ret = wc_SlhDsaKey_Init(key, (enum SlhDsaParam)param, NULL,
|
|
INVALID_DEVID);
|
|
}
|
|
|
|
if (ret != 0) {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_Init(key=%p, param=%d) = %d\n", key, (int)param, ret);
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
(void)param;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1free
|
|
(JNIEnv* env, jobject this)
|
|
{
|
|
#ifdef WOLFSSL_HAVE_SLHDSA
|
|
SlhDsaKey* key = NULL;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return;
|
|
}
|
|
|
|
if (key != NULL) {
|
|
wc_SlhDsaKey_Free(key);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_Free(key=%p)\n", key);
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1get_1param
|
|
(JNIEnv* env, jobject this)
|
|
{
|
|
#ifdef WOLFSSL_HAVE_SLHDSA
|
|
SlhDsaKey* key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return -1;
|
|
}
|
|
|
|
if (key == NULL || key->params == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
return (jint)key->params->param;
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
throwNotCompiledInException(env);
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1make_1key
|
|
(JNIEnv* env, jobject this, jobject rng_object)
|
|
{
|
|
#if defined(WOLFSSL_HAVE_SLHDSA) && defined(WC_JNI_SLHDSA_HAVE_MAKE_KEY)
|
|
int ret = 0;
|
|
SlhDsaKey* key = NULL;
|
|
WC_RNG* rng = NULL;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return;
|
|
}
|
|
|
|
rng = (WC_RNG*) getNativeStruct(env, rng_object);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return;
|
|
}
|
|
|
|
if (key == NULL || rng == NULL) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
else {
|
|
ret = wc_SlhDsaKey_MakeKey(key, rng);
|
|
}
|
|
|
|
if (ret != 0) {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_MakeKey(key=%p) = %d\n", key, ret);
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
(void)rng_object;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1make_1key_1with_1seeds
|
|
(JNIEnv* env, jobject this, jbyteArray skSeed_object, jbyteArray skPrf_object, jbyteArray pkSeed_object)
|
|
{
|
|
#if defined(WOLFSSL_HAVE_SLHDSA) && defined(WC_JNI_SLHDSA_HAVE_MAKE_KEY)
|
|
int ret = 0;
|
|
SlhDsaKey* key = NULL;
|
|
byte* skSeed = NULL;
|
|
byte* skPrf = NULL;
|
|
byte* pkSeed = NULL;
|
|
word32 skSeedLen = 0;
|
|
word32 skPrfLen = 0;
|
|
word32 pkSeedLen = 0;
|
|
jboolean skSeedIsCopy = JNI_FALSE;
|
|
jboolean skPrfIsCopy = JNI_FALSE;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return;
|
|
}
|
|
|
|
if (skSeed_object != NULL) {
|
|
skSeed = getSecretByteArray(env, skSeed_object, &skSeedIsCopy);
|
|
skSeedLen = getByteArrayLength(env, skSeed_object);
|
|
}
|
|
|
|
if (skPrf_object != NULL) {
|
|
skPrf = getSecretByteArray(env, skPrf_object, &skPrfIsCopy);
|
|
skPrfLen = getByteArrayLength(env, skPrf_object);
|
|
}
|
|
|
|
if (pkSeed_object != NULL) {
|
|
pkSeed = getByteArray(env, pkSeed_object);
|
|
pkSeedLen = getByteArrayLength(env, pkSeed_object);
|
|
}
|
|
|
|
if ((skSeed_object != NULL && skSeed == NULL) ||
|
|
(skPrf_object != NULL && skPrf == NULL) ||
|
|
(pkSeed_object != NULL && pkSeed == NULL)) {
|
|
|
|
releaseSecretByteArray(env, skSeed_object, skSeed, skSeedLen,
|
|
skSeedIsCopy);
|
|
releaseSecretByteArray(env, skPrf_object, skPrf, skPrfLen,
|
|
skPrfIsCopy);
|
|
if (pkSeed != NULL) {
|
|
releaseByteArray(env, pkSeed_object, pkSeed, JNI_ABORT);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (key == NULL || skSeed == NULL || skPrf == NULL || pkSeed == NULL) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
else {
|
|
ret = wc_SlhDsaKey_MakeKeyWithRandom(key, skSeed, skSeedLen,
|
|
skPrf, skPrfLen, pkSeed, pkSeedLen);
|
|
}
|
|
|
|
if (ret != 0) {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_MakeKeyWithRandom(key=%p) = %d\n", key, ret);
|
|
|
|
releaseSecretByteArray(env, skSeed_object, skSeed, skSeedLen,
|
|
skSeedIsCopy);
|
|
releaseSecretByteArray(env, skPrf_object, skPrf, skPrfLen,
|
|
skPrfIsCopy);
|
|
if (pkSeed_object != NULL) {
|
|
releaseByteArray(env, pkSeed_object, pkSeed, JNI_ABORT);
|
|
}
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
(void)skSeed_object;
|
|
(void)skPrf_object;
|
|
(void)pkSeed_object;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1sign
|
|
(JNIEnv* env, jobject this, jbyteArray ctx_object, jbyteArray msg_object, jobject rng_object)
|
|
{
|
|
jbyteArray result = NULL;
|
|
#if defined(WOLFSSL_HAVE_SLHDSA) && defined(WC_JNI_SLHDSA_HAVE_SIGN)
|
|
int ret = 0;
|
|
int sigSz = 0;
|
|
SlhDsaKey* key = NULL;
|
|
WC_RNG* rng = NULL;
|
|
byte* ctx = NULL;
|
|
byte* msg = NULL;
|
|
byte* sig = NULL;
|
|
word32 ctxLen = 0;
|
|
word32 msgLen = 0;
|
|
word32 sigLen = 0;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return NULL;
|
|
}
|
|
|
|
rng = (WC_RNG*) getNativeStruct(env, rng_object);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return NULL;
|
|
}
|
|
|
|
if (key == NULL || rng == NULL) {
|
|
throwWolfCryptExceptionFromError(env, BAD_FUNC_ARG);
|
|
return NULL;
|
|
}
|
|
|
|
/* ctx_object may be null for an empty context. */
|
|
if (ctx_object != NULL) {
|
|
ctx = getByteArray(env, ctx_object);
|
|
ctxLen = getByteArrayLength(env, ctx_object);
|
|
}
|
|
|
|
if (msg_object != NULL) {
|
|
msg = getByteArray(env, msg_object);
|
|
msgLen = getByteArrayLength(env, msg_object);
|
|
}
|
|
|
|
if ((ctx_object != NULL && ctx == NULL) ||
|
|
(msg_object != NULL && msg == NULL)) {
|
|
if (ctx != NULL) {
|
|
releaseByteArray(env, ctx_object, ctx, JNI_ABORT);
|
|
}
|
|
if (msg != NULL) {
|
|
releaseByteArray(env, msg_object, msg, JNI_ABORT);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* FIPS 205 caps context length at 255 bytes (also enforced in Java). */
|
|
if (ctxLen > com_wolfssl_wolfcrypt_SlhDsa_SLH_DSA_MAX_CONTEXT_LEN) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
|
|
if (ret == 0) {
|
|
sigSz = wc_SlhDsaKey_SigSize(key);
|
|
if (sigSz < 0) {
|
|
ret = sigSz;
|
|
}
|
|
else {
|
|
sigLen = (word32)sigSz;
|
|
}
|
|
}
|
|
|
|
if (ret == 0) {
|
|
sig = (byte*)XMALLOC(sigLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (sig == NULL) {
|
|
ret = MEMORY_E;
|
|
}
|
|
else {
|
|
XMEMSET(sig, 0, sigLen);
|
|
}
|
|
}
|
|
|
|
if (ret == 0) {
|
|
ret = wc_SlhDsaKey_Sign(key, ctx, (byte)ctxLen, msg, msgLen,
|
|
sig, &sigLen, rng);
|
|
}
|
|
|
|
if (ret == 0) {
|
|
result = (*env)->NewByteArray(env, sigLen);
|
|
if (result != NULL) {
|
|
(*env)->SetByteArrayRegion(env, result, 0, sigLen,
|
|
(const jbyte*)sig);
|
|
}
|
|
else {
|
|
throwWolfCryptException(env, "Failed to allocate sig");
|
|
}
|
|
}
|
|
else {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_Sign(key=%p) = %d\n", key, ret);
|
|
|
|
if (sig != NULL) {
|
|
XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
if (ctx_object != NULL) {
|
|
releaseByteArray(env, ctx_object, ctx, JNI_ABORT);
|
|
}
|
|
if (msg_object != NULL) {
|
|
releaseByteArray(env, msg_object, msg, JNI_ABORT);
|
|
}
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
(void)ctx_object;
|
|
(void)msg_object;
|
|
(void)rng_object;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1sign_1msg_1prehash
|
|
(JNIEnv* env, jobject this, jbyteArray ctx_object, jbyteArray msg_object, jobject rng_object)
|
|
{
|
|
jbyteArray result = NULL;
|
|
#if defined(WOLFSSL_HAVE_SLHDSA) && defined(WC_JNI_SLHDSA_HAVE_SIGN)
|
|
int ret = 0;
|
|
int sigSz = 0;
|
|
SlhDsaKey* key = NULL;
|
|
WC_RNG* rng = NULL;
|
|
byte* ctx = NULL;
|
|
byte* msg = NULL;
|
|
byte* sig = NULL;
|
|
word32 ctxLen = 0;
|
|
word32 msgLen = 0;
|
|
word32 sigLen = 0;
|
|
byte digest[WC_JNI_SLHDSA_MAX_PH_LEN];
|
|
word32 digestLen = 0;
|
|
enum wc_HashType hashType = WC_HASH_TYPE_NONE;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return NULL;
|
|
}
|
|
|
|
rng = (WC_RNG*) getNativeStruct(env, rng_object);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return NULL;
|
|
}
|
|
|
|
if (key == NULL || rng == NULL) {
|
|
throwWolfCryptExceptionFromError(env, BAD_FUNC_ARG);
|
|
return NULL;
|
|
}
|
|
|
|
/* ctx_object may be null for an empty context. */
|
|
if (ctx_object != NULL) {
|
|
ctx = getByteArray(env, ctx_object);
|
|
ctxLen = getByteArrayLength(env, ctx_object);
|
|
}
|
|
|
|
if (msg_object != NULL) {
|
|
msg = getByteArray(env, msg_object);
|
|
msgLen = getByteArrayLength(env, msg_object);
|
|
}
|
|
|
|
if ((ctx_object != NULL && ctx == NULL) ||
|
|
(msg_object != NULL && msg == NULL)) {
|
|
if (ctx != NULL) {
|
|
releaseByteArray(env, ctx_object, ctx, JNI_ABORT);
|
|
}
|
|
if (msg != NULL) {
|
|
releaseByteArray(env, msg_object, msg, JNI_ABORT);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* FIPS 205 caps context length at 255 bytes (also enforced in Java). */
|
|
if (ctxLen > com_wolfssl_wolfcrypt_SlhDsa_SLH_DSA_MAX_CONTEXT_LEN) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
|
|
if (ret == 0) {
|
|
ret = slhdsa_prehash_msg(key, msg, msgLen, digest, &digestLen,
|
|
&hashType);
|
|
}
|
|
|
|
if (ret == 0) {
|
|
sigSz = wc_SlhDsaKey_SigSize(key);
|
|
if (sigSz < 0) {
|
|
ret = sigSz;
|
|
}
|
|
else {
|
|
sigLen = (word32)sigSz;
|
|
}
|
|
}
|
|
|
|
if (ret == 0) {
|
|
sig = (byte*)XMALLOC(sigLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (sig == NULL) {
|
|
ret = MEMORY_E;
|
|
}
|
|
else {
|
|
XMEMSET(sig, 0, sigLen);
|
|
}
|
|
}
|
|
|
|
if (ret == 0) {
|
|
ret = wc_SlhDsaKey_SignHash(key, ctx, (byte)ctxLen, digest, digestLen,
|
|
hashType, sig, &sigLen, rng);
|
|
}
|
|
|
|
if (ret == 0) {
|
|
result = (*env)->NewByteArray(env, sigLen);
|
|
if (result != NULL) {
|
|
(*env)->SetByteArrayRegion(env, result, 0, sigLen,
|
|
(const jbyte*)sig);
|
|
}
|
|
else {
|
|
throwWolfCryptException(env, "Failed to allocate sig");
|
|
}
|
|
}
|
|
else {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_SignHash(prehash, key=%p) = %d\n", key, ret);
|
|
|
|
if (sig != NULL) {
|
|
XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
if (ctx_object != NULL) {
|
|
releaseByteArray(env, ctx_object, ctx, JNI_ABORT);
|
|
}
|
|
if (msg_object != NULL) {
|
|
releaseByteArray(env, msg_object, msg, JNI_ABORT);
|
|
}
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
(void)ctx_object;
|
|
(void)msg_object;
|
|
(void)rng_object;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1sign_1deterministic
|
|
(JNIEnv* env, jobject this, jbyteArray ctx_object, jbyteArray msg_object)
|
|
{
|
|
jbyteArray result = NULL;
|
|
#if defined(WOLFSSL_HAVE_SLHDSA) && defined(WC_JNI_SLHDSA_HAVE_SIGN)
|
|
int ret = 0;
|
|
int sigSz = 0;
|
|
SlhDsaKey* key = NULL;
|
|
byte* ctx = NULL;
|
|
byte* msg = NULL;
|
|
byte* sig = NULL;
|
|
word32 ctxLen = 0;
|
|
word32 msgLen = 0;
|
|
word32 sigLen = 0;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return NULL;
|
|
}
|
|
|
|
if (key == NULL) {
|
|
throwWolfCryptExceptionFromError(env, BAD_FUNC_ARG);
|
|
return NULL;
|
|
}
|
|
|
|
if (ctx_object != NULL) {
|
|
ctx = getByteArray(env, ctx_object);
|
|
ctxLen = getByteArrayLength(env, ctx_object);
|
|
}
|
|
|
|
if (msg_object != NULL) {
|
|
msg = getByteArray(env, msg_object);
|
|
msgLen = getByteArrayLength(env, msg_object);
|
|
}
|
|
|
|
if ((ctx_object != NULL && ctx == NULL) ||
|
|
(msg_object != NULL && msg == NULL)) {
|
|
if (ctx != NULL) {
|
|
releaseByteArray(env, ctx_object, ctx, JNI_ABORT);
|
|
}
|
|
if (msg != NULL) {
|
|
releaseByteArray(env, msg_object, msg, JNI_ABORT);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* FIPS 205 caps context length at 255 bytes (also enforced in Java). */
|
|
if (ctxLen > com_wolfssl_wolfcrypt_SlhDsa_SLH_DSA_MAX_CONTEXT_LEN) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
|
|
if (ret == 0) {
|
|
sigSz = wc_SlhDsaKey_SigSize(key);
|
|
if (sigSz < 0) {
|
|
ret = sigSz;
|
|
}
|
|
else {
|
|
sigLen = (word32)sigSz;
|
|
}
|
|
}
|
|
|
|
if (ret == 0) {
|
|
sig = (byte*)XMALLOC(sigLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (sig == NULL) {
|
|
ret = MEMORY_E;
|
|
}
|
|
else {
|
|
XMEMSET(sig, 0, sigLen);
|
|
}
|
|
}
|
|
|
|
if (ret == 0) {
|
|
ret = wc_SlhDsaKey_SignDeterministic(key, ctx, (byte)ctxLen, msg,
|
|
msgLen, sig, &sigLen);
|
|
}
|
|
|
|
if (ret == 0) {
|
|
result = (*env)->NewByteArray(env, sigLen);
|
|
if (result != NULL) {
|
|
(*env)->SetByteArrayRegion(env, result, 0, sigLen,
|
|
(const jbyte*)sig);
|
|
}
|
|
else {
|
|
throwWolfCryptException(env, "Failed to allocate sig");
|
|
}
|
|
}
|
|
else {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_SignDeterministic(key=%p) = %d\n", key, ret);
|
|
|
|
if (sig != NULL) {
|
|
XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
if (ctx_object != NULL) {
|
|
releaseByteArray(env, ctx_object, ctx, JNI_ABORT);
|
|
}
|
|
if (msg_object != NULL) {
|
|
releaseByteArray(env, msg_object, msg, JNI_ABORT);
|
|
}
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
(void)ctx_object;
|
|
(void)msg_object;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1sign_1hash
|
|
(JNIEnv* env, jobject this, jbyteArray ctx_object, jint hashAlg, jbyteArray hash_object, jobject rng_object)
|
|
{
|
|
jbyteArray result = NULL;
|
|
#if defined(WOLFSSL_HAVE_SLHDSA) && defined(WC_JNI_SLHDSA_HAVE_SIGN)
|
|
int ret = 0;
|
|
int sigSz = 0;
|
|
SlhDsaKey* key = NULL;
|
|
WC_RNG* rng = NULL;
|
|
byte* ctx = NULL;
|
|
byte* hash = NULL;
|
|
byte* sig = NULL;
|
|
word32 ctxLen = 0;
|
|
word32 hashLen = 0;
|
|
word32 sigLen = 0;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return NULL;
|
|
}
|
|
|
|
rng = (WC_RNG*) getNativeStruct(env, rng_object);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return NULL;
|
|
}
|
|
|
|
if (key == NULL || rng == NULL) {
|
|
throwWolfCryptExceptionFromError(env, BAD_FUNC_ARG);
|
|
return NULL;
|
|
}
|
|
|
|
if (ctx_object != NULL) {
|
|
ctx = getByteArray(env, ctx_object);
|
|
ctxLen = getByteArrayLength(env, ctx_object);
|
|
}
|
|
|
|
if (hash_object != NULL) {
|
|
hash = getByteArray(env, hash_object);
|
|
hashLen = getByteArrayLength(env, hash_object);
|
|
}
|
|
|
|
if ((ctx_object != NULL && ctx == NULL) ||
|
|
(hash_object != NULL && hash == NULL)) {
|
|
if (ctx != NULL) {
|
|
releaseByteArray(env, ctx_object, ctx, JNI_ABORT);
|
|
}
|
|
if (hash != NULL) {
|
|
releaseByteArray(env, hash_object, hash, JNI_ABORT);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* FIPS 205 caps context length at 255 bytes. */
|
|
if (ctxLen > com_wolfssl_wolfcrypt_SlhDsa_SLH_DSA_MAX_CONTEXT_LEN) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
|
|
if (ret == 0) {
|
|
sigSz = wc_SlhDsaKey_SigSize(key);
|
|
if (sigSz < 0) {
|
|
ret = sigSz;
|
|
}
|
|
else {
|
|
sigLen = (word32)sigSz;
|
|
}
|
|
}
|
|
|
|
if (ret == 0) {
|
|
sig = (byte*)XMALLOC(sigLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (sig == NULL) {
|
|
ret = MEMORY_E;
|
|
}
|
|
else {
|
|
XMEMSET(sig, 0, sigLen);
|
|
}
|
|
}
|
|
|
|
if (ret == 0) {
|
|
ret = wc_SlhDsaKey_SignHash(key, ctx, (byte)ctxLen, hash, hashLen,
|
|
(enum wc_HashType)hashAlg, sig, &sigLen, rng);
|
|
}
|
|
|
|
if (ret == 0) {
|
|
result = (*env)->NewByteArray(env, sigLen);
|
|
if (result != NULL) {
|
|
(*env)->SetByteArrayRegion(env, result, 0, sigLen,
|
|
(const jbyte*)sig);
|
|
}
|
|
else {
|
|
throwWolfCryptException(env, "Failed to allocate sig");
|
|
}
|
|
}
|
|
else {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_SignHash(key=%p) = %d\n", key, ret);
|
|
|
|
if (sig != NULL) {
|
|
XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
if (ctx_object != NULL) {
|
|
releaseByteArray(env, ctx_object, ctx, JNI_ABORT);
|
|
}
|
|
if (hash_object != NULL) {
|
|
releaseByteArray(env, hash_object, hash, JNI_ABORT);
|
|
}
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
(void)ctx_object;
|
|
(void)hashAlg;
|
|
(void)hash_object;
|
|
(void)rng_object;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1verify
|
|
(JNIEnv* env, jobject this, jbyteArray sig_object, jbyteArray ctx_object, jbyteArray msg_object)
|
|
{
|
|
jboolean result = JNI_FALSE;
|
|
#ifdef WOLFSSL_HAVE_SLHDSA
|
|
int ret = 0;
|
|
SlhDsaKey* key = NULL;
|
|
byte* sig = NULL;
|
|
byte* ctx = NULL;
|
|
byte* msg = NULL;
|
|
word32 sigLen = 0;
|
|
word32 ctxLen = 0;
|
|
word32 msgLen = 0;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
if (key == NULL) {
|
|
throwWolfCryptExceptionFromError(env, BAD_FUNC_ARG);
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
if (sig_object != NULL) {
|
|
sig = getByteArray(env, sig_object);
|
|
sigLen = getByteArrayLength(env, sig_object);
|
|
}
|
|
|
|
if (ctx_object != NULL) {
|
|
ctx = getByteArray(env, ctx_object);
|
|
ctxLen = getByteArrayLength(env, ctx_object);
|
|
}
|
|
|
|
if (msg_object != NULL) {
|
|
msg = getByteArray(env, msg_object);
|
|
msgLen = getByteArrayLength(env, msg_object);
|
|
}
|
|
|
|
if ((sig_object != NULL && sig == NULL) ||
|
|
(ctx_object != NULL && ctx == NULL) ||
|
|
(msg_object != NULL && msg == NULL)) {
|
|
if (sig != NULL) {
|
|
releaseByteArray(env, sig_object, sig, JNI_ABORT);
|
|
}
|
|
if (ctx != NULL) {
|
|
releaseByteArray(env, ctx_object, ctx, JNI_ABORT);
|
|
}
|
|
if (msg != NULL) {
|
|
releaseByteArray(env, msg_object, msg, JNI_ABORT);
|
|
}
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
/* FIPS 205 caps context length at 255 bytes. */
|
|
if (ctxLen > com_wolfssl_wolfcrypt_SlhDsa_SLH_DSA_MAX_CONTEXT_LEN) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
|
|
if (ret == 0) {
|
|
ret = wc_SlhDsaKey_Verify(key, ctx, (byte)ctxLen, msg, msgLen,
|
|
sig, sigLen);
|
|
}
|
|
|
|
if (ret == 0) {
|
|
result = JNI_TRUE;
|
|
}
|
|
else if (ret != SIG_VERIFY_E && ret != BAD_LENGTH_E) {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_Verify(key=%p) = %d\n", key, ret);
|
|
|
|
if (sig_object != NULL) {
|
|
releaseByteArray(env, sig_object, sig, JNI_ABORT);
|
|
}
|
|
if (ctx_object != NULL) {
|
|
releaseByteArray(env, ctx_object, ctx, JNI_ABORT);
|
|
}
|
|
if (msg_object != NULL) {
|
|
releaseByteArray(env, msg_object, msg, JNI_ABORT);
|
|
}
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
(void)sig_object;
|
|
(void)ctx_object;
|
|
(void)msg_object;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1verify_1msg_1prehash
|
|
(JNIEnv* env, jobject this, jbyteArray sig_object, jbyteArray ctx_object, jbyteArray msg_object)
|
|
{
|
|
jboolean result = JNI_FALSE;
|
|
#ifdef WOLFSSL_HAVE_SLHDSA
|
|
int ret = 0;
|
|
SlhDsaKey* key = NULL;
|
|
byte* sig = NULL;
|
|
byte* ctx = NULL;
|
|
byte* msg = NULL;
|
|
word32 sigLen = 0;
|
|
word32 ctxLen = 0;
|
|
word32 msgLen = 0;
|
|
byte digest[WC_JNI_SLHDSA_MAX_PH_LEN];
|
|
word32 digestLen = 0;
|
|
enum wc_HashType hashType = WC_HASH_TYPE_NONE;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
if (key == NULL) {
|
|
throwWolfCryptExceptionFromError(env, BAD_FUNC_ARG);
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
if (sig_object != NULL) {
|
|
sig = getByteArray(env, sig_object);
|
|
sigLen = getByteArrayLength(env, sig_object);
|
|
}
|
|
|
|
if (ctx_object != NULL) {
|
|
ctx = getByteArray(env, ctx_object);
|
|
ctxLen = getByteArrayLength(env, ctx_object);
|
|
}
|
|
|
|
if (msg_object != NULL) {
|
|
msg = getByteArray(env, msg_object);
|
|
msgLen = getByteArrayLength(env, msg_object);
|
|
}
|
|
|
|
if ((sig_object != NULL && sig == NULL) ||
|
|
(ctx_object != NULL && ctx == NULL) ||
|
|
(msg_object != NULL && msg == NULL)) {
|
|
if (sig != NULL) {
|
|
releaseByteArray(env, sig_object, sig, JNI_ABORT);
|
|
}
|
|
if (ctx != NULL) {
|
|
releaseByteArray(env, ctx_object, ctx, JNI_ABORT);
|
|
}
|
|
if (msg != NULL) {
|
|
releaseByteArray(env, msg_object, msg, JNI_ABORT);
|
|
}
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
/* FIPS 205 caps context length at 255 bytes. */
|
|
if (ctxLen > com_wolfssl_wolfcrypt_SlhDsa_SLH_DSA_MAX_CONTEXT_LEN) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
|
|
if (ret == 0) {
|
|
ret = slhdsa_prehash_msg(key, msg, msgLen, digest, &digestLen,
|
|
&hashType);
|
|
}
|
|
|
|
if (ret == 0) {
|
|
ret = wc_SlhDsaKey_VerifyHash(key, ctx, (byte)ctxLen, digest,
|
|
digestLen, hashType, sig, sigLen);
|
|
}
|
|
|
|
if (ret == 0) {
|
|
result = JNI_TRUE;
|
|
}
|
|
else if (ret != SIG_VERIFY_E && ret != BAD_LENGTH_E) {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_VerifyHash(prehash, key=%p) = %d\n", key, ret);
|
|
|
|
if (sig_object != NULL) {
|
|
releaseByteArray(env, sig_object, sig, JNI_ABORT);
|
|
}
|
|
if (ctx_object != NULL) {
|
|
releaseByteArray(env, ctx_object, ctx, JNI_ABORT);
|
|
}
|
|
if (msg_object != NULL) {
|
|
releaseByteArray(env, msg_object, msg, JNI_ABORT);
|
|
}
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
(void)sig_object;
|
|
(void)ctx_object;
|
|
(void)msg_object;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1verify_1hash
|
|
(JNIEnv* env, jobject this, jbyteArray sig_object, jbyteArray ctx_object, jint hashAlg, jbyteArray hash_object)
|
|
{
|
|
jboolean result = JNI_FALSE;
|
|
#ifdef WOLFSSL_HAVE_SLHDSA
|
|
int ret = 0;
|
|
SlhDsaKey* key = NULL;
|
|
byte* sig = NULL;
|
|
byte* ctx = NULL;
|
|
byte* hash = NULL;
|
|
word32 sigLen = 0;
|
|
word32 ctxLen = 0;
|
|
word32 hashLen = 0;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
if (key == NULL) {
|
|
throwWolfCryptExceptionFromError(env, BAD_FUNC_ARG);
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
if (sig_object != NULL) {
|
|
sig = getByteArray(env, sig_object);
|
|
sigLen = getByteArrayLength(env, sig_object);
|
|
}
|
|
|
|
if (ctx_object != NULL) {
|
|
ctx = getByteArray(env, ctx_object);
|
|
ctxLen = getByteArrayLength(env, ctx_object);
|
|
}
|
|
|
|
if (hash_object != NULL) {
|
|
hash = getByteArray(env, hash_object);
|
|
hashLen = getByteArrayLength(env, hash_object);
|
|
}
|
|
|
|
if ((sig_object != NULL && sig == NULL) ||
|
|
(ctx_object != NULL && ctx == NULL) ||
|
|
(hash_object != NULL && hash == NULL)) {
|
|
if (sig != NULL) {
|
|
releaseByteArray(env, sig_object, sig, JNI_ABORT);
|
|
}
|
|
if (ctx != NULL) {
|
|
releaseByteArray(env, ctx_object, ctx, JNI_ABORT);
|
|
}
|
|
if (hash != NULL) {
|
|
releaseByteArray(env, hash_object, hash, JNI_ABORT);
|
|
}
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
/* FIPS 205 caps context length at 255 bytes. */
|
|
if (ctxLen > com_wolfssl_wolfcrypt_SlhDsa_SLH_DSA_MAX_CONTEXT_LEN) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
|
|
if (ret == 0) {
|
|
ret = wc_SlhDsaKey_VerifyHash(key, ctx, (byte)ctxLen, hash, hashLen,
|
|
(enum wc_HashType)hashAlg, sig, sigLen);
|
|
}
|
|
|
|
if (ret == 0) {
|
|
result = JNI_TRUE;
|
|
}
|
|
else if (ret != SIG_VERIFY_E && ret != BAD_LENGTH_E) {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_VerifyHash(key=%p) = %d\n", key, ret);
|
|
|
|
if (sig_object != NULL) {
|
|
releaseByteArray(env, sig_object, sig, JNI_ABORT);
|
|
}
|
|
if (ctx_object != NULL) {
|
|
releaseByteArray(env, ctx_object, ctx, JNI_ABORT);
|
|
}
|
|
if (hash_object != NULL) {
|
|
releaseByteArray(env, hash_object, hash, JNI_ABORT);
|
|
}
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
(void)sig_object;
|
|
(void)ctx_object;
|
|
(void)hashAlg;
|
|
(void)hash_object;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1export_1public
|
|
(JNIEnv* env, jobject this)
|
|
{
|
|
jbyteArray result = NULL;
|
|
#ifdef WOLFSSL_HAVE_SLHDSA
|
|
int ret = 0;
|
|
int pubSz = 0;
|
|
SlhDsaKey* key = NULL;
|
|
byte* output = NULL;
|
|
word32 outputSz = 0;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return NULL;
|
|
}
|
|
|
|
if (key == NULL) {
|
|
throwWolfCryptExceptionFromError(env, BAD_FUNC_ARG);
|
|
return NULL;
|
|
}
|
|
|
|
pubSz = wc_SlhDsaKey_PublicSize(key);
|
|
if (pubSz < 0) {
|
|
throwWolfCryptExceptionFromError(env, pubSz);
|
|
return NULL;
|
|
}
|
|
outputSz = (word32)pubSz;
|
|
|
|
output = (byte*)XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (output == NULL) {
|
|
throwOutOfMemoryException(env, "Failed to allocate public key buffer");
|
|
return NULL;
|
|
}
|
|
XMEMSET(output, 0, outputSz);
|
|
|
|
ret = wc_SlhDsaKey_ExportPublic(key, output, &outputSz);
|
|
if (ret == 0) {
|
|
result = (*env)->NewByteArray(env, outputSz);
|
|
if (result != NULL) {
|
|
(*env)->SetByteArrayRegion(env, result, 0, outputSz,
|
|
(const jbyte*)output);
|
|
}
|
|
else {
|
|
throwWolfCryptException(env, "Failed to allocate public key");
|
|
}
|
|
}
|
|
else {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_ExportPublic(key=%p) = %d\n", key, ret);
|
|
|
|
XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1export_1private
|
|
(JNIEnv* env, jobject this)
|
|
{
|
|
jbyteArray result = NULL;
|
|
#if defined(WOLFSSL_HAVE_SLHDSA) && defined(WC_JNI_SLHDSA_HAVE_PRIV_KEY)
|
|
int ret = 0;
|
|
int privSz = 0;
|
|
SlhDsaKey* key = NULL;
|
|
byte* output = NULL;
|
|
word32 outputSz = 0;
|
|
word32 outputBufSz = 0;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return NULL;
|
|
}
|
|
|
|
if (key == NULL) {
|
|
throwWolfCryptExceptionFromError(env, BAD_FUNC_ARG);
|
|
return NULL;
|
|
}
|
|
|
|
privSz = wc_SlhDsaKey_PrivateSize(key);
|
|
if (privSz < 0) {
|
|
throwWolfCryptExceptionFromError(env, privSz);
|
|
return NULL;
|
|
}
|
|
outputSz = (word32)privSz;
|
|
outputBufSz = outputSz;
|
|
|
|
output = (byte*)XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (output == NULL) {
|
|
throwOutOfMemoryException(env, "Failed to allocate private key buffer");
|
|
return NULL;
|
|
}
|
|
XMEMSET(output, 0, outputSz);
|
|
|
|
PRIVATE_KEY_UNLOCK();
|
|
ret = wc_SlhDsaKey_ExportPrivate(key, output, &outputSz);
|
|
PRIVATE_KEY_LOCK();
|
|
if (ret == 0) {
|
|
result = (*env)->NewByteArray(env, outputSz);
|
|
if (result != NULL) {
|
|
(*env)->SetByteArrayRegion(env, result, 0, outputSz,
|
|
(const jbyte*)output);
|
|
}
|
|
else {
|
|
throwWolfCryptException(env, "Failed to allocate private key");
|
|
}
|
|
}
|
|
else {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_ExportPrivate(key=%p) = %d\n", key, ret);
|
|
|
|
SLHDSA_FORCE_ZERO(output, outputBufSz);
|
|
XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1import_1public
|
|
(JNIEnv* env, jobject this, jbyteArray in_object)
|
|
{
|
|
#ifdef WOLFSSL_HAVE_SLHDSA
|
|
int ret = 0;
|
|
SlhDsaKey* key = NULL;
|
|
byte* in = NULL;
|
|
word32 inLen = 0;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return;
|
|
}
|
|
|
|
in = getByteArray(env, in_object);
|
|
inLen = getByteArrayLength(env, in_object);
|
|
|
|
if (key == NULL || in == NULL) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
else {
|
|
ret = wc_SlhDsaKey_ImportPublic(key, in, inLen);
|
|
}
|
|
|
|
if (ret != 0) {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_ImportPublic(key=%p) = %d\n", key, ret);
|
|
|
|
releaseByteArray(env, in_object, in, JNI_ABORT);
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
(void)in_object;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1import_1private
|
|
(JNIEnv* env, jobject this, jbyteArray in_object)
|
|
{
|
|
#if defined(WOLFSSL_HAVE_SLHDSA) && defined(WC_JNI_SLHDSA_HAVE_PRIV_KEY)
|
|
int ret = 0;
|
|
SlhDsaKey* key = NULL;
|
|
byte* in = NULL;
|
|
word32 inLen = 0;
|
|
jboolean inIsCopy = JNI_FALSE;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return;
|
|
}
|
|
|
|
in = getSecretByteArray(env, in_object, &inIsCopy);
|
|
inLen = getByteArrayLength(env, in_object);
|
|
|
|
if (key == NULL || in == NULL) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
else {
|
|
ret = wc_SlhDsaKey_ImportPrivate(key, in, inLen);
|
|
}
|
|
|
|
if (ret != 0) {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_ImportPrivate(key=%p) = %d\n", key, ret);
|
|
|
|
releaseSecretByteArray(env, in_object, in, inLen, inIsCopy);
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
(void)in_object;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1PublicKeyToDer
|
|
(JNIEnv* env, jobject this, jboolean withAlg)
|
|
{
|
|
jbyteArray result = NULL;
|
|
#if defined(WOLFSSL_HAVE_SLHDSA) && defined(WC_JNI_SLHDSA_HAVE_ASN1_EXPORT)
|
|
int ret = 0;
|
|
SlhDsaKey* key = NULL;
|
|
byte* output = NULL;
|
|
word32 outputSz = 0;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return NULL;
|
|
}
|
|
|
|
if (key == NULL) {
|
|
throwWolfCryptExceptionFromError(env, BAD_FUNC_ARG);
|
|
return NULL;
|
|
}
|
|
|
|
/* Call with NULL output to get required size. */
|
|
ret = wc_SlhDsaKey_PublicKeyToDer(key, NULL, 0, (int)withAlg);
|
|
if (ret <= 0) {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
return NULL;
|
|
}
|
|
outputSz = (word32)ret;
|
|
|
|
output = (byte*)XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (output == NULL) {
|
|
throwOutOfMemoryException(env, "Failed to allocate public DER buffer");
|
|
return NULL;
|
|
}
|
|
XMEMSET(output, 0, outputSz);
|
|
|
|
ret = wc_SlhDsaKey_PublicKeyToDer(key, output, outputSz, (int)withAlg);
|
|
if (ret > 0) {
|
|
result = (*env)->NewByteArray(env, ret);
|
|
if (result != NULL) {
|
|
(*env)->SetByteArrayRegion(env, result, 0, ret,
|
|
(const jbyte*)output);
|
|
}
|
|
else {
|
|
throwWolfCryptException(env, "Failed to allocate public DER");
|
|
}
|
|
}
|
|
else {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_PublicKeyToDer(key=%p) = %d\n", key, ret);
|
|
|
|
XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
(void)withAlg;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1KeyToDer
|
|
(JNIEnv* env, jobject this)
|
|
{
|
|
jbyteArray result = NULL;
|
|
#if defined(WOLFSSL_HAVE_SLHDSA) && defined(WC_JNI_SLHDSA_HAVE_PRIV_KEY) && \
|
|
defined(WC_JNI_SLHDSA_HAVE_ASN1_EXPORT)
|
|
int ret = 0;
|
|
SlhDsaKey* key = NULL;
|
|
byte* output = NULL;
|
|
word32 outputSz = 0;
|
|
word32 outputBufSz = 0;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return NULL;
|
|
}
|
|
|
|
if (key == NULL) {
|
|
throwWolfCryptExceptionFromError(env, BAD_FUNC_ARG);
|
|
return NULL;
|
|
}
|
|
|
|
/* Call with NULL output to get required size. */
|
|
ret = wc_SlhDsaKey_KeyToDer(key, NULL, 0);
|
|
if (ret <= 0) {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
return NULL;
|
|
}
|
|
outputSz = (word32)ret;
|
|
outputBufSz = outputSz;
|
|
|
|
output = (byte*)XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (output == NULL) {
|
|
throwOutOfMemoryException(env, "Failed to allocate PKCS#8 buffer");
|
|
return NULL;
|
|
}
|
|
XMEMSET(output, 0, outputSz);
|
|
|
|
ret = wc_SlhDsaKey_KeyToDer(key, output, outputSz);
|
|
if (ret > 0) {
|
|
result = (*env)->NewByteArray(env, ret);
|
|
if (result != NULL) {
|
|
(*env)->SetByteArrayRegion(env, result, 0, ret,
|
|
(const jbyte*)output);
|
|
}
|
|
else {
|
|
throwWolfCryptException(env, "Failed to allocate PKCS#8 DER");
|
|
}
|
|
}
|
|
else {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_KeyToDer(key=%p) = %d\n", key, ret);
|
|
|
|
SLHDSA_FORCE_ZERO(output, outputBufSz);
|
|
XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1PublicKeyDecode
|
|
(JNIEnv* env, jobject this, jbyteArray der_object)
|
|
{
|
|
#ifdef WOLFSSL_HAVE_SLHDSA
|
|
int ret = 0;
|
|
SlhDsaKey* key = NULL;
|
|
byte* der = NULL;
|
|
word32 derLen = 0;
|
|
word32 idx = 0;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return;
|
|
}
|
|
|
|
der = getByteArray(env, der_object);
|
|
derLen = getByteArrayLength(env, der_object);
|
|
|
|
if (key == NULL || der == NULL || derLen == 0) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
else {
|
|
ret = wc_SlhDsaKey_PublicKeyDecode(der, &idx, key, derLen);
|
|
}
|
|
|
|
if (ret != 0) {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_PublicKeyDecode(key=%p) = %d\n", key, ret);
|
|
|
|
releaseByteArray(env, der_object, der, JNI_ABORT);
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
(void)der_object;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1PrivateKeyDecode
|
|
(JNIEnv* env, jobject this, jbyteArray der_object)
|
|
{
|
|
#if defined(WOLFSSL_HAVE_SLHDSA) && defined(WC_JNI_SLHDSA_HAVE_PRIV_KEY)
|
|
int ret = 0;
|
|
SlhDsaKey* key = NULL;
|
|
byte* der = NULL;
|
|
byte* derCopy = NULL;
|
|
word32 derLen = 0;
|
|
word32 idx = 0;
|
|
jboolean derIsCopy = JNI_FALSE;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return;
|
|
}
|
|
|
|
der = getSecretByteArray(env, der_object, &derIsCopy);
|
|
derLen = getByteArrayLength(env, der_object);
|
|
|
|
if (key == NULL || der == NULL || derLen == 0) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
|
|
if (ret == 0) {
|
|
/* Copy because PrivateKeyDecode may modify the input buffer. */
|
|
derCopy = (byte*)XMALLOC(derLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (derCopy == NULL) {
|
|
ret = MEMORY_E;
|
|
}
|
|
else {
|
|
XMEMCPY(derCopy, der, derLen);
|
|
}
|
|
}
|
|
|
|
if (ret == 0) {
|
|
ret = wc_SlhDsaKey_PrivateKeyDecode(derCopy, &idx, key, derLen);
|
|
}
|
|
|
|
if (ret != 0) {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_PrivateKeyDecode(key=%p) = %d\n", key, ret);
|
|
|
|
if (derCopy != NULL) {
|
|
SLHDSA_FORCE_ZERO(derCopy, derLen);
|
|
XFREE(derCopy, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
releaseSecretByteArray(env, der_object, der, derLen, derIsCopy);
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
(void)der_object;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1pub_1size
|
|
(JNIEnv* env, jobject this)
|
|
{
|
|
#ifdef WOLFSSL_HAVE_SLHDSA
|
|
int ret = 0;
|
|
SlhDsaKey* key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return 0;
|
|
}
|
|
|
|
if (key == NULL) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
else {
|
|
ret = wc_SlhDsaKey_PublicSize(key);
|
|
}
|
|
|
|
if (ret < 0) {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
return 0;
|
|
}
|
|
return (jint)ret;
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
throwNotCompiledInException(env);
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1priv_1size
|
|
(JNIEnv* env, jobject this)
|
|
{
|
|
#if defined(WOLFSSL_HAVE_SLHDSA) && defined(WC_JNI_SLHDSA_HAVE_PRIV_KEY)
|
|
int ret = 0;
|
|
SlhDsaKey* key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return 0;
|
|
}
|
|
|
|
if (key == NULL) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
else {
|
|
ret = wc_SlhDsaKey_PrivateSize(key);
|
|
}
|
|
|
|
if (ret < 0) {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
return 0;
|
|
}
|
|
return (jint)ret;
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
throwNotCompiledInException(env);
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1sig_1size
|
|
(JNIEnv* env, jobject this)
|
|
{
|
|
#ifdef WOLFSSL_HAVE_SLHDSA
|
|
int ret = 0;
|
|
SlhDsaKey* key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return 0;
|
|
}
|
|
|
|
if (key == NULL) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
else {
|
|
ret = wc_SlhDsaKey_SigSize(key);
|
|
}
|
|
|
|
if (ret < 0) {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
return 0;
|
|
}
|
|
return (jint)ret;
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
throwNotCompiledInException(env);
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1check_1key
|
|
(JNIEnv* env, jobject this)
|
|
{
|
|
#if defined(WOLFSSL_HAVE_SLHDSA) && defined(WC_JNI_SLHDSA_HAVE_PRIV_KEY)
|
|
int ret = 0;
|
|
SlhDsaKey* key = NULL;
|
|
|
|
key = (SlhDsaKey*) getNativeStruct(env, this);
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
return;
|
|
}
|
|
|
|
if (key == NULL) {
|
|
ret = BAD_FUNC_ARG;
|
|
}
|
|
else {
|
|
ret = wc_SlhDsaKey_CheckKey(key);
|
|
}
|
|
|
|
if (ret != 0) {
|
|
throwWolfCryptExceptionFromError(env, ret);
|
|
}
|
|
|
|
LogStr("wc_SlhDsaKey_CheckKey(key=%p) = %d\n", key, ret);
|
|
#else
|
|
(void)env;
|
|
(void)this;
|
|
throwNotCompiledInException(env);
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_FeatureDetect_SlhDsaParamEnabled
|
|
(JNIEnv* env, jclass jcl, jint param)
|
|
{
|
|
(void)env;
|
|
(void)jcl;
|
|
#ifdef WOLFSSL_HAVE_SLHDSA
|
|
jboolean enabled = JNI_FALSE;
|
|
SlhDsaKey* key = NULL;
|
|
|
|
key = (SlhDsaKey*)XMALLOC(sizeof(SlhDsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (key != NULL) {
|
|
if (wc_SlhDsaKey_Init(key, (enum SlhDsaParam)param, NULL,
|
|
INVALID_DEVID) == 0) {
|
|
enabled = JNI_TRUE;
|
|
wc_SlhDsaKey_Free(key);
|
|
}
|
|
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
|
|
return enabled;
|
|
#else
|
|
(void)param;
|
|
return JNI_FALSE;
|
|
#endif
|
|
}
|