diff --git a/src/test/java/KeyPairGeneratorSpecTest.java b/src/test/java/KeyPairGeneratorSpecTest.java
new file mode 100644
index 0000000..7406ccb
--- /dev/null
+++ b/src/test/java/KeyPairGeneratorSpecTest.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) Canonical, Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+import java.math.BigInteger;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.Security;
+import java.security.spec.ECGenParameterSpec;
+import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.IvParameterSpec;
+import com.canonical.openssl.provider.OpenSSLFIPSProvider;
+
+import org.junit.Test;
+import org.junit.BeforeClass;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+public class KeyPairGeneratorSpecTest {
+
+ @BeforeClass
+ public static void addProvider() {
+ Security.addProvider(new OpenSSLFIPSProvider());
+ }
+
+ private static KeyPairGenerator ec() throws Exception {
+ return KeyPairGenerator.getInstance("EC", "OpenSSLFIPSProvider");
+ }
+
+ private static KeyPairGenerator dh() throws Exception {
+ return KeyPairGenerator.getInstance("DH", "OpenSSLFIPSProvider");
+ }
+
+ private static void assertCurveAcceptedAndGenerates(String curveName) throws Exception {
+ KeyPairGenerator kpg = ec();
+ kpg.initialize(new ECGenParameterSpec(curveName));
+ KeyPair kp = kpg.generateKeyPair();
+ assertNotNull("Null KeyPair for " + curveName, kp);
+ assertNotNull("Null private key for " + curveName, kp.getPrivate());
+ assertNotNull("Null public key for " + curveName, kp.getPublic());
+ }
+
+ @Test
+ public void ecAcceptsCanonicalOpenSSLName_P256() throws Exception {
+ assertCurveAcceptedAndGenerates("prime256v1");
+ }
+
+ @Test
+ public void ecAcceptsSecName_P256() throws Exception {
+ assertCurveAcceptedAndGenerates("secp256r1");
+ }
+
+ @Test
+ public void ecAcceptsPName_P256() throws Exception {
+ assertCurveAcceptedAndGenerates("P-256");
+ }
+
+ @Test
+ public void ecAcceptsNistName_P256() throws Exception {
+ assertCurveAcceptedAndGenerates("NIST P-256");
+ }
+
+ @Test
+ public void ecAcceptsSecName_P384() throws Exception {
+ assertCurveAcceptedAndGenerates("secp384r1");
+ }
+
+ @Test
+ public void ecAcceptsPName_P384() throws Exception {
+ assertCurveAcceptedAndGenerates("P-384");
+ }
+
+ @Test
+ public void ecAcceptsNistName_P384() throws Exception {
+ assertCurveAcceptedAndGenerates("NIST P-384");
+ }
+
+ @Test
+ public void ecAcceptsSecName_P521() throws Exception {
+ assertCurveAcceptedAndGenerates("secp521r1");
+ }
+
+ @Test
+ public void ecAcceptsPName_P521() throws Exception {
+ assertCurveAcceptedAndGenerates("P-521");
+ }
+
+ @Test
+ public void ecAcceptsNistName_P521() throws Exception {
+ assertCurveAcceptedAndGenerates("NIST P-521");
+ }
+
+ @Test(expected = InvalidAlgorithmParameterException.class)
+ public void ecRejectsUnsupportedCurve() throws Exception {
+ ec().initialize(new ECGenParameterSpec("secp192r1"));
+ }
+
+ @Test(expected = InvalidAlgorithmParameterException.class)
+ public void ecRejectsNonECGenParameterSpec() throws Exception {
+ ec().initialize(new IvParameterSpec(new byte[16]));
+ }
+
+ @Test(expected = InvalidAlgorithmParameterException.class)
+ public void dhRejectsDHParameterSpec() throws Exception {
+ BigInteger p = new BigInteger(
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
+ + "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
+ + "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
+ + "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
+ + "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8"
+ + "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ + "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 16);
+ BigInteger g = BigInteger.valueOf(2);
+ dh().initialize(new DHParameterSpec(p, g));
+ }
+
+ @Test
+ public void ecKeysizeStillWorks() throws Exception {
+ KeyPairGenerator kpg = ec();
+ kpg.initialize(384);
+ assertNotNull(kpg.generateKeyPair());
+ }
+
+ @Test
+ public void dhKeysizeStillWorks() throws Exception {
+ KeyPairGenerator kpg = dh();
+ kpg.initialize(2048);
+ assertNotNull(kpg.generateKeyPair());
+ }
+
+ @Test
+ public void ecKeysizeUnsupportedThrows() {
+ try {
+ ec().initialize(123);
+ fail("expected IllegalArgumentException for unsupported EC keysize");
+ } catch (IllegalArgumentException expected) {
+ } catch (Exception e) {
+ fail("expected IllegalArgumentException, got " + e.getClass().getName());
+ }
+ }
+
+ @Test
+ public void dhKeysizeUnsupportedThrows() {
+ try {
+ dh().initialize(1024);
+ fail("expected IllegalArgumentException for unsupported DH keysize");
+ } catch (IllegalArgumentException expected) {
+ } catch (Exception e) {
+ fail("expected IllegalArgumentException, got " + e.getClass().getName());
+ }
+ }
+}
diff --git a/src/test/java/PSSParameterTest.java b/src/test/java/PSSParameterTest.java
new file mode 100644
index 0000000..d8b0f32
--- /dev/null
+++ b/src/test/java/PSSParameterTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) Canonical, Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+import com.canonical.openssl.provider.OpenSSLFIPSProvider;
+
+import java.security.AlgorithmParameters;
+import java.security.Security;
+import java.security.Signature;
+import java.security.spec.MGF1ParameterSpec;
+import java.security.spec.PSSParameterSpec;
+
+import java.security.InvalidAlgorithmParameterException;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+public class PSSParameterTest {
+
+ @BeforeClass
+ public static void addProvider() {
+ Security.addProvider(new OpenSSLFIPSProvider());
+ }
+
+ @Test
+ public void testExplicitPSSParametersRoundTrip() throws Exception {
+ Signature sig = Signature.getInstance("RSAwithSHA256", "OpenSSLFIPSProvider");
+
+ PSSParameterSpec original = new PSSParameterSpec(
+ "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1);
+ sig.setParameter(original);
+
+ AlgorithmParameters ap = sig.getParameters();
+ assertNotNull("getParameters() must not return null after PSS params are set", ap);
+
+ PSSParameterSpec returned = ap.getParameterSpec(PSSParameterSpec.class);
+ assertEquals("digest algorithm", "SHA-256", returned.getDigestAlgorithm());
+ assertEquals("MGF algorithm", "MGF1", returned.getMGFAlgorithm());
+ assertEquals("salt length", 32, returned.getSaltLength());
+ assertEquals("trailer field", 1, returned.getTrailerField());
+
+ MGF1ParameterSpec mgf1 = (MGF1ParameterSpec) returned.getMGFParameters();
+ assertNotNull("MGF1 parameters must not be null", mgf1);
+ assertEquals("MGF1 digest", "SHA-256", mgf1.getDigestAlgorithm());
+ }
+
+ @Test
+ public void testMGF1DigestDefaultsToMessageDigest() throws Exception {
+ Signature sig = Signature.getInstance("RSAwithSHA256", "OpenSSLFIPSProvider");
+
+ // PSSParameterSpec(int) leaves MGFParameters null; mgf1Digest must fall
+ // back to the message digest ("SHA-1") inside engineGetParameters().
+ sig.setParameter(new PSSParameterSpec(20));
+
+ AlgorithmParameters ap = sig.getParameters();
+ assertNotNull("getParameters() must not return null after PSS params are set", ap);
+
+ PSSParameterSpec returned = ap.getParameterSpec(PSSParameterSpec.class);
+ assertEquals("message digest", "SHA-1", returned.getDigestAlgorithm());
+
+ MGF1ParameterSpec mgf1 = (MGF1ParameterSpec) returned.getMGFParameters();
+ assertNotNull("MGF1 parameters must not be null", mgf1);
+ assertEquals("MGF1 digest must default to message digest", "SHA-1", mgf1.getDigestAlgorithm());
+ }
+
+ @Test
+ public void testRejectsNonMGF1Algorithm() throws Exception {
+ Signature sig = Signature.getInstance("RSAwithSHA256", "OpenSSLFIPSProvider");
+ try {
+ sig.setParameter(new PSSParameterSpec(
+ "SHA-256", "SHAKE128", MGF1ParameterSpec.SHA256, 32, 1));
+ fail("Expected InvalidAlgorithmParameterException for non-MGF1 MGF");
+ } catch (InvalidAlgorithmParameterException expected) {
+ // correct
+ }
+ }
+
+ @Test
+ public void testRejectsNonOneTrailerField() throws Exception {
+ Signature sig = Signature.getInstance("RSAwithSHA256", "OpenSSLFIPSProvider");
+ try {
+ sig.setParameter(new PSSParameterSpec(
+ "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 2));
+ fail("Expected InvalidAlgorithmParameterException for trailerField != 1");
+ } catch (InvalidAlgorithmParameterException expected) {
+ // correct
+ }
+ }
+}