commit
a1f4cfac71
|
|
@ -20,8 +20,9 @@ verify_sha256() {
|
|||
elif command -v shasum >/dev/null; then
|
||||
actual=$(shasum -a 256 "$file" | awk '{print $1}')
|
||||
else
|
||||
echo "Warning: no sha256sum or shasum available, skipping hash verification"
|
||||
return 0
|
||||
echo "Error: no sha256sum or shasum found, refusing unverified $file"
|
||||
rm -f "$file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$actual" != "$expected" ]; then
|
||||
|
|
@ -40,6 +41,13 @@ download_bc_jars() {
|
|||
local lib_dir="$LIB_DIR"
|
||||
local bc_url="https://repo1.maven.org/maven2/org/bouncycastle"
|
||||
|
||||
# Require a SHA-256 tool before any download, JARs are only added to the
|
||||
# classpath after hash verification
|
||||
if ! command -v sha256sum >/dev/null && ! command -v shasum >/dev/null; then
|
||||
echo "failed (no sha256sum or shasum for hash verification)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo -n "Downloading Bouncy Castle JARs (version $bc_version)... "
|
||||
mkdir -p "$lib_dir" || {
|
||||
echo "failed (cannot create $lib_dir)"
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ Java_com_wolfssl_wolfcrypt_Aes_native_1set_1key_1internal(
|
|||
byte* key = NULL;
|
||||
byte* iv = NULL;
|
||||
word32 keySz = 0;
|
||||
word32 ivSz = 0;
|
||||
|
||||
aes = (Aes*) getNativeStruct(env, this);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
|
|
@ -109,10 +110,15 @@ Java_com_wolfssl_wolfcrypt_Aes_native_1set_1key_1internal(
|
|||
key = getByteArray(env, key_object);
|
||||
iv = getByteArray(env, iv_object);
|
||||
keySz = getByteArrayLength(env, key_object);
|
||||
ivSz = getByteArrayLength(env, iv_object);
|
||||
|
||||
ret = (!aes || !key) /* iv is optional */
|
||||
? BAD_FUNC_ARG
|
||||
: wc_AesSetKey(aes, key, keySz, iv, opmode);
|
||||
/* IV optional. If provided, reject under/oversized array. */
|
||||
if (!aes || !key || (iv != NULL && ivSz != AES_BLOCK_SIZE)) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
else {
|
||||
ret = wc_AesSetKey(aes, key, keySz, iv, opmode);
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
throwWolfCryptExceptionFromError(env, ret);
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ Java_com_wolfssl_wolfcrypt_AesCtr_native_1set_1key_1internal(
|
|||
byte* key = NULL;
|
||||
byte* iv = NULL;
|
||||
word32 keySz = 0;
|
||||
word32 ivSz = 0;
|
||||
|
||||
aes = (Aes*) getNativeStruct(env, this);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
|
|
@ -108,8 +109,10 @@ Java_com_wolfssl_wolfcrypt_AesCtr_native_1set_1key_1internal(
|
|||
key = getByteArray(env, key_object);
|
||||
iv = getByteArray(env, iv_object);
|
||||
keySz = getByteArrayLength(env, key_object);
|
||||
ivSz = getByteArrayLength(env, iv_object);
|
||||
|
||||
if (aes == NULL || key == NULL || iv == NULL) {
|
||||
/* wc_AesSetKey reads AES_BLOCK_SIZE IV bytes, reject a short array */
|
||||
if (aes == NULL || key == NULL || iv == NULL || ivSz != AES_BLOCK_SIZE) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ Java_com_wolfssl_wolfcrypt_AesOfb_native_1set_1key_1internal(
|
|||
byte* key = NULL;
|
||||
byte* iv = NULL;
|
||||
word32 keySz = 0;
|
||||
word32 ivSz = 0;
|
||||
(void)opmode;
|
||||
|
||||
aes = (Aes*) getNativeStruct(env, this);
|
||||
|
|
@ -110,8 +111,10 @@ Java_com_wolfssl_wolfcrypt_AesOfb_native_1set_1key_1internal(
|
|||
key = getByteArray(env, key_object);
|
||||
iv = getByteArray(env, iv_object);
|
||||
keySz = getByteArrayLength(env, key_object);
|
||||
ivSz = getByteArrayLength(env, iv_object);
|
||||
|
||||
if (aes == NULL || key == NULL || iv == NULL) {
|
||||
/* wc_AesSetKey reads AES_BLOCK_SIZE IV bytes, reject a short array */
|
||||
if (aes == NULL || key == NULL || iv == NULL || ivSz != AES_BLOCK_SIZE) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1setIV
|
|||
int ret = 0;
|
||||
ChaCha* chacha = NULL;
|
||||
byte* iv = NULL;
|
||||
word32 ivSz = 0;
|
||||
|
||||
chacha = (ChaCha*)(uintptr_t)getNativeStruct(env, this);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
|
|
@ -79,8 +80,9 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1setIV
|
|||
return;
|
||||
}
|
||||
iv = getByteArray(env, iv_object);
|
||||
ivSz = getByteArrayLength(env, iv_object);
|
||||
|
||||
if (chacha == NULL || iv == NULL) {
|
||||
if (chacha == NULL || iv == NULL || ivSz != CHACHA_IV_BYTES) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
|
|
@ -107,13 +109,16 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1setKey
|
|||
ChaCha* chacha = NULL;
|
||||
byte* key = NULL;
|
||||
word32 keySz = 0;
|
||||
jboolean keyIsCopy = JNI_FALSE;
|
||||
|
||||
chacha = (ChaCha*)(uintptr_t)getNativeStruct(env, this);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
/* getNativeStruct may throw exception, prevent throwing another */
|
||||
return;
|
||||
}
|
||||
key = getByteArray(env, key_object);
|
||||
if (key_object != NULL) {
|
||||
key = (byte*)(*env)->GetByteArrayElements(env, key_object, &keyIsCopy);
|
||||
}
|
||||
keySz = getByteArrayLength(env, key_object);
|
||||
|
||||
if (chacha == NULL || key == NULL) {
|
||||
|
|
@ -129,6 +134,14 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1setKey
|
|||
|
||||
LogStr("wc_Chacha_SetKey(chacha=%p) = %d\n", chacha, ret);
|
||||
|
||||
if (key != NULL && keyIsCopy == JNI_TRUE) {
|
||||
#if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \
|
||||
!defined(WOLFSSL_NO_FORCE_ZERO)
|
||||
wc_ForceZero(key, keySz);
|
||||
#else
|
||||
XMEMSET(key, 0, keySz);
|
||||
#endif
|
||||
}
|
||||
releaseByteArray(env, key_object, key, JNI_ABORT);
|
||||
#else
|
||||
throwNotCompiledInException(env);
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ Java_com_wolfssl_wolfcrypt_Des3_native_1set_1key_1internal(
|
|||
byte* key = NULL;
|
||||
byte* iv = NULL;
|
||||
word32 keySz = 0;
|
||||
word32 ivSz = 0;
|
||||
jboolean keyIsCopy = JNI_FALSE;
|
||||
|
||||
des = (Des3*) getNativeStruct(env, this);
|
||||
|
|
@ -109,10 +110,15 @@ Java_com_wolfssl_wolfcrypt_Des3_native_1set_1key_1internal(
|
|||
key = getByteArrayIsCopy(env, key_object, &keyIsCopy);
|
||||
keySz = getByteArrayLength(env, key_object);
|
||||
iv = getByteArray(env, iv_object);
|
||||
ivSz = getByteArrayLength(env, iv_object);
|
||||
|
||||
ret = (!des || !key) /* iv is optional */
|
||||
? BAD_FUNC_ARG
|
||||
: wc_Des3_SetKey(des, key, iv, opmode);
|
||||
if (!des || !key || keySz != DES3_KEY_SIZE ||
|
||||
(iv != NULL && ivSz != DES_BLOCK_SIZE)) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
else {
|
||||
ret = wc_Des3_SetKey(des, key, iv, opmode);
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
throwWolfCryptExceptionFromError(env, ret);
|
||||
|
|
|
|||
|
|
@ -767,13 +767,16 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1dilithium_1import_1p
|
|||
wc_MlDsaKey* key = NULL;
|
||||
byte* in = NULL;
|
||||
word32 inLen = 0;
|
||||
jboolean inIsCopy = JNI_FALSE;
|
||||
|
||||
key = (wc_MlDsaKey*) getNativeStruct(env, this);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
return;
|
||||
}
|
||||
|
||||
in = getByteArray(env, in_object);
|
||||
if (in_object != NULL) {
|
||||
in = (byte*)(*env)->GetByteArrayElements(env, in_object, &inIsCopy);
|
||||
}
|
||||
inLen = getByteArrayLength(env, in_object);
|
||||
|
||||
if (key == NULL || in == NULL) {
|
||||
|
|
@ -789,6 +792,9 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1dilithium_1import_1p
|
|||
|
||||
LogStr("wc_MlDsaKey_ImportPrivRaw(key=%p) = %d\n", key, ret);
|
||||
|
||||
if (in != NULL && inIsCopy == JNI_TRUE) {
|
||||
MLDSA_FORCE_ZERO(in, inLen);
|
||||
}
|
||||
releaseByteArray(env, in_object, in, JNI_ABORT);
|
||||
#else
|
||||
(void)env;
|
||||
|
|
@ -1132,13 +1138,17 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1dilithium_1make_1key
|
|||
wc_MlDsaKey* key = NULL;
|
||||
byte* seed = NULL;
|
||||
word32 seedLen = 0;
|
||||
jboolean seedIsCopy = JNI_FALSE;
|
||||
|
||||
key = (wc_MlDsaKey*) getNativeStruct(env, this);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
return;
|
||||
}
|
||||
|
||||
seed = getByteArray(env, seed_object);
|
||||
if (seed_object != NULL) {
|
||||
seed = (byte*)(*env)->GetByteArrayElements(env, seed_object,
|
||||
&seedIsCopy);
|
||||
}
|
||||
seedLen = getByteArrayLength(env, seed_object);
|
||||
|
||||
/* Native API takes no seed length, seed must be exactly 32 bytes */
|
||||
|
|
@ -1158,6 +1168,9 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1dilithium_1make_1key
|
|||
|
||||
LogStr("wc_MlDsaKey_MakeKeyFromSeed(key=%p) = %d\n", key, ret);
|
||||
|
||||
if (seed != NULL && seedIsCopy == JNI_TRUE) {
|
||||
MLDSA_FORCE_ZERO(seed, seedLen);
|
||||
}
|
||||
releaseByteArray(env, seed_object, seed, JNI_ABORT);
|
||||
#else
|
||||
(void)env;
|
||||
|
|
@ -1305,6 +1318,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1dilithium_1sig
|
|||
word32 msgLen = 0;
|
||||
word32 seedLen = 0;
|
||||
word32 sigLen = 0;
|
||||
jboolean seedIsCopy = JNI_FALSE;
|
||||
|
||||
key = (wc_MlDsaKey*) getNativeStruct(env, this);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
|
|
@ -1328,7 +1342,8 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1dilithium_1sig
|
|||
}
|
||||
|
||||
if (seed_object != NULL) {
|
||||
seed = getByteArray(env, seed_object);
|
||||
seed = (byte*)(*env)->GetByteArrayElements(env, seed_object,
|
||||
&seedIsCopy);
|
||||
seedLen = getByteArrayLength(env, seed_object);
|
||||
}
|
||||
|
||||
|
|
@ -1345,6 +1360,9 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1dilithium_1sig
|
|||
releaseByteArray(env, msg_object, msg, JNI_ABORT);
|
||||
}
|
||||
if (seed != NULL) {
|
||||
if (seedIsCopy == JNI_TRUE) {
|
||||
MLDSA_FORCE_ZERO(seed, seedLen);
|
||||
}
|
||||
releaseByteArray(env, seed_object, seed, JNI_ABORT);
|
||||
}
|
||||
return NULL;
|
||||
|
|
@ -1409,6 +1427,9 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1dilithium_1sig
|
|||
releaseByteArray(env, msg_object, msg, JNI_ABORT);
|
||||
}
|
||||
if (seed_object != NULL) {
|
||||
if (seed != NULL && seedIsCopy == JNI_TRUE) {
|
||||
MLDSA_FORCE_ZERO(seed, seedLen);
|
||||
}
|
||||
releaseByteArray(env, seed_object, seed, JNI_ABORT);
|
||||
}
|
||||
#else
|
||||
|
|
@ -1439,6 +1460,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1dilithium_1sig
|
|||
word32 hashLen = 0;
|
||||
word32 seedLen = 0;
|
||||
word32 sigLen = 0;
|
||||
jboolean seedIsCopy = JNI_FALSE;
|
||||
|
||||
key = (wc_MlDsaKey*) getNativeStruct(env, this);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
|
|
@ -1462,7 +1484,8 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1dilithium_1sig
|
|||
}
|
||||
|
||||
if (seed_object != NULL) {
|
||||
seed = getByteArray(env, seed_object);
|
||||
seed = (byte*)(*env)->GetByteArrayElements(env, seed_object,
|
||||
&seedIsCopy);
|
||||
seedLen = getByteArrayLength(env, seed_object);
|
||||
}
|
||||
|
||||
|
|
@ -1479,6 +1502,9 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1dilithium_1sig
|
|||
releaseByteArray(env, hash_object, hash, JNI_ABORT);
|
||||
}
|
||||
if (seed != NULL) {
|
||||
if (seedIsCopy == JNI_TRUE) {
|
||||
MLDSA_FORCE_ZERO(seed, seedLen);
|
||||
}
|
||||
releaseByteArray(env, seed_object, seed, JNI_ABORT);
|
||||
}
|
||||
return NULL;
|
||||
|
|
@ -1543,6 +1569,9 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1dilithium_1sig
|
|||
releaseByteArray(env, hash_object, hash, JNI_ABORT);
|
||||
}
|
||||
if (seed_object != NULL) {
|
||||
if (seed != NULL && seedIsCopy == JNI_TRUE) {
|
||||
MLDSA_FORCE_ZERO(seed, seedLen);
|
||||
}
|
||||
releaseByteArray(env, seed_object, seed, JNI_ABORT);
|
||||
}
|
||||
#else
|
||||
|
|
@ -1673,6 +1702,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1MlDsaKey_1Sign
|
|||
word32 muLen = 0;
|
||||
word32 seedLen = 0;
|
||||
word32 sigLen = 0;
|
||||
jboolean seedIsCopy = JNI_FALSE;
|
||||
|
||||
key = (wc_MlDsaKey*) getNativeStruct(env, this);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
|
|
@ -1690,7 +1720,8 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1MlDsaKey_1Sign
|
|||
}
|
||||
|
||||
if (seed_object != NULL) {
|
||||
seed = getByteArray(env, seed_object);
|
||||
seed = (byte*)(*env)->GetByteArrayElements(env, seed_object,
|
||||
&seedIsCopy);
|
||||
seedLen = getByteArrayLength(env, seed_object);
|
||||
}
|
||||
|
||||
|
|
@ -1703,6 +1734,9 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1MlDsaKey_1Sign
|
|||
releaseByteArray(env, mu_object, mu, JNI_ABORT);
|
||||
}
|
||||
if (seed != NULL) {
|
||||
if (seedIsCopy == JNI_TRUE) {
|
||||
MLDSA_FORCE_ZERO(seed, seedLen);
|
||||
}
|
||||
releaseByteArray(env, seed_object, seed, JNI_ABORT);
|
||||
}
|
||||
return NULL;
|
||||
|
|
@ -1758,6 +1792,9 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1MlDsaKey_1Sign
|
|||
releaseByteArray(env, mu_object, mu, JNI_ABORT);
|
||||
}
|
||||
if (seed_object != NULL) {
|
||||
if (seed != NULL && seedIsCopy == JNI_TRUE) {
|
||||
MLDSA_FORCE_ZERO(seed, seedLen);
|
||||
}
|
||||
releaseByteArray(env, seed_object, seed, JNI_ABORT);
|
||||
}
|
||||
#else
|
||||
|
|
@ -1859,13 +1896,17 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1dilithium_1import_1k
|
|||
byte* pub = NULL;
|
||||
word32 privLen = 0;
|
||||
word32 pubLen = 0;
|
||||
jboolean privIsCopy = JNI_FALSE;
|
||||
|
||||
key = (wc_MlDsaKey*) getNativeStruct(env, this);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
return;
|
||||
}
|
||||
|
||||
priv = getByteArray(env, priv_object);
|
||||
if (priv_object != NULL) {
|
||||
priv = (byte*)(*env)->GetByteArrayElements(env, priv_object,
|
||||
&privIsCopy);
|
||||
}
|
||||
privLen = getByteArrayLength(env, priv_object);
|
||||
pub = getByteArray(env, pub_object);
|
||||
pubLen = getByteArrayLength(env, pub_object);
|
||||
|
|
@ -1883,6 +1924,9 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_MlDsa_wc_1dilithium_1import_1k
|
|||
|
||||
LogStr("wc_MlDsaKey_ImportKey(key=%p) = %d\n", key, ret);
|
||||
|
||||
if (priv != NULL && privIsCopy == JNI_TRUE) {
|
||||
MLDSA_FORCE_ZERO(priv, privLen);
|
||||
}
|
||||
releaseByteArray(env, priv_object, priv, JNI_ABORT);
|
||||
releaseByteArray(env, pub_object, pub, JNI_ABORT);
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -1016,7 +1016,7 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPrivateDecrypt(
|
|||
RsaKey* key = NULL;
|
||||
byte* ciphertext = NULL;
|
||||
byte* output = NULL;
|
||||
word32 size = 0, outputSz = 0;
|
||||
word32 size = 0, outputSz = 0, outputBufSz = 0;
|
||||
int encSz = 0;
|
||||
|
||||
key = (RsaKey*) getNativeStruct(env, this);
|
||||
|
|
@ -1041,6 +1041,9 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPrivateDecrypt(
|
|||
ret = BAD_FUNC_ARG;
|
||||
} else {
|
||||
outputSz = (word32)encSz;
|
||||
/* Keep full allocation size for zeroization, outputSz shrinks
|
||||
* to plaintext len after decrypt */
|
||||
outputBufSz = outputSz;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1081,9 +1084,9 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPrivateDecrypt(
|
|||
if (output != NULL) {
|
||||
#if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \
|
||||
!defined(WOLFSSL_NO_FORCE_ZERO)
|
||||
wc_ForceZero(output, outputSz);
|
||||
wc_ForceZero(output, outputBufSz);
|
||||
#else
|
||||
XMEMSET(output, 0, outputSz);
|
||||
XMEMSET(output, 0, outputBufSz);
|
||||
#endif
|
||||
XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
|
|
@ -1207,7 +1210,7 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPrivateDecrypt_1ex(
|
|||
RsaKey* key = NULL;
|
||||
byte* ciphertext = NULL;
|
||||
byte* output = NULL;
|
||||
word32 size = 0, outputSz = 0;
|
||||
word32 size = 0, outputSz = 0, outputBufSz = 0;
|
||||
int encSz = 0;
|
||||
|
||||
key = (RsaKey*) getNativeStruct(env, this);
|
||||
|
|
@ -1237,6 +1240,9 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPrivateDecrypt_1ex(
|
|||
ret = BAD_FUNC_ARG;
|
||||
} else {
|
||||
outputSz = (word32)encSz;
|
||||
/* Keep full allocation size for zeroization, outputSz shrinks to
|
||||
* the plaintext len after decrypt */
|
||||
outputBufSz = outputSz;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1277,9 +1283,9 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPrivateDecrypt_1ex(
|
|||
if (output != NULL) {
|
||||
#if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \
|
||||
!defined(WOLFSSL_NO_FORCE_ZERO)
|
||||
wc_ForceZero(output, outputSz);
|
||||
wc_ForceZero(output, outputBufSz);
|
||||
#else
|
||||
XMEMSET(output, 0, outputSz);
|
||||
XMEMSET(output, 0, outputBufSz);
|
||||
#endif
|
||||
XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1748,8 +1748,20 @@ public class WolfCryptCipher extends CipherSpi {
|
|||
tmpIn = Arrays.copyOfRange(tmpIn, 0,
|
||||
tmpIn.length - this.gcmTagLen);
|
||||
|
||||
tmpOut = this.aesCcm.decrypt(tmpIn, this.iv, tag,
|
||||
aad);
|
||||
try {
|
||||
tmpOut = this.aesCcm.decrypt(tmpIn, this.iv,
|
||||
tag, aad);
|
||||
|
||||
} catch (WolfCryptException e) {
|
||||
/* Convert to AEADBadTagException */
|
||||
if (e.getCode() ==
|
||||
WolfCryptError.AES_CCM_AUTH_E.getCode()) {
|
||||
/* Authentication check fail */
|
||||
throw new AEADBadTagException(
|
||||
e.getMessage());
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cipherMode == CipherMode.WC_ECB) {
|
||||
|
|
|
|||
|
|
@ -295,6 +295,9 @@ public class WolfCryptDHKeyFactory extends KeyFactorySpi {
|
|||
"Private key value must be positive");
|
||||
}
|
||||
|
||||
/* Reject a prime below the minimum wolfCrypt will generate */
|
||||
checkDhPrimeSize(keySpec.getP());
|
||||
|
||||
try {
|
||||
/* Create DHParameterSpec from p and g */
|
||||
DHParameterSpec paramSpec = new DHParameterSpec(
|
||||
|
|
@ -311,6 +314,26 @@ public class WolfCryptDHKeyFactory extends KeyFactorySpi {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforce a minimum DH prime size on imported keys.
|
||||
*
|
||||
* wolfCrypt does not generate DH keys below DH_MIN_SIZE, so accepting a
|
||||
* smaller prime on import would allow a group weaker than any wolfJCE
|
||||
* produces. Reject those at the KeyFactory boundary.
|
||||
*
|
||||
* @param p DH prime modulus to check
|
||||
*
|
||||
* @throws InvalidKeySpecException if p has fewer than DH_MIN_SIZE bits
|
||||
*/
|
||||
private static void checkDhPrimeSize(BigInteger p)
|
||||
throws InvalidKeySpecException {
|
||||
|
||||
if (p.bitLength() < Dh.DH_MIN_SIZE) {
|
||||
throw new InvalidKeySpecException(
|
||||
"DH prime must be at least " + Dh.DH_MIN_SIZE + " bits");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Private helper method for generating DHPublicKey from
|
||||
* X509EncodedKeySpec.
|
||||
|
|
@ -403,6 +426,9 @@ public class WolfCryptDHKeyFactory extends KeyFactorySpi {
|
|||
"Public key out of valid range: must satisfy 1 < Y < p-1");
|
||||
}
|
||||
|
||||
/* Reject a prime below the minimum wolfCrypt will generate */
|
||||
checkDhPrimeSize(keySpec.getP());
|
||||
|
||||
try {
|
||||
/* Create DHParameterSpec from p and g */
|
||||
DHParameterSpec paramSpec = new DHParameterSpec(
|
||||
|
|
|
|||
|
|
@ -207,6 +207,12 @@ public class WolfCryptDHPrivateKey implements DHPrivateKey, Destroyable {
|
|||
p = new BigInteger(1, pBytes);
|
||||
idx += pLen;
|
||||
|
||||
/* Reject a prime below the minimum wolfCrypt will generate */
|
||||
if (p.bitLength() < Dh.DH_MIN_SIZE) {
|
||||
throw new IllegalArgumentException(
|
||||
"DH prime must be at least " + Dh.DH_MIN_SIZE + " bits");
|
||||
}
|
||||
|
||||
/* g INTEGER */
|
||||
if (derData[idx++] != 0x02) {
|
||||
throw new IllegalArgumentException(
|
||||
|
|
|
|||
|
|
@ -250,6 +250,12 @@ public class WolfCryptDHPublicKey implements DHPublicKey, Destroyable {
|
|||
"must satisfy 1 < Y < p-1");
|
||||
}
|
||||
|
||||
/* Reject a prime below the minimum wolfCrypt will generate */
|
||||
if (p.bitLength() < Dh.DH_MIN_SIZE) {
|
||||
throw new IllegalArgumentException(
|
||||
"DH prime must be at least " + Dh.DH_MIN_SIZE + " bits");
|
||||
}
|
||||
|
||||
/* Store extracted values */
|
||||
this.publicValue = publicVal;
|
||||
this.paramSpec = new DHParameterSpec(p, g);
|
||||
|
|
|
|||
|
|
@ -182,7 +182,10 @@ public class Hmac extends NativeStruct {
|
|||
|
||||
this.type = type;
|
||||
|
||||
/* Save copy of key[] into this.key */
|
||||
/* Save copy of key[] into this.key, zero old one first */
|
||||
if (this.key != null) {
|
||||
Arrays.fill(this.key, (byte)0);
|
||||
}
|
||||
this.key = new byte[key.length];
|
||||
System.arraycopy(key, 0, this.key, 0, key.length);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3053,6 +3053,69 @@ public class WolfCryptCipherTest {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AES-CCM decrypt failure should throw AEADBadTagException.
|
||||
*/
|
||||
@Test
|
||||
public void testAesCcmBadTagExceptionRegression()
|
||||
throws NoSuchProviderException, NoSuchAlgorithmException,
|
||||
NoSuchPaddingException, InvalidKeyException,
|
||||
IllegalBlockSizeException, InvalidAlgorithmParameterException,
|
||||
BadPaddingException {
|
||||
|
||||
if (!enabledJCEAlgos.contains("AES/CCM/NoPadding")) {
|
||||
/* skip if AES-CCM is not enabled */
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] key = new byte[] {
|
||||
(byte)0x2b, (byte)0x7e, (byte)0x15, (byte)0x16,
|
||||
(byte)0x28, (byte)0xae, (byte)0xd2, (byte)0xa6,
|
||||
(byte)0xab, (byte)0xf7, (byte)0x15, (byte)0x88,
|
||||
(byte)0x09, (byte)0xcf, (byte)0x4f, (byte)0x3c
|
||||
};
|
||||
|
||||
byte[] nonce = new byte[] {
|
||||
(byte)0x00, (byte)0x01, (byte)0x02, (byte)0x03,
|
||||
(byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07,
|
||||
(byte)0x08, (byte)0x09, (byte)0x0a, (byte)0x0b
|
||||
};
|
||||
|
||||
byte[] plaintext = new byte[] {
|
||||
(byte)0x48, (byte)0x65, (byte)0x6c, (byte)0x6c,
|
||||
(byte)0x6f, (byte)0x20, (byte)0x57, (byte)0x6f,
|
||||
(byte)0x72, (byte)0x6c, (byte)0x64, (byte)0x21
|
||||
};
|
||||
|
||||
Cipher cipher = Cipher.getInstance("AES/CCM/NoPadding", jceProvider);
|
||||
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
|
||||
GCMParameterSpec ccmSpec = new GCMParameterSpec(128, nonce);
|
||||
|
||||
/* First encrypt to get valid ciphertext */
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ccmSpec);
|
||||
byte[] ciphertext = cipher.doFinal(plaintext);
|
||||
|
||||
/* Corrupt the authentication tag (last 16 bytes) */
|
||||
byte[] corruptedCiphertext = ciphertext.clone();
|
||||
int tagStart = corruptedCiphertext.length - 16;
|
||||
for (int i = tagStart; i < corruptedCiphertext.length; i++) {
|
||||
corruptedCiphertext[i] = (byte)0xFF;
|
||||
}
|
||||
|
||||
/* Attempt to decrypt with corrupted tag, should throw
|
||||
* AEADBadTagException */
|
||||
cipher.init(Cipher.DECRYPT_MODE, keySpec, ccmSpec);
|
||||
try {
|
||||
cipher.doFinal(corruptedCiphertext);
|
||||
fail("Expected AEADBadTagException for corrupted CCM tag");
|
||||
} catch (AEADBadTagException e) {
|
||||
/* Expected */
|
||||
} catch (Exception e) {
|
||||
fail("Expected AEADBadTagException but got: " +
|
||||
e.getClass().getSimpleName() + " - " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAesEcbNoPadding()
|
||||
throws NoSuchProviderException, NoSuchAlgorithmException,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import java.math.BigInteger;
|
|||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.Provider;
|
||||
|
|
@ -53,6 +54,8 @@ import org.junit.Test;
|
|||
import com.wolfssl.provider.jce.WolfCryptProvider;
|
||||
import java.lang.reflect.Field;
|
||||
import com.wolfssl.provider.jce.WolfCryptDHPublicKey;
|
||||
import com.wolfssl.provider.jce.WolfCryptDHPrivateKey;
|
||||
import com.wolfssl.wolfcrypt.Dh;
|
||||
import com.wolfssl.wolfcrypt.FeatureDetect;
|
||||
import com.wolfssl.wolfcrypt.test.TimedTestWatcher;
|
||||
|
||||
|
|
@ -443,6 +446,68 @@ public class WolfCryptDHKeyFactoryTest {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A prime below Dh.DH_MIN_SIZE, the floor wolfCrypt uses when generating
|
||||
* DH keys, must be rejected on import so the KeyFactory doesn't accept a
|
||||
* group weaker than one wolfJCE produces.
|
||||
*/
|
||||
@Test
|
||||
public void testWeakPrimeRejected() throws Exception {
|
||||
|
||||
Assume.assumeTrue(FeatureDetect.DhEnabled());
|
||||
|
||||
KeyFactory kf = KeyFactory.getInstance("DH", "wolfJCE");
|
||||
|
||||
/* Prime one bit below the enforced minimum, this is not a real
|
||||
* DH prime but only the bit length is checked at intake */
|
||||
BigInteger weakP = BigInteger.ONE.shiftLeft(Dh.DH_MIN_SIZE - 2);
|
||||
BigInteger g = BigInteger.valueOf(2);
|
||||
BigInteger y = BigInteger.valueOf(3);
|
||||
BigInteger x = BigInteger.valueOf(3);
|
||||
|
||||
try {
|
||||
kf.generatePublic(new DHPublicKeySpec(y, weakP, g));
|
||||
fail("weak DH prime should be rejected on public key import");
|
||||
} catch (InvalidKeySpecException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
try {
|
||||
kf.generatePrivate(new DHPrivateKeySpec(x, weakP, g));
|
||||
fail("weak DH prime should be rejected on private key import");
|
||||
} catch (InvalidKeySpecException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
/* Build weak-prime DER via the raw key constructors (which do not
|
||||
* validate) and confirm the X.509 and PKCS#8 DER import paths and
|
||||
* translateKey all reject it */
|
||||
DHParameterSpec weakParams = new DHParameterSpec(weakP, g);
|
||||
byte[] pubDer = new WolfCryptDHPublicKey(y, weakParams).getEncoded();
|
||||
byte[] privDer = new WolfCryptDHPrivateKey(x, weakParams).getEncoded();
|
||||
|
||||
try {
|
||||
kf.generatePublic(new X509EncodedKeySpec(pubDer));
|
||||
fail("weak DH prime should be rejected on X.509 import");
|
||||
} catch (InvalidKeySpecException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
try {
|
||||
kf.generatePrivate(new PKCS8EncodedKeySpec(privDer));
|
||||
fail("weak DH prime should be rejected on PKCS#8 import");
|
||||
} catch (InvalidKeySpecException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
try {
|
||||
kf.translateKey(new WolfCryptDHPublicKey(y, weakParams));
|
||||
fail("weak DH prime should be rejected on translateKey");
|
||||
} catch (InvalidKeyException e) {
|
||||
/* expected */
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidKeySpecs() throws Exception {
|
||||
|
||||
|
|
|
|||
|
|
@ -125,6 +125,21 @@ public class AesCtrTest {
|
|||
/* test must throw */
|
||||
}
|
||||
|
||||
/* wc_AesSetKey reads AES block size iv bytes, reject a short iv */
|
||||
try {
|
||||
aesCtr.setKey(KEY_128, new byte[1]);
|
||||
fail("undersized iv should be rejected.");
|
||||
} catch (WolfCryptException e) {
|
||||
/* test must throw */
|
||||
}
|
||||
|
||||
try {
|
||||
aesCtr.setKey(KEY_128, new byte[AesCtr.BLOCK_SIZE + 1]);
|
||||
fail("oversized iv should be rejected.");
|
||||
} catch (WolfCryptException e) {
|
||||
/* test must throw */
|
||||
}
|
||||
|
||||
aesCtr.setKey(KEY_128, IV_128);
|
||||
aesCtr.releaseNativeStruct();
|
||||
|
||||
|
|
|
|||
|
|
@ -135,6 +135,21 @@ public class AesOfbTest {
|
|||
/* test must throw */
|
||||
}
|
||||
|
||||
/* wc_AesSetKey reads AES block size iv bytes, reject a short iv */
|
||||
try {
|
||||
aesOfb.setKey(KEY_128, new byte[1]);
|
||||
fail("undersized iv should be rejected.");
|
||||
} catch (WolfCryptException e) {
|
||||
/* test must throw */
|
||||
}
|
||||
|
||||
try {
|
||||
aesOfb.setKey(KEY_128, new byte[AesOfb.BLOCK_SIZE + 1]);
|
||||
fail("oversized iv should be rejected.");
|
||||
} catch (WolfCryptException e) {
|
||||
/* test must throw */
|
||||
}
|
||||
|
||||
aesOfb.setKey(KEY_128, IV_128);
|
||||
aesOfb.releaseNativeStruct();
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,22 @@ public class AesTest {
|
|||
/* test must throw */
|
||||
}
|
||||
|
||||
/* iv is optional, but a non-null iv must be the block size,
|
||||
* wc_AesSetKey reads AES_BLOCK_SIZE bytes */
|
||||
try {
|
||||
aes.setKey(KEY, new byte[1], Aes.ENCRYPT_MODE);
|
||||
fail("undersized iv should be rejected.");
|
||||
} catch (WolfCryptException e) {
|
||||
/* test must throw */
|
||||
}
|
||||
|
||||
try {
|
||||
aes.setKey(KEY, new byte[Aes.BLOCK_SIZE + 1], Aes.ENCRYPT_MODE);
|
||||
fail("oversized iv should be rejected.");
|
||||
} catch (WolfCryptException e) {
|
||||
/* test must throw */
|
||||
}
|
||||
|
||||
aes.setKey(KEY, IV, Aes.ENCRYPT_MODE);
|
||||
aes.releaseNativeStruct();
|
||||
|
||||
|
|
|
|||
|
|
@ -132,6 +132,22 @@ public class ChachaTest {
|
|||
/* test must throw */
|
||||
}
|
||||
|
||||
/* IV shorter than 12 bytes should be rejected */
|
||||
try {
|
||||
chacha.setIV(new byte[4]);
|
||||
fail("IV shorter than 12 bytes should be rejected.");
|
||||
} catch (WolfCryptException e) {
|
||||
/* test must throw */
|
||||
}
|
||||
|
||||
/* An IV longer than 12 bytes is not a valid ChaCha nonce */
|
||||
try {
|
||||
chacha.setIV(new byte[16]);
|
||||
fail("IV longer than 12 bytes should be rejected.");
|
||||
} catch (WolfCryptException e) {
|
||||
/* test must throw */
|
||||
}
|
||||
|
||||
chacha.setIV(IV);
|
||||
chacha.releaseNativeStruct();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,6 +99,48 @@ public class Des3Test {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkSetKeyParams() {
|
||||
byte[] key = Util.h2b(
|
||||
"e61a38548694f1fd8cef251c518cc70bb613751c1ce52aa8");
|
||||
byte[] iv = Util.h2b("48a8ceb8551fd4ad");
|
||||
|
||||
Des3 des = new Des3();
|
||||
|
||||
/* wc_Des3_SetKey reads full 24 byte key, reject a short/long key */
|
||||
try {
|
||||
des.setKey(new byte[1], iv, Des3.ENCRYPT_MODE);
|
||||
fail("undersized key should be rejected.");
|
||||
} catch (WolfCryptException e) {
|
||||
/* test must throw */
|
||||
}
|
||||
|
||||
try {
|
||||
des.setKey(new byte[Des3.KEY_SIZE + 1], iv, Des3.ENCRYPT_MODE);
|
||||
fail("oversized key should be rejected.");
|
||||
} catch (WolfCryptException e) {
|
||||
/* test must throw */
|
||||
}
|
||||
|
||||
/* IV is optional, but non-null iv must be the block size */
|
||||
try {
|
||||
des.setKey(key, new byte[1], Des3.ENCRYPT_MODE);
|
||||
fail("undersized iv should be rejected.");
|
||||
} catch (WolfCryptException e) {
|
||||
/* test must throw */
|
||||
}
|
||||
|
||||
try {
|
||||
des.setKey(key, new byte[Des3.BLOCK_SIZE + 1], Des3.ENCRYPT_MODE);
|
||||
fail("oversized iv should be rejected.");
|
||||
} catch (WolfCryptException e) {
|
||||
/* test must throw */
|
||||
}
|
||||
|
||||
des.setKey(key, iv, Des3.ENCRYPT_MODE);
|
||||
des.releaseNativeStruct();
|
||||
}
|
||||
|
||||
@Test(expected=ShortBufferException.class)
|
||||
public void updateShouldMatchUsingByteByffer() throws ShortBufferException {
|
||||
String[] keys = new String[] {
|
||||
|
|
|
|||
Loading…
Reference in New Issue