diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index e0746ab792b2..370cb395e47b 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -205,6 +205,10 @@ Key exchange ``vectors/cryptography_vectors/asymmetric/DH/dhpub.der`` contains are the above parameters and keys in DER format. + ``vectors/cryptography_vectors/asymmetric/DH/dhpub_v41_0_7.pem`` contains + a Diffie-Hellman public key created with version 41.0.7 of this + package. + * ``vectors/cryptography_vectors/asymmetric/DH/dhp_rfc5114_2.pem``, ``vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.pem`` and ``vectors/cryptography_vectors/asymmetric/DH/dhpub_rfc5114_2.pem`` contains diff --git a/src/rust/src/backend/dh.rs b/src/rust/src/backend/dh.rs index 008f0674a07b..66ec8bbe9fe1 100644 --- a/src/rust/src/backend/dh.rs +++ b/src/rust/src/backend/dh.rs @@ -12,6 +12,13 @@ use pyo3::prelude::{PyAnyMethods, PyModuleMethods}; const MIN_MODULUS_SIZE: u32 = 512; +#[allow(dead_code)] +#[derive(Debug, PartialEq)] +pub(crate) enum AllowDHX { + True, + False, +} + #[pyo3::prelude::pyclass(frozen, module = "cryptography.hazmat.bindings._rust.openssl.dh")] pub(crate) struct DHPrivateKey { pkey: openssl::pkey::PKey, @@ -70,14 +77,17 @@ pub(crate) fn public_key_from_pkey( } #[cfg(not(CRYPTOGRAPHY_IS_BORINGSSL))] +#[allow(unused_variables)] fn pkey_from_dh( dh: openssl::dh::Dh, + allow_dhx: AllowDHX, ) -> CryptographyResult> { cfg_if::cfg_if! { if #[cfg(CRYPTOGRAPHY_IS_LIBRESSL)] { Ok(openssl::pkey::PKey::from_dh(dh)?) } else { - if dh.prime_q().is_some() { + if dh.prime_q().is_some() + && allow_dhx == AllowDHX::True { Ok(openssl::pkey::PKey::from_dhx(dh)?) } else { Ok(openssl::pkey::PKey::from_dh(dh)?) @@ -211,7 +221,10 @@ impl DHPrivateKey { let orig_dh = self.pkey.dh().unwrap(); let dh = clone_dh(&orig_dh)?; - let pkey = pkey_from_dh(dh.set_public_key(orig_dh.public_key().to_owned()?)?)?; + let pkey = pkey_from_dh( + dh.set_public_key(orig_dh.public_key().to_owned()?)?, + AllowDHX::False, + )?; Ok(DHPublicKey { pkey }) } @@ -319,7 +332,7 @@ impl DHParameters { fn generate_private_key(&self) -> CryptographyResult { let dh = clone_dh(&self.dh)?.generate_key()?; Ok(DHPrivateKey { - pkey: pkey_from_dh(dh)?, + pkey: pkey_from_dh(dh, AllowDHX::False)?, }) } @@ -431,7 +444,7 @@ impl DHPrivateNumbers { )); } - let pkey = pkey_from_dh(dh)?; + let pkey = pkey_from_dh(dh, AllowDHX::True)?; Ok(DHPrivateKey { pkey }) } @@ -473,7 +486,7 @@ impl DHPublicNumbers { let pub_key = utils::py_int_to_bn(py, self.y.bind(py))?; - let pkey = pkey_from_dh(dh.set_public_key(pub_key)?)?; + let pkey = pkey_from_dh(dh.set_public_key(pub_key)?, AllowDHX::True)?; Ok(DHPublicKey { pkey }) } diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index d287d29460ae..e0244d3203c3 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -473,6 +473,25 @@ def test_public_key_copy(self): assert key1 == key2 + def test_old_public_key_exchange(self, backend): + vector = load_vectors_from_file( + os.path.join("asymmetric", "DH", "dhpub_v41_0_7.pem"), + lambda pemfile: pemfile.read(), + mode="rb", + ) + + public_key = serialization.load_pem_public_key(vector, backend) + + assert isinstance(public_key, dh.DHPublicKey) + + params = public_key.parameters() + + private_key = params.generate_private_key() + + # test that we can do a key exchange with a public key + # generated with an older version + private_key.exchange(public_key) + @pytest.mark.supported( only_if=lambda backend: backend.dh_supported(), diff --git a/vectors/cryptography_vectors/asymmetric/DH/dhpub_v41_0_7.pem b/vectors/cryptography_vectors/asymmetric/DH/dhpub_v41_0_7.pem new file mode 100644 index 000000000000..59e94b5834a4 --- /dev/null +++ b/vectors/cryptography_vectors/asymmetric/DH/dhpub_v41_0_7.pem @@ -0,0 +1,15 @@ +# A public key generated with cryptograpy 41.0.7 +-----BEGIN PUBLIC KEY----- +MIICJTCCARcGCSqGSIb3DQEDATCCAQgCggEBAP//////////yQ/aoiFowjTExmKL +gNwc0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVt +bVHCReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR +7ORbPcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkH +cJaWbWcMNU5KvJgE8XRsCMoYIXwykF5GLjbOO+OedywYDoY DmyeDouwHoo+1xV3w +b0xSyd4ry/aVWBcYOZVJfOqVauUV0iYYmPoFEBVyjlqKrKpo//////////8CAQID +ggEGAAKCAQEAoely6vSHw+/Q3zGYLaJj7eeQkfd25K8SvtC+FMY9D7jwS4g71pyr +U3FJ98Fi45Wdksh+d4u7U089trF5Xbgui29bZ0HcQZtfHEEz0Mh69tkipCm2/QIj +6eDlo6sPk9hhhvgg4MMGiWKhCtHrub3x1FHdmf7KjOhrGeb5apiudo7blGFzGhZ3 +NFnbff+ArVNd+rdVmSoZn0aMhXRConlDu/44IYe5/24VLl7G+BzZlIZO4P2M83fd +mBOvR13cmYssQjEFTbaZVQvQHa3t0+aywfdCgsXGmTTK6QDCBP8D+vf1bmhEswzs +oYn1GLtJ3VyYyMBPDBomd2ctchZgTzsX1w== +-----END PUBLIC KEY-----