update for rust-asn1 0.4 (#6030)

This commit is contained in:
Alex Gaynor 2021-05-03 12:10:32 -04:00 committed by GitHub
parent a67f3066dc
commit 5c434bb073
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 116 additions and 136 deletions

16
src/rust/Cargo.lock generated
View file

@ -4,13 +4,25 @@ version = 3
[[package]]
name = "asn1"
version = "0.3.8"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "842b2cc51640a5737c94248d328936d11f53ea8080e3fdba6ba523b41fa6ea15"
checksum = "85bdcc33cd1ec0ebfee9cc2d1f6497454f984c1f5c6550ad27af4b7bd7731442"
dependencies = [
"asn1_derive",
"chrono",
]
[[package]]
name = "asn1_derive"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce75fd5d9c4402a45fdec13c4701db332b4dfd307a3220494d6888c86edfff4b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "autocfg"
version = "1.0.1"

View file

@ -8,7 +8,7 @@ publish = false
[dependencies]
lazy_static = "1"
pyo3 = { version = "0.13.1" }
asn1 = { version = "0.3.8", default-features = false }
asn1 = { version = "0.4.1", default-features = false, features = ["derive"] }
[features]
extension-module = ["pyo3/extension-module"]

View file

@ -45,81 +45,60 @@ fn encode_tls_feature(py: pyo3::Python<'_>, ext: &pyo3::PyAny) -> pyo3::PyResult
els.push(el?.getattr("value")?.extract::<u64>()?);
}
let result = asn1::write(|w| {
w.write_element_with_type::<asn1::SequenceOf<u64>>(&els);
});
let result = asn1::write_single(&asn1::SequenceOfWriter::new(&els));
Ok(pyo3::types::PyBytes::new(py, &result).to_object(py))
}
#[pyo3::prelude::pyfunction]
fn parse_tls_feature(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult<pyo3::PyObject> {
fn parse_tls_feature(py: pyo3::Python<'_>, data: &[u8]) -> Result<pyo3::PyObject, PyAsn1Error> {
let x509_mod = py.import("cryptography.x509.extensions")?;
let tls_feature_type_to_enum = x509_mod.getattr("_TLS_FEATURE_TYPE_TO_ENUM")?;
let features = asn1::parse::<_, PyAsn1Error, _>(data, |p| {
let features = pyo3::types::PyList::empty(py);
for el in p.read_element::<asn1::SequenceOf<u64>>()? {
let feature = el?;
let py_feature = tls_feature_type_to_enum.get_item(feature.to_object(py))?;
features.append(py_feature)?;
}
Ok(features)
})?;
let features = pyo3::types::PyList::empty(py);
for el in asn1::parse_single::<asn1::SequenceOf<u64>>(data)? {
let feature = el?;
let py_feature = tls_feature_type_to_enum.get_item(feature.to_object(py))?;
features.append(py_feature)?;
}
let x509_module = py.import("cryptography.x509")?;
x509_module
.call1("TLSFeature", (features,))
.map(|o| o.to_object(py))
Ok(x509_module.call1("TLSFeature", (features,))?.to_object(py))
}
#[pyo3::prelude::pyfunction]
fn encode_precert_poison(py: pyo3::Python<'_>, _ext: &pyo3::PyAny) -> pyo3::PyObject {
let result = asn1::write(|w| {
w.write_element(());
});
let result = asn1::write_single(&());
pyo3::types::PyBytes::new(py, &result).to_object(py)
}
#[pyo3::prelude::pyfunction]
fn parse_precert_poison(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult<pyo3::PyObject> {
asn1::parse::<_, PyAsn1Error, _>(data, |p| {
p.read_element::<()>()?;
Ok(())
})?;
fn parse_precert_poison(py: pyo3::Python<'_>, data: &[u8]) -> Result<pyo3::PyObject, PyAsn1Error> {
asn1::parse_single::<()>(data)?;
let x509_module = py.import("cryptography.x509")?;
x509_module.call0("PrecertPoison").map(|o| o.to_object(py))
Ok(x509_module.call0("PrecertPoison")?.to_object(py))
}
#[derive(asn1::Asn1Read)]
struct AlgorithmIdentifier<'a> {
_oid: asn1::ObjectIdentifier<'a>,
_params: Option<asn1::Tlv<'a>>,
}
#[derive(asn1::Asn1Read)]
struct Spki<'a> {
_algorithm: AlgorithmIdentifier<'a>,
data: asn1::BitString<'a>,
}
#[pyo3::prelude::pyfunction]
fn parse_spki_for_data(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult<pyo3::PyObject> {
let result = asn1::parse::<_, PyAsn1Error, _>(data, |p| {
p.read_element::<asn1::Sequence>()?
.parse::<_, PyAsn1Error, _>(|p| {
// AlgorithmIdentifier
p.read_element::<asn1::Sequence>()?
.parse::<_, PyAsn1Error, _>(|p| {
p.read_element::<asn1::ObjectIdentifier>()?;
if !p.is_empty() {
p.read_element::<asn1::Tlv>()?;
}
Ok(())
})?;
fn parse_spki_for_data(py: pyo3::Python<'_>, data: &[u8]) -> Result<pyo3::PyObject, PyAsn1Error> {
let spki = asn1::parse_single::<Spki>(data)?;
if spki.data.padding_bits() != 0 {
return Err(pyo3::exceptions::PyValueError::new_err("Invalid public key encoding").into());
}
let pubkey_data = p.read_element::<asn1::BitString>()?;
if pubkey_data.padding_bits() != 0 {
return Err(pyo3::exceptions::PyValueError::new_err(
"Invalid public key encoding",
)
.into());
}
Ok(pubkey_data.as_bytes())
})
})?;
Ok(pyo3::types::PyBytes::new(py, result).to_object(py))
Ok(pyo3::types::PyBytes::new(py, spki.data.as_bytes()).to_object(py))
}
lazy_static::lazy_static! {
@ -153,6 +132,12 @@ fn parse_ocsp_req_extension(
}
}
#[derive(asn1::Asn1Read, asn1::Asn1Write)]
struct DssSignature<'a> {
r: asn1::BigUint<'a>,
s: asn1::BigUint<'a>,
}
fn big_asn1_uint_to_py<'p>(
py: pyo3::Python<'p>,
v: asn1::BigUint,
@ -162,16 +147,14 @@ fn big_asn1_uint_to_py<'p>(
}
#[pyo3::prelude::pyfunction]
fn decode_dss_signature(py: pyo3::Python<'_>, data: &[u8]) -> pyo3::PyResult<pyo3::PyObject> {
let (r, s) = asn1::parse::<_, PyAsn1Error, _>(data, |p| {
p.read_element::<asn1::Sequence>()?.parse(|p| {
let r = p.read_element::<asn1::BigUint>()?;
let s = p.read_element::<asn1::BigUint>()?;
Ok((r, s))
})
})?;
fn decode_dss_signature(py: pyo3::Python<'_>, data: &[u8]) -> Result<pyo3::PyObject, PyAsn1Error> {
let sig = asn1::parse_single::<DssSignature>(data)?;
Ok((big_asn1_uint_to_py(py, r)?, big_asn1_uint_to_py(py, s)?).to_object(py))
Ok((
big_asn1_uint_to_py(py, sig.r)?,
big_asn1_uint_to_py(py, sig.s)?,
)
.to_object(py))
}
fn py_uint_to_big_endian_bytes<'p>(
@ -198,15 +181,11 @@ fn encode_dss_signature(
r: &pyo3::types::PyLong,
s: &pyo3::types::PyLong,
) -> pyo3::PyResult<pyo3::PyObject> {
let r = asn1::BigUint::new(py_uint_to_big_endian_bytes(py, r)?).unwrap();
let s = asn1::BigUint::new(py_uint_to_big_endian_bytes(py, s)?).unwrap();
let result = asn1::write(|w| {
w.write_element_with_type::<asn1::Sequence>(&|w| {
w.write_element(r);
w.write_element(s);
});
});
let sig = DssSignature {
r: asn1::BigUint::new(py_uint_to_big_endian_bytes(py, r)?).unwrap(),
s: asn1::BigUint::new(py_uint_to_big_endian_bytes(py, s)?).unwrap(),
};
let result = asn1::write_single(&sig);
Ok(pyo3::types::PyBytes::new(py, &result).to_object(py))
}
@ -222,79 +201,68 @@ struct TestCertificate {
subject_value_tags: Vec<u8>,
}
fn parse_name_value_tags(p: &mut asn1::Parser) -> asn1::ParseResult<Vec<u8>> {
#[derive(asn1::Asn1Read)]
struct Asn1Certificate<'a> {
tbs_cert: TbsCertificate<'a>,
_signature_alg: asn1::Sequence<'a>,
_signature: asn1::BitString<'a>,
}
#[derive(asn1::Asn1Read)]
struct TbsCertificate<'a> {
#[explicit(0)]
_version: Option<u8>,
_serial: asn1::BigUint<'a>,
_signature_alg: asn1::Sequence<'a>,
issuer: Name<'a>,
validity: Validity<'a>,
subject: Name<'a>,
_spki: asn1::Sequence<'a>,
#[implicit(1)]
_issuer_unique_id: Option<asn1::BitString<'a>>,
#[implicit(2)]
_subject_unique_id: Option<asn1::BitString<'a>>,
#[explicit(3)]
_extensions: Option<asn1::Sequence<'a>>,
}
type Name<'a> = asn1::SequenceOf<'a, asn1::SetOf<'a, AttributeTypeValue<'a>>>;
#[derive(asn1::Asn1Read)]
struct AttributeTypeValue<'a> {
_type: asn1::ObjectIdentifier<'a>,
value: asn1::Tlv<'a>,
}
#[derive(asn1::Asn1Read)]
struct Validity<'a> {
not_before: asn1::Tlv<'a>,
not_after: asn1::Tlv<'a>,
}
fn parse_name_value_tags(rdns: &mut Name<'_>) -> Result<Vec<u8>, PyAsn1Error> {
let mut tags = vec![];
for rdn in p.read_element::<asn1::SequenceOf<asn1::SetOf<asn1::Sequence>>>()? {
for rdn in rdns {
let mut attributes = rdn?.collect::<asn1::ParseResult<Vec<_>>>()?;
assert_eq!(attributes.len(), 1);
let tag = attributes
.pop()
.unwrap()
.parse::<_, asn1::ParseError, _>(|p| {
p.read_element::<asn1::ObjectIdentifier>()?;
let tlv = p.read_element::<asn1::Tlv>()?;
Ok(tlv.tag())
})?;
tags.push(tag);
tags.push(attributes.pop().unwrap().value.tag());
}
Ok(tags)
}
#[pyo3::prelude::pyfunction]
fn test_parse_certificate(data: &[u8]) -> pyo3::PyResult<TestCertificate> {
let result = asn1::parse::<_, PyAsn1Error, _>(data, |p| {
// Outer SEQUENCE
p.read_element::<asn1::Sequence>()?.parse(|p| {
// TBS certificate
let result = p
.read_element::<asn1::Sequence>()?
.parse::<_, PyAsn1Error, _>(|p| {
// Version
p.read_optional_explicit_element::<u8>(0)?;
// Serial number
p.read_element::<asn1::BigUint>()?;
// Inner signature algorithm
p.read_element::<asn1::Sequence>()?;
fn test_parse_certificate(data: &[u8]) -> Result<TestCertificate, PyAsn1Error> {
let mut asn1_cert = asn1::parse_single::<Asn1Certificate>(data)?;
// Issuer
let issuer_value_tags = parse_name_value_tags(p)?;
// Validity
let (not_before_tag, not_after_tag) = p
.read_element::<asn1::Sequence>()?
.parse::<_, asn1::ParseError, _>(|p| {
let not_before_tag = p.read_element::<asn1::Tlv>()?.tag();
let not_after_tag = p.read_element::<asn1::Tlv>()?.tag();
Ok((not_before_tag, not_after_tag))
})?;
// Subject
let subject_value_tags = parse_name_value_tags(p)?;
// Subject public key info
p.read_element::<asn1::Sequence>()?;
// Issuer unique ID - never used in the real world
p.read_optional_implicit_element::<asn1::BitString>(1)?;
// Subject unique ID - never used in the real world
p.read_optional_implicit_element::<asn1::BitString>(2)?;
// Extensions
p.read_optional_explicit_element::<asn1::Sequence>(3)?;
Ok(TestCertificate {
not_before_tag,
not_after_tag,
issuer_value_tags,
subject_value_tags,
})
})?;
// Outer signature algorithm
p.read_element::<asn1::Sequence>()?;
// Signature
p.read_element::<asn1::BitString>()?;
Ok(result)
})
})?;
Ok(result)
Ok(TestCertificate {
not_before_tag: asn1_cert.tbs_cert.validity.not_before.tag(),
not_after_tag: asn1_cert.tbs_cert.validity.not_after.tag(),
issuer_value_tags: parse_name_value_tags(&mut asn1_cert.tbs_cert.issuer)?,
subject_value_tags: parse_name_value_tags(&mut asn1_cert.tbs_cert.subject)?,
})
}
pub(crate) fn create_submodule(py: pyo3::Python) -> pyo3::PyResult<&pyo3::prelude::PyModule> {