Skip to content

Commit 34d52b7

Browse files
authored
Merge pull request #155 from cconlon/rsaKeyPairGenDefaultParams
Default RSA KeyPairGenerator params, null AlgorithmParameters for non-PSS, RSA exponent sanitization
2 parents 2fd62a2 + 6851635 commit 34d52b7

File tree

4 files changed

+261
-29
lines changed

4 files changed

+261
-29
lines changed

src/main/java/com/wolfssl/provider/jce/WolfCryptKeyPairGenerator.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,20 @@ private WolfCryptKeyPairGenerator(KeyType type) {
8383

8484
this.type = type;
8585

86+
/* Set default parameters for RSA key generation */
87+
if (type == KeyType.WC_RSA) {
88+
this.keysize = 2048; /* Default RSA key size */
89+
this.publicExponent = Rsa.getDefaultRsaExponent();
90+
91+
/* Initialize RNG for default key generation */
92+
synchronized (rngLock) {
93+
if (this.rng == null) {
94+
this.rng = new Rng();
95+
this.rng.init();
96+
}
97+
}
98+
}
99+
86100
if (WolfCryptDebug.DEBUG) {
87101
algString = typeToString(type);
88102
}
@@ -142,8 +156,13 @@ public synchronized void initialize(AlgorithmParameterSpec params,
142156
RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec)params;
143157
this.keysize = rsaSpec.getKeysize();
144158

145-
this.publicExponent =
146-
rsaSpec.getPublicExponent().longValue();
159+
/* Exponent should be larger than 1 and odd */
160+
long exp = rsaSpec.getPublicExponent().longValue();
161+
if ((exp <= 1) || (exp % 2 == 0)) {
162+
throw new InvalidAlgorithmParameterException(
163+
"RSA public exponent must be positive and odd" );
164+
}
165+
this.publicExponent = exp;
147166

148167
/* Double check longValue() converted correctly. Some platforms
149168
* do not have longValueExact() */

src/main/java/com/wolfssl/provider/jce/WolfCryptSignature.java

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -534,41 +534,50 @@ protected synchronized void engineSetParameter(
534534
AlgorithmParameterSpec params)
535535
throws InvalidAlgorithmParameterException {
536536

537-
if (this.paddingType != PaddingType.WC_RSA_PSS) {
538-
throw new InvalidAlgorithmParameterException(
539-
"Parameters only supported for RSA-PSS");
540-
}
541-
542-
if (!(params instanceof PSSParameterSpec)) {
543-
throw new InvalidAlgorithmParameterException(
544-
"Only PSSParameterSpec supported");
545-
}
537+
/* For RSA-PSS signatures, parameters are required */
538+
if (this.paddingType == PaddingType.WC_RSA_PSS) {
539+
if (!(params instanceof PSSParameterSpec)) {
540+
throw new InvalidAlgorithmParameterException(
541+
"Only PSSParameterSpec supported for RSA-PSS");
542+
}
546543

547-
PSSParameterSpec pss = (PSSParameterSpec)params;
548-
validatePSSParameters(pss);
549-
this.pssParams = pss;
544+
PSSParameterSpec pss = (PSSParameterSpec)params;
545+
validatePSSParameters(pss);
546+
this.pssParams = pss;
550547

551-
/* For RSASSA-PSS, (re)initialize digest based on parameters */
552-
String hashAlg = pss.getDigestAlgorithm();
553-
DigestType newDigestType = javaNameToDigestType(hashAlg);
548+
/* For RSASSA-PSS, (re)initialize digest based on parameters */
549+
String hashAlg = pss.getDigestAlgorithm();
550+
DigestType newDigestType = javaNameToDigestType(hashAlg);
554551

555-
/* Check if digest type has changed or needs initialization */
556-
if (this.digestType == null || this.digestType != newDigestType) {
557-
this.digestType = newDigestType;
552+
/* Check if digest type has changed or needs initialization */
553+
if (this.digestType == null || this.digestType != newDigestType) {
554+
this.digestType = newDigestType;
558555

559-
try {
560-
/* (re)initialize with the new digest type */
561-
init(this.keyType, this.digestType, this.paddingType);
556+
try {
557+
/* (re)initialize with the new digest type */
558+
init(this.keyType, this.digestType, this.paddingType);
562559

563-
/* Initialize hash object for existing key if already set */
564-
if ((this.rsa != null || this.ecc != null)) {
565-
initHashObject();
560+
/* Initialize hash object for existing key if already set */
561+
if ((this.rsa != null || this.ecc != null)) {
562+
initHashObject();
563+
}
564+
} catch (NoSuchAlgorithmException e) {
565+
throw new InvalidAlgorithmParameterException(
566+
"Failed to initialize with digest: " + hashAlg, e);
566567
}
567-
} catch (NoSuchAlgorithmException e) {
568-
throw new InvalidAlgorithmParameterException(
569-
"Failed to initialize with digest: " + hashAlg, e);
570568
}
569+
return;
571570
}
571+
572+
/* For non-PSS signatures, allow null parameters (ignore) */
573+
if (params == null) {
574+
return;
575+
}
576+
577+
/* For non-PSS signatures, reject any non-null parameters */
578+
throw new InvalidAlgorithmParameterException(
579+
"Parameters not supported for " +
580+
keyTypeToString(this.keyType) + " with PKCS#1 v1.5 padding");
572581
}
573582

574583
@Override

src/test/java/com/wolfssl/provider/jce/test/WolfCryptKeyPairGeneratorTest.java

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
import java.security.spec.ECGenParameterSpec;
5050
import java.security.spec.X509EncodedKeySpec;
5151
import java.security.spec.PKCS8EncodedKeySpec;
52+
import java.security.interfaces.RSAPrivateKey;
53+
import java.security.interfaces.RSAPublicKey;
5254

5355
import com.wolfssl.wolfcrypt.Rsa;
5456
import com.wolfssl.wolfcrypt.Ecc;
@@ -556,6 +558,40 @@ public void testKeyPairGeneratorDhMultipleKeyGen()
556558
assertNotNull(kp2);
557559
}
558560

561+
@Test
562+
public void testKeyPairGeneratorRsaDefaultKeySize()
563+
throws NoSuchProviderException, NoSuchAlgorithmException {
564+
565+
/* Test that RSA KeyPairGenerator works with default parameters
566+
* without explicit initialization */
567+
KeyPairGenerator kpg =
568+
KeyPairGenerator.getInstance("RSA", "wolfJCE");
569+
570+
/* Generate key pair without calling initialize() first */
571+
KeyPair kp = kpg.generateKeyPair();
572+
assertNotNull(kp);
573+
assertNotNull(kp.getPublic());
574+
assertNotNull(kp.getPrivate());
575+
576+
/* Verify the generated key is RSA and has expected default size */
577+
assertTrue(kp.getPublic() instanceof RSAPublicKey);
578+
assertTrue(kp.getPrivate() instanceof RSAPrivateKey);
579+
580+
RSAPublicKey pubKey = (RSAPublicKey) kp.getPublic();
581+
RSAPrivateKey privKey = (RSAPrivateKey) kp.getPrivate();
582+
583+
/* Default key size should be 2048 bits */
584+
assertEquals("Default RSA key size should be 2048 bits",
585+
2048, pubKey.getModulus().bitLength());
586+
assertEquals("Private key modulus should match public key",
587+
pubKey.getModulus(), privKey.getModulus());
588+
589+
/* Verify the default public exponent */
590+
assertEquals("Default RSA public exponent should match wolfSSL default",
591+
BigInteger.valueOf(Rsa.getDefaultRsaExponent()),
592+
pubKey.getPublicExponent());
593+
}
594+
559595
@Test
560596
public void testKeyPairGeneratorRsassaPssKeyGeneration()
561597
throws NoSuchProviderException, NoSuchAlgorithmException,
@@ -596,5 +632,59 @@ public void testKeyPairGeneratorRsassaPssKeyGeneration()
596632
}
597633
}
598634
}
635+
636+
@Test
637+
public void testKeyPairGenerationInvalidExponent()
638+
throws NoSuchProviderException, NoSuchAlgorithmException,
639+
InvalidAlgorithmParameterException {
640+
641+
if (testedRSAKeySizes.size() > 0) {
642+
643+
KeyPairGenerator kpg =
644+
KeyPairGenerator.getInstance("RSA", "wolfJCE");
645+
646+
/* Negative exponent */
647+
try {
648+
RSAKeyGenParameterSpec rsaSpec =
649+
new RSAKeyGenParameterSpec(testedRSAKeySizes.get(0),
650+
BigInteger.valueOf(-1));
651+
kpg.initialize(rsaSpec);
652+
fail("KeyPairGenerator.initialize() should throw " +
653+
"InvalidAlgorithmParameterException when given " +
654+
"invalid negative RSA public exponent");
655+
656+
} catch (InvalidAlgorithmParameterException e) {
657+
/* expected */
658+
}
659+
660+
/* Zero exponent */
661+
try {
662+
RSAKeyGenParameterSpec rsaSpec =
663+
new RSAKeyGenParameterSpec(testedRSAKeySizes.get(0),
664+
BigInteger.valueOf(0));
665+
kpg.initialize(rsaSpec);
666+
fail("KeyPairGenerator.initialize() should throw " +
667+
"InvalidAlgorithmParameterException when given " +
668+
"invalid RSA public exponent of zero");
669+
670+
} catch (InvalidAlgorithmParameterException e) {
671+
/* expected */
672+
}
673+
674+
/* Even exponent */
675+
try {
676+
RSAKeyGenParameterSpec rsaSpec =
677+
new RSAKeyGenParameterSpec(testedRSAKeySizes.get(0),
678+
BigInteger.valueOf(4));
679+
kpg.initialize(rsaSpec);
680+
fail("KeyPairGenerator.initialize() should throw " +
681+
"InvalidAlgorithmParameterException when given " +
682+
"invalid even RSA public exponent");
683+
684+
} catch (InvalidAlgorithmParameterException e) {
685+
/* expected */
686+
}
687+
}
688+
}
599689
}
600690

src/test/java/com/wolfssl/provider/jce/test/WolfCryptSignatureTest.java

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,5 +1929,119 @@ private void testRsaPssZeroSalt()
19291929

19301930
assertTrue("RSA-PSS verification failed with zero salt", verified);
19311931
}
1932+
1933+
@Test
1934+
public void testNonPssSignatureNullParameters()
1935+
throws NoSuchProviderException, NoSuchAlgorithmException,
1936+
SignatureException, InvalidKeyException,
1937+
InvalidAlgorithmParameterException {
1938+
1939+
/* Test that non-PSS signatures accept null parameters */
1940+
String message = "Testing null parameters for non-PSS signatures";
1941+
byte[] messageBytes = message.getBytes();
1942+
1943+
for (String algo : enabledAlgos) {
1944+
if (algo.contains("PSS")) {
1945+
continue; /* Skip PSS algorithms */
1946+
}
1947+
1948+
/* Generate appropriate key pair */
1949+
KeyPair pair = generateKeyPair(algo, secureRandom);
1950+
assertNotNull("Key pair should not be null for " + algo, pair);
1951+
1952+
PrivateKey priv = pair.getPrivate();
1953+
PublicKey pub = pair.getPublic();
1954+
1955+
/* Create signature instances */
1956+
Signature signer = Signature.getInstance(algo, "wolfJCE");
1957+
Signature verifier = Signature.getInstance(algo, "wolfJCE");
1958+
1959+
assertNotNull("Signer should not be null for " + algo, signer);
1960+
assertNotNull("Verifier should not be null for " + algo, verifier);
1961+
1962+
/* Test setting null parameters - should not throw exception */
1963+
try {
1964+
signer.setParameter(null);
1965+
verifier.setParameter(null);
1966+
} catch (InvalidAlgorithmParameterException e) {
1967+
fail("Should not throw exception when setting null " +
1968+
"parameters for non-PSS algorithm: " + algo +
1969+
". Error: " + e.getMessage());
1970+
}
1971+
1972+
/* Test that signature still works after setting null parameters */
1973+
signer.initSign(priv);
1974+
signer.update(messageBytes);
1975+
byte[] signature = signer.sign();
1976+
1977+
assertNotNull("Signature should not be null for " + algo +
1978+
" with null parameters", signature);
1979+
assertTrue("Signature should have non-zero length for " + algo +
1980+
" with null parameters", signature.length > 0);
1981+
1982+
/* Verify signature */
1983+
verifier.initVerify(pub);
1984+
verifier.update(messageBytes);
1985+
boolean verified = verifier.verify(signature);
1986+
1987+
assertTrue("Signature verification should succeed for " + algo +
1988+
" with null parameters", verified);
1989+
}
1990+
}
1991+
1992+
@Test
1993+
public void testNonPssSignatureRejectsNonNullParameters()
1994+
throws NoSuchProviderException, NoSuchAlgorithmException,
1995+
SignatureException, InvalidKeyException,
1996+
InvalidAlgorithmParameterException {
1997+
1998+
/* Test that non-PSS signatures reject non-null parameters */
1999+
for (String algo : enabledAlgos) {
2000+
if (algo.contains("PSS")) {
2001+
continue; /* Skip PSS algorithms */
2002+
}
2003+
2004+
/* Only test a algo subset to get coverage */
2005+
if (!algo.equals("SHA256withRSA") &&
2006+
!algo.equals("SHA256withECDSA")) {
2007+
continue;
2008+
}
2009+
2010+
/* Generate appropriate key pair */
2011+
KeyPair pair = generateKeyPair(algo, secureRandom);
2012+
assertNotNull("Key pair should not be null for " + algo, pair);
2013+
2014+
/* Create signature instance */
2015+
Signature signer = Signature.getInstance(algo, "wolfJCE");
2016+
assertNotNull("Signer should not be null for " + algo, signer);
2017+
2018+
/* Test setting PSS parameters on non-PSS algorithm should fail */
2019+
java.security.spec.PSSParameterSpec pssSpec =
2020+
new java.security.spec.PSSParameterSpec("SHA-256", "MGF1",
2021+
java.security.spec.MGF1ParameterSpec.SHA256, 32, 1);
2022+
2023+
try {
2024+
signer.setParameter(pssSpec);
2025+
fail("Should have thrown InvalidAlgorithmParameterException " +
2026+
"when setting PSS parameters on non-PSS algorithm: " +
2027+
algo);
2028+
} catch (InvalidAlgorithmParameterException e) {
2029+
/* Expected */
2030+
}
2031+
2032+
/* Test setting some other non-null parameter object should fail */
2033+
java.security.spec.ECGenParameterSpec ecSpec =
2034+
new java.security.spec.ECGenParameterSpec("secp256r1");
2035+
2036+
try {
2037+
signer.setParameter(ecSpec);
2038+
fail("Should have thrown InvalidAlgorithmParameterException " +
2039+
"when setting non-null parameters on non-PSS algorithm: " +
2040+
algo);
2041+
} catch (InvalidAlgorithmParameterException e) {
2042+
/* Expected */
2043+
}
2044+
}
2045+
}
19322046
}
19332047

0 commit comments

Comments
 (0)