Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions jni/include/com_wolfssl_wolfcrypt_Rsa.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 44 additions & 1 deletion jni/jni_rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/

#include <stdint.h>
#include <limits.h>

#ifdef WOLFSSL_USER_SETTINGS
#include <wolfssl/wolfcrypt/settings.h>
Expand Down Expand Up @@ -98,6 +99,47 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Rsa_rsaMinSize
return (jint)RSA_MIN_SIZE;
}

JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Rsa_rsaMinExponent
(JNIEnv *env, jclass jcl)
{
/* wc_MakeRsaKey() minimum public exponent, smallest odd e > 1 */
jlong minExp = 3;
(void)env;
(void)jcl;

#if !defined(NO_RSA) && defined(HAVE_FIPS)
/* FIPS 186-4/186-5 key generation requires e > 2^16 */
minExp = WC_RSA_EXPONENT;
#endif

return minExp;
}

JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_Rsa_keyGenSizeAllowed
(JNIEnv *env, jclass jcl, jint size)
{
(void)env;
(void)jcl;

#ifdef NO_RSA
(void)size;
return JNI_FALSE;
#else
if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE) {
return JNI_FALSE;
}

#ifdef WC_RSA_FIPS_GEN_MIN
/* wc_MakeRsaKey_fips() minimum, defined on FIPS v6+ */
if (size < WC_RSA_FIPS_GEN_MIN) {
return JNI_FALSE;
}
#endif

return JNI_TRUE;
#endif
}

JNIEXPORT void JNICALL
Java_com_wolfssl_wolfcrypt_Rsa_MakeRsaKey(
JNIEnv *env, jobject this, jint size, jlong e, jobject rng_object)
Expand All @@ -119,7 +161,8 @@ Java_com_wolfssl_wolfcrypt_Rsa_MakeRsaKey(
return;
}

if (key == NULL || rng == NULL) {
/* e is passed as a C long, reject values that would be truncated */
if (key == NULL || rng == NULL || e < LONG_MIN || e > LONG_MAX) {
ret = BAD_FUNC_ARG;
}
else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -426,11 +426,9 @@ else if (keysize == 8192) {

if (type == KeyType.WC_RSA || type == KeyType.WC_RSA_PSS) {

/* Sanity check on key size */
if (keysize < Rsa.RSA_MIN_SIZE) {
throw new InvalidParameterException(
"RSA key size too small, min is " +
Rsa.RSA_MIN_SIZE);
if (!Rsa.keyGenSizeAllowed(keysize)) {
throw new InvalidParameterException("RSA key size " + keysize +
" not supported for key generation");
}

/* Set default RSA exponent for wolfSSL */
Expand Down Expand Up @@ -474,13 +472,19 @@ public synchronized void initialize(AlgorithmParameterSpec params,
}

RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec)params;
if (!Rsa.keyGenSizeAllowed(rsaSpec.getKeysize())) {
throw new InvalidAlgorithmParameterException(
"RSA key size " + rsaSpec.getKeysize() +
" not supported for key generation");
}
this.keysize = rsaSpec.getKeysize();

/* Exponent should be larger than 1 and odd */
/* Exponent must be odd and at least the native minimum */
long exp = rsaSpec.getPublicExponent().longValue();
if ((exp <= 1) || (exp % 2 == 0)) {
if ((exp < Rsa.RSA_MIN_EXPONENT) || (exp % 2 == 0)) {
Comment thread
cconlon marked this conversation as resolved.
throw new InvalidAlgorithmParameterException(
"RSA public exponent must be positive and odd" );
"RSA public exponent must be odd and at least " +
Rsa.RSA_MIN_EXPONENT);
}
this.publicExponent = exp;

Expand Down
19 changes: 19 additions & 0 deletions src/main/java/com/wolfssl/wolfcrypt/Rsa.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ public class Rsa extends NativeStruct {
*/
public static final int RSA_MIN_SIZE = Rsa.rsaMinSize();

/**
* Minimum RSA public exponent for key generation, as supported by
* native wolfSSL. WC_RSA_EXPONENT (65537) on wolfCrypt FIPS builds per
* FIPS 186-4/186-5, otherwise 3.
*/
public static final long RSA_MIN_EXPONENT = Rsa.rsaMinExponent();

/** direct() operation, encrypt with public key */
public static final int RSA_PUBLIC_ENCRYPT = 0;
/** direct() operation, decrypt with public key */
Expand Down Expand Up @@ -167,6 +174,7 @@ private native byte[] wc_RsaSSL_Sign(byte[] data, Rng rng)
private native byte[] wc_RsaSSL_Verify(byte[] data)
throws WolfCryptException;
private static native int rsaMinSize();
private static native long rsaMinExponent();

/* RSA-PSS functions */
private native byte[] wc_RsaPSS_Sign(byte[] data, long hashType, int mgf,
Expand Down Expand Up @@ -258,6 +266,17 @@ public Rsa(byte[] n, byte[] e) throws WolfCryptException {
*/
public static native long getDefaultRsaExponent();

/**
* Checks if native wolfCrypt RSA key generation supports a key size,
* from native RSA_MIN_SIZE, RSA_MAX_SIZE, and the wolfCrypt FIPS v6+
* WC_RSA_FIPS_GEN_MIN.
*
* @param size RSA key size in bits
*
* @return true if key generation supports this size
*/
public static native boolean keyGenSizeAllowed(int size);

@Override
public synchronized void releaseNativeStruct() {
synchronized (stateLock) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,19 +158,10 @@ public static void testProviderInstallationAtRuntime() {
Provider p = Security.getProvider("wolfJCE");
assertNotNull(p);

/* FIPS after 2425 doesn't allow 1024-bit RSA key gen */
if ((!Fips.enabled || Fips.fipsVersion < 5) &&
(Rsa.RSA_MIN_SIZE <= 1024)) {
testedRSAKeySizes.add(Integer.valueOf(1024));
}
if (Rsa.RSA_MIN_SIZE <= 2048) {
testedRSAKeySizes.add(Integer.valueOf(2048));
}
if (Rsa.RSA_MIN_SIZE <= 3072) {
testedRSAKeySizes.add(Integer.valueOf(3072));
}
if (Rsa.RSA_MIN_SIZE <= 4096) {
testedRSAKeySizes.add(Integer.valueOf(4096));
for (int size : new int[] { 1024, 2048, 3072, 4096 }) {
if (Rsa.keyGenSizeAllowed(size)) {
testedRSAKeySizes.add(Integer.valueOf(size));
}
}

/* build list of enabled curves and key sizes,
Expand Down Expand Up @@ -267,10 +258,68 @@ public void testKeyPairGeneratorRsaInitializeWithParamSpec()
rsaSpec = new RSAKeyGenParameterSpec(10,
BigInteger.valueOf(Rsa.getDefaultRsaExponent()));
kpg.initialize(rsaSpec);
fail("RSA key size 10 should be rejected");
} catch (InvalidAlgorithmParameterException e) {}
}
}

@Test
public void testKeyPairGeneratorRsaInitializeWithBadKeySize()
throws NoSuchProviderException, NoSuchAlgorithmException {

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "wolfJCE");
BigInteger e = BigInteger.valueOf(Rsa.getDefaultRsaExponent());

/* Rejected sizes depend on native limits, MAX_VALUE never allowed */
assertFalse(Rsa.keyGenSizeAllowed(Integer.MAX_VALUE));
for (int size : new int[] { 10, 1024, 5000, Integer.MAX_VALUE }) {
if (Rsa.keyGenSizeAllowed(size)) {
continue;
}
try {
kpg.initialize(size);
fail("RSA key size " + size + " should be rejected");
} catch (InvalidParameterException ex) {
/* expected */
}
try {
kpg.initialize(new RSAKeyGenParameterSpec(size, e));
fail("RSA key size " + size + " should be rejected");
} catch (InvalidAlgorithmParameterException ex) {
/* expected */
}
}
}

@Test
public void testKeyPairGeneratorRsaInitializeWithBadExponent()
throws NoSuchProviderException, NoSuchAlgorithmException,
InvalidAlgorithmParameterException {

Assume.assumeTrue(testedRSAKeySizes.size() > 0);
int size = testedRSAKeySizes.get(0);
long[] badExps = {
-1, 0, 1, 4, Rsa.RSA_MIN_EXPONENT - 2, Rsa.RSA_MIN_EXPONENT + 1
};

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "wolfJCE");

for (long e : badExps) {
try {
kpg.initialize(new RSAKeyGenParameterSpec(size,
BigInteger.valueOf(e)));
fail("RSA public exponent " + e + " should be rejected");
} catch (InvalidAlgorithmParameterException ex) {
/* expected */
}
}

/* Minimum exponent must be accepted by native key generation */
kpg.initialize(new RSAKeyGenParameterSpec(size,
BigInteger.valueOf(Rsa.RSA_MIN_EXPONENT)));
assertNotNull(kpg.generateKeyPair());
}

@Test
public void testKeyPairGeneratorRsaInitializeWithKeySize()
throws NoSuchProviderException, NoSuchAlgorithmException,
Expand Down
Loading