summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2021-10-18 07:19:48 +0800
committerGitHub <noreply@github.com>2021-10-17 19:19:48 -0400
commitdf8ca37f5fca0053a6a84495474a4f2413ea4d0d (patch)
treeb25e1b670c16f2465cd71d6b7ad52a23a8ae8200 /src
parentb65aa2003e271eae8fd9b9cb3b0ac47e4fb59ba2 (diff)
downloadcryptography-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.py55
-rw-r--r--src/cryptography/x509/general_name.py11
-rw-r--r--src/rust/src/x509/certificate.rs57
-rw-r--r--src/rust/src/x509/common.rs2
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> {