diff options
author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2023-05-14 20:54:23 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-14 08:54:23 -0400 |
commit | 2a1f42976206a39d0196786857b8d21a877ca42b (patch) | |
tree | db3c52a956ec4c21513153349049408ac2d7a302 | |
parent | 6cac7bcaf743d56215dd68a88f121c0811cfeb2b (diff) | |
download | cryptography-2a1f42976206a39d0196786857b8d21a877ca42b.tar.gz |
support PSS signatures in verify_directly_issued_by (#8908)
-rw-r--r-- | src/rust/src/x509/certificate.rs | 2 | ||||
-rw-r--r-- | src/rust/src/x509/crl.rs | 2 | ||||
-rw-r--r-- | src/rust/src/x509/csr.rs | 5 | ||||
-rw-r--r-- | src/rust/src/x509/sign.rs | 347 | ||||
-rw-r--r-- | tests/x509/test_x509.py | 44 |
5 files changed, 152 insertions, 248 deletions
diff --git a/src/rust/src/x509/certificate.rs b/src/rust/src/x509/certificate.rs index 4c0725023..34e9ec0ec 100644 --- a/src/rust/src/x509/certificate.rs +++ b/src/rust/src/x509/certificate.rs @@ -335,7 +335,7 @@ impl Certificate { ), )); }; - sign::verify_signature_with_oid( + sign::verify_signature_with_signature_algorithm( py, issuer.public_key(py)?, &self.raw.borrow_value().signature_alg, diff --git a/src/rust/src/x509/crl.rs b/src/rust/src/x509/crl.rs index 9dc63aa8d..923015035 100644 --- a/src/rust/src/x509/crl.rs +++ b/src/rust/src/x509/crl.rs @@ -393,7 +393,7 @@ impl CertificateRevocationList { // being an invalid signature. sign::identify_public_key_type(py, public_key)?; - Ok(sign::verify_signature_with_oid( + Ok(sign::verify_signature_with_signature_algorithm( py, public_key, &slf.owned.borrow_value().signature_algorithm, diff --git a/src/rust/src/x509/csr.rs b/src/rust/src/x509/csr.rs index 28ec67ed2..2e7797f49 100644 --- a/src/rust/src/x509/csr.rs +++ b/src/rust/src/x509/csr.rs @@ -235,9 +235,10 @@ impl CertificateSigningRequest { slf: pyo3::PyRef<'_, Self>, py: pyo3::Python<'_>, ) -> CryptographyResult<bool> { - Ok(sign::verify_signature_with_oid( + let public_key = slf.public_key(py)?; + Ok(sign::verify_signature_with_signature_algorithm( py, - slf.public_key(py)?, + public_key, &slf.raw.borrow_value().signature_alg, slf.raw.borrow_value().signature.as_bytes(), &asn1::write_single(&slf.raw.borrow_value().csr_info)?, diff --git a/src/rust/src/x509/sign.rs b/src/rust/src/x509/sign.rs index c0b0ec5de..054300420 100644 --- a/src/rust/src/x509/sign.rs +++ b/src/rust/src/x509/sign.rs @@ -4,6 +4,7 @@ use crate::error::{CryptographyError, CryptographyResult}; use crate::exceptions; +use crate::x509::certificate; use cryptography_x509::{common, oid}; #[derive(Debug, PartialEq)] @@ -15,7 +16,6 @@ pub(crate) enum KeyType { Ed448, } -#[derive(Debug, PartialEq)] enum HashType { None, Sha224, @@ -351,21 +351,7 @@ pub(crate) fn sign_data<'p>( signature.extract() } -fn py_hash_name_from_hash_type(hash_type: HashType) -> Option<&'static str> { - match hash_type { - HashType::None => None, - HashType::Sha224 => Some("SHA224"), - HashType::Sha256 => Some("SHA256"), - HashType::Sha384 => Some("SHA384"), - HashType::Sha512 => Some("SHA512"), - HashType::Sha3_224 => Some("SHA3_224"), - HashType::Sha3_256 => Some("SHA3_256"), - HashType::Sha3_384 => Some("SHA3_384"), - HashType::Sha3_512 => Some("SHA3_512"), - } -} - -pub(crate) fn verify_signature_with_oid<'p>( +pub(crate) fn verify_signature_with_signature_algorithm<'p>( py: pyo3::Python<'p>, issuer_public_key: &'p pyo3::PyAny, signature_algorithm: &common::AlgorithmIdentifier<'_>, @@ -373,8 +359,7 @@ pub(crate) fn verify_signature_with_oid<'p>( data: &[u8], ) -> CryptographyResult<()> { let key_type = identify_public_key_type(py, issuer_public_key)?; - let (sig_key_type, sig_hash_type) = - identify_key_hash_type_for_algorithm_params(&signature_algorithm.params)?; + let sig_key_type = identify_key_type_for_algorithm_params(&signature_algorithm.params)?; if key_type != sig_key_type { return Err(CryptographyError::from( pyo3::exceptions::PyValueError::new_err( @@ -382,43 +367,30 @@ pub(crate) fn verify_signature_with_oid<'p>( ), )); } - let sig_hash_name = py_hash_name_from_hash_type(sig_hash_type); - let hashes = py.import(pyo3::intern!(py, "cryptography.hazmat.primitives.hashes"))?; - let signature_hash = match sig_hash_name { - Some(data) => hashes.getattr(data)?.call0()?, - None => py.None().into_ref(py), - }; - + let py_signature_algorithm_parameters = + certificate::identify_signature_algorithm_parameters(py, signature_algorithm)?; + let py_signature_hash_algorithm = + certificate::identify_signature_hash_algorithm(py, signature_algorithm)?; match key_type { KeyType::Ed25519 | KeyType::Ed448 => { issuer_public_key.call_method1(pyo3::intern!(py, "verify"), (signature, data))? } - KeyType::Ec => { - let ec_mod = py.import(pyo3::intern!( - py, - "cryptography.hazmat.primitives.asymmetric.ec" - ))?; - let ecdsa = ec_mod - .getattr(pyo3::intern!(py, "ECDSA"))? - .call1((signature_hash,))?; - issuer_public_key.call_method1(pyo3::intern!(py, "verify"), (signature, data, ecdsa))? - } - KeyType::Rsa => { - let padding_mod = py.import(pyo3::intern!( - py, - "cryptography.hazmat.primitives.asymmetric.padding" - ))?; - let pkcs1v15 = padding_mod - .getattr(pyo3::intern!(py, "PKCS1v15"))? - .call0()?; - issuer_public_key.call_method1( - pyo3::intern!(py, "verify"), - (signature, data, pkcs1v15, signature_hash), - )? - } + KeyType::Ec => issuer_public_key.call_method1( + pyo3::intern!(py, "verify"), + (signature, data, py_signature_algorithm_parameters), + )?, + KeyType::Rsa => issuer_public_key.call_method1( + pyo3::intern!(py, "verify"), + ( + signature, + data, + py_signature_algorithm_parameters, + py_signature_hash_algorithm, + ), + )?, KeyType::Dsa => issuer_public_key.call_method1( pyo3::intern!(py, "verify"), - (signature, data, signature_hash), + (signature, data, py_signature_hash_algorithm), )?, }; Ok(()) @@ -481,32 +453,33 @@ pub(crate) fn identify_public_key_type( } } -fn identify_key_hash_type_for_algorithm_params( +fn identify_key_type_for_algorithm_params( params: &common::AlgorithmParameters<'_>, -) -> pyo3::PyResult<(KeyType, HashType)> { +) -> pyo3::PyResult<KeyType> { match params { - common::AlgorithmParameters::RsaWithSha224(..) => Ok((KeyType::Rsa, HashType::Sha224)), - common::AlgorithmParameters::RsaWithSha256(..) => Ok((KeyType::Rsa, HashType::Sha256)), - common::AlgorithmParameters::RsaWithSha384(..) => Ok((KeyType::Rsa, HashType::Sha384)), - common::AlgorithmParameters::RsaWithSha512(..) => Ok((KeyType::Rsa, HashType::Sha512)), - common::AlgorithmParameters::RsaWithSha3_224(..) => Ok((KeyType::Rsa, HashType::Sha3_224)), - common::AlgorithmParameters::RsaWithSha3_256(..) => Ok((KeyType::Rsa, HashType::Sha3_256)), - common::AlgorithmParameters::RsaWithSha3_384(..) => Ok((KeyType::Rsa, HashType::Sha3_384)), - common::AlgorithmParameters::RsaWithSha3_512(..) => Ok((KeyType::Rsa, HashType::Sha3_512)), - common::AlgorithmParameters::EcDsaWithSha224 => Ok((KeyType::Ec, HashType::Sha224)), - common::AlgorithmParameters::EcDsaWithSha256 => Ok((KeyType::Ec, HashType::Sha256)), - common::AlgorithmParameters::EcDsaWithSha384 => Ok((KeyType::Ec, HashType::Sha384)), - common::AlgorithmParameters::EcDsaWithSha512 => Ok((KeyType::Ec, HashType::Sha512)), - common::AlgorithmParameters::EcDsaWithSha3_224 => Ok((KeyType::Ec, HashType::Sha3_224)), - common::AlgorithmParameters::EcDsaWithSha3_256 => Ok((KeyType::Ec, HashType::Sha3_256)), - common::AlgorithmParameters::EcDsaWithSha3_384 => Ok((KeyType::Ec, HashType::Sha3_384)), - common::AlgorithmParameters::EcDsaWithSha3_512 => Ok((KeyType::Ec, HashType::Sha3_512)), - common::AlgorithmParameters::Ed25519 => Ok((KeyType::Ed25519, HashType::None)), - common::AlgorithmParameters::Ed448 => Ok((KeyType::Ed448, HashType::None)), - common::AlgorithmParameters::DsaWithSha224 => Ok((KeyType::Dsa, HashType::Sha224)), - common::AlgorithmParameters::DsaWithSha256 => Ok((KeyType::Dsa, HashType::Sha256)), - common::AlgorithmParameters::DsaWithSha384 => Ok((KeyType::Dsa, HashType::Sha384)), - common::AlgorithmParameters::DsaWithSha512 => Ok((KeyType::Dsa, HashType::Sha512)), + common::AlgorithmParameters::RsaWithSha224(..) + | common::AlgorithmParameters::RsaWithSha256(..) + | common::AlgorithmParameters::RsaWithSha384(..) + | common::AlgorithmParameters::RsaWithSha512(..) + | common::AlgorithmParameters::RsaWithSha3_224(..) + | common::AlgorithmParameters::RsaWithSha3_256(..) + | common::AlgorithmParameters::RsaWithSha3_384(..) + | common::AlgorithmParameters::RsaWithSha3_512(..) + | common::AlgorithmParameters::RsaPss(..) => Ok(KeyType::Rsa), + common::AlgorithmParameters::EcDsaWithSha224 + | common::AlgorithmParameters::EcDsaWithSha256 + | common::AlgorithmParameters::EcDsaWithSha384 + | common::AlgorithmParameters::EcDsaWithSha512 + | common::AlgorithmParameters::EcDsaWithSha3_224 + | common::AlgorithmParameters::EcDsaWithSha3_256 + | common::AlgorithmParameters::EcDsaWithSha3_384 + | common::AlgorithmParameters::EcDsaWithSha3_512 => Ok(KeyType::Ec), + common::AlgorithmParameters::Ed25519 => Ok(KeyType::Ed25519), + common::AlgorithmParameters::Ed448 => Ok(KeyType::Ed448), + common::AlgorithmParameters::DsaWithSha224 + | common::AlgorithmParameters::DsaWithSha256 + | common::AlgorithmParameters::DsaWithSha384 + | common::AlgorithmParameters::DsaWithSha512 => Ok(KeyType::Dsa), _ => Err(pyo3::exceptions::PyValueError::new_err( "Unsupported signature algorithm", )), @@ -534,165 +507,68 @@ fn identify_alg_params_for_hash_type( #[cfg(test)] mod tests { use super::{ - identify_alg_params_for_hash_type, identify_key_hash_type_for_algorithm_params, - py_hash_name_from_hash_type, HashType, KeyType, + identify_alg_params_for_hash_type, identify_key_type_for_algorithm_params, HashType, + KeyType, }; use cryptography_x509::{common, oid}; #[test] - fn test_identify_key_hash_type_for_algorithm_params() { - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::RsaWithSha224(Some(())) - ) - .unwrap(), - (KeyType::Rsa, HashType::Sha224) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::RsaWithSha256(Some(())) - ) - .unwrap(), - (KeyType::Rsa, HashType::Sha256) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::RsaWithSha384(Some(())) - ) - .unwrap(), - (KeyType::Rsa, HashType::Sha384) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::RsaWithSha512(Some(())) - ) - .unwrap(), - (KeyType::Rsa, HashType::Sha512) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::RsaWithSha3_224(Some(())) - ) - .unwrap(), - (KeyType::Rsa, HashType::Sha3_224) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::RsaWithSha3_256(Some(())) - ) - .unwrap(), - (KeyType::Rsa, HashType::Sha3_256) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::RsaWithSha3_384(Some(())) - ) - .unwrap(), - (KeyType::Rsa, HashType::Sha3_384) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::RsaWithSha3_512(Some(())) - ) - .unwrap(), - (KeyType::Rsa, HashType::Sha3_512) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::EcDsaWithSha224 - ) - .unwrap(), - (KeyType::Ec, HashType::Sha224) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::EcDsaWithSha256 - ) - .unwrap(), - (KeyType::Ec, HashType::Sha256) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::EcDsaWithSha384 - ) - .unwrap(), - (KeyType::Ec, HashType::Sha384) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::EcDsaWithSha512 - ) - .unwrap(), - (KeyType::Ec, HashType::Sha512) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::EcDsaWithSha3_224 - ) - .unwrap(), - (KeyType::Ec, HashType::Sha3_224) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::EcDsaWithSha3_256 - ) - .unwrap(), - (KeyType::Ec, HashType::Sha3_256) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::EcDsaWithSha3_384 - ) - .unwrap(), - (KeyType::Ec, HashType::Sha3_384) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::EcDsaWithSha3_512 - ) - .unwrap(), - (KeyType::Ec, HashType::Sha3_512) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params(&common::AlgorithmParameters::Ed25519) - .unwrap(), - (KeyType::Ed25519, HashType::None) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params(&common::AlgorithmParameters::Ed448) - .unwrap(), - (KeyType::Ed448, HashType::None) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::DsaWithSha224 - ) - .unwrap(), - (KeyType::Dsa, HashType::Sha224) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::DsaWithSha256 - ) - .unwrap(), - (KeyType::Dsa, HashType::Sha256) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::DsaWithSha384 - ) - .unwrap(), - (KeyType::Dsa, HashType::Sha384) - ); - assert_eq!( - identify_key_hash_type_for_algorithm_params( - &common::AlgorithmParameters::DsaWithSha512 - ) - .unwrap(), - (KeyType::Dsa, HashType::Sha512) - ); + fn test_identify_key_type_for_algorithm_params() { + for (params, keytype) in [ + ( + &common::AlgorithmParameters::RsaWithSha224(Some(())), + KeyType::Rsa, + ), + ( + &common::AlgorithmParameters::RsaWithSha256(Some(())), + KeyType::Rsa, + ), + ( + &common::AlgorithmParameters::RsaWithSha384(Some(())), + KeyType::Rsa, + ), + ( + &common::AlgorithmParameters::RsaWithSha512(Some(())), + KeyType::Rsa, + ), + ( + &common::AlgorithmParameters::RsaWithSha3_224(Some(())), + KeyType::Rsa, + ), + ( + &common::AlgorithmParameters::RsaWithSha3_256(Some(())), + KeyType::Rsa, + ), + ( + &common::AlgorithmParameters::RsaWithSha3_384(Some(())), + KeyType::Rsa, + ), + ( + &common::AlgorithmParameters::RsaWithSha3_512(Some(())), + KeyType::Rsa, + ), + (&common::AlgorithmParameters::EcDsaWithSha224, KeyType::Ec), + (&common::AlgorithmParameters::EcDsaWithSha256, KeyType::Ec), + (&common::AlgorithmParameters::EcDsaWithSha384, KeyType::Ec), + (&common::AlgorithmParameters::EcDsaWithSha512, KeyType::Ec), + (&common::AlgorithmParameters::EcDsaWithSha3_224, KeyType::Ec), + (&common::AlgorithmParameters::EcDsaWithSha3_256, KeyType::Ec), + (&common::AlgorithmParameters::EcDsaWithSha3_384, KeyType::Ec), + (&common::AlgorithmParameters::EcDsaWithSha3_512, KeyType::Ec), + (&common::AlgorithmParameters::Ed25519, KeyType::Ed25519), + (&common::AlgorithmParameters::Ed448, KeyType::Ed448), + (&common::AlgorithmParameters::DsaWithSha224, KeyType::Dsa), + (&common::AlgorithmParameters::DsaWithSha256, KeyType::Dsa), + (&common::AlgorithmParameters::DsaWithSha384, KeyType::Dsa), + (&common::AlgorithmParameters::DsaWithSha512, KeyType::Dsa), + ] { + assert_eq!( + identify_key_type_for_algorithm_params(params).unwrap(), + keytype + ); + } assert!( - identify_key_hash_type_for_algorithm_params(&common::AlgorithmParameters::Other( + identify_key_type_for_algorithm_params(&common::AlgorithmParameters::Other( oid::TLS_FEATURE_OID, None )) @@ -727,21 +603,4 @@ mod tests { assert_eq!(identify_alg_params_for_hash_type(hash).unwrap(), params); } } - - #[test] - fn test_py_hash_name_from_hash_type() { - for (hash, name) in [ - (HashType::Sha224, "SHA224"), - (HashType::Sha256, "SHA256"), - (HashType::Sha384, "SHA384"), - (HashType::Sha512, "SHA512"), - (HashType::Sha3_224, "SHA3_224"), - (HashType::Sha3_256, "SHA3_256"), - (HashType::Sha3_384, "SHA3_384"), - (HashType::Sha3_512, "SHA3_512"), - ] { - let hash_str = py_hash_name_from_hash_type(hash).unwrap(); - assert_eq!(hash_str, name); - } - } } diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 19a854e24..5fd5265b7 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -1558,6 +1558,50 @@ class TestRSACertificate: [x509.TLSFeatureType.status_request] ) + def test_verify_directly_issued_by_rsa_pss( + self, rsa_key_2048: rsa.RSAPrivateKey + ): + subject_private_key = RSA_KEY_2048_ALT.private_key( + unsafe_skip_rsa_key_validation=True + ) + + builder = ( + x509.CertificateBuilder() + .subject_name( + x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "PyCA CA")]) + ) + .issuer_name( + x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "PyCA CA")]) + ) + .public_key(rsa_key_2048.public_key()) + .serial_number(1) + .not_valid_before(datetime.datetime(2020, 1, 1)) + .not_valid_after(datetime.datetime(2030, 1, 1)) + ) + ca = builder.sign(rsa_key_2048, hashes.SHA256()) + builder = ( + x509.CertificateBuilder() + .subject_name( + x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "leaf")]) + ) + .issuer_name( + x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "PyCA CA")]) + ) + .public_key(subject_private_key.public_key()) + .serial_number(100) + .not_valid_before(datetime.datetime(2020, 1, 1)) + .not_valid_after(datetime.datetime(2025, 1, 1)) + ) + cert = builder.sign( + rsa_key_2048, + hashes.SHA256(), + rsa_padding=padding.PSS( + padding.MGF1(hashes.SHA256()), + salt_length=padding.PSS.DIGEST_LENGTH, + ), + ) + cert.verify_directly_issued_by(ca) + def test_verify_directly_issued_by_rsa( self, rsa_key_2048: rsa.RSAPrivateKey ): |