diff --git a/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java b/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java index a7c9c3362f..04c2911ce7 100644 --- a/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java +++ b/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java @@ -227,7 +227,12 @@ protected void doInitFromKey(Key key, AlgorithmParameterSpec parameterSpec, Secu MQVPrivateParameters localParams = new MQVPrivateParameters(staticPrivKey, ephemPrivKey, ephemPubKey); this.parameters = staticPrivKey.getParameters(); - // TODO Validate that all the keys are using the same parameters? + validateSameDomainParameters(staticPrivKey.getParameters(), ephemPrivKey.getParameters()); + + if (ephemPubKey != null) + { + validateSameDomainParameters(staticPrivKey.getParameters(), ephemPubKey.getParameters()); + } ((ECMQVBasicAgreement)agreement).init(localParams); } @@ -286,6 +291,20 @@ private static String getSimpleName(Class clazz) return fullName.substring(fullName.lastIndexOf('.') + 1); } + + private static void validateSameDomainParameters(ECDomainParameters a, ECDomainParameters b) + throws InvalidKeyException + { + if (a == b) + { + return; + } + + if (a == null || !a.equals(b)) + { + throw new InvalidKeyException("EC domain parameters do not match"); + } + } protected byte[] doCalcSecret() { diff --git a/prov/src/test/java/org/bouncycastle/jcajce/provider/test/AllTests.java b/prov/src/test/java/org/bouncycastle/jcajce/provider/test/AllTests.java index b14545d2f2..5eeaac6a18 100644 --- a/prov/src/test/java/org/bouncycastle/jcajce/provider/test/AllTests.java +++ b/prov/src/test/java/org/bouncycastle/jcajce/provider/test/AllTests.java @@ -34,6 +34,7 @@ public static Test suite() suite.addTestSuite(BouncyCastleProviderTest.class); suite.addTestSuite(PQCSignatureTest.class); suite.addTestSuite(SecretKeyUtilTest.class); + suite.addTestSuite(ECKeyAgreementDomainValidationTest.class); return new BCTestSetup(suite); } diff --git a/prov/src/test/java/org/bouncycastle/jcajce/provider/test/ECKeyAgreementDomainValidationTest.java b/prov/src/test/java/org/bouncycastle/jcajce/provider/test/ECKeyAgreementDomainValidationTest.java new file mode 100644 index 0000000000..09eab78661 --- /dev/null +++ b/prov/src/test/java/org/bouncycastle/jcajce/provider/test/ECKeyAgreementDomainValidationTest.java @@ -0,0 +1,72 @@ +package org.bouncycastle.jcajce.provider.test; + +import junit.framework.TestCase; +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import javax.crypto.KeyAgreement; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.Security; +import java.security.spec.ECGenParameterSpec; + +public class ECKeyAgreementDomainValidationTest extends TestCase { + protected void setUp() { + Security.addProvider(new BouncyCastleProvider()); + } + + protected void tearDown() { + Security.removeProvider("BC"); + } + + /** + * Same curve should succeed. + */ + public void testSameCurveAgreement() + throws Exception { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "BC"); + + kpg.initialize(new ECGenParameterSpec("secp256r1")); + + KeyPair kp1 = kpg.generateKeyPair(); + KeyPair kp2 = kpg.generateKeyPair(); + + KeyAgreement ka1 = KeyAgreement.getInstance("ECDH", "BC"); + KeyAgreement ka2 = KeyAgreement.getInstance("ECDH", "BC"); + + ka1.init(kp1.getPrivate()); + ka1.doPhase(kp2.getPublic(), true); + + ka2.init(kp2.getPrivate()); + ka2.doPhase(kp1.getPublic(), true); + + byte[] s1 = ka1.generateSecret(); + byte[] s2 = ka2.generateSecret(); + + assertTrue(java.util.Arrays.equals(s1, s2)); + } + + /** + * Different curves should fail due to domain parameter mismatch. + */ + public void testDifferentCurveAgreement() + throws Exception { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "BC"); + + kpg.initialize(new ECGenParameterSpec("secp256r1")); + KeyPair kp256 = kpg.generateKeyPair(); + + kpg.initialize(new ECGenParameterSpec("secp384r1")); + KeyPair kp384 = kpg.generateKeyPair(); + + KeyAgreement ka = KeyAgreement.getInstance("ECDH", "BC"); + + try { + ka.init(kp256.getPrivate()); + ka.doPhase(kp384.getPublic(), true); + + fail("Expected InvalidKeyException for mismatched EC domain parameters"); + } catch (java.security.InvalidKeyException e) { + // expected + } + } +} \ No newline at end of file