diff --git a/README_JCE.md b/README_JCE.md index adc3f5e..ac8db06 100644 --- a/README_JCE.md +++ b/README_JCE.md @@ -65,6 +65,7 @@ The JCE provider currently supports the following algorithms: ECDH KeyPairGenerator Class + RSA EC DH diff --git a/jni/include/com_wolfssl_wolfcrypt_Rsa.h b/jni/include/com_wolfssl_wolfcrypt_Rsa.h index dce6a68..b75d427 100644 --- a/jni/include/com_wolfssl_wolfcrypt_Rsa.h +++ b/jni/include/com_wolfssl_wolfcrypt_Rsa.h @@ -57,6 +57,30 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Rsa_RsaFlattenPublicKey___3B_3 JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Rsa_MakeRsaKey (JNIEnv *, jobject, jint, jlong, jobject); +/* + * Class: com_wolfssl_wolfcrypt_Rsa + * Method: wc_RsaKeyToDer + * Signature: ()[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaKeyToDer + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Rsa + * Method: wc_RsaKeyToPublicDer + * Signature: ()[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaKeyToPublicDer + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Rsa + * Method: wc_RsaPrivateKeyToPkcs8 + * Signature: ()[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPrivateKeyToPkcs8 + (JNIEnv *, jobject); + /* * Class: com_wolfssl_wolfcrypt_Rsa * Method: wc_InitRsaKey @@ -145,6 +169,14 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaSSL_1Sign JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaSSL_1Verify (JNIEnv *, jobject, jbyteArray); +/* + * Class: com_wolfssl_wolfcrypt_Rsa + * Method: getDefaultRsaExponent + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Rsa_getDefaultRsaExponent + (JNIEnv *, jclass); + #ifdef __cplusplus } #endif diff --git a/jni/jni_rsa.c b/jni/jni_rsa.c index af7968a..1e78391 100644 --- a/jni/jni_rsa.c +++ b/jni/jni_rsa.c @@ -25,8 +25,10 @@ #include #endif #include +#include #include #include +#include #include #include @@ -43,20 +45,36 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Rsa_mallocNativeStruct( JNIEnv* env, jobject this) { - jlong ret = 0; + void* ret = NULL; #ifndef NO_RSA - ret = (jlong) XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); - - if (!ret) + ret = (void*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (ret == NULL) { throwOutOfMemoryException(env, "Failed to allocate Rsa object"); + } + else { + XMEMSET(ret, 0, sizeof(RsaKey)); + } LogStr("new Rsa() = %p\n", (void*)ret); #else throwNotCompiledInException(env); #endif - return ret; + return (jlong)ret; +} + +JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Rsa_getDefaultRsaExponent + (JNIEnv *env, jclass jcl) +{ + (void)env; + (void)jcl; + +#ifndef NO_RSA + return WC_RSA_EXPONENT; +#else + return 0; +#endif } JNIEXPORT void JNICALL @@ -87,10 +105,11 @@ Java_com_wolfssl_wolfcrypt_Rsa_MakeRsaKey( ret = wc_MakeRsaKey(key, size, (long)e, rng); } - if (ret != 0) + if (ret != 0) { throwWolfCryptExceptionFromError(env, ret); + } - LogStr("MakeRsaKey(%d, %lu) = %d\n", size, e, ret); + LogStr("wc_MakeRsaKey(%d, %lu) = %d\n", size, e, ret); #else throwNotCompiledInException(env); #endif @@ -123,8 +142,9 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPublicKeyDecodeRaw__Ljava_nio_ByteBuffer_2 ret = wc_RsaPublicKeyDecodeRaw(n, (long)nSize, e, (long)eSize, key); } - if (ret != 0) + if (ret != 0) { throwWolfCryptExceptionFromError(env, ret); + } LogStr("wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz) = %d\n", ret); LogStr("n[%u]: [%p]\n", (word32)nSize, n); @@ -163,8 +183,9 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPublicKeyDecodeRaw___3BJ_3BJ( ret = wc_RsaPublicKeyDecodeRaw(n, (long)nSize, e, (long)eSize, key); } - if (ret != 0) + if (ret != 0) { throwWolfCryptExceptionFromError(env, ret); + } LogStr("wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz) = %d\n", ret); LogStr("n[%u]: [%p]\n", (word32)nSize, n); @@ -201,9 +222,12 @@ Java_com_wolfssl_wolfcrypt_Rsa_RsaFlattenPublicKey__Ljava_nio_ByteBuffer_2Ljava_ nSize = n ? getDirectBufferLimit(env, n_object) : 0; eSize = e ? getDirectBufferLimit(env, e_object) : 0; - ret = (!key || !n || !e) - ? BAD_FUNC_ARG - : wc_RsaFlattenPublicKey(key, e, &eSize, n, &nSize); + if (key == NULL || n == NULL || e == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = wc_RsaFlattenPublicKey(key, e, &eSize, n, &nSize); + } if (ret != 0) { throwWolfCryptExceptionFromError(env, ret); @@ -220,7 +244,7 @@ Java_com_wolfssl_wolfcrypt_Rsa_RsaFlattenPublicKey__Ljava_nio_ByteBuffer_2Ljava_ } } - LogStr("RsaFlattenPublicKey(key, e, eSz, n, nSz) = %d\n", ret); + LogStr("wc_RsaFlattenPublicKey(key, e, eSz, n, nSz) = %d\n", ret); LogStr("n[%u]: [%p]\n", (word32)nSize, n); LogHex((byte*) n, 0, nSize); LogStr("e[%u]: [%p]\n", (word32)eSize, e); @@ -263,9 +287,12 @@ Java_com_wolfssl_wolfcrypt_Rsa_RsaFlattenPublicKey___3B_3J_3B_3J( return; } - ret = (!key || !n || !e) - ? BAD_FUNC_ARG - : wc_RsaFlattenPublicKey(key, e, (word32*) &eSz, n, (word32*) &nSz); + if (key == NULL || n == NULL || e == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = wc_RsaFlattenPublicKey(key, e, (word32*) &eSz, n, (word32*) &nSz); + } if (ret != 0) { throwWolfCryptExceptionFromError(env, ret); @@ -299,6 +326,270 @@ Java_com_wolfssl_wolfcrypt_Rsa_RsaFlattenPublicKey___3B_3J_3B_3J( #endif } +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaKeyToDer + (JNIEnv* env, jobject this) +{ + jbyteArray result = NULL; +#if !defined(NO_RSA) && (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) + int ret = 0; + RsaKey* key = NULL; + byte* output = NULL; + word32 outputSz = 0; + word32 outputBufSz = 0; + + key = (RsaKey*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + ret = BAD_FUNC_ARG; + } + + if (ret == 0 && key == NULL) { + ret = BAD_FUNC_ARG; + } + + /* Get length of DER encoded RSA private key */ + if (ret == 0) { + ret = wc_RsaKeyToDer(key, NULL, 0); + if (ret > 0) { + outputSz = ret; + outputBufSz = outputSz; + ret = 0; + } + } + + /* Allocate temp buffer to hold DER encoded key */ + if (ret == 0) { + output = (byte*)XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (output == NULL) { + ret = MEMORY_E; + } + } + + if (ret == 0) { + ret = wc_RsaKeyToDer(key, output, outputSz); + if (ret > 0) { + outputSz = ret; + ret = 0; + } + } + + if (ret == 0) { + result = (*env)->NewByteArray(env, outputSz); + + if (result) { + (*env)->SetByteArrayRegion(env, result, 0, outputSz, + (const jbyte*) output); + } else { + throwWolfCryptException(env, "Failed NewByteArray() for DER key"); + } + } else { + throwWolfCryptExceptionFromError(env, ret); + } + + LogStr("wc_RsaKeyToDer() = %d\n", ret); + LogStr("output[%u]: [%p]\n", outputSz, output); + LogHex((byte*) output, 0, outputSz); + + if (output != NULL) { + XMEMSET(output, 0, outputBufSz); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#else + throwNotCompiledInException(env); +#endif + + return result; +} + +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaKeyToPublicDer + (JNIEnv* env, jobject this) +{ + jbyteArray result = NULL; +#ifndef NO_RSA + int ret = 0; + RsaKey* key = NULL; + byte* output = NULL; + word32 outputSz = 0; + word32 outputBufSz = 0; + + key = (RsaKey*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + ret = BAD_FUNC_ARG; + } + + if (ret == 0 && key == NULL) { + ret = BAD_FUNC_ARG; + } + + /* Get length of DER encoded RSA private key */ + if (ret == 0) { + ret = wc_RsaKeyToPublicDer(key, NULL, 0); + if (ret > 0) { + outputSz = ret; + outputBufSz = outputSz; + ret = 0; + } + } + + /* Allocate temp buffer to hold DER encoded key */ + if (ret == 0) { + output = (byte*)XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (output == NULL) { + ret = MEMORY_E; + } + } + + if (ret == 0) { + ret = wc_RsaKeyToPublicDer(key, output, outputSz); + if (ret > 0) { + outputSz = ret; + ret = 0; + } + } + + if (ret == 0) { + result = (*env)->NewByteArray(env, outputSz); + if (result) { + (*env)->SetByteArrayRegion(env, result, 0, outputSz, + (const jbyte*) output); + } else { + throwWolfCryptException(env, + "Failed NewByteArray() for DER public key"); + } + } else { + throwWolfCryptExceptionFromError(env, ret); + } + + LogStr("wc_RsaKeyToPublicDer() = %d\n", ret); + LogStr("output[%u]: [%p]\n", outputSz, output); + LogHex((byte*) output, 0, outputSz); + + if (output != NULL) { + XMEMSET(output, 0, outputBufSz); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#else + throwNotCompiledInException(env); +#endif + + return result; +} + +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPrivateKeyToPkcs8 + (JNIEnv* env, jobject this) +{ + jbyteArray result = NULL; +#ifndef NO_RSA + int ret = 0; + RsaKey* key = NULL; + byte* derKey = NULL; + byte* pkcs8 = NULL; + word32 derKeySz = 0; + word32 pkcs8Sz = 0; + + /* Keep track of malloc sizes for memset cleanup */ + word32 derKeyBufSz = 0; + word32 pkcs8BufSz = 0; + + int algoID = RSAk; + word32 oidSz = 0; + const byte* curveOID = NULL; + + key = (RsaKey*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + ret = BAD_FUNC_ARG; + } + + if (ret == 0 && key == NULL) { + ret = BAD_FUNC_ARG; + } + + /* Get length of DER encoded RSA private key */ + if (ret == 0) { + ret = wc_RsaKeyToDer(key, NULL, 0); + if (ret > 0) { + derKeySz = ret; + ret = 0; + } + } + + /* Get PKCS#8 output size, into pkcs8Sz */ + if (ret == 0) { + ret = wc_CreatePKCS8Key(NULL, &pkcs8Sz, derKey, derKeySz, algoID, + curveOID, oidSz); + if (ret == LENGTH_ONLY_E) { + pkcs8 = (byte*)XMALLOC(pkcs8Sz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pkcs8 == NULL) { + ret = MEMORY_E; + } + else { + XMEMSET(pkcs8, 0, pkcs8Sz); + pkcs8BufSz = pkcs8Sz; + ret = 0; + } + } + } + + if (ret == 0) { + /* Allocate temp buffer to hold DER encoded key */ + derKey = (byte*)XMALLOC(derKeySz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (derKey == NULL) { + ret = MEMORY_E; + } + else { + XMEMSET(derKey, 0, derKeySz); + derKeyBufSz = derKeySz; + } + } + + /* Get DER encoded RSA private key */ + if (ret == 0) { + ret = wc_RsaKeyToDer(key, derKey, derKeySz); + if (ret > 0) { + derKeySz = ret; + ret = 0; + } + } + + /* Create PKCS#8 from DER key */ + if (ret == 0) { + ret = wc_CreatePKCS8Key(pkcs8, &pkcs8Sz, derKey, derKeySz, + algoID, curveOID, oidSz); + if (ret > 0) { + pkcs8Sz = ret; + ret = 0; + } + } + + /* Create new Java byte[] and return */ + if (ret == 0) { + result = (*env)->NewByteArray(env, pkcs8Sz); + if (result) { + (*env)->SetByteArrayRegion(env, result, 0, pkcs8Sz, + (const jbyte*) pkcs8); + } + } + + if (derKey != NULL) { + XMEMSET(derKey, 0, derKeyBufSz); + XFREE(derKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (pkcs8 != NULL) { + XMEMSET(pkcs8, 0, pkcs8BufSz); + XFREE(pkcs8, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + if (ret < 0) { + throwWolfCryptExceptionFromError(env, ret); + } +#else + throwNotCompiledInException(env); +#endif /* !NO_RSA */ + return result; +} + JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Rsa_wc_1InitRsaKey( JNIEnv* env, jobject this) @@ -311,14 +602,18 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1InitRsaKey( return; } - ret = (!key) - ? BAD_FUNC_ARG - : wc_InitRsaKey(key, NULL); + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = wc_InitRsaKey(key, NULL); + } - if (ret != 0) + if (ret != 0) { throwWolfCryptExceptionFromError(env, ret); + } - LogStr("RsaInitKey(key) = %d\n", ret); + LogStr("wc_InitRsaKey(key) = %d\n", ret); #else throwNotCompiledInException(env); #endif @@ -336,12 +631,16 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1FreeRsaKey( return; } - ret = (!key) - ? BAD_FUNC_ARG - : wc_FreeRsaKey(key); + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = wc_FreeRsaKey(key); + } - if (ret != 0) + if (ret != 0) { throwWolfCryptExceptionFromError(env, ret); + } LogStr("wc_FreeRsaKey(key) = %d\n", ret); #else @@ -372,16 +671,21 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaSetRNG( return JNI_FALSE; } - ret = (key == NULL) - ? BAD_FUNC_ARG - : wc_RsaSetRNG(key, rng); + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = wc_RsaSetRNG(key, rng); + } LogStr("wc_RsaSetRNG(key, rng) = %d\n", ret); - if (ret != 0) + if (ret != 0) { throwWolfCryptExceptionFromError(env, ret); - else + } + else { return JNI_TRUE; + } #endif #else @@ -410,18 +714,23 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPrivateKeyDecode( k = getByteArray(env, key_object); kSz = getByteArrayLength(env, key_object); - ret = (!key || !k) - ? BAD_FUNC_ARG - : wc_RsaPrivateKeyDecode(k, &index, key, kSz); + if (key == NULL || k == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = wc_RsaPrivateKeyDecode(k, &index, key, kSz); + } - if (ret != 0) + if (ret != 0) { throwWolfCryptExceptionFromError(env, ret); + } + + releaseByteArray(env, key_object, k, JNI_ABORT); LogStr("wc_RsaPrivateKeyDecode(k, kSize, key) = %d\n", ret); LogStr("key[%u]: [%p]\n", (word32)kSz, k); LogHex((byte*) k, 0, kSz); - releaseByteArray(env, key_object, k, JNI_ABORT); #else throwNotCompiledInException(env); #endif @@ -446,18 +755,24 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPrivateKeyDecodePKC k = getByteArray(env, key_object); kSz = getByteArrayLength(env, key_object); - if (!key || !k) { + if (key == NULL || k == NULL) { ret = BAD_FUNC_ARG; - } else { - length = wc_GetPkcs8TraditionalOffset(k, &offset, kSz); - - ret = (length < 0) - ? length - : wc_RsaPrivateKeyDecode(k, &offset, key, kSz); } - if (ret != 0) + if (ret == 0) { + length = wc_GetPkcs8TraditionalOffset(k, &offset, kSz); + if (length < 0) { + ret = length; + } + } + + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(k, &offset, key, kSz); + } + + if (ret != 0) { throwWolfCryptExceptionFromError(env, ret); + } LogStr("wc_RsaPrivateKeyDecodePKCS8(k, kSize, key) = %d\n", ret); LogStr("key[%u]: [%p]\n", (word32)kSz, k); @@ -485,12 +800,16 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPublicKeyDecode k = getByteArray(env, key_object); kSz = getByteArrayLength(env, key_object); - ret = (!key || !k) - ? BAD_FUNC_ARG - : wc_RsaPublicKeyDecode(k, &index, key, kSz); + if (key == NULL || k == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = wc_RsaPublicKeyDecode(k, &index, key, kSz); + } - if (ret != 0) + if (ret != 0) { throwWolfCryptExceptionFromError(env, ret); + } LogStr("wc_RsaPublicKeyDecode(k, kSize, key) = %d\n", ret); LogStr("key[%u]: [%p]\n", (word32)kSz, k); @@ -512,15 +831,18 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaEncryptSize return 0; } - ret = (!key) - ? BAD_FUNC_ARG - : wc_RsaEncryptSize(key); + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = wc_RsaEncryptSize(key); + } - if (ret < 0) + if (ret < 0) { throwWolfCryptExceptionFromError(env, ret); + } LogStr("wc_RsaEncryptSize(key=%p) = %d\n", key, ret); - #else throwNotCompiledInException(env); #endif @@ -556,30 +878,41 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPublicEncrypt( plaintext = getByteArray(env, plaintext_object); size = getByteArrayLength(env, plaintext_object); - outputSz = wc_RsaEncryptSize(key); - output = XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (output == NULL) { - throwOutOfMemoryException(env, "Failed to allocate ciphertext buffer"); - - releaseByteArray(env, plaintext_object, plaintext, JNI_ABORT); - - return result; + if (key == NULL || rng == NULL || plaintext == NULL) { + ret = BAD_FUNC_ARG; } - ret = (!key || !rng || !plaintext) - ? BAD_FUNC_ARG - : wc_RsaPublicEncrypt(plaintext, size, output, outputSz, key, rng); + if (ret == 0) { + outputSz = wc_RsaEncryptSize(key); + if (outputSz < 0) { + ret = outputSz; + } + } - if (ret >= 0) { - outputSz = ret; + if (ret == 0) { + output = (byte*)XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (output == NULL) { + ret = MEMORY_E; + } + } + + if (ret == 0) { + ret = wc_RsaPublicEncrypt(plaintext, size, output, outputSz, key, rng); + if (ret > 0) { + outputSz = ret; + ret = 0; + } + } + + if (ret == 0) { result = (*env)->NewByteArray(env, outputSz); if (result) { (*env)->SetByteArrayRegion(env, result, 0, outputSz, - (const jbyte*) output); + (const jbyte*) output); } else { - throwWolfCryptException(env, "Failed to allocate ciphertext"); + throwWolfCryptException(env, "Failed to create ciphertext array"); } } else { throwWolfCryptExceptionFromError(env, ret); @@ -589,8 +922,9 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPublicEncrypt( LogStr("output[%u]: [%p]\n", outputSz, output); LogHex((byte*) output, 0, outputSz); - XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); - + if (output != NULL) { + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } releaseByteArray(env, plaintext_object, plaintext, JNI_ABORT); #else throwNotCompiledInException(env); @@ -620,30 +954,41 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPrivateDecrypt( ciphertext = getByteArray(env, ciphertext_object); size = getByteArrayLength(env, ciphertext_object); - outputSz = wc_RsaEncryptSize(key); - output = XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (output == NULL) { - throwOutOfMemoryException(env, "Failed to allocate plaintext buffer"); - - releaseByteArray(env, ciphertext_object, ciphertext, JNI_ABORT); - - return result; + if (key == NULL || ciphertext == NULL) { + ret = BAD_FUNC_ARG; } - ret = (!key || !ciphertext) - ? BAD_FUNC_ARG - : wc_RsaPrivateDecrypt(ciphertext, size, output, outputSz, key); + if (ret == 0) { + outputSz = wc_RsaEncryptSize(key); + if (outputSz < 0) { + ret = outputSz; + } + } - if (ret >= 0) { - outputSz = ret; + if (ret == 0) { + output = (byte*)XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (output == NULL) { + ret = MEMORY_E; + } + } + + if (ret == 0) { + ret = wc_RsaPrivateDecrypt(ciphertext, size, output, outputSz, key); + if (ret > 0) { + outputSz = ret; + ret = 0; + } + } + + if (ret == 0) { result = (*env)->NewByteArray(env, outputSz); if (result) { (*env)->SetByteArrayRegion(env, result, 0, outputSz, - (const jbyte*) output); + (const jbyte*) output); } else { - throwWolfCryptException(env, "Failed to allocate plaintext"); + throwWolfCryptException(env, "Failed to create plaintext array"); } } else { throwWolfCryptExceptionFromError(env, ret); @@ -653,8 +998,9 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPrivateDecrypt( LogStr("output[%u]: [%p]\n", outputSz, output); LogHex((byte*) output, 0, outputSz); - XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); - + if (output != NULL) { + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } releaseByteArray(env, ciphertext_object, ciphertext, JNI_ABORT); #else throwNotCompiledInException(env); @@ -691,30 +1037,42 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaSSL_1Sign( data = getByteArray(env, data_object); size = getByteArrayLength(env, data_object); - outputSz = wc_RsaEncryptSize(key); - output = XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (output == NULL) { - throwOutOfMemoryException(env, "Failed to allocate signature buffer"); - - releaseByteArray(env, data_object, data, JNI_ABORT); - - return result; + if (key == NULL || rng == NULL || data == NULL) { + ret = BAD_FUNC_ARG; } - ret = (!key || !rng || !data) - ? BAD_FUNC_ARG - : wc_RsaSSL_Sign(data, size, output, outputSz, key, rng); + if (ret == 0) { + outputSz = wc_RsaEncryptSize(key); + if (outputSz < 0) { + ret = outputSz; + } + } - if (ret >= 0) { - outputSz = ret; + if (ret == 0) { + output = (byte*)XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (output == NULL) { + ret = MEMORY_E; + } + } + + if (ret == 0) { + ret = wc_RsaSSL_Sign(data, size, output, outputSz, key, rng); + if (ret > 0) { + outputSz = ret; + ret = 0; + } + } + + if (ret == 0) { result = (*env)->NewByteArray(env, outputSz); if (result) { (*env)->SetByteArrayRegion(env, result, 0, outputSz, - (const jbyte*) output); + (const jbyte*) output); } else { - throwWolfCryptException(env, "Failed to allocate signature"); + throwWolfCryptException(env, + "Failed to create new signature array"); } } else { throwWolfCryptExceptionFromError(env, ret); @@ -724,8 +1082,9 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaSSL_1Sign( LogStr("output[%u]: [%p]\n", outputSz, output); LogHex((byte*) output, 0, outputSz); - XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); - + if (output != NULL) { + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } releaseByteArray(env, data_object, data, JNI_ABORT); #else throwNotCompiledInException(env); @@ -739,7 +1098,6 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaSSL_1Verify( JNIEnv* env, jobject this, jbyteArray signature_object) { jbyteArray result = NULL; - #ifndef NO_RSA int ret = 0; RsaKey* key = NULL; @@ -755,30 +1113,41 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaSSL_1Verify( signature = getByteArray(env, signature_object); size = getByteArrayLength(env, signature_object); - outputSz = wc_RsaEncryptSize(key); - output = XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (output == NULL) { - throwOutOfMemoryException(env, "Failed to allocate verify buffer"); - - releaseByteArray(env, signature_object, signature, JNI_ABORT); - - return result; + if (key == NULL || signature == NULL) { + ret = BAD_FUNC_ARG; } - ret = (!key || !signature) - ? BAD_FUNC_ARG - : wc_RsaSSL_Verify(signature, size, output, outputSz, key); + if (ret == 0) { + outputSz = wc_RsaEncryptSize(key); + if (outputSz < 0) { + ret = outputSz; + } + } - if (ret >= 0) { - outputSz = ret; + if (ret == 0) { + output = (byte*)XMALLOC(outputSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (output == NULL) { + ret = MEMORY_E; + } + } + + if (ret == 0) { + ret = wc_RsaSSL_Verify(signature, size, output, outputSz, key); + if (ret > 0) { + outputSz = ret; + ret = 0; + } + } + + if (ret == 0) { result = (*env)->NewByteArray(env, outputSz); if (result) { (*env)->SetByteArrayRegion(env, result, 0, outputSz, - (const jbyte*) output); + (const jbyte*) output); } else { - throwWolfCryptException(env, "Failed to allocate verify"); + throwWolfCryptException(env, "Failed to create new verify array"); } } else { throwWolfCryptExceptionFromError(env, ret); @@ -788,8 +1157,9 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaSSL_1Verify( LogStr("output[%u]: [%p]\n", outputSz, output); LogHex((byte*) output, 0, outputSz); - XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); - + if (output != NULL) { + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } releaseByteArray(env, signature_object, signature, JNI_ABORT); #else throwNotCompiledInException(env); @@ -797,3 +1167,4 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaSSL_1Verify( return result; } + diff --git a/src/main/java/com/wolfssl/provider/jce/WolfCryptKeyPairGenerator.java b/src/main/java/com/wolfssl/provider/jce/WolfCryptKeyPairGenerator.java index 497e6b3..bc70587 100644 --- a/src/main/java/com/wolfssl/provider/jce/WolfCryptKeyPairGenerator.java +++ b/src/main/java/com/wolfssl/provider/jce/WolfCryptKeyPairGenerator.java @@ -38,7 +38,10 @@ import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.security.spec.ECGenParameterSpec; +import java.security.spec.RSAKeyGenParameterSpec; import java.security.spec.InvalidKeySpecException; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; @@ -48,6 +51,7 @@ import javax.crypto.spec.DHParameterSpec; import javax.crypto.spec.DHPrivateKeySpec; import javax.crypto.spec.DHPublicKeySpec; +import com.wolfssl.wolfcrypt.Rsa; import com.wolfssl.wolfcrypt.Ecc; import com.wolfssl.wolfcrypt.Dh; import com.wolfssl.wolfcrypt.Rng; @@ -60,6 +64,7 @@ import com.wolfssl.provider.jce.WolfCryptDebug; public class WolfCryptKeyPairGenerator extends KeyPairGeneratorSpi { enum KeyType { + WC_RSA, WC_ECC, WC_DH } @@ -68,6 +73,7 @@ public class WolfCryptKeyPairGenerator extends KeyPairGeneratorSpi { private String curve = null; private int keysize = 0; + private long publicExponent = 0; private byte[] dhP = null; private byte[] dhG = null; @@ -100,6 +106,11 @@ public class WolfCryptKeyPairGenerator extends KeyPairGeneratorSpi { this.keysize = keysize; + if (type == KeyType.WC_RSA) { + /* Set default RSA exponent for wolfSSL */ + this.publicExponent = Rsa.getDefaultRsaExponent(); + } + if (debug.DEBUG) log("init with keysize: " + keysize); } @@ -115,6 +126,31 @@ public class WolfCryptKeyPairGenerator extends KeyPairGeneratorSpi { switch (type) { + case WC_RSA: + + if (!(params instanceof RSAKeyGenParameterSpec)) { + throw new InvalidAlgorithmParameterException( + "params must be of type RSAKeyGenParameterSpec"); + } + + RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec)params; + this.keysize = rsaSpec.getKeysize(); + + try { + this.publicExponent = + rsaSpec.getPublicExponent().longValueExact(); + } catch (ArithmeticException e) { + throw new InvalidAlgorithmParameterException( + "RSA public exponent value larger than long"); + } + + if (debug.DEBUG) { + log("init with RSA spec, keysize = " + keysize + + ", public exponent = " + publicExponent); + } + + break; + case WC_ECC: int curvesize; @@ -183,6 +219,58 @@ public class WolfCryptKeyPairGenerator extends KeyPairGeneratorSpi { switch (this.type) { + case WC_RSA: + + if (keysize == 0) { + throw new RuntimeException( + "keysize is 0, please set before generating key"); + } + + RSAPrivateKey rsaPriv = null; + RSAPublicKey rsaPub = null; + + Rsa rsa = new Rsa(); + + try { + rsa.makeKey(this.keysize, this.publicExponent, rng); + + /* private key */ + privDer = rsa.privateKeyEncodePKCS8(); + if (privDer == null) { + throw new RuntimeException( + "Unable to get RSA private key DER"); + } + privSpec = new PKCS8EncodedKeySpec(privDer); + + /* public key */ + pubDer = rsa.exportPublicDer(); + if (pubDer == null) { + throw new RuntimeException( + "Unable to get RSA public key DER"); + } + pubSpec = new X509EncodedKeySpec(pubDer); + + zeroArray(privDer); + zeroArray(pubDer); + rsa.releaseNativeStruct(); + + KeyFactory kf = KeyFactory.getInstance("RSA"); + + rsaPriv = (RSAPrivateKey)kf.generatePrivate(privSpec); + rsaPub = (RSAPublicKey)kf.generatePublic(pubSpec); + + pair = new KeyPair(rsaPub, rsaPriv); + + } catch (Exception e) { + throw new RuntimeException(e); + } + + if (debug.DEBUG) { + log("generated RSA KeyPair"); + } + + break; + case WC_ECC: if (keysize == 0) { @@ -203,10 +291,18 @@ public class WolfCryptKeyPairGenerator extends KeyPairGeneratorSpi { /* private key */ privDer = ecc.privateKeyEncodePKCS8(); + if (privDer == null) { + throw new RuntimeException( + "Unable to get ECC private key DER"); + } privSpec = new PKCS8EncodedKeySpec(privDer); /* public key */ pubDer = ecc.publicKeyEncode(); + if (pubDer == null) { + throw new RuntimeException( + "Unable to get ECC public key DER"); + } pubSpec = new X509EncodedKeySpec(pubDer); zeroArray(privDer); @@ -226,7 +322,7 @@ public class WolfCryptKeyPairGenerator extends KeyPairGeneratorSpi { } if (debug.DEBUG) - log("generated KeyPair"); + log("generated ECC KeyPair"); break; @@ -274,13 +370,13 @@ public class WolfCryptKeyPairGenerator extends KeyPairGeneratorSpi { } if (debug.DEBUG) - log("generated KeyPair"); + log("generated DH KeyPair"); break; default: throw new RuntimeException( - "Unsupported algorithm for key generation"); + "Unsupported algorithm for key generation: " + this.type); } return pair; @@ -288,6 +384,8 @@ public class WolfCryptKeyPairGenerator extends KeyPairGeneratorSpi { private String typeToString(KeyType type) { switch (type) { + case WC_RSA: + return "RSA"; case WC_ECC: return "ECC"; case WC_DH: @@ -324,6 +422,19 @@ public class WolfCryptKeyPairGenerator extends KeyPairGeneratorSpi { } } + /** + * wolfCrypt RSA key pair generator class + */ + public static final class wcKeyPairGenRSA + extends WolfCryptKeyPairGenerator { + /** + * Create new wcKeyPairGenRSA object + */ + public wcKeyPairGenRSA() { + super(KeyType.WC_RSA); + } + } + /** * wolfCrypt ECC key pair generator class */ diff --git a/src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java b/src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java index 30d6713..0833992 100644 --- a/src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java +++ b/src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java @@ -136,6 +136,8 @@ public final class WolfCryptProvider extends Provider { "com.wolfssl.provider.jce.WolfCryptKeyAgreement$wcECDH"); /* KeyPairGenerator */ + put("KeyPairGenerator.RSA", + "com.wolfssl.provider.jce.WolfCryptKeyPairGenerator$wcKeyPairGenRSA"); put("KeyPairGenerator.EC", "com.wolfssl.provider.jce.WolfCryptKeyPairGenerator$wcKeyPairGenECC"); put("KeyPairGenerator.DH", diff --git a/src/main/java/com/wolfssl/wolfcrypt/Rsa.java b/src/main/java/com/wolfssl/wolfcrypt/Rsa.java index b449289..8fd1243 100644 --- a/src/main/java/com/wolfssl/wolfcrypt/Rsa.java +++ b/src/main/java/com/wolfssl/wolfcrypt/Rsa.java @@ -52,24 +52,43 @@ public class Rsa extends NativeStruct { * @throws WolfCryptException if native operation fails */ private native void wc_RsaPublicKeyDecodeRaw(ByteBuffer n, long nSize, - ByteBuffer e, long eSize); + ByteBuffer e, long eSize) throws WolfCryptException; private native void wc_RsaPublicKeyDecodeRaw(byte[] n, long nSize, byte[] e, - long eSize); - private native void RsaFlattenPublicKey(ByteBuffer n, ByteBuffer e); + long eSize) throws WolfCryptException; + private native void RsaFlattenPublicKey(ByteBuffer n, ByteBuffer e) + throws WolfCryptException; private native void RsaFlattenPublicKey(byte[] n, long[] nSize, byte[] e, - long[] eSize); - private native void MakeRsaKey(int size, long e, Rng rng); - private native void wc_InitRsaKey(); - private native void wc_FreeRsaKey(); - private native boolean wc_RsaSetRNG(Rng rng); - private native void wc_RsaPrivateKeyDecode(byte[] key); - private native void wc_RsaPrivateKeyDecodePKCS8(byte[] key); - private native void wc_RsaPublicKeyDecode(byte[] key); - private native int wc_RsaEncryptSize(); - private native byte[] wc_RsaPublicEncrypt(byte[] data, Rng rng); - private native byte[] wc_RsaPrivateDecrypt(byte[] data); - private native byte[] wc_RsaSSL_Sign(byte[] data, Rng rng); - private native byte[] wc_RsaSSL_Verify(byte[] data); + long[] eSize) throws WolfCryptException; + private native void MakeRsaKey(int size, long e, Rng rng) + throws WolfCryptException; + private native byte[] wc_RsaKeyToDer() + throws WolfCryptException; + private native byte[] wc_RsaKeyToPublicDer() + throws WolfCryptException; + private native byte[] wc_RsaPrivateKeyToPkcs8() + throws WolfCryptException; + private native void wc_InitRsaKey() + throws WolfCryptException; + private native void wc_FreeRsaKey() + throws WolfCryptException; + private native boolean wc_RsaSetRNG(Rng rng) + throws WolfCryptException; + private native void wc_RsaPrivateKeyDecode(byte[] key) + throws WolfCryptException; + private native void wc_RsaPrivateKeyDecodePKCS8(byte[] key) + throws WolfCryptException; + private native void wc_RsaPublicKeyDecode(byte[] key) + throws WolfCryptException; + private native int wc_RsaEncryptSize() + throws WolfCryptException; + private native byte[] wc_RsaPublicEncrypt(byte[] data, Rng rng) + throws WolfCryptException; + private native byte[] wc_RsaPrivateDecrypt(byte[] data) + throws WolfCryptException; + private native byte[] wc_RsaSSL_Sign(byte[] data, Rng rng) + throws WolfCryptException; + private native byte[] wc_RsaSSL_Verify(byte[] data) + throws WolfCryptException; /** * Create new Rsa object @@ -85,7 +104,7 @@ public class Rsa extends NativeStruct { * * @throws WolfCryptException if native operation fails */ - public Rsa(byte[] key) { + public Rsa(byte[] key) throws WolfCryptException { decodePrivateKey(key); } @@ -97,10 +116,18 @@ public class Rsa extends NativeStruct { * * @throws WolfCryptException if native operation fails */ - public Rsa(byte[] n, byte[] e) { + public Rsa(byte[] n, byte[] e) throws WolfCryptException { decodeRawPublicKey(n, e); } + /** + * Return the value of native wolfCrypt default RSA public exponent size. + * Native default is stored in the WC_RSA_EXPONENT define. + * + * @return value of native WC_RSA_EXPONENT, default RSA expoonent size + */ + public static native long getDefaultRsaExponent(); + /** * Set Rng for Rsa object * @@ -108,7 +135,7 @@ public class Rsa extends NativeStruct { * * @throws WolfCryptException if native operation fails */ - public void setRng(Rng rng) { + public void setRng(Rng rng) throws WolfCryptException { init(); if (wc_RsaSetRNG(rng)) @@ -124,8 +151,10 @@ public class Rsa extends NativeStruct { /** * Initialize Rsa object + * + * @throws WolfCryptException if native operation fails */ - protected void init() { + protected void init() throws WolfCryptException { if (state == WolfCryptState.UNINITIALIZED) { wc_InitRsaKey(); state = WolfCryptState.INITIALIZED; @@ -135,9 +164,12 @@ public class Rsa extends NativeStruct { /** * Initialize native RsaKey struct, check if object already has key * + * @throws WolfCryptException if native operation fails * @throws IllegalStateException if object already has key */ - protected void willSetKey() throws IllegalStateException { + protected void willSetKey() + throws WolfCryptException, IllegalStateException { + init(); if (state != WolfCryptState.INITIALIZED) @@ -155,17 +187,19 @@ public class Rsa extends NativeStruct { protected void willUseKey(boolean priv) throws IllegalStateException { if (priv && !hasPrivateKey) throw new IllegalStateException( - "No available private key to perform the opperation."); + "No available private key to perform the operation."); if (state != WolfCryptState.READY) throw new IllegalStateException( - "No available key to perform the opperation."); + "No available key to perform the operation."); } /** * Free Rsa object + * + * @throws WolfCryptException if native operation fails */ - protected void free() { + protected void free() throws WolfCryptException { if (state != WolfCryptState.UNINITIALIZED) { wc_FreeRsaKey(); state = WolfCryptState.UNINITIALIZED; @@ -182,7 +216,8 @@ public class Rsa extends NativeStruct { * @throws WolfCryptException if native operation fails * @throws IllegalStateException if object is already initialized */ - public void makeKey(int size, long e, Rng rng) { + public void makeKey(int size, long e, Rng rng) + throws WolfCryptException, IllegalStateException { willSetKey(); MakeRsaKey(size, e, rng); @@ -199,7 +234,8 @@ public class Rsa extends NativeStruct { * @throws WolfCryptException if native operation fails * @throws IllegalStateException if object is already initialized */ - public void decodePublicKey(byte[] key) { + public void decodePublicKey(byte[] key) + throws WolfCryptException, IllegalStateException { willSetKey(); wc_RsaPublicKeyDecode(key); @@ -214,7 +250,8 @@ public class Rsa extends NativeStruct { * @throws WolfCryptException if native operation fails * @throws IllegalStateException if object is already initialized */ - public void decodePrivateKey(byte[] key) { + public void decodePrivateKey(byte[] key) + throws WolfCryptException, IllegalStateException { willSetKey(); wc_RsaPrivateKeyDecode(key); @@ -230,7 +267,8 @@ public class Rsa extends NativeStruct { * @throws WolfCryptException if native operation fails * @throws IllegalStateException if object is already initialized */ - public void decodePrivateKeyPKCS8(byte[] key) { + public void decodePrivateKeyPKCS8(byte[] key) + throws WolfCryptException, IllegalStateException { willSetKey(); wc_RsaPrivateKeyDecodePKCS8(key); @@ -248,7 +286,8 @@ public class Rsa extends NativeStruct { * @throws WolfCryptException if native operation fails * @throws IllegalStateException if object is already initialized */ - public void decodeRawPublicKey(byte[] n, byte[] e) { + public void decodeRawPublicKey(byte[] n, byte[] e) + throws WolfCryptException, IllegalStateException { decodeRawPublicKey(n, n.length, e, e.length); } @@ -263,7 +302,8 @@ public class Rsa extends NativeStruct { * @throws WolfCryptException if native operation fails * @throws IllegalStateException if object is already initialized */ - public void decodeRawPublicKey(byte[] n, long nSize, byte[] e, long eSize) { + public void decodeRawPublicKey(byte[] n, long nSize, byte[] e, long eSize) + throws WolfCryptException, IllegalStateException { willSetKey(); wc_RsaPublicKeyDecodeRaw(n, nSize, e, eSize); @@ -279,7 +319,8 @@ public class Rsa extends NativeStruct { * @throws WolfCryptException if native operation fails * @throws IllegalStateException if object is already initialized */ - public void decodeRawPublicKey(ByteBuffer n, ByteBuffer e) { + public void decodeRawPublicKey(ByteBuffer n, ByteBuffer e) + throws WolfCryptException, IllegalStateException { decodeRawPublicKey(n, n.limit(), e, e.limit()); } @@ -295,7 +336,7 @@ public class Rsa extends NativeStruct { * @throws IllegalStateException if object is already initialized */ public void decodeRawPublicKey(ByteBuffer n, long nSz, ByteBuffer e, - long eSz) { + long eSz) throws WolfCryptException, IllegalStateException { willSetKey(); wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz); @@ -314,7 +355,8 @@ public class Rsa extends NativeStruct { * * @throws WolfCryptException if native operation fails */ - public void exportRawPublicKey(byte[] n, long[] nSz, byte[] e, long[] eSz) { + public void exportRawPublicKey(byte[] n, long[] nSz, byte[] e, long[] eSz) + throws WolfCryptException { willUseKey(false); RsaFlattenPublicKey(n, nSz, e, eSz); @@ -328,12 +370,52 @@ public class Rsa extends NativeStruct { * * @throws WolfCryptException if native operation fails */ - public void exportRawPublicKey(ByteBuffer n, ByteBuffer e) { + public void exportRawPublicKey(ByteBuffer n, ByteBuffer e) + throws WolfCryptException { willUseKey(false); RsaFlattenPublicKey(n, e); } + /** + * Export RSA private key in DER format. + * + * @return DER encoded byte array with private RSA key + * + * @throws WolfCryptException if native operation fails + */ + public byte[] exportPrivateDer() throws WolfCryptException { + willUseKey(true); + + return wc_RsaKeyToDer(); + } + + /** + * Export RSA public key in DER format. + * + * @return DER encoded byte array with public RSA key + * + * @throws WolfCryptException if native operation fails + */ + public byte[] exportPublicDer() throws WolfCryptException { + willUseKey(false); + + return wc_RsaKeyToPublicDer(); + } + + /** + * Encode and return RSA private key in PKCS#8 format. + * + * @return encoded private key as byte array + * + * @throws WolfCryptException if native operation fails + */ + public byte[] privateKeyEncodePKCS8() throws WolfCryptException { + willUseKey(true); + + return wc_RsaPrivateKeyToPkcs8(); + } + /** * Get RSA encrypt size * @@ -341,7 +423,7 @@ public class Rsa extends NativeStruct { * * @throws WolfCryptException if native operation fails */ - public int getEncryptSize() { + public int getEncryptSize() throws WolfCryptException { willUseKey(false); return wc_RsaEncryptSize(); @@ -357,7 +439,7 @@ public class Rsa extends NativeStruct { * * @throws WolfCryptException if native operation fails */ - public byte[] encrypt(byte[] plain, Rng rng) { + public byte[] encrypt(byte[] plain, Rng rng) throws WolfCryptException { willUseKey(false); return wc_RsaPublicEncrypt(plain, rng); @@ -372,7 +454,7 @@ public class Rsa extends NativeStruct { * * @throws WolfCryptException if native operation fails */ - public byte[] decrypt(byte[] ciphertext) { + public byte[] decrypt(byte[] ciphertext) throws WolfCryptException { willUseKey(true); return wc_RsaPrivateDecrypt(ciphertext); @@ -389,7 +471,7 @@ public class Rsa extends NativeStruct { * @throws WolfCryptException if native operation fails * @throws IllegalStateException if object does not have key */ - public byte[] sign(byte[] data, Rng rng) { + public byte[] sign(byte[] data, Rng rng) throws WolfCryptException { willUseKey(true); return wc_RsaSSL_Sign(data, rng); @@ -404,7 +486,7 @@ public class Rsa extends NativeStruct { * * @throws WolfCryptException if native operation fails */ - public byte[] verify(byte[] signature) { + public byte[] verify(byte[] signature) throws WolfCryptException { willUseKey(false); return wc_RsaSSL_Verify(signature); diff --git a/src/test/java/com/wolfssl/provider/jce/test/WolfCryptKeyPairGeneratorTest.java b/src/test/java/com/wolfssl/provider/jce/test/WolfCryptKeyPairGeneratorTest.java index e35185a..1408d86 100644 --- a/src/test/java/com/wolfssl/provider/jce/test/WolfCryptKeyPairGeneratorTest.java +++ b/src/test/java/com/wolfssl/provider/jce/test/WolfCryptKeyPairGeneratorTest.java @@ -48,10 +48,12 @@ import java.security.KeyFactory; import java.security.InvalidAlgorithmParameterException; import java.security.spec.InvalidParameterSpecException; import java.security.spec.InvalidKeySpecException; +import java.security.spec.RSAKeyGenParameterSpec; import java.security.spec.ECGenParameterSpec; import java.security.spec.X509EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec; +import com.wolfssl.wolfcrypt.Rsa; import com.wolfssl.wolfcrypt.Ecc; import com.wolfssl.wolfcrypt.test.Util; import com.wolfssl.wolfcrypt.WolfCryptException; @@ -94,13 +96,14 @@ public class WolfCryptKeyPairGeneratorTest { private static ArrayList enabledCurves = new ArrayList(); - private static int supportedKeySizes[] = { - 112, 128, 160, 192, 224, 239, 256, 320, 384, 521 - }; - - private static ArrayList enabledKeySizes = + private static ArrayList enabledEccKeySizes = new ArrayList(); + /* Test generation of these RSA key sizes */ + private static int testedRSAKeySizes[] = { + 1024, 2048, 3072, 4096 + }; + /* DH test params */ private static byte[] prime = Util.h2b( "B0A108069C0813BA59063CBC30D5F500C14F44A7D6EF4AC625271CE8D" + @@ -119,7 +122,7 @@ public class WolfCryptKeyPairGeneratorTest { public static void testProviderInstallationAtRuntime() { /* install wolfJCE provider at runtime */ - Security.addProvider(new WolfCryptProvider()); + Security.insertProviderAt(new WolfCryptProvider(), 1); Provider p = Security.getProvider("wolfJCE"); assertNotNull(p); @@ -135,8 +138,8 @@ public class WolfCryptKeyPairGeneratorTest { if (size > 0) { enabledCurves.add(supportedCurves[i]); - if (!enabledKeySizes.contains(Integer.valueOf(size))) { - enabledKeySizes.add(Integer.valueOf(size)); + if (!enabledEccKeySizes.contains(Integer.valueOf(size))) { + enabledEccKeySizes.add(Integer.valueOf(size)); } } } @@ -148,6 +151,8 @@ public class WolfCryptKeyPairGeneratorTest { KeyPairGenerator kpg; kpg = KeyPairGenerator.getInstance("EC", "wolfJCE"); + kpg = KeyPairGenerator.getInstance("RSA", "wolfJCE"); + kpg = KeyPairGenerator.getInstance("DH", "wolfJCE"); /* getting a garbage algorithm should throw an exception */ try { @@ -159,6 +164,135 @@ public class WolfCryptKeyPairGeneratorTest { } catch (NoSuchAlgorithmException e) { } } + @Test + public void testKeyPairGeneratorRsaInitializeWithParamSpec() + throws NoSuchProviderException, NoSuchAlgorithmException, + InvalidAlgorithmParameterException { + + /* try initializing KPG for all tested key sizes */ + for (int i = 0; i < testedRSAKeySizes.length; i++) { + + KeyPairGenerator kpg = + KeyPairGenerator.getInstance("RSA", "wolfJCE"); + + RSAKeyGenParameterSpec rsaSpec = + new RSAKeyGenParameterSpec(testedRSAKeySizes[i], + BigInteger.valueOf(Rsa.getDefaultRsaExponent())); + kpg.initialize(rsaSpec); + + /* bad key size should fail */ + try { + rsaSpec = new RSAKeyGenParameterSpec(10, + BigInteger.valueOf(Rsa.getDefaultRsaExponent())); + kpg.initialize(rsaSpec); + } catch (InvalidAlgorithmParameterException e) {} + } + } + + @Test + public void testKeyPairGeneratorRsaInitializeWithKeySize() + throws NoSuchProviderException, NoSuchAlgorithmException, + InvalidAlgorithmParameterException { + + /* try initializing KPG for all tested key sizes */ + for (int i = 0; i < testedRSAKeySizes.length; i++) { + + KeyPairGenerator kpg = + KeyPairGenerator.getInstance("RSA", "wolfJCE"); + + kpg.initialize(testedRSAKeySizes[i]); + + /* bad key size should fail */ + try { + kpg.initialize(10); + } catch (WolfCryptException e) {} + } + } + + @Test + public void testKeyPairGeneratorRsaKeyGenAllSizes() + throws NoSuchProviderException, NoSuchAlgorithmException, + InvalidAlgorithmParameterException { + + /* try generating keys for all tested sizes */ + for (int i = 0; i < testedRSAKeySizes.length; i++) { + + KeyPairGenerator kpg = + KeyPairGenerator.getInstance("RSA", "wolfJCE"); + + RSAKeyGenParameterSpec rsaSpec = + new RSAKeyGenParameterSpec(testedRSAKeySizes[i], + BigInteger.valueOf(Rsa.getDefaultRsaExponent())); + kpg.initialize(rsaSpec); + + KeyPair kp = kpg.generateKeyPair(); + } + } + + @Test + public void testKeyPairGeneratorRsaMultipleInits() + throws NoSuchProviderException, NoSuchAlgorithmException, + InvalidAlgorithmParameterException { + + if (testedRSAKeySizes.length > 0) { + + KeyPairGenerator kpg = + KeyPairGenerator.getInstance("RSA", "wolfJCE"); + + RSAKeyGenParameterSpec rsaSpec = + new RSAKeyGenParameterSpec(testedRSAKeySizes[0], + BigInteger.valueOf(Rsa.getDefaultRsaExponent())); + + kpg.initialize(rsaSpec); + kpg.initialize(rsaSpec); + } + } + + @Test + public void testKeyPairGeneratorRsaMultipleKeyGen() + throws NoSuchProviderException, NoSuchAlgorithmException, + InvalidAlgorithmParameterException { + + if (testedRSAKeySizes.length > 0) { + + KeyPairGenerator kpg = + KeyPairGenerator.getInstance("RSA", "wolfJCE"); + + RSAKeyGenParameterSpec rsaSpec = + new RSAKeyGenParameterSpec(testedRSAKeySizes[0], + BigInteger.valueOf(Rsa.getDefaultRsaExponent())); + kpg.initialize(rsaSpec); + + KeyPair kp1 = kpg.generateKeyPair(); + KeyPair kp2 = kpg.generateKeyPair(); + } + } + + @Test + public void testKeyPairGeneratorRsaNewKeyFromExisting() + throws NoSuchProviderException, NoSuchAlgorithmException, + InvalidAlgorithmParameterException, InvalidKeySpecException { + + if (testedRSAKeySizes.length > 0) { + + KeyPairGenerator kpg = + KeyPairGenerator.getInstance("RSA", "wolfJCE"); + + RSAKeyGenParameterSpec rsaSpec = + new RSAKeyGenParameterSpec(testedRSAKeySizes[0], + BigInteger.valueOf(Rsa.getDefaultRsaExponent())); + kpg.initialize(rsaSpec); + + KeyPair kp = kpg.generateKeyPair(); + + KeyFactory kf = KeyFactory.getInstance("RSA"); + PublicKey pub = kf.generatePublic(new X509EncodedKeySpec( + kp.getPublic().getEncoded())); + PrivateKey priv = kf.generatePrivate(new PKCS8EncodedKeySpec( + kp.getPrivate().getEncoded())); + } + } + @Test public void testKeyPairGeneratorEccInitializeWithParamSpec() throws NoSuchProviderException, NoSuchAlgorithmException, @@ -178,7 +312,9 @@ public class WolfCryptKeyPairGeneratorTest { try { ecSpec = new ECGenParameterSpec("BADCURVE"); kpg.initialize(ecSpec); - } catch (InvalidAlgorithmParameterException e) {} + } catch (InvalidAlgorithmParameterException e) { + /* expected */ + } } } @@ -188,17 +324,19 @@ public class WolfCryptKeyPairGeneratorTest { InvalidAlgorithmParameterException { /* try initializing KPG for all supported key sizes */ - for (int i = 0; i < enabledKeySizes.size(); i++) { + for (int i = 0; i < enabledEccKeySizes.size(); i++) { KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "wolfJCE"); - kpg.initialize(enabledKeySizes.get(i)); + kpg.initialize(enabledEccKeySizes.get(i)); /* bad key size should fail */ try { kpg.initialize(9999); - } catch (WolfCryptException e) {} + } catch (WolfCryptException e) { + /* expected */ + } } } diff --git a/src/test/java/com/wolfssl/wolfcrypt/test/RsaTest.java b/src/test/java/com/wolfssl/wolfcrypt/test/RsaTest.java index 9811f68..44275c9 100644 --- a/src/test/java/com/wolfssl/wolfcrypt/test/RsaTest.java +++ b/src/test/java/com/wolfssl/wolfcrypt/test/RsaTest.java @@ -31,6 +31,7 @@ import org.junit.Test; import com.wolfssl.wolfcrypt.Rsa; import com.wolfssl.wolfcrypt.Rng; +import com.wolfssl.wolfcrypt.Fips; import com.wolfssl.wolfcrypt.NativeStruct; import com.wolfssl.wolfcrypt.WolfCryptError; import com.wolfssl.wolfcrypt.WolfCryptException; @@ -60,10 +61,177 @@ public class RsaTest { } @Test - public void makeKeyShouldNotRaiseExceptions() { - Rsa key = new Rsa(); + public void testMakeKey() { + Rsa key = new Rsa(); key.makeKey(1024, 65537, rng); + key.releaseNativeStruct(); + + key = new Rsa(); + key.makeKey(2048, 65537, rng); + key.releaseNativeStruct(); + + key = new Rsa(); + key.makeKey(3072, 65537, rng); + key.releaseNativeStruct(); + + key = new Rsa(); + key.makeKey(4096, 65537, rng); + key.releaseNativeStruct(); + } + + @Test + public void testDerExportImportSignVerify() { + + /* generate new 2048-bit key */ + Rsa key = new Rsa(); + key.makeKey(2048, 65537, rng); + + /* export key to DER */ + byte[] rsaDer = key.exportPrivateDer(); + assertNotNull(rsaDer); + assertTrue(rsaDer.length > 0); + key.releaseNativeStruct(); + + /* try to re-import DER into new Rsa object */ + key = new Rsa(); + key.decodePrivateKey(rsaDer); + + /* sign data */ + byte[] data = "Hello wolfSSL".getBytes(); + byte[] signed = key.sign(data, rng); + + /* verify data matches original */ + byte[] verify = key.verify(signed); + assertNotNull(verify); + assertArrayEquals(data, verify); + + key.releaseNativeStruct(); + } + + @Test + public void rsaPrivateToPkcs8() { + Rsa key = new Rsa(); + byte[] pkcs8; + int size; + byte[] prvKey = Util.h2b( + "308204a40201000282010100c303d12bfe39a432453b53c8842b2a7c" + + "749abdaa2a520747d6a636b207328ed0ba697bc6c3449ed48148" + + "fd2d68a28b67bba175c8362c4ad21bf78bbacf0df9efecf1811e" + + "7b9b03479abf65cc7f652469a6e814895be434f7c5b01493f567" + + "7b3a7a78e101565691a613428dd23c409c4cefd186df37511b0c" + + "a13bf5f1a34a35e4e1ce96df1b7ebf4e97d010e8a8083081af20" + + "0b4314c57467b432826f8d86c28840993683ba1e40722217d752" + + "652473b0ceef19cdaeff786c7bc01203d44e720d506d3ba33ba3" + + "995e9dc8d90c85b3d98ad95426db6dfaacbbff254cc4d179f471" + + "d386401813b063b5724e30c49784862d562fd715f77fc0aef5fc" + + "5be5fba1bad302030100010282010100a2e6d85f107164089e2e" + + "6dd16d1e85d20ab18c47ce2c516aa0129e53de914c1d6dea597b" + + "f277aad9c6d98aabd8e116e46326ffb56c1359b8e3a5c872172e" + + "0c9f6fe5593f766f49b111c25a2e16290ddeb78edc40d5a2eee0" + + "1ea1f4be97db86639614cd9809602d30769c3ccde688ee479279" + + "0b5a00e25e5f117c7df908b72006892a5dfd00ab22e1f0b3bc24" + + "a95e260e1f002dfe219a535b6dd32bab9482684336d8f62fc622" + + "fcb5415d0d3360eaa47d7ee84b559156d35c578f1f94172faade" + + "e99ea8f4cf8a4c8ea0e45673b2cf4f86c5693cf324208b5c960c" + + "fa6b123b9a67c1dfc696b2a5d5920d9b094268241045d450e417" + + "3948d0358b946d11de8fca5902818100ea24a7f96933e971dc52" + + "7d8821282f49deba7216e9cc477a880d94578458163a81b03fa2" + + "cfa66c1eb00629008fe77776acdbcac7d95e9b3f269052aefc38" + + "900014bbb40f5894e72f6a7e1c4f4121d431591f4e8a1a8da757" + + "6c22d8e5f47e32a610cb64a5550387a627058cc3d7b627b24dba" + + "30da478f54d33d8b848d949858a502818100d5381bc38fc5930c" + + "470b6f3592c5b08d46c892188ff5800af7efa1fe80b9b52abaca" + + "18b05da507d0938dd89c041cd4628ea6268101ffce8a2a633435" + + "40aa6d80de89236a574d9e6ead934e56900b6d9d738b0cae273d" + + "de4ef0aac56c78676c94529c37676c2defbbafdfa6903cc447cf" + + "8d969e98a9b49fc5a650dcb3f0fb74170281805e830962bdba7c" + + "a2bf4274f57c1cd269c9040d857e3e3d2412c3187bf329f35f0e" + + "766c5975e44184699d32f3cd22abb035ba4ab23ce5d958b6624f" + + "5ddee59e0aca53b22cf79eb36b0a5b7965ec6e914e9220f6fcfc" + + "16edd3760ce2ec7fb269136b780e5a4664b45eb725a05a753a4b" + + "efc73c3ef7fd26b820c4990a9a73bec31902818100ba449314ac" + + "34193b5f9160acf7b4d681053651533de865dcaf2edc613ec97d" + + "b87f87f03b9b03822937ce724e11d5b1c10c07a099914a8d7fec" + + "79cff139b5e985ec62f7da7dbc644d223c0ef2d651f587d899c0" + + "11205d0f29fd5be2aed91cd921566dfc84d05fed10151c1821e7" + + "c43d4bd7d09e6a95cf22c9037b9ee36001fc2f02818011d04bcf" + + "1b67b99f1075478665ae31c2c630ac590650d90fb57006f7f0d3" + + "c8627ca8da6ef6213fd37f5fea8aab3fd92a5ef351d2c23037e3" + + "2da3750d1e4d2134d557705c89bf72ec4a6e68d5cd1874334e8c" + + "3a458fe69640eb63f919863a51dd894bb0f3f99f5d289538be35" + + "abca5ce7935334a1455d1339654246a19fcdf5bf"); + + byte[] expectedPkcs8 = Util.h2b( + "308204be020100300d06092a864886f70d0101010500048204a8" + + "308204a40201000282010100c303d12bfe39a432453b53c8842b" + + "2a7c749abdaa2a520747d6a636b207328ed0ba697bc6c3449ed4" + + "8148fd2d68a28b67bba175c8362c4ad21bf78bbacf0df9efecf1" + + "811e7b9b03479abf65cc7f652469a6e814895be434f7c5b01493" + + "f5677b3a7a78e101565691a613428dd23c409c4cefd186df3751" + + "1b0ca13bf5f1a34a35e4e1ce96df1b7ebf4e97d010e8a8083081" + + "af200b4314c57467b432826f8d86c28840993683ba1e40722217" + + "d752652473b0ceef19cdaeff786c7bc01203d44e720d506d3ba3" + + "3ba3995e9dc8d90c85b3d98ad95426db6dfaacbbff254cc4d179" + + "f471d386401813b063b5724e30c49784862d562fd715f77fc0ae" + + "f5fc5be5fba1bad302030100010282010100a2e6d85f10716408" + + "9e2e6dd16d1e85d20ab18c47ce2c516aa0129e53de914c1d6dea" + + "597bf277aad9c6d98aabd8e116e46326ffb56c1359b8e3a5c872" + + "172e0c9f6fe5593f766f49b111c25a2e16290ddeb78edc40d5a2" + + "eee01ea1f4be97db86639614cd9809602d30769c3ccde688ee47" + + "92790b5a00e25e5f117c7df908b72006892a5dfd00ab22e1f0b3" + + "bc24a95e260e1f002dfe219a535b6dd32bab9482684336d8f62f" + + "c622fcb5415d0d3360eaa47d7ee84b559156d35c578f1f94172f" + + "aadee99ea8f4cf8a4c8ea0e45673b2cf4f86c5693cf324208b5c" + + "960cfa6b123b9a67c1dfc696b2a5d5920d9b094268241045d450" + + "e4173948d0358b946d11de8fca5902818100ea24a7f96933e971" + + "dc527d8821282f49deba7216e9cc477a880d94578458163a81b0" + + "3fa2cfa66c1eb00629008fe77776acdbcac7d95e9b3f269052ae" + + "fc38900014bbb40f5894e72f6a7e1c4f4121d431591f4e8a1a8d" + + "a7576c22d8e5f47e32a610cb64a5550387a627058cc3d7b627b2" + + "4dba30da478f54d33d8b848d949858a502818100d5381bc38fc5" + + "930c470b6f3592c5b08d46c892188ff5800af7efa1fe80b9b52a" + + "baca18b05da507d0938dd89c041cd4628ea6268101ffce8a2a63" + + "343540aa6d80de89236a574d9e6ead934e56900b6d9d738b0cae" + + "273dde4ef0aac56c78676c94529c37676c2defbbafdfa6903cc4" + + "47cf8d969e98a9b49fc5a650dcb3f0fb74170281805e830962bd" + + "ba7ca2bf4274f57c1cd269c9040d857e3e3d2412c3187bf329f3" + + "5f0e766c5975e44184699d32f3cd22abb035ba4ab23ce5d958b6" + + "624f5ddee59e0aca53b22cf79eb36b0a5b7965ec6e914e9220f6" + + "fcfc16edd3760ce2ec7fb269136b780e5a4664b45eb725a05a75" + + "3a4befc73c3ef7fd26b820c4990a9a73bec31902818100ba4493" + + "14ac34193b5f9160acf7b4d681053651533de865dcaf2edc613e" + + "c97db87f87f03b9b03822937ce724e11d5b1c10c07a099914a8d" + + "7fec79cff139b5e985ec62f7da7dbc644d223c0ef2d651f587d8" + + "99c011205d0f29fd5be2aed91cd921566dfc84d05fed10151c18" + + "21e7c43d4bd7d09e6a95cf22c9037b9ee36001fc2f02818011d0" + + "4bcf1b67b99f1075478665ae31c2c630ac590650d90fb57006f7" + + "f0d3c8627ca8da6ef6213fd37f5fea8aab3fd92a5ef351d2c230" + + "37e32da3750d1e4d2134d557705c89bf72ec4a6e68d5cd187433" + + "4e8c3a458fe69640eb63f919863a51dd894bb0f3f99f5d289538" + + "be35abca5ce7935334a1455d1339654246a19fcdf5bf"); + + /* Test that exception is thrown without private key available */ + try { + pkcs8 = key.privateKeyEncodePKCS8(); + fail("Rsa.privateKeyEncodePKCS8() should throw exception"); + } catch (IllegalStateException e) { + /* expected */ + } + + /* Test that encoded PKCS#8 private key matches expected */ + key.decodePrivateKey(prvKey); + pkcs8 = key.privateKeyEncodePKCS8(); + assertArrayEquals(pkcs8, expectedPkcs8); + key.releaseNativeStruct(); + + /* Test that generated key encodes without error */ + key = new Rsa(); + key.makeKey(1024, 65537, rng); + pkcs8 = key.privateKeyEncodePKCS8(); + assertTrue(pkcs8 != null); + assertTrue(pkcs8.length != 0); + key.releaseNativeStruct(); } @Test