diff options
| author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2021-10-18 07:19:48 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-17 19:19:48 -0400 |
| commit | df8ca37f5fca0053a6a84495474a4f2413ea4d0d (patch) | |
| tree | b25e1b670c16f2465cd71d6b7ad52a23a8ae8200 /src | |
| parent | b65aa2003e271eae8fd9b9cb3b0ac47e4fb59ba2 (diff) | |
| download | cryptography-df8ca37f5fca0053a6a84495474a4f2413ea4d0d.tar.gz | |
rust nameconstraints (#6427)
* rust nameconstraints
* remove a todo
* remove underscores
* clippy
* remove ipaddr ossl encode
Diffstat (limited to 'src')
| -rw-r--r-- | src/cryptography/hazmat/backends/openssl/encode_asn1.py | 55 | ||||
| -rw-r--r-- | src/cryptography/x509/general_name.py | 11 | ||||
| -rw-r--r-- | src/rust/src/x509/certificate.rs | 57 | ||||
| -rw-r--r-- | src/rust/src/x509/common.rs | 2 |
4 files changed, 59 insertions, 66 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/encode_asn1.py b/src/cryptography/hazmat/backends/openssl/encode_asn1.py index 2d8e80f8c..89af134d4 100644 --- a/src/cryptography/hazmat/backends/openssl/encode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/encode_asn1.py @@ -3,9 +3,7 @@ # for complete details. -import ipaddress - -from cryptography import utils, x509 +from cryptography import x509 from cryptography.hazmat.backends.openssl.decode_asn1 import ( _DISTPOINT_TYPE_FULLNAME, _DISTPOINT_TYPE_RELATIVENAME, @@ -219,7 +217,8 @@ def _encode_general_name(backend, name): def _encode_general_name_preallocated(backend, name, gn): assert not isinstance( - name, (x509.RegisteredID, x509.OtherName, x509.RFC822Name) + name, + (x509.RegisteredID, x509.OtherName, x509.RFC822Name, x509.IPAddress), ) if isinstance(name, x509.DNSName): backend.openssl_assert(gn != backend._ffi.NULL) @@ -239,23 +238,6 @@ def _encode_general_name_preallocated(backend, name, gn): dir_name = _encode_name(backend, name.value) gn.type = backend._lib.GEN_DIRNAME gn.d.directoryName = dir_name - elif isinstance(name, x509.IPAddress): - backend.openssl_assert(gn != backend._ffi.NULL) - assert not isinstance( - name.value, (ipaddress.IPv4Address, ipaddress.IPv6Address) - ) - if isinstance(name.value, ipaddress.IPv4Network): - packed = name.value.network_address.packed + utils.int_to_bytes( - ((1 << 32) - name.value.num_addresses), 4 - ) - else: - assert isinstance(name.value, ipaddress.IPv6Network) - packed = name.value.network_address.packed + utils.int_to_bytes( - (1 << 128) - name.value.num_addresses, 16 - ) - ipaddr = _encode_asn1_str(backend, packed) - gn.type = backend._lib.GEN_IPADD - gn.d.iPAddress = ipaddr else: assert isinstance(name, x509.UniformResourceIdentifier) backend.openssl_assert(gn != backend._ffi.NULL) @@ -332,43 +314,12 @@ def _encode_cdps_freshest_crl(backend, cdps): return cdp -def _encode_name_constraints(backend, name_constraints): - nc = backend._lib.NAME_CONSTRAINTS_new() - backend.openssl_assert(nc != backend._ffi.NULL) - nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free) - permitted = _encode_general_subtree( - backend, name_constraints.permitted_subtrees - ) - nc.permittedSubtrees = permitted - excluded = _encode_general_subtree( - backend, name_constraints.excluded_subtrees - ) - nc.excludedSubtrees = excluded - - return nc - - -def _encode_general_subtree(backend, subtrees): - if subtrees is None: - return backend._ffi.NULL - else: - general_subtrees = backend._lib.sk_GENERAL_SUBTREE_new_null() - for name in subtrees: - gs = backend._lib.GENERAL_SUBTREE_new() - gs.base = _encode_general_name(backend, name) - res = backend._lib.sk_GENERAL_SUBTREE_push(general_subtrees, gs) - backend.openssl_assert(res >= 1) - - return general_subtrees - - _EXTENSION_ENCODE_HANDLERS = { ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _encode_authority_key_identifier, ExtensionOID.AUTHORITY_INFORMATION_ACCESS: _encode_information_access, ExtensionOID.SUBJECT_INFORMATION_ACCESS: _encode_information_access, ExtensionOID.CRL_DISTRIBUTION_POINTS: _encode_cdps_freshest_crl, ExtensionOID.FRESHEST_CRL: _encode_cdps_freshest_crl, - ExtensionOID.NAME_CONSTRAINTS: _encode_name_constraints, } _CRL_EXTENSION_ENCODE_HANDLERS = { diff --git a/src/cryptography/x509/general_name.py b/src/cryptography/x509/general_name.py index 051bb04c5..7ddf90b54 100644 --- a/src/cryptography/x509/general_name.py +++ b/src/cryptography/x509/general_name.py @@ -243,12 +243,15 @@ class IPAddress(GeneralName): def value(self) -> _IPADDRESS_TYPES: return self._value - # TODO: This needs to support IP networks when we implement NC def _packed(self) -> bytes: - assert isinstance( + if isinstance( self.value, (ipaddress.IPv4Address, ipaddress.IPv6Address) - ) - return self.value.packed + ): + return self.value.packed + else: + return ( + self.value.network_address.packed + self.value.netmask.packed + ) def __repr__(self) -> str: return "<IPAddress(value={})>".format(self.value) diff --git a/src/rust/src/x509/certificate.rs b/src/rust/src/x509/certificate.rs index 0fce15f32..d30c729cc 100644 --- a/src/rust/src/x509/certificate.rs +++ b/src/rust/src/x509/certificate.rs @@ -510,33 +510,62 @@ fn parse_cp(py: pyo3::Python<'_>, ext_data: &[u8]) -> Result<pyo3::PyObject, PyA Ok(certificate_policies.to_object(py)) } -#[derive(asn1::Asn1Read)] +// Needed due to clippy type complexity warning. +type SequenceOfSubtrees<'a> = x509::Asn1ReadableOrWritable< + 'a, + asn1::SequenceOf<'a, GeneralSubtree<'a>>, + asn1::SequenceOfWriter<'a, GeneralSubtree<'a>, Vec<GeneralSubtree<'a>>>, +>; + +#[derive(asn1::Asn1Read, asn1::Asn1Write)] struct NameConstraints<'a> { #[implicit(0)] - permitted_subtrees: Option<asn1::SequenceOf<'a, GeneralSubtree<'a>>>, + permitted_subtrees: Option<SequenceOfSubtrees<'a>>, #[implicit(1)] - excluded_subtrees: Option<asn1::SequenceOf<'a, GeneralSubtree<'a>>>, + excluded_subtrees: Option<SequenceOfSubtrees<'a>>, } -#[derive(asn1::Asn1Read)] +#[derive(asn1::Asn1Read, asn1::Asn1Write)] struct GeneralSubtree<'a> { base: x509::GeneralName<'a>, #[implicit(0)] #[default(0u64)] - _minimum: u64, + minimum: u64, #[implicit(1)] - _maximum: Option<u64>, + maximum: Option<u64>, } -fn parse_general_subtrees<'a>( +fn encode_general_subtrees<'a>( + py: pyo3::Python<'a>, + subtrees: &'a pyo3::PyAny, +) -> Result<Option<SequenceOfSubtrees<'a>>, PyAsn1Error> { + if subtrees.is_none() { + Ok(None) + } else { + let mut subtree_seq = vec![]; + for name in subtrees.iter()? { + let gn = x509::common::encode_general_name(py, name?)?; + subtree_seq.push(GeneralSubtree { + base: gn, + minimum: 0, + maximum: None, + }); + } + Ok(Some(x509::Asn1ReadableOrWritable::new_write( + asn1::SequenceOfWriter::new(subtree_seq), + ))) + } +} + +fn parse_general_subtrees( py: pyo3::Python<'_>, - subtrees: asn1::SequenceOf<'a, GeneralSubtree<'a>>, + subtrees: SequenceOfSubtrees<'_>, ) -> Result<pyo3::PyObject, PyAsn1Error> { let gns = pyo3::types::PyList::empty(py); - for gs in subtrees { + for gs in subtrees.unwrap_read().clone() { gns.append(x509::parse_general_name(py, gs.base)?)?; } Ok(gns.to_object(py)) @@ -1043,6 +1072,16 @@ fn encode_certificate_extension<'p>( }; let result = asn1::write_single(&pc); Ok(pyo3::types::PyBytes::new(py, &result)) + } else if oid == *NAME_CONSTRAINTS_OID { + let py_nc = ext.getattr("value")?; + let permitted = py_nc.getattr("permitted_subtrees")?; + let excluded = py_nc.getattr("excluded_subtrees")?; + let nc = NameConstraints { + permitted_subtrees: encode_general_subtrees(py, permitted)?, + excluded_subtrees: encode_general_subtrees(py, excluded)?, + }; + let result = asn1::write_single(&nc); + Ok(pyo3::types::PyBytes::new(py, &result)) } else if oid == *INHIBIT_ANY_POLICY_OID { let intval = ext .getattr("value")? diff --git a/src/rust/src/x509/common.rs b/src/rust/src/x509/common.rs index e0183d7eb..3165a8ef6 100644 --- a/src/rust/src/x509/common.rs +++ b/src/rust/src/x509/common.rs @@ -218,7 +218,7 @@ pub(crate) fn encode_general_names<'a>( Ok(gns) } -fn encode_general_name<'a>( +pub(crate) fn encode_general_name<'a>( py: pyo3::Python<'a>, gn: &'a pyo3::PyAny, ) -> Result<GeneralName<'a>, PyAsn1Error> { |
