F-5224 / F-5796: enforce 512-bit minimum DH prime in KeyPairGenerator spec init
parent
a02707230d
commit
e314b928b5
|
|
@ -19,6 +19,14 @@ extern "C" {
|
|||
#define com_wolfssl_wolfcrypt_Dh_WC_FFDHE_6144 259L
|
||||
#undef com_wolfssl_wolfcrypt_Dh_WC_FFDHE_8192
|
||||
#define com_wolfssl_wolfcrypt_Dh_WC_FFDHE_8192 260L
|
||||
/*
|
||||
* Class: com_wolfssl_wolfcrypt_Dh
|
||||
* Method: dhMinSize
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Dh_dhMinSize
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: com_wolfssl_wolfcrypt_Dh
|
||||
* Method: mallocNativeStruct_internal
|
||||
|
|
|
|||
25
jni/jni_dh.c
25
jni/jni_dh.c
|
|
@ -41,6 +41,18 @@
|
|||
#define RNG WC_RNG
|
||||
#endif
|
||||
|
||||
/* Some FIPS versions don't have DH_MIN_SIZE defined. Values match those
|
||||
* used by wolfSSL settings.h. */
|
||||
#ifndef DH_MIN_SIZE
|
||||
#ifdef HAVE_FIPS
|
||||
#define DH_MIN_SIZE 2048
|
||||
#elif defined(WOLFSSL_MIN_DHKEY_BITS)
|
||||
#define DH_MIN_SIZE WOLFSSL_MIN_DHKEY_BITS
|
||||
#else
|
||||
#define DH_MIN_SIZE 1024
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Some FIPS versions don't have DH_MAX_SIZE defined */
|
||||
#ifndef DH_MAX_SIZE
|
||||
#ifdef USE_FAST_MATH
|
||||
|
|
@ -60,6 +72,19 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Dh_dhMinSize
|
||||
(JNIEnv* env, jclass jcl)
|
||||
{
|
||||
(void)env;
|
||||
(void)jcl;
|
||||
|
||||
#if !defined(NO_DH)
|
||||
return (jint)DH_MIN_SIZE;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Dh_mallocNativeStruct_1internal(
|
||||
JNIEnv* env, jobject this)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -476,14 +476,31 @@ public class WolfCryptKeyPairGenerator extends KeyPairGeneratorSpi {
|
|||
}
|
||||
|
||||
DHParameterSpec dhSpec = (DHParameterSpec)params;
|
||||
this.dhP = dhSpec.getP().toByteArray();
|
||||
this.dhG = dhSpec.getG().toByteArray();
|
||||
BigInteger dhSpecP = dhSpec.getP();
|
||||
BigInteger dhSpecG = dhSpec.getG();
|
||||
|
||||
if (dhP == null || dhG == null) {
|
||||
if (dhSpecP == null || dhSpecG == null) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Invalid parameters, either p or g is null");
|
||||
}
|
||||
|
||||
if (dhSpecP.signum() <= 0 || dhSpecG.signum() <= 0) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"DH parameters p and g must be positive");
|
||||
}
|
||||
|
||||
/* Reject primes the native library would refuse, so the
|
||||
* failure throws here instead of from generateKeyPair() */
|
||||
int dhPrimeBits = dhSpecP.bitLength();
|
||||
if (dhPrimeBits < Dh.DH_MIN_SIZE) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"DH prime size must be at least " + Dh.DH_MIN_SIZE +
|
||||
" bits, got " + dhPrimeBits);
|
||||
}
|
||||
|
||||
this.dhP = dhSpecP.toByteArray();
|
||||
this.dhG = dhSpecG.toByteArray();
|
||||
|
||||
log("init with spec, prime len: " + this.dhP.length);
|
||||
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,13 @@ public class Dh extends NativeStruct {
|
|||
/** Lock around object state */
|
||||
protected final Object stateLock = new Object();
|
||||
|
||||
/**
|
||||
* Minimum DH prime size in bits accepted by the native wolfSSL build.
|
||||
* Tracks native DH_MIN_SIZE, which is build configurable through
|
||||
* WOLFSSL_MIN_DHKEY_BITS.
|
||||
*/
|
||||
public static final int DH_MIN_SIZE = Dh.dhMinSize();
|
||||
|
||||
/* Named DH group constants (FFDHE from RFC 7919) */
|
||||
/** FFDHE 2048-bit group */
|
||||
public static final int WC_FFDHE_2048 = 256;
|
||||
|
|
@ -103,6 +110,7 @@ public class Dh extends NativeStruct {
|
|||
}
|
||||
}
|
||||
|
||||
private static native int dhMinSize();
|
||||
private native long mallocNativeStruct_internal() throws OutOfMemoryError;
|
||||
private native void wc_InitDhKey();
|
||||
private native void wc_FreeDhKey();
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ import java.security.interfaces.ECPrivateKey;
|
|||
import java.security.spec.ECParameterSpec;
|
||||
|
||||
import com.wolfssl.wolfcrypt.Rsa;
|
||||
import com.wolfssl.wolfcrypt.Dh;
|
||||
import com.wolfssl.wolfcrypt.Ecc;
|
||||
import com.wolfssl.wolfcrypt.Fips;
|
||||
import com.wolfssl.wolfcrypt.FeatureDetect;
|
||||
|
|
@ -598,7 +599,7 @@ public class WolfCryptKeyPairGeneratorTest {
|
|||
KeyPairGenerator.getInstance("DH", "wolfJCE");
|
||||
|
||||
DHParameterSpec spec = new DHParameterSpec(
|
||||
new BigInteger(prime),
|
||||
new BigInteger(1, prime),
|
||||
new BigInteger(base),
|
||||
testDHKeySizes[i]);
|
||||
|
||||
|
|
@ -609,6 +610,103 @@ public class WolfCryptKeyPairGeneratorTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeyPairGeneratorDhRejectsSmallPrimeSpec()
|
||||
throws NoSuchProviderException, NoSuchAlgorithmException,
|
||||
InvalidAlgorithmParameterException {
|
||||
|
||||
/* skip test if DH is not compiled in native wolfSSL */
|
||||
if (!FeatureDetect.DhEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH", "wolfJCE");
|
||||
|
||||
/* 255-bit prime (Curve25519 field prime), below the 512-bit min,
|
||||
* must be rejected before key generation */
|
||||
DHParameterSpec weakSpec = new DHParameterSpec(
|
||||
new BigInteger("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +
|
||||
"FFFFFFFFFFFFFFFFFFED", 16),
|
||||
new BigInteger(base));
|
||||
|
||||
try {
|
||||
kpg.initialize(weakSpec);
|
||||
fail("initialize(DHParameterSpec) should reject a prime " +
|
||||
"below the native minimum");
|
||||
} catch (InvalidAlgorithmParameterException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
/* Positive check: 2048-bit prime spec should be accepted */
|
||||
DHParameterSpec goodSpec = new DHParameterSpec(
|
||||
new BigInteger(1, prime), new BigInteger(base));
|
||||
kpg.initialize(goodSpec);
|
||||
assertNotNull(kpg.generateKeyPair());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeyPairGeneratorDhRejectsNonPositiveParams()
|
||||
throws NoSuchProviderException, NoSuchAlgorithmException,
|
||||
InvalidAlgorithmParameterException {
|
||||
|
||||
/* skip test if DH is not compiled in native wolfSSL */
|
||||
if (!FeatureDetect.DhEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BigInteger goodP = new BigInteger(1, prime);
|
||||
BigInteger goodG = new BigInteger(base);
|
||||
|
||||
/* A negative p can still clear the minimum bit length check */
|
||||
BigInteger[][] bad = new BigInteger[][] {
|
||||
{ goodP.negate(), goodG },
|
||||
{ goodP, goodG.negate() },
|
||||
{ BigInteger.ZERO, goodG },
|
||||
{ goodP, BigInteger.ZERO }
|
||||
};
|
||||
|
||||
for (BigInteger[] pg : bad) {
|
||||
KeyPairGenerator kpg =
|
||||
KeyPairGenerator.getInstance("DH", "wolfJCE");
|
||||
try {
|
||||
kpg.initialize(new DHParameterSpec(pg[0], pg[1]));
|
||||
fail("initialize() should reject non-positive DH params");
|
||||
} catch (InvalidAlgorithmParameterException e) {
|
||||
/* expected */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeyPairGeneratorDhRejectedSpecLeavesStateIntact()
|
||||
throws NoSuchProviderException, NoSuchAlgorithmException,
|
||||
InvalidAlgorithmParameterException {
|
||||
|
||||
/* skip test if DH is not compiled in native wolfSSL */
|
||||
if (!FeatureDetect.DhEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH", "wolfJCE");
|
||||
kpg.initialize(2048);
|
||||
|
||||
DHParameterSpec weakSpec = new DHParameterSpec(
|
||||
BigInteger.ONE.shiftLeft(255).setBit(0), new BigInteger(base));
|
||||
|
||||
try {
|
||||
kpg.initialize(weakSpec);
|
||||
fail("initialize(DHParameterSpec) should reject a prime " +
|
||||
"below the native minimum");
|
||||
} catch (InvalidAlgorithmParameterException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
/* The rejected spec must not have replaced the 2048-bit params */
|
||||
DHPrivateKey priv = (DHPrivateKey)kpg.generateKeyPair().getPrivate();
|
||||
assertTrue("Rejected spec must not weaken generator state",
|
||||
priv.getParams().getP().bitLength() >= Dh.DH_MIN_SIZE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeyPairGeneratorDhInitWithKeySize()
|
||||
throws NoSuchProviderException, NoSuchAlgorithmException,
|
||||
|
|
@ -684,7 +782,7 @@ public class WolfCryptKeyPairGeneratorTest {
|
|||
KeyPairGenerator.getInstance("DH", "wolfJCE");
|
||||
|
||||
DHParameterSpec spec = new DHParameterSpec(
|
||||
new BigInteger(prime), new BigInteger(base), 512);
|
||||
new BigInteger(1, prime), new BigInteger(base), 512);
|
||||
|
||||
kpg.initialize(spec);
|
||||
kpg.initialize(spec);
|
||||
|
|
@ -704,7 +802,7 @@ public class WolfCryptKeyPairGeneratorTest {
|
|||
KeyPairGenerator.getInstance("DH", "wolfJCE");
|
||||
|
||||
DHParameterSpec spec = new DHParameterSpec(
|
||||
new BigInteger(prime), new BigInteger(base), 512);
|
||||
new BigInteger(1, prime), new BigInteger(base), 512);
|
||||
|
||||
kpg.initialize(spec);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue