summaryrefslogtreecommitdiff
path: root/src/rust
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2023-04-17 05:45:25 +0800
committerGitHub <noreply@github.com>2023-04-16 17:45:25 -0400
commit3e40017b5fff43b2bc3be774eca47c0643e97649 (patch)
treef5dc6fc955a9d885d81c0f279f8ccae7a2b0bf60 /src/rust
parent9c09a67204223578896026035ce877d7ea2ffdf4 (diff)
downloadcryptography-3e40017b5fff43b2bc3be774eca47c0643e97649.tar.gz
begin separation of x509 crate from cryptography crate (#8740)
* begin separation of x509 crate from cryptography crate this will not be a published crate for now and the separation is incomplete. * no more rawcertificate, no more re-exporting * rename RawCsr * rename rawcrl * port ocsprequest and rename * more raw renaming * switch to a workspace, rename * remove unneeded imports * add license headers, remove more unneeded imports * coverage * this should actually be possible iwth just --all * merge all the coverage files * path fix * one last guess * coverage * remove extra definition
Diffstat (limited to 'src/rust')
-rw-r--r--src/rust/Cargo.lock8
-rw-r--r--src/rust/Cargo.toml4
-rw-r--r--src/rust/cryptography-x509/Cargo.toml11
-rw-r--r--src/rust/cryptography-x509/src/certificate.rs41
-rw-r--r--src/rust/cryptography-x509/src/common.rs142
-rw-r--r--src/rust/cryptography-x509/src/crl.rs69
-rw-r--r--src/rust/cryptography-x509/src/csr.rs70
-rw-r--r--src/rust/cryptography-x509/src/extensions.rs175
-rw-r--r--src/rust/cryptography-x509/src/lib.rs14
-rw-r--r--src/rust/cryptography-x509/src/name.rs88
-rw-r--r--src/rust/cryptography-x509/src/ocsp_req.rs46
-rw-r--r--src/rust/cryptography-x509/src/oid.rs86
-rw-r--r--src/rust/src/asn1.rs2
-rw-r--r--src/rust/src/pkcs7.rs51
-rw-r--r--src/rust/src/x509/certificate.rs234
-rw-r--r--src/rust/src/x509/common.rs240
-rw-r--r--src/rust/src/x509/crl.rs193
-rw-r--r--src/rust/src/x509/csr.rs105
-rw-r--r--src/rust/src/x509/extensions.rs80
-rw-r--r--src/rust/src/x509/mod.rs5
-rw-r--r--src/rust/src/x509/ocsp.rs116
-rw-r--r--src/rust/src/x509/ocsp_req.rs66
-rw-r--r--src/rust/src/x509/ocsp_resp.rs57
-rw-r--r--src/rust/src/x509/oid.rs101
-rw-r--r--src/rust/src/x509/sign.rs51
25 files changed, 1093 insertions, 962 deletions
diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock
index c16a7fcec..1fc04cecd 100644
--- a/src/rust/Cargo.lock
+++ b/src/rust/Cargo.lock
@@ -70,6 +70,7 @@ version = "0.1.0"
dependencies = [
"asn1",
"cc",
+ "cryptography-x509",
"foreign-types-shared",
"once_cell",
"openssl",
@@ -80,6 +81,13 @@ dependencies = [
]
[[package]]
+name = "cryptography-x509"
+version = "0.1.0"
+dependencies = [
+ "asn1",
+]
+
+[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml
index 3175cd12b..e96b1fc2b 100644
--- a/src/rust/Cargo.toml
+++ b/src/rust/Cargo.toml
@@ -11,6 +11,7 @@ rust-version = "1.56.0"
once_cell = "1"
pyo3 = { version = "0.18" }
asn1 = { version = "0.14.0", default-features = false }
+cryptography-x509 = { path = "cryptography-x509" }
pem = "1.1"
ouroboros = "0.15"
openssl = "0.10.50"
@@ -31,3 +32,6 @@ crate-type = ["cdylib"]
[profile.release]
lto = "thin"
overflow-checks = true
+
+[workspace]
+members = ["cryptography-x509"]
diff --git a/src/rust/cryptography-x509/Cargo.toml b/src/rust/cryptography-x509/Cargo.toml
new file mode 100644
index 000000000..b062ddbbf
--- /dev/null
+++ b/src/rust/cryptography-x509/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "cryptography-x509"
+version = "0.1.0"
+authors = ["The cryptography developers <cryptography-dev@python.org>"]
+edition = "2021"
+publish = false
+# This specifies the MSRV
+rust-version = "1.56.0"
+
+[dependencies]
+asn1 = { version = "0.14.0", default-features = false }
diff --git a/src/rust/cryptography-x509/src/certificate.rs b/src/rust/cryptography-x509/src/certificate.rs
new file mode 100644
index 000000000..bb9a666f5
--- /dev/null
+++ b/src/rust/cryptography-x509/src/certificate.rs
@@ -0,0 +1,41 @@
+// This file is dual licensed under the terms of the Apache License, Version
+// 2.0, and the BSD License. See the LICENSE file in the root of this repository
+// for complete details.
+
+use crate::common;
+use crate::extensions;
+use crate::name;
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write, Hash, PartialEq, Clone)]
+pub struct Certificate<'a> {
+ pub tbs_cert: TbsCertificate<'a>,
+ pub signature_alg: common::AlgorithmIdentifier<'a>,
+ pub signature: asn1::BitString<'a>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write, Hash, PartialEq, Clone)]
+pub struct TbsCertificate<'a> {
+ #[explicit(0)]
+ #[default(0)]
+ pub version: u8,
+ pub serial: asn1::BigInt<'a>,
+ pub signature_alg: common::AlgorithmIdentifier<'a>,
+
+ pub issuer: name::Name<'a>,
+ pub validity: Validity,
+ pub subject: name::Name<'a>,
+
+ pub spki: common::SubjectPublicKeyInfo<'a>,
+ #[implicit(1)]
+ pub issuer_unique_id: Option<asn1::BitString<'a>>,
+ #[implicit(2)]
+ pub subject_unique_id: Option<asn1::BitString<'a>>,
+ #[explicit(3)]
+ pub extensions: Option<extensions::Extensions<'a>>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write, Hash, PartialEq, Clone)]
+pub struct Validity {
+ pub not_before: common::Time,
+ pub not_after: common::Time,
+}
diff --git a/src/rust/cryptography-x509/src/common.rs b/src/rust/cryptography-x509/src/common.rs
new file mode 100644
index 000000000..13fcb3368
--- /dev/null
+++ b/src/rust/cryptography-x509/src/common.rs
@@ -0,0 +1,142 @@
+// This file is dual licensed under the terms of the Apache License, Version
+// 2.0, and the BSD License. See the LICENSE file in the root of this repository
+// for complete details.
+
+use std::marker::PhantomData;
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash, Clone)]
+pub struct AlgorithmIdentifier<'a> {
+ pub oid: asn1::ObjectIdentifier,
+ pub params: Option<asn1::Tlv<'a>>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write, Hash, PartialEq, Clone)]
+pub struct SubjectPublicKeyInfo<'a> {
+ _algorithm: AlgorithmIdentifier<'a>,
+ pub subject_public_key: asn1::BitString<'a>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Eq, Hash, Clone)]
+pub struct AttributeTypeValue<'a> {
+ pub type_id: asn1::ObjectIdentifier,
+ pub value: RawTlv<'a>,
+}
+
+// Like `asn1::Tlv` but doesn't store `full_data` so it can be constructed from
+// an un-encoded tag and value.
+#[derive(Hash, PartialEq, Eq, Clone)]
+pub struct RawTlv<'a> {
+ tag: asn1::Tag,
+ value: &'a [u8],
+}
+
+impl<'a> RawTlv<'a> {
+ pub fn new(tag: asn1::Tag, value: &'a [u8]) -> Self {
+ RawTlv { tag, value }
+ }
+
+ pub fn tag(&self) -> asn1::Tag {
+ self.tag
+ }
+ pub fn data(&self) -> &'a [u8] {
+ self.value
+ }
+}
+impl<'a> asn1::Asn1Readable<'a> for RawTlv<'a> {
+ fn parse(parser: &mut asn1::Parser<'a>) -> asn1::ParseResult<Self> {
+ let tlv = parser.read_element::<asn1::Tlv<'a>>()?;
+ Ok(RawTlv::new(tlv.tag(), tlv.data()))
+ }
+
+ fn can_parse(_tag: asn1::Tag) -> bool {
+ true
+ }
+}
+impl<'a> asn1::Asn1Writable for RawTlv<'a> {
+ fn write(&self, w: &mut asn1::Writer<'_>) -> asn1::WriteResult {
+ w.write_tlv(self.tag, move |dest| dest.push_slice(self.value))
+ }
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash, Clone)]
+pub enum Time {
+ UtcTime(asn1::UtcTime),
+ GeneralizedTime(asn1::GeneralizedTime),
+}
+
+impl Time {
+ pub fn as_datetime(&self) -> &asn1::DateTime {
+ match self {
+ Time::UtcTime(data) => data.as_datetime(),
+ Time::GeneralizedTime(data) => data.as_datetime(),
+ }
+ }
+}
+
+#[derive(Hash, PartialEq, Clone)]
+pub enum Asn1ReadableOrWritable<'a, T, U> {
+ Read(T, PhantomData<&'a ()>),
+ Write(U, PhantomData<&'a ()>),
+}
+
+impl<'a, T, U> Asn1ReadableOrWritable<'a, T, U> {
+ pub fn new_read(v: T) -> Self {
+ Asn1ReadableOrWritable::Read(v, PhantomData)
+ }
+
+ pub fn new_write(v: U) -> Self {
+ Asn1ReadableOrWritable::Write(v, PhantomData)
+ }
+
+ pub fn unwrap_read(&self) -> &T {
+ match self {
+ Asn1ReadableOrWritable::Read(v, _) => v,
+ Asn1ReadableOrWritable::Write(_, _) => panic!("unwrap_read called on a Write value"),
+ }
+ }
+}
+
+impl<'a, T: asn1::SimpleAsn1Readable<'a>, U> asn1::SimpleAsn1Readable<'a>
+ for Asn1ReadableOrWritable<'a, T, U>
+{
+ const TAG: asn1::Tag = T::TAG;
+ fn parse_data(data: &'a [u8]) -> asn1::ParseResult<Self> {
+ Ok(Self::new_read(T::parse_data(data)?))
+ }
+}
+
+impl<'a, T: asn1::SimpleAsn1Writable, U: asn1::SimpleAsn1Writable> asn1::SimpleAsn1Writable
+ for Asn1ReadableOrWritable<'a, T, U>
+{
+ const TAG: asn1::Tag = U::TAG;
+ fn write_data(&self, w: &mut asn1::WriteBuf) -> asn1::WriteResult {
+ match self {
+ Asn1ReadableOrWritable::Read(v, _) => T::write_data(v, w),
+ Asn1ReadableOrWritable::Write(v, _) => U::write_data(v, w),
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::{Asn1ReadableOrWritable, RawTlv};
+ use asn1::Asn1Readable;
+
+ #[test]
+ #[should_panic]
+ fn test_asn1_readable_or_writable_unwrap_read() {
+ Asn1ReadableOrWritable::<u32, u32>::new_write(17).unwrap_read();
+ }
+
+ #[test]
+ fn test_asn1_readable_or_writable_write_read_data() {
+ let v = Asn1ReadableOrWritable::<u32, u32>::new_read(17);
+ assert_eq!(&asn1::write_single(&v).unwrap(), b"\x02\x01\x11");
+ }
+
+ #[test]
+ fn test_raw_tlv_can_parse() {
+ let t = asn1::Tag::from_bytes(&[0]).unwrap().0;
+ assert!(RawTlv::can_parse(t));
+ }
+}
diff --git a/src/rust/cryptography-x509/src/crl.rs b/src/rust/cryptography-x509/src/crl.rs
new file mode 100644
index 000000000..3a47e0a37
--- /dev/null
+++ b/src/rust/cryptography-x509/src/crl.rs
@@ -0,0 +1,69 @@
+// This file is dual licensed under the terms of the Apache License, Version
+// 2.0, and the BSD License. See the LICENSE file in the root of this repository
+// for complete details.
+
+use crate::{common, extensions, name};
+
+pub type ReasonFlags<'a> =
+ Option<common::Asn1ReadableOrWritable<'a, asn1::BitString<'a>, asn1::OwnedBitString>>;
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash)]
+pub struct CertificateRevocationList<'a> {
+ pub tbs_cert_list: TBSCertList<'a>,
+ pub signature_algorithm: common::AlgorithmIdentifier<'a>,
+ pub signature_value: asn1::BitString<'a>,
+}
+
+pub type RevokedCertificates<'a> = Option<
+ common::Asn1ReadableOrWritable<
+ 'a,
+ asn1::SequenceOf<'a, RevokedCertificate<'a>>,
+ asn1::SequenceOfWriter<'a, RevokedCertificate<'a>, Vec<RevokedCertificate<'a>>>,
+ >,
+>;
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash)]
+pub struct TBSCertList<'a> {
+ pub version: Option<u8>,
+ pub signature: common::AlgorithmIdentifier<'a>,
+ pub issuer: name::Name<'a>,
+ pub this_update: common::Time,
+ pub next_update: Option<common::Time>,
+ pub revoked_certificates: RevokedCertificates<'a>,
+ #[explicit(0)]
+ pub crl_extensions: Option<extensions::Extensions<'a>>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash, Clone)]
+pub struct RevokedCertificate<'a> {
+ pub user_certificate: asn1::BigUint<'a>,
+ pub revocation_date: common::Time,
+ pub crl_entry_extensions: Option<extensions::Extensions<'a>>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct IssuingDistributionPoint<'a> {
+ #[explicit(0)]
+ pub distribution_point: Option<extensions::DistributionPointName<'a>>,
+
+ #[implicit(1)]
+ #[default(false)]
+ pub only_contains_user_certs: bool,
+
+ #[implicit(2)]
+ #[default(false)]
+ pub only_contains_ca_certs: bool,
+
+ #[implicit(3)]
+ pub only_some_reasons: ReasonFlags<'a>,
+
+ #[implicit(4)]
+ #[default(false)]
+ pub indirect_crl: bool,
+
+ #[implicit(5)]
+ #[default(false)]
+ pub only_contains_attribute_certs: bool,
+}
+
+pub type CRLReason = asn1::Enumerated;
diff --git a/src/rust/cryptography-x509/src/csr.rs b/src/rust/cryptography-x509/src/csr.rs
new file mode 100644
index 000000000..c23d22d0f
--- /dev/null
+++ b/src/rust/cryptography-x509/src/csr.rs
@@ -0,0 +1,70 @@
+// This file is dual licensed under the terms of the Apache License, Version
+// 2.0, and the BSD License. See the LICENSE file in the root of this repository
+// for complete details.
+
+use crate::common;
+use crate::extensions;
+use crate::name;
+use crate::oid;
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct Csr<'a> {
+ pub csr_info: CertificationRequestInfo<'a>,
+ pub signature_alg: common::AlgorithmIdentifier<'a>,
+ pub signature: asn1::BitString<'a>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct CertificationRequestInfo<'a> {
+ pub version: u8,
+ pub subject: name::Name<'a>,
+ pub spki: common::SubjectPublicKeyInfo<'a>,
+ #[implicit(0, required)]
+ pub attributes: Attributes<'a>,
+}
+
+impl CertificationRequestInfo<'_> {
+ pub fn get_extension_attribute(
+ &self,
+ ) -> Result<Option<extensions::Extensions<'_>>, asn1::ParseError> {
+ for attribute in self.attributes.unwrap_read().clone() {
+ if attribute.type_id == oid::EXTENSION_REQUEST
+ || attribute.type_id == oid::MS_EXTENSION_REQUEST
+ {
+ check_attribute_length(attribute.values.unwrap_read().clone())?;
+ let val = attribute.values.unwrap_read().clone().next().unwrap();
+ let exts = asn1::parse_single(val.full_data())?;
+ return Ok(Some(exts));
+ }
+ }
+ Ok(None)
+ }
+}
+
+pub fn check_attribute_length<'a>(
+ values: asn1::SetOf<'a, asn1::Tlv<'a>>,
+) -> Result<(), asn1::ParseError> {
+ if values.count() > 1 {
+ // TODO: We should raise a more specific error here
+ // Only single-valued attributes are supported
+ Err(asn1::ParseError::new(asn1::ParseErrorKind::InvalidValue))
+ } else {
+ Ok(())
+ }
+}
+
+pub type Attributes<'a> = common::Asn1ReadableOrWritable<
+ 'a,
+ asn1::SetOf<'a, Attribute<'a>>,
+ asn1::SetOfWriter<'a, Attribute<'a>, Vec<Attribute<'a>>>,
+>;
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct Attribute<'a> {
+ pub type_id: asn1::ObjectIdentifier,
+ pub values: common::Asn1ReadableOrWritable<
+ 'a,
+ asn1::SetOf<'a, asn1::Tlv<'a>>,
+ asn1::SetOfWriter<'a, common::RawTlv<'a>, [common::RawTlv<'a>; 1]>,
+ >,
+}
diff --git a/src/rust/cryptography-x509/src/extensions.rs b/src/rust/cryptography-x509/src/extensions.rs
new file mode 100644
index 000000000..11c6e54a4
--- /dev/null
+++ b/src/rust/cryptography-x509/src/extensions.rs
@@ -0,0 +1,175 @@
+// This file is dual licensed under the terms of the Apache License, Version
+// 2.0, and the BSD License. See the LICENSE file in the root of this repository
+// for complete details.
+
+use crate::common;
+use crate::crl;
+use crate::name;
+
+pub type Extensions<'a> = common::Asn1ReadableOrWritable<
+ 'a,
+ asn1::SequenceOf<'a, Extension<'a>>,
+ asn1::SequenceOfWriter<'a, Extension<'a>, Vec<Extension<'a>>>,
+>;
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Eq, Hash, Clone)]
+pub struct Extension<'a> {
+ pub extn_id: asn1::ObjectIdentifier,
+ #[default(false)]
+ pub critical: bool,
+ pub extn_value: &'a [u8],
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct PolicyConstraints {
+ #[implicit(0)]
+ pub require_explicit_policy: Option<u64>,
+ #[implicit(1)]
+ pub inhibit_policy_mapping: Option<u64>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct AccessDescription<'a> {
+ pub access_method: asn1::ObjectIdentifier,
+ pub access_location: name::GeneralName<'a>,
+}
+
+pub type SequenceOfAccessDescriptions<'a> = common::Asn1ReadableOrWritable<
+ 'a,
+ asn1::SequenceOf<'a, AccessDescription<'a>>,
+ asn1::SequenceOfWriter<'a, AccessDescription<'a>, Vec<AccessDescription<'a>>>,
+>;
+
+// Needed due to clippy type complexity warning.
+type SequenceOfPolicyQualifiers<'a> = common::Asn1ReadableOrWritable<
+ 'a,
+ asn1::SequenceOf<'a, PolicyQualifierInfo<'a>>,
+ asn1::SequenceOfWriter<'a, PolicyQualifierInfo<'a>, Vec<PolicyQualifierInfo<'a>>>,
+>;
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct PolicyInformation<'a> {
+ pub policy_identifier: asn1::ObjectIdentifier,
+ pub policy_qualifiers: Option<SequenceOfPolicyQualifiers<'a>>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct PolicyQualifierInfo<'a> {
+ pub policy_qualifier_id: asn1::ObjectIdentifier,
+ pub qualifier: Qualifier<'a>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub enum Qualifier<'a> {
+ CpsUri(asn1::IA5String<'a>),
+ UserNotice(UserNotice<'a>),
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct UserNotice<'a> {
+ pub notice_ref: Option<NoticeReference<'a>>,
+ pub explicit_text: Option<DisplayText<'a>>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct NoticeReference<'a> {
+ pub organization: DisplayText<'a>,
+ pub notice_numbers: common::Asn1ReadableOrWritable<
+ 'a,
+ asn1::SequenceOf<'a, asn1::BigUint<'a>>,
+ asn1::SequenceOfWriter<'a, asn1::BigUint<'a>, Vec<asn1::BigUint<'a>>>,
+ >,
+}
+
+// DisplayText also allows BMPString, which we currently do not support.
+#[allow(clippy::enum_variant_names)]
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub enum DisplayText<'a> {
+ IA5String(asn1::IA5String<'a>),
+ Utf8String(asn1::Utf8String<'a>),
+ VisibleString(asn1::VisibleString<'a>),
+ BmpString(asn1::BMPString<'a>),
+}
+
+// Needed due to clippy type complexity warning.
+pub type SequenceOfSubtrees<'a> = common::Asn1ReadableOrWritable<
+ 'a,
+ asn1::SequenceOf<'a, GeneralSubtree<'a>>,
+ asn1::SequenceOfWriter<'a, GeneralSubtree<'a>, Vec<GeneralSubtree<'a>>>,
+>;
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct NameConstraints<'a> {
+ #[implicit(0)]
+ pub permitted_subtrees: Option<SequenceOfSubtrees<'a>>,
+
+ #[implicit(1)]
+ pub excluded_subtrees: Option<SequenceOfSubtrees<'a>>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct GeneralSubtree<'a> {
+ pub base: name::GeneralName<'a>,
+
+ #[implicit(0)]
+ #[default(0u64)]
+ pub minimum: u64,
+
+ #[implicit(1)]
+ pub maximum: Option<u64>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct MSCertificateTemplate {
+ pub template_id: asn1::ObjectIdentifier,
+ pub major_version: Option<u32>,
+ pub minor_version: Option<u32>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct DistributionPoint<'a> {
+ #[explicit(0)]
+ pub distribution_point: Option<DistributionPointName<'a>>,
+
+ #[implicit(1)]
+ pub reasons: crl::ReasonFlags<'a>,
+
+ #[implicit(2)]
+ pub crl_issuer: Option<name::SequenceOfGeneralName<'a>>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub enum DistributionPointName<'a> {
+ #[implicit(0)]
+ FullName(name::SequenceOfGeneralName<'a>),
+
+ #[implicit(1)]
+ NameRelativeToCRLIssuer(
+ common::Asn1ReadableOrWritable<
+ 'a,
+ asn1::SetOf<'a, common::AttributeTypeValue<'a>>,
+ asn1::SetOfWriter<
+ 'a,
+ common::AttributeTypeValue<'a>,
+ Vec<common::AttributeTypeValue<'a>>,
+ >,
+ >,
+ ),
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct AuthorityKeyIdentifier<'a> {
+ #[implicit(0)]
+ pub key_identifier: Option<&'a [u8]>,
+ #[implicit(1)]
+ pub authority_cert_issuer: Option<name::SequenceOfGeneralName<'a>>,
+ #[implicit(2)]
+ pub authority_cert_serial_number: Option<asn1::BigUint<'a>>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct BasicConstraints {
+ #[default(false)]
+ pub ca: bool,
+ pub path_length: Option<u64>,
+}
diff --git a/src/rust/cryptography-x509/src/lib.rs b/src/rust/cryptography-x509/src/lib.rs
new file mode 100644
index 000000000..3f8878772
--- /dev/null
+++ b/src/rust/cryptography-x509/src/lib.rs
@@ -0,0 +1,14 @@
+// This file is dual licensed under the terms of the Apache License, Version
+// 2.0, and the BSD License. See the LICENSE file in the root of this repository
+// for complete details.
+
+#![forbid(unsafe_code)]
+
+pub mod certificate;
+pub mod common;
+pub mod crl;
+pub mod csr;
+pub mod extensions;
+pub mod name;
+pub mod ocsp_req;
+pub mod oid;
diff --git a/src/rust/cryptography-x509/src/name.rs b/src/rust/cryptography-x509/src/name.rs
new file mode 100644
index 000000000..f53e342cb
--- /dev/null
+++ b/src/rust/cryptography-x509/src/name.rs
@@ -0,0 +1,88 @@
+// This file is dual licensed under the terms of the Apache License, Version
+// 2.0, and the BSD License. See the LICENSE file in the root of this repository
+// for complete details.
+
+use crate::common;
+
+pub type Name<'a> = common::Asn1ReadableOrWritable<
+ 'a,
+ asn1::SequenceOf<'a, asn1::SetOf<'a, common::AttributeTypeValue<'a>>>,
+ asn1::SequenceOfWriter<
+ 'a,
+ asn1::SetOfWriter<'a, common::AttributeTypeValue<'a>, Vec<common::AttributeTypeValue<'a>>>,
+ Vec<
+ asn1::SetOfWriter<
+ 'a,
+ common::AttributeTypeValue<'a>,
+ Vec<common::AttributeTypeValue<'a>>,
+ >,
+ >,
+ >,
+>;
+
+/// An IA5String ASN.1 element whose contents is not validated as meeting the
+/// requirements (ASCII characters only), and instead is only known to be
+/// valid UTF-8.
+pub struct UnvalidatedIA5String<'a>(pub &'a str);
+
+impl<'a> asn1::SimpleAsn1Readable<'a> for UnvalidatedIA5String<'a> {
+ const TAG: asn1::Tag = asn1::IA5String::TAG;
+ fn parse_data(data: &'a [u8]) -> asn1::ParseResult<Self> {
+ Ok(UnvalidatedIA5String(std::str::from_utf8(data).map_err(
+ |_| asn1::ParseError::new(asn1::ParseErrorKind::InvalidValue),
+ )?))
+ }
+}
+
+impl<'a> asn1::SimpleAsn1Writable for UnvalidatedIA5String<'a> {
+ const TAG: asn1::Tag = asn1::IA5String::TAG;
+ fn write_data(&self, dest: &mut asn1::WriteBuf) -> asn1::WriteResult {
+ dest.push_slice(self.0.as_bytes())
+ }
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash)]
+pub struct OtherName<'a> {
+ pub type_id: asn1::ObjectIdentifier,
+ #[explicit(0, required)]
+ pub value: asn1::Tlv<'a>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub enum GeneralName<'a> {
+ #[implicit(0)]
+ OtherName(OtherName<'a>),
+
+ #[implicit(1)]
+ RFC822Name(UnvalidatedIA5String<'a>),
+
+ #[implicit(2)]
+ DNSName(UnvalidatedIA5String<'a>),
+
+ #[implicit(3)]
+ // unsupported
+ X400Address(asn1::Sequence<'a>),
+
+ // Name is explicit per RFC 5280 Appendix A.1.
+ #[explicit(4)]
+ DirectoryName(Name<'a>),
+
+ #[implicit(5)]
+ // unsupported
+ EDIPartyName(asn1::Sequence<'a>),
+
+ #[implicit(6)]
+ UniformResourceIdentifier(UnvalidatedIA5String<'a>),
+
+ #[implicit(7)]
+ IPAddress(&'a [u8]),
+
+ #[implicit(8)]
+ RegisteredID(asn1::ObjectIdentifier),
+}
+
+pub(crate) type SequenceOfGeneralName<'a> = common::Asn1ReadableOrWritable<
+ 'a,
+ asn1::SequenceOf<'a, GeneralName<'a>>,
+ asn1::SequenceOfWriter<'a, GeneralName<'a>, Vec<GeneralName<'a>>>,
+>;
diff --git a/src/rust/cryptography-x509/src/ocsp_req.rs b/src/rust/cryptography-x509/src/ocsp_req.rs
new file mode 100644
index 000000000..1e096e71f
--- /dev/null
+++ b/src/rust/cryptography-x509/src/ocsp_req.rs
@@ -0,0 +1,46 @@
+// This file is dual licensed under the terms of the Apache License, Version
+// 2.0, and the BSD License. See the LICENSE file in the root of this repository
+// for complete details.
+
+use crate::{common, extensions, name};
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct TBSRequest<'a> {
+ #[explicit(0)]
+ #[default(0)]
+ pub version: u8,
+ #[explicit(1)]
+ pub requestor_name: Option<name::GeneralName<'a>>,
+ pub request_list: common::Asn1ReadableOrWritable<
+ 'a,
+ asn1::SequenceOf<'a, Request<'a>>,
+ asn1::SequenceOfWriter<'a, Request<'a>>,
+ >,
+ #[explicit(2)]
+ pub request_extensions: Option<extensions::Extensions<'a>>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct Request<'a> {
+ pub req_cert: CertID<'a>,
+ #[explicit(0)]
+ pub single_request_extensions: Option<extensions::Extensions<'a>>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct CertID<'a> {
+ pub hash_algorithm: common::AlgorithmIdentifier<'a>,
+ pub issuer_name_hash: &'a [u8],
+ pub issuer_key_hash: &'a [u8],
+ pub serial_number: asn1::BigInt<'a>,
+}
+
+#[derive(asn1::Asn1Read, asn1::Asn1Write)]
+pub struct OCSPRequest<'a> {
+ pub tbs_request: TBSRequest<'a>,
+ // Parsing out the full structure, which includes the entirety of a
+ // certificate is more trouble than it's worth, since it's not in the
+ // Python API.
+ #[explicit(0)]
+ pub optional_signature: Option<asn1::Sequence<'a>>,
+}
diff --git a/src/rust/cryptography-x509/src/oid.rs b/src/rust/cryptography-x509/src/oid.rs
new file mode 100644
index 000000000..b2d22ebdd
--- /dev/null
+++ b/src/rust/cryptography-x509/src/oid.rs
@@ -0,0 +1,86 @@
+// This file is dual licensed under the terms of the Apache License, Version
+// 2.0, and the BSD License. See the LICENSE file in the root of this repository
+// for complete details.
+
+pub const EXTENSION_REQUEST: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 9, 14);
+pub const MS_EXTENSION_REQUEST: asn1::ObjectIdentifier =
+ asn1::oid!(1, 3, 6, 1, 4, 1, 311, 2, 1, 14);
+pub const MS_CERTIFICATE_TEMPLATE: asn1::ObjectIdentifier =
+ asn1::oid!(1, 3, 6, 1, 4, 1, 311, 21, 7);
+pub const PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS_OID: asn1::ObjectIdentifier =
+ asn1::oid!(1, 3, 6, 1, 4, 1, 11129, 2, 4, 2);
+pub const PRECERT_POISON_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 6, 1, 4, 1, 11129, 2, 4, 3);
+pub const SIGNED_CERTIFICATE_TIMESTAMPS_OID: asn1::ObjectIdentifier =
+ asn1::oid!(1, 3, 6, 1, 4, 1, 11129, 2, 4, 5);
+pub const AUTHORITY_INFORMATION_ACCESS_OID: asn1::ObjectIdentifier =
+ asn1::oid!(1, 3, 6, 1, 5, 5, 7, 1, 1);
+pub const SUBJECT_INFORMATION_ACCESS_OID: asn1::ObjectIdentifier =
+ asn1::oid!(1, 3, 6, 1, 5, 5, 7, 1, 11);
+pub const TLS_FEATURE_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 6, 1, 5, 5, 7, 1, 24);
+pub const CP_CPS_URI_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 6, 1, 5, 5, 7, 2, 1);
+pub const CP_USER_NOTICE_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 6, 1, 5, 5, 7, 2, 2);
+pub const NONCE_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 6, 1, 5, 5, 7, 48, 1, 2);
+pub const OCSP_NO_CHECK_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 6, 1, 5, 5, 7, 48, 1, 5);
+pub const SUBJECT_KEY_IDENTIFIER_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 14);
+pub const KEY_USAGE_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 15);
+pub const SUBJECT_ALTERNATIVE_NAME_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 17);
+pub const ISSUER_ALTERNATIVE_NAME_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 18);
+pub const BASIC_CONSTRAINTS_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 19);
+pub const CRL_NUMBER_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 20);
+pub const CRL_REASON_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 21);
+pub const INVALIDITY_DATE_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 24);
+pub const DELTA_CRL_INDICATOR_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 27);
+pub const ISSUING_DISTRIBUTION_POINT_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 28);
+pub const CERTIFICATE_ISSUER_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 29);
+pub const NAME_CONSTRAINTS_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 30);
+pub const CRL_DISTRIBUTION_POINTS_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 31);
+pub const CERTIFICATE_POLICIES_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 32);
+pub const AUTHORITY_KEY_IDENTIFIER_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 35);
+pub const POLICY_CONSTRAINTS_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 36);
+pub const EXTENDED_KEY_USAGE_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 37);
+pub const FRESHEST_CRL_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 46);
+pub const INHIBIT_ANY_POLICY_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 54);
+pub const ACCEPTABLE_RESPONSES_OID: asn1::ObjectIdentifier =
+ asn1::oid!(1, 3, 6, 1, 5, 5, 7, 48, 1, 4);
+
+// Signing methods
+pub const ECDSA_WITH_SHA224_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 10045, 4, 3, 1);
+pub const ECDSA_WITH_SHA256_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 10045, 4, 3, 2);
+pub const ECDSA_WITH_SHA384_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 10045, 4, 3, 3);
+pub const ECDSA_WITH_SHA512_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 10045, 4, 3, 4);
+pub const ECDSA_WITH_SHA3_224_OID: asn1::ObjectIdentifier =
+ asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 9);
+pub const ECDSA_WITH_SHA3_256_OID: asn1::ObjectIdentifier =
+ asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 10);
+pub const ECDSA_WITH_SHA3_384_OID: asn1::ObjectIdentifier =
+ asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 11);
+pub const ECDSA_WITH_SHA3_512_OID: asn1::ObjectIdentifier =
+ asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 12);
+
+pub const RSA_WITH_SHA224_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 1, 14);
+pub const RSA_WITH_SHA256_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 1, 11);
+pub const RSA_WITH_SHA384_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 1, 12);
+pub const RSA_WITH_SHA512_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 1, 13);
+pub const RSA_WITH_SHA3_224_OID: asn1::ObjectIdentifier =
+ asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 13);
+pub const RSA_WITH_SHA3_256_OID: asn1::ObjectIdentifier =
+ asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 14);
+pub const RSA_WITH_SHA3_384_OID: asn1::ObjectIdentifier =
+ asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 15);
+pub const RSA_WITH_SHA3_512_OID: asn1::ObjectIdentifier =
+ asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 16);
+
+pub const DSA_WITH_SHA224_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 1);
+pub const DSA_WITH_SHA256_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 2);
+pub const DSA_WITH_SHA384_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 3);
+pub const DSA_WITH_SHA512_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 4);
+
+pub const ED25519_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 101, 112);
+pub const ED448_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 101, 113);
+
+// Hashes
+pub const SHA1_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 14, 3, 2, 26);
+pub const SHA224_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 2, 4);
+pub const SHA256_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 2, 1);
+pub const SHA384_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 2, 2);
+pub const SHA512_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 2, 3);
diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs
index 53981ddac..cad48a73f 100644
--- a/src/rust/src/asn1.rs
+++ b/src/rust/src/asn1.rs
@@ -3,7 +3,7 @@
// for complete details.
use crate::error::{CryptographyError, CryptographyResult};
-use crate::x509::Name;
+use cryptography_x509::name::Name;
use pyo3::basic::CompareOp;
use pyo3::types::IntoPyDict;
use pyo3::ToPyObject;
diff --git a/src/rust/src/pkcs7.rs b/src/rust/src/pkcs7.rs
index bb5161434..2fdb610e3 100644
--- a/src/rust/src/pkcs7.rs
+++ b/src/rust/src/pkcs7.rs
@@ -6,6 +6,8 @@ use crate::asn1::encode_der_data;
use crate::buf::CffiBuf;
use crate::error::CryptographyResult;
use crate::x509;
+use cryptography_x509::csr::{Attribute, Attributes};
+use cryptography_x509::{common, name, oid};
use once_cell::sync::Lazy;
use std::borrow::Cow;
@@ -26,10 +28,10 @@ const AES_128_CBC_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3
static OIDS_TO_MIC_NAME: Lazy<HashMap<&asn1::ObjectIdentifier, &str>> = Lazy::new(|| {
let mut h = HashMap::new();
- h.insert(&x509::oid::SHA224_OID, "sha-224");
- h.insert(&x509::oid::SHA256_OID, "sha-256");
- h.insert(&x509::oid::SHA384_OID, "sha-384");
- h.insert(&x509::oid::SHA512_OID, "sha-512");
+ h.insert(&oid::SHA224_OID, "sha-224");
+ h.insert(&oid::SHA256_OID, "sha-256");
+ h.insert(&oid::SHA384_OID, "sha-384");
+ h.insert(&oid::SHA512_OID, "sha-512");
h
});
@@ -52,10 +54,11 @@ enum Content<'a> {
#[derive(asn1::Asn1Write)]
struct SignedData<'a> {
version: u8,
- digest_algorithms: asn1::SetOfWriter<'a, x509::AlgorithmIdentifier<'a>>,
+ digest_algorithms: asn1::SetOfWriter<'a, common::AlgorithmIdentifier<'a>>,
content_info: ContentInfo<'a>,
#[implicit(0)]
- certificates: Option<asn1::SetOfWriter<'a, &'a x509::certificate::RawCertificate<'a>>>,
+ certificates:
+ Option<asn1::SetOfWriter<'a, &'a cryptography_x509::certificate::Certificate<'a>>>,
// We don't ever supply any of these, so for now, don't fill out the fields.
#[implicit(1)]
@@ -68,27 +71,27 @@ struct SignedData<'a> {
struct SignerInfo<'a> {
version: u8,
issuer_and_serial_number: IssuerAndSerialNumber<'a>,
- digest_algorithm: x509::AlgorithmIdentifier<'a>,
+ digest_algorithm: common::AlgorithmIdentifier<'a>,
#[implicit(0)]
- authenticated_attributes: Option<x509::csr::Attributes<'a>>,
+ authenticated_attributes: Option<Attributes<'a>>,
- digest_encryption_algorithm: x509::AlgorithmIdentifier<'a>,
+ digest_encryption_algorithm: common::AlgorithmIdentifier<'a>,
encrypted_digest: &'a [u8],
#[implicit(1)]
- unauthenticated_attributes: Option<x509::csr::Attributes<'a>>,
+ unauthenticated_attributes: Option<Attributes<'a>>,
}
#[derive(asn1::Asn1Write)]
struct IssuerAndSerialNumber<'a> {
- issuer: x509::Name<'a>,
+ issuer: name::Name<'a>,
serial_number: asn1::BigInt<'a>,
}
#[pyo3::prelude::pyfunction]
fn serialize_certificates<'p>(
py: pyo3::Python<'p>,
- py_certs: Vec<pyo3::PyRef<'p, x509::Certificate>>,
+ py_certs: Vec<pyo3::PyRef<'p, x509::certificate::Certificate>>,
encoding: &'p pyo3::PyAny,
) -> CryptographyResult<&'p pyo3::types::PyBytes> {
if py_certs.is_empty() {
@@ -163,12 +166,12 @@ fn sign_and_serialize<'p>(
]))?;
let py_signers: Vec<(
- pyo3::PyRef<'p, x509::Certificate>,
+ pyo3::PyRef<'p, x509::certificate::Certificate>,
&pyo3::PyAny,
&pyo3::PyAny,
)> = builder.getattr(pyo3::intern!(py, "_signers"))?.extract()?;
- let py_certs: Vec<pyo3::PyRef<'p, x509::Certificate>> = builder
+ let py_certs: Vec<pyo3::PyRef<'p, x509::certificate::Certificate>> = builder
.getattr(pyo3::intern!(py, "_additional_certs"))?
.extract()?;
@@ -189,15 +192,15 @@ fn sign_and_serialize<'p>(
} else {
let mut authenticated_attrs = vec![];
- authenticated_attrs.push(x509::csr::Attribute {
+ authenticated_attrs.push(Attribute {
type_id: PKCS7_CONTENT_TYPE_OID,
- values: x509::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([
+ values: common::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([
asn1::parse_single(&content_type_bytes).unwrap(),
])),
});
- authenticated_attrs.push(x509::csr::Attribute {
+ authenticated_attrs.push(Attribute {
type_id: PKCS7_SIGNING_TIME_OID,
- values: x509::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([
+ values: common::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([
asn1::parse_single(&signing_time_bytes).unwrap(),
])),
});
@@ -206,17 +209,17 @@ fn sign_and_serialize<'p>(
asn1::write_single(&x509::ocsp::hash_data(py, py_hash_alg, &data_with_header)?)?;
// Gross hack: copy to PyBytes to extend the lifetime to 'p
let digest_bytes = pyo3::types::PyBytes::new(py, &digest);
- authenticated_attrs.push(x509::csr::Attribute {
+ authenticated_attrs.push(Attribute {
type_id: PKCS7_MESSAGE_DIGEST_OID,
- values: x509::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([
+ values: common::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([
asn1::parse_single(digest_bytes.as_bytes()).unwrap(),
])),
});
if !options.contains(pkcs7_options.getattr(pyo3::intern!(py, "NoCapabilities"))?)? {
- authenticated_attrs.push(x509::csr::Attribute {
+ authenticated_attrs.push(Attribute {
type_id: PKCS7_SMIME_CAP_OID,
- values: x509::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([
+ values: common::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([
asn1::parse_single(&smime_cap_bytes).unwrap(),
])),
});
@@ -226,14 +229,14 @@ fn sign_and_serialize<'p>(
asn1::write_single(&asn1::SetOfWriter::new(authenticated_attrs.as_slice()))?;
(
- Some(x509::Asn1ReadableOrWritable::new_write(
+ Some(common::Asn1ReadableOrWritable::new_write(
asn1::SetOfWriter::new(authenticated_attrs),
)),
x509::sign::sign_data(py, py_private_key, py_hash_alg, &signed_data)?,
)
};
- let digest_alg = x509::AlgorithmIdentifier {
+ let digest_alg = common::AlgorithmIdentifier {
oid: x509::ocsp::HASH_NAME_TO_OIDS[py_hash_alg
.getattr(pyo3::intern!(py, "name"))?
.extract::<&str>()?]
diff --git a/src/rust/src/x509/certificate.rs b/src/rust/src/x509/certificate.rs
index 6ccde6542..a20e3fe5f 100644
--- a/src/rust/src/x509/certificate.rs
+++ b/src/rust/src/x509/certificate.rs
@@ -7,79 +7,49 @@ use crate::asn1::{
};
use crate::error::{CryptographyError, CryptographyResult};
use crate::x509;
-use crate::x509::{crl, extensions, oid, sct, sign, Asn1ReadableOrWritable};
+use crate::x509::{extensions, sct, sign};
+use cryptography_x509::common::Asn1ReadableOrWritable;
+use cryptography_x509::extensions::{
+ AuthorityKeyIdentifier, BasicConstraints, DisplayText, DistributionPoint,
+ DistributionPointName, MSCertificateTemplate, NameConstraints, PolicyConstraints,
+ PolicyInformation, PolicyQualifierInfo, Qualifier, SequenceOfAccessDescriptions,
+ SequenceOfSubtrees, UserNotice,
+};
+use cryptography_x509::extensions::{Extension, Extensions};
+use cryptography_x509::{common, name, oid};
use pyo3::{IntoPy, ToPyObject};
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
-#[derive(asn1::Asn1Read, asn1::Asn1Write, Hash, PartialEq, Clone)]
-pub(crate) struct RawCertificate<'a> {
- pub(crate) tbs_cert: TbsCertificate<'a>,
- signature_alg: x509::AlgorithmIdentifier<'a>,
- signature: asn1::BitString<'a>,
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write, Hash, PartialEq, Clone)]
-pub(crate) struct TbsCertificate<'a> {
- #[explicit(0)]
- #[default(0)]
- version: u8,
- pub(crate) serial: asn1::BigInt<'a>,
- signature_alg: x509::AlgorithmIdentifier<'a>,
-
- pub(crate) issuer: x509::Name<'a>,
- validity: Validity,
- pub(crate) subject: x509::Name<'a>,
-
- pub(crate) spki: SubjectPublicKeyInfo<'a>,
- #[implicit(1)]
- issuer_unique_id: Option<asn1::BitString<'a>>,
- #[implicit(2)]
- subject_unique_id: Option<asn1::BitString<'a>>,
- #[explicit(3)]
- extensions: Option<x509::Extensions<'a>>,
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write, Hash, PartialEq, Clone)]
-pub(crate) struct Validity {
- not_before: x509::Time,
- not_after: x509::Time,
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write, Hash, PartialEq, Clone)]
-pub(crate) struct SubjectPublicKeyInfo<'a> {
- _algorithm: x509::AlgorithmIdentifier<'a>,
- pub(crate) subject_public_key: asn1::BitString<'a>,
-}
-
#[ouroboros::self_referencing]
-pub(crate) struct OwnedRawCertificate {
+pub(crate) struct OwnedCertificate {
data: pyo3::Py<pyo3::types::PyBytes>,
#[borrows(data)]
#[covariant]
- value: RawCertificate<'this>,
+ value: cryptography_x509::certificate::Certificate<'this>,
}
-impl OwnedRawCertificate {
+impl OwnedCertificate {
// Re-expose ::new with `pub(crate)` visibility.
pub(crate) fn new_public(
data: pyo3::Py<pyo3::types::PyBytes>,
value_ref_builder: impl for<'this> FnOnce(
&'this pyo3::Py<pyo3::types::PyBytes>,
- ) -> RawCertificate<'this>,
- ) -> OwnedRawCertificate {
- OwnedRawCertificate::new(data, value_ref_builder)
+ )
+ -> cryptography_x509::certificate::Certificate<'this>,
+ ) -> OwnedCertificate {
+ OwnedCertificate::new(data, value_ref_builder)
}
- pub(crate) fn borrow_value_public(&self) -> &RawCertificate<'_> {
+ pub(crate) fn borrow_value_public(&self) -> &cryptography_x509::certificate::Certificate<'_> {
self.borrow_value()
}
}
#[pyo3::prelude::pyclass(module = "cryptography.hazmat.bindings._rust.x509")]
pub(crate) struct Certificate {
- pub(crate) raw: OwnedRawCertificate,
+ pub(crate) raw: OwnedCertificate,
pub(crate) cached_extensions: Option<pyo3::PyObject>,
}
@@ -209,7 +179,7 @@ impl Certificate {
Some(extensions) => {
let readable_extensions = extensions.unwrap_read().clone();
let ext_count = readable_extensions.len();
- let filtered_extensions: Vec<x509::common::Extension<'_>> = readable_extensions
+ let filtered_extensions: Vec<Extension<'_>> = readable_extensions
.filter(|x| x.extn_id != oid::PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS_OID)
.collect();
if filtered_extensions.len() == ext_count {
@@ -219,7 +189,7 @@ impl Certificate {
),
));
}
- let filtered_extensions: x509::Extensions<'_> = Asn1ReadableOrWritable::new_write(
+ let filtered_extensions: Extensions<'_> = Asn1ReadableOrWritable::new_write(
asn1::SequenceOfWriter::new(filtered_extensions),
);
tbs_precert.extensions = Some(filtered_extensions);
@@ -409,7 +379,7 @@ fn load_der_x509_certificate(
py: pyo3::Python<'_>,
data: pyo3::Py<pyo3::types::PyBytes>,
) -> CryptographyResult<Certificate> {
- let raw = OwnedRawCertificate::try_new(data, |data| asn1::parse_single(data.as_bytes(py)))?;
+ let raw = OwnedCertificate::try_new(data, |data| asn1::parse_single(data.as_bytes(py)))?;
// Parse cert version immediately so we can raise error on parse if it is invalid.
cert_version(py, raw.borrow_value().tbs_cert.version)?;
// determine if the serial is negative and raise a warning if it is. We want to drop support
@@ -437,57 +407,6 @@ fn warn_if_negative_serial(py: pyo3::Python<'_>, bytes: &'_ [u8]) -> pyo3::PyRes
Ok(())
}
-// Needed due to clippy type complexity warning.
-type SequenceOfPolicyQualifiers<'a> = x509::Asn1ReadableOrWritable<
- 'a,
- asn1::SequenceOf<'a, PolicyQualifierInfo<'a>>,
- asn1::SequenceOfWriter<'a, PolicyQualifierInfo<'a>, Vec<PolicyQualifierInfo<'a>>>,
->;
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) struct PolicyInformation<'a> {
- pub policy_identifier: asn1::ObjectIdentifier,
- pub policy_qualifiers: Option<SequenceOfPolicyQualifiers<'a>>,
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) struct PolicyQualifierInfo<'a> {
- pub policy_qualifier_id: asn1::ObjectIdentifier,
- pub qualifier: Qualifier<'a>,
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) enum Qualifier<'a> {
- CpsUri(asn1::IA5String<'a>),
- UserNotice(UserNotice<'a>),
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) struct UserNotice<'a> {
- pub notice_ref: Option<NoticeReference<'a>>,
- pub explicit_text: Option<DisplayText<'a>>,
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) struct NoticeReference<'a> {
- pub organization: DisplayText<'a>,
- pub notice_numbers: x509::Asn1ReadableOrWritable<
- 'a,
- asn1::SequenceOf<'a, asn1::BigUint<'a>>,
- asn1::SequenceOfWriter<'a, asn1::BigUint<'a>, Vec<asn1::BigUint<'a>>>,
- >,
-}
-
-// DisplayText also allows BMPString, which we currently do not support.
-#[allow(clippy::enum_variant_names)]
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) enum DisplayText<'a> {
- IA5String(asn1::IA5String<'a>),
- Utf8String(asn1::Utf8String<'a>),
- VisibleString(asn1::VisibleString<'a>),
- BmpString(asn1::BMPString<'a>),
-}
-
fn parse_display_text(
py: pyo3::Python<'_>,
text: DisplayText<'_>,
@@ -592,41 +511,6 @@ fn parse_cp(py: pyo3::Python<'_>, ext_data: &[u8]) -> Result<pyo3::PyObject, Cry
Ok(certificate_policies.to_object(py))
}
-// Needed due to clippy type complexity warning.
-pub(crate) type SequenceOfSubtrees<'a> = x509::Asn1ReadableOrWritable<
- 'a,
- asn1::SequenceOf<'a, GeneralSubtree<'a>>,
- asn1::SequenceOfWriter<'a, GeneralSubtree<'a>, Vec<GeneralSubtree<'a>>>,
->;
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) struct NameConstraints<'a> {
- #[implicit(0)]
- pub permitted_subtrees: Option<SequenceOfSubtrees<'a>>,
-
- #[implicit(1)]
- pub excluded_subtrees: Option<SequenceOfSubtrees<'a>>,
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) struct GeneralSubtree<'a> {
- pub base: x509::GeneralName<'a>,
-
- #[implicit(0)]
- #[default(0u64)]
- pub minimum: u64,
-
- #[implicit(1)]
- pub maximum: Option<u64>,
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) struct MSCertificateTemplate {
- pub template_id: asn1::ObjectIdentifier,
- pub major_version: Option<u32>,
- pub minor_version: Option<u32>,
-}
-
fn parse_general_subtrees(
py: pyo3::Python<'_>,
subtrees: SequenceOfSubtrees<'_>,
@@ -638,43 +522,6 @@ fn parse_general_subtrees(
Ok(gns.to_object(py))
}
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) struct DistributionPoint<'a> {
- #[explicit(0)]
- pub distribution_point: Option<DistributionPointName<'a>>,
-
- #[implicit(1)]
- pub reasons: crl::ReasonFlags<'a>,
-
- #[implicit(2)]
- pub crl_issuer: Option<x509::common::SequenceOfGeneralName<'a>>,
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) enum DistributionPointName<'a> {
- #[implicit(0)]
- FullName(x509::common::SequenceOfGeneralName<'a>),
-
- #[implicit(1)]
- NameRelativeToCRLIssuer(
- x509::Asn1ReadableOrWritable<
- 'a,
- asn1::SetOf<'a, x509::AttributeTypeValue<'a>>,
- asn1::SetOfWriter<'a, x509::AttributeTypeValue<'a>, Vec<x509::AttributeTypeValue<'a>>>,
- >,
- ),
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) struct AuthorityKeyIdentifier<'a> {
- #[implicit(0)]
- pub key_identifier: Option<&'a [u8]>,
- #[implicit(1)]
- pub authority_cert_issuer: Option<x509::common::SequenceOfGeneralName<'a>>,
- #[implicit(2)]
- pub authority_cert_serial_number: Option<asn1::BigUint<'a>>,
-}
-
pub(crate) fn parse_distribution_point_name(
py: pyo3::Python<'_>,
dp: DistributionPointName<'_>,
@@ -767,21 +614,6 @@ pub(crate) fn encode_distribution_point_reasons(
Ok(asn1::OwnedBitString::new(bits, unused_bits).unwrap())
}
-#[derive(asn1::Asn1Read, asn1::Asn1Write, pyo3::prelude::FromPyObject)]
-pub(crate) struct BasicConstraints {
- #[default(false)]
- pub ca: bool,
- pub path_length: Option<u64>,
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) struct PolicyConstraints {
- #[implicit(0)]
- pub require_explicit_policy: Option<u64>,
- #[implicit(1)]
- pub inhibit_policy_mapping: Option<u64>,
-}
-
pub(crate) fn parse_authority_key_identifier<'p>(
py: pyo3::Python<'p>,
ext_data: &[u8],
@@ -807,7 +639,7 @@ pub(crate) fn parse_access_descriptions(
) -> Result<pyo3::PyObject, CryptographyError> {
let x509_module = py.import(pyo3::intern!(py, "cryptography.x509"))?;
let ads = pyo3::types::PyList::empty(py);
- let parsed = asn1::parse_single::<x509::common::SequenceOfAccessDescriptions<'_>>(ext_data)?;
+ let parsed = asn1::parse_single::<SequenceOfAccessDescriptions<'_>>(ext_data)?;
for access in parsed.unwrap_read().clone() {
let py_oid = oid_to_py_oid(py, &access.access_method)?.to_object(py);
let gn = x509::parse_general_name(py, access.access_location)?;
@@ -829,7 +661,7 @@ pub fn parse_cert_ext<'p>(
match oid {
oid::SUBJECT_ALTERNATIVE_NAME_OID => {
let gn_seq =
- asn1::parse_single::<asn1::SequenceOf<'_, x509::GeneralName<'_>>>(ext_data)?;
+ asn1::parse_single::<asn1::SequenceOf<'_, name::GeneralName<'_>>>(ext_data)?;
let sans = x509::parse_general_names(py, &gn_seq)?;
Ok(Some(
x509_module
@@ -839,7 +671,7 @@ pub fn parse_cert_ext<'p>(
}
oid::ISSUER_ALTERNATIVE_NAME_OID => {
let gn_seq =
- asn1::parse_single::<asn1::SequenceOf<'_, x509::GeneralName<'_>>>(ext_data)?;
+ asn1::parse_single::<asn1::SequenceOf<'_, name::GeneralName<'_>>>(ext_data)?;
let ians = x509::parse_general_names(py, &gn_seq)?;
Ok(Some(
x509_module
@@ -1016,16 +848,18 @@ pub fn parse_cert_ext<'p>(
pub(crate) fn time_from_py(
py: pyo3::Python<'_>,
val: &pyo3::PyAny,
-) -> CryptographyResult<x509::Time> {
+) -> CryptographyResult<common::Time> {
let dt = x509::py_to_datetime(py, val)?;
time_from_datetime(dt)
}
-pub(crate) fn time_from_datetime(dt: asn1::DateTime) -> CryptographyResult<x509::Time> {
+pub(crate) fn time_from_datetime(dt: asn1::DateTime) -> CryptographyResult<common::Time> {
if dt.year() >= 2050 {
- Ok(x509::Time::GeneralizedTime(asn1::GeneralizedTime::new(dt)?))
+ Ok(common::Time::GeneralizedTime(asn1::GeneralizedTime::new(
+ dt,
+ )?))
} else {
- Ok(x509::Time::UtcTime(asn1::UtcTime::new(dt).unwrap()))
+ Ok(common::Time::UtcTime(asn1::UtcTime::new(dt).unwrap()))
}
}
@@ -1065,7 +899,7 @@ fn create_x509_certificate(
let py_not_before = builder.getattr(pyo3::intern!(py, "_not_valid_before"))?;
let py_not_after = builder.getattr(pyo3::intern!(py, "_not_valid_after"))?;
- let tbs_cert = TbsCertificate {
+ let tbs_cert = cryptography_x509::certificate::TbsCertificate {
version: builder
.getattr(pyo3::intern!(py, "_version"))?
.getattr(pyo3::intern!(py, "value"))?
@@ -1073,7 +907,7 @@ fn create_x509_certificate(
serial: asn1::BigInt::new(py_uint_to_big_endian_bytes(py, py_serial)?).unwrap(),
signature_alg: sigalg.clone(),
issuer: x509::common::encode_name(py, py_issuer_name)?,
- validity: Validity {
+ validity: cryptography_x509::certificate::Validity {
not_before: time_from_py(py, py_not_before)?,
not_after: time_from_py(py, py_not_after)?,
},
@@ -1090,7 +924,7 @@ fn create_x509_certificate(
let tbs_bytes = asn1::write_single(&tbs_cert)?;
let signature = x509::sign::sign_data(py, private_key, hash_algorithm, &tbs_bytes)?;
- let data = asn1::write_single(&RawCertificate {
+ let data = asn1::write_single(&cryptography_x509::certificate::Certificate {
tbs_cert,
signature_alg: sigalg,
signature: asn1::BitString::new(signature, 0).unwrap(),
diff --git a/src/rust/src/x509/common.rs b/src/rust/src/x509/common.rs
index 3d4aec39c..4d977a921 100644
--- a/src/rust/src/x509/common.rs
+++ b/src/rust/src/x509/common.rs
@@ -5,10 +5,14 @@
use crate::asn1::{oid_to_py_oid, py_oid_to_oid};
use crate::error::{CryptographyError, CryptographyResult};
use crate::x509;
+use cryptography_x509::common::{Asn1ReadableOrWritable, AttributeTypeValue, RawTlv};
+use cryptography_x509::extensions::{
+ AccessDescription, Extension, Extensions, SequenceOfAccessDescriptions,
+};
+use cryptography_x509::name::{GeneralName, Name, OtherName, UnvalidatedIA5String};
use pyo3::types::IntoPyDict;
use pyo3::ToPyObject;
use std::collections::HashSet;
-use std::marker::PhantomData;
/// Parse all sections in a PEM file and return the first matching section.
/// If no matching sections are found, return an error.
@@ -26,58 +30,6 @@ pub(crate) fn find_in_pem(
})
}
-pub(crate) type Name<'a> = Asn1ReadableOrWritable<
- 'a,
- asn1::SequenceOf<'a, asn1::SetOf<'a, AttributeTypeValue<'a>>>,
- asn1::SequenceOfWriter<
- 'a,
- asn1::SetOfWriter<'a, AttributeTypeValue<'a>, Vec<AttributeTypeValue<'a>>>,
- Vec<asn1::SetOfWriter<'a, AttributeTypeValue<'a>, Vec<AttributeTypeValue<'a>>>>,
- >,
->;
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Eq, Hash, Clone)]
-pub(crate) struct AttributeTypeValue<'a> {
- pub(crate) type_id: asn1::ObjectIdentifier,
- pub(crate) value: RawTlv<'a>,
-}
-
-// Like `asn1::Tlv` but doesn't store `full_data` so it can be constructed from
-// an un-encoded tag and value.
-#[derive(Hash, PartialEq, Eq, Clone)]
-pub(crate) struct RawTlv<'a> {
- tag: asn1::Tag,
- value: &'a [u8],
-}
-
-impl<'a> RawTlv<'a> {
- pub(crate) fn new(tag: asn1::Tag, value: &'a [u8]) -> Self {
- RawTlv { tag, value }
- }
-
- pub(crate) fn tag(&self) -> asn1::Tag {
- self.tag
- }
- pub(crate) fn data(&self) -> &'a [u8] {
- self.value
- }
-}
-impl<'a> asn1::Asn1Readable<'a> for RawTlv<'a> {
- fn parse(parser: &mut asn1::Parser<'a>) -> asn1::ParseResult<Self> {
- let tlv = parser.read_element::<asn1::Tlv<'a>>()?;
- Ok(RawTlv::new(tlv.tag(), tlv.data()))
- }
-
- fn can_parse(_tag: asn1::Tag) -> bool {
- true
- }
-}
-impl<'a> asn1::Asn1Writable for RawTlv<'a> {
- fn write(&self, w: &mut asn1::Writer<'_>) -> asn1::WriteResult {
- w.write_tlv(self.tag, move |dest| dest.push_slice(self.value))
- }
-}
-
pub(crate) fn encode_name<'p>(
py: pyo3::Python<'p>,
py_name: &'p pyo3::PyAny,
@@ -145,73 +97,6 @@ fn encode_name_bytes<'p>(
Ok(pyo3::types::PyBytes::new(py, &result))
}
-/// An IA5String ASN.1 element whose contents is not validated as meeting the
-/// requirements (ASCII characters only), and instead is only known to be
-/// valid UTF-8.
-pub(crate) struct UnvalidatedIA5String<'a>(pub(crate) &'a str);
-
-impl<'a> asn1::SimpleAsn1Readable<'a> for UnvalidatedIA5String<'a> {
- const TAG: asn1::Tag = asn1::IA5String::TAG;
- fn parse_data(data: &'a [u8]) -> asn1::ParseResult<Self> {
- Ok(UnvalidatedIA5String(std::str::from_utf8(data).map_err(
- |_| asn1::ParseError::new(asn1::ParseErrorKind::InvalidValue),
- )?))
- }
-}
-
-impl<'a> asn1::SimpleAsn1Writable for UnvalidatedIA5String<'a> {
- const TAG: asn1::Tag = asn1::IA5String::TAG;
- fn write_data(&self, dest: &mut asn1::WriteBuf) -> asn1::WriteResult {
- dest.push_slice(self.0.as_bytes())
- }
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash)]
-pub(crate) struct OtherName<'a> {
- pub(crate) type_id: asn1::ObjectIdentifier,
- #[explicit(0, required)]
- pub(crate) value: asn1::Tlv<'a>,
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) enum GeneralName<'a> {
- #[implicit(0)]
- OtherName(OtherName<'a>),
-
- #[implicit(1)]
- RFC822Name(UnvalidatedIA5String<'a>),
-
- #[implicit(2)]
- DNSName(UnvalidatedIA5String<'a>),
-
- #[implicit(3)]
- // unsupported
- X400Address(asn1::Sequence<'a>),
-
- // Name is explicit per RFC 5280 Appendix A.1.
- #[explicit(4)]
- DirectoryName(Name<'a>),
-
- #[implicit(5)]
- // unsupported
- EDIPartyName(asn1::Sequence<'a>),
-
- #[implicit(6)]
- UniformResourceIdentifier(UnvalidatedIA5String<'a>),
-
- #[implicit(7)]
- IPAddress(&'a [u8]),
-
- #[implicit(8)]
- RegisteredID(asn1::ObjectIdentifier),
-}
-
-pub(crate) type SequenceOfGeneralName<'a> = Asn1ReadableOrWritable<
- 'a,
- asn1::SequenceOf<'a, GeneralName<'a>>,
- asn1::SequenceOfWriter<'a, GeneralName<'a>, Vec<GeneralName<'a>>>,
->;
-
pub(crate) fn encode_general_names<'a>(
py: pyo3::Python<'a>,
py_gns: &'a pyo3::PyAny,
@@ -271,18 +156,6 @@ pub(crate) fn encode_general_name<'a>(
}
}
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) struct AccessDescription<'a> {
- pub(crate) access_method: asn1::ObjectIdentifier,
- pub(crate) access_location: GeneralName<'a>,
-}
-
-pub(crate) type SequenceOfAccessDescriptions<'a> = Asn1ReadableOrWritable<
- 'a,
- asn1::SequenceOf<'a, AccessDescription<'a>>,
- asn1::SequenceOfWriter<'a, AccessDescription<'a>, Vec<AccessDescription<'a>>>,
->;
-
pub(crate) fn encode_access_descriptions<'a>(
py: pyo3::Python<'a>,
py_ads: &'a pyo3::PyAny,
@@ -303,41 +176,6 @@ pub(crate) fn encode_access_descriptions<'a>(
))
}
-#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash, Clone)]
-pub(crate) enum Time {
- UtcTime(asn1::UtcTime),
- GeneralizedTime(asn1::GeneralizedTime),
-}
-
-impl Time {
- pub(crate) fn as_datetime(&self) -> &asn1::DateTime {
- match self {
- Time::UtcTime(data) => data.as_datetime(),
- Time::GeneralizedTime(data) => data.as_datetime(),
- }
- }
-}
-
-pub(crate) type Extensions<'a> = Asn1ReadableOrWritable<
- 'a,
- asn1::SequenceOf<'a, Extension<'a>>,
- asn1::SequenceOfWriter<'a, Extension<'a>, Vec<Extension<'a>>>,
->;
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash, Clone)]
-pub(crate) struct AlgorithmIdentifier<'a> {
- pub(crate) oid: asn1::ObjectIdentifier,
- pub(crate) params: Option<asn1::Tlv<'a>>,
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Eq, Hash, Clone)]
-pub(crate) struct Extension<'a> {
- pub(crate) extn_id: asn1::ObjectIdentifier,
- #[default(false)]
- pub(crate) critical: bool,
- pub(crate) extn_value: &'a [u8],
-}
-
pub(crate) fn parse_name<'p>(
py: pyo3::Python<'p>,
name: &Name<'_>,
@@ -723,77 +561,9 @@ pub(crate) fn datetime_now(py: pyo3::Python<'_>) -> pyo3::PyResult<asn1::DateTim
)
}
-#[derive(Hash, PartialEq, Clone)]
-pub(crate) enum Asn1ReadableOrWritable<'a, T, U> {
- Read(T, PhantomData<&'a ()>),
- Write(U, PhantomData<&'a ()>),
-}
-
-impl<'a, T, U> Asn1ReadableOrWritable<'a, T, U> {
- pub(crate) fn new_read(v: T) -> Self {
- Asn1ReadableOrWritable::Read(v, PhantomData)
- }
-
- pub(crate) fn new_write(v: U) -> Self {
- Asn1ReadableOrWritable::Write(v, PhantomData)
- }
-
- pub(crate) fn unwrap_read(&self) -> &T {
- match self {
- Asn1ReadableOrWritable::Read(v, _) => v,
- Asn1ReadableOrWritable::Write(_, _) => panic!("unwrap_read called on a Write value"),
- }
- }
-}
-
-impl<'a, T: asn1::SimpleAsn1Readable<'a>, U> asn1::SimpleAsn1Readable<'a>
- for Asn1ReadableOrWritable<'a, T, U>
-{
- const TAG: asn1::Tag = T::TAG;
- fn parse_data(data: &'a [u8]) -> asn1::ParseResult<Self> {
- Ok(Self::new_read(T::parse_data(data)?))
- }
-}
-
-impl<'a, T: asn1::SimpleAsn1Writable, U: asn1::SimpleAsn1Writable> asn1::SimpleAsn1Writable
- for Asn1ReadableOrWritable<'a, T, U>
-{
- const TAG: asn1::Tag = U::TAG;
- fn write_data(&self, w: &mut asn1::WriteBuf) -> asn1::WriteResult {
- match self {
- Asn1ReadableOrWritable::Read(v, _) => T::write_data(v, w),
- Asn1ReadableOrWritable::Write(v, _) => U::write_data(v, w),
- }
- }
-}
-
pub(crate) fn add_to_module(module: &pyo3::prelude::PyModule) -> pyo3::PyResult<()> {
module.add_wrapped(pyo3::wrap_pyfunction!(encode_extension_value))?;
module.add_wrapped(pyo3::wrap_pyfunction!(encode_name_bytes))?;
Ok(())
}
-
-#[cfg(test)]
-mod tests {
- use super::{Asn1ReadableOrWritable, RawTlv};
- use asn1::Asn1Readable;
-
- #[test]
- #[should_panic]
- fn test_asn1_readable_or_writable_unwrap_read() {
- Asn1ReadableOrWritable::<u32, u32>::new_write(17).unwrap_read();
- }
-
- #[test]
- fn test_asn1_readable_or_writable_write_read_data() {
- let v = Asn1ReadableOrWritable::<u32, u32>::new_read(17);
- assert_eq!(&asn1::write_single(&v).unwrap(), b"\x02\x01\x11");
- }
-
- #[test]
- fn test_raw_tlv_can_parse() {
- let t = asn1::Tag::from_bytes(&[0]).unwrap().0;
- assert!(RawTlv::can_parse(t));
- }
-}
diff --git a/src/rust/src/x509/crl.rs b/src/rust/src/x509/crl.rs
index f5ab1b0c0..ea04bb984 100644
--- a/src/rust/src/x509/crl.rs
+++ b/src/rust/src/x509/crl.rs
@@ -7,7 +7,8 @@ use crate::asn1::{
};
use crate::error::{CryptographyError, CryptographyResult};
use crate::x509;
-use crate::x509::{certificate, extensions, oid, sign};
+use crate::x509::{certificate, extensions, sign};
+use cryptography_x509::{common, crl, name, oid};
use pyo3::{IntoPy, ToPyObject};
use std::sync::Arc;
@@ -16,13 +17,13 @@ fn load_der_x509_crl(
py: pyo3::Python<'_>,
data: pyo3::Py<pyo3::types::PyBytes>,
) -> Result<CertificateRevocationList, CryptographyError> {
- let raw = OwnedRawCertificateRevocationList::try_new(
+ let owned = OwnedCertificateRevocationList::try_new(
data,
|data| asn1::parse_single(data.as_bytes(py)),
|_| Ok(pyo3::once_cell::GILOnceCell::new()),
)?;
- let version = raw.borrow_value().tbs_cert_list.version.unwrap_or(1);
+ let version = owned.borrow_value().tbs_cert_list.version.unwrap_or(1);
if version != 1 {
let x509_module = py.import(pyo3::intern!(py, "cryptography.x509"))?;
return Err(CryptographyError::from(pyo3::PyErr::from_value(
@@ -33,7 +34,7 @@ fn load_der_x509_crl(
}
Ok(CertificateRevocationList {
- raw: Arc::new(raw),
+ owned: Arc::new(owned),
cached_extensions: None,
})
}
@@ -55,41 +56,41 @@ fn load_pem_x509_crl(
}
#[ouroboros::self_referencing]
-struct OwnedRawCertificateRevocationList {
+struct OwnedCertificateRevocationList {
data: pyo3::Py<pyo3::types::PyBytes>,
#[borrows(data)]
#[covariant]
- value: RawCertificateRevocationList<'this>,
+ value: crl::CertificateRevocationList<'this>,
#[borrows(data)]
#[not_covariant]
- revoked_certs: pyo3::once_cell::GILOnceCell<Vec<RawRevokedCertificate<'this>>>,
+ revoked_certs: pyo3::once_cell::GILOnceCell<Vec<crl::RevokedCertificate<'this>>>,
}
#[pyo3::prelude::pyclass(module = "cryptography.hazmat.bindings._rust.x509")]
struct CertificateRevocationList {
- raw: Arc<OwnedRawCertificateRevocationList>,
+ owned: Arc<OwnedCertificateRevocationList>,
cached_extensions: Option<pyo3::PyObject>,
}
impl CertificateRevocationList {
fn public_bytes_der(&self) -> CryptographyResult<Vec<u8>> {
- Ok(asn1::write_single(self.raw.borrow_value())?)
+ Ok(asn1::write_single(self.owned.borrow_value())?)
}
fn revoked_cert(&self, py: pyo3::Python<'_>, idx: usize) -> pyo3::PyResult<RevokedCertificate> {
- let raw = try_map_arc_data_crl(&self.raw, |_crl, revoked_certs| {
+ let owned = try_map_arc_data_crl(&self.owned, |_crl, revoked_certs| {
let revoked_certs = revoked_certs.get(py).unwrap();
Ok::<_, pyo3::PyErr>(revoked_certs[idx].clone())
})?;
Ok(RevokedCertificate {
- raw,
+ owned,
cached_extensions: None,
})
}
fn len(&self) -> usize {
- self.raw
+ self.owned
.borrow_value()
.tbs_cert_list
.revoked_certificates
@@ -106,8 +107,12 @@ impl CertificateRevocationList {
op: pyo3::basic::CompareOp,
) -> pyo3::PyResult<bool> {
match op {
- pyo3::basic::CompareOp::Eq => Ok(self.raw.borrow_value() == other.raw.borrow_value()),
- pyo3::basic::CompareOp::Ne => Ok(self.raw.borrow_value() != other.raw.borrow_value()),
+ pyo3::basic::CompareOp::Eq => {
+ Ok(self.owned.borrow_value() == other.owned.borrow_value())
+ }
+ pyo3::basic::CompareOp::Ne => {
+ Ok(self.owned.borrow_value() != other.owned.borrow_value())
+ }
_ => Err(pyo3::exceptions::PyTypeError::new_err(
"CRLs cannot be ordered",
)),
@@ -120,7 +125,7 @@ impl CertificateRevocationList {
fn __iter__(&self) -> CRLIterator {
CRLIterator {
- contents: OwnedCRLIteratorData::try_new(Arc::clone(&self.raw), |v| {
+ contents: OwnedCRLIteratorData::try_new(Arc::clone(&self.owned), |v| {
Ok::<_, ()>(
v.borrow_value()
.tbs_cert_list
@@ -138,7 +143,7 @@ impl CertificateRevocationList {
py: pyo3::Python<'_>,
idx: &pyo3::PyAny,
) -> pyo3::PyResult<pyo3::PyObject> {
- self.raw.with(|val| {
+ self.owned.with(|val| {
val.revoked_certs.get_or_init(py, || {
match &val.value.tbs_cert_list.revoked_certificates {
Some(c) => c.unwrap_read().clone().collect(),
@@ -186,7 +191,7 @@ impl CertificateRevocationList {
#[getter]
fn signature_algorithm_oid<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> {
- oid_to_py_oid(py, &self.raw.borrow_value().signature_algorithm.oid)
+ oid_to_py_oid(py, &self.owned.borrow_value().signature_algorithm.oid)
}
#[getter]
@@ -206,7 +211,7 @@ impl CertificateRevocationList {
"UnsupportedAlgorithm",
(format!(
"Signature algorithm OID:{} not recognized",
- self.raw.borrow_value().signature_algorithm.oid
+ self.owned.borrow_value().signature_algorithm.oid
),),
)?)),
}
@@ -214,7 +219,7 @@ impl CertificateRevocationList {
#[getter]
fn signature(&self) -> &[u8] {
- self.raw.borrow_value().signature_value.as_bytes()
+ self.owned.borrow_value().signature_value.as_bytes()
}
#[getter]
@@ -222,7 +227,7 @@ impl CertificateRevocationList {
&self,
py: pyo3::Python<'p>,
) -> CryptographyResult<&'p pyo3::types::PyBytes> {
- let b = asn1::write_single(&self.raw.borrow_value().tbs_cert_list)?;
+ let b = asn1::write_single(&self.owned.borrow_value().tbs_cert_list)?;
Ok(pyo3::types::PyBytes::new(py, &b))
}
@@ -231,7 +236,7 @@ impl CertificateRevocationList {
py: pyo3::Python<'p>,
encoding: &'p pyo3::PyAny,
) -> CryptographyResult<&'p pyo3::types::PyBytes> {
- let result = asn1::write_single(self.raw.borrow_value())?;
+ let result = asn1::write_single(self.owned.borrow_value())?;
encode_der_data(py, "X509 CRL".to_string(), result, encoding)
}
@@ -240,13 +245,13 @@ impl CertificateRevocationList {
fn issuer<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> {
Ok(x509::parse_name(
py,
- &self.raw.borrow_value().tbs_cert_list.issuer,
+ &self.owned.borrow_value().tbs_cert_list.issuer,
)?)
}
#[getter]
fn next_update<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> {
- match &self.raw.borrow_value().tbs_cert_list.next_update {
+ match &self.owned.borrow_value().tbs_cert_list.next_update {
Some(t) => x509::datetime_to_py(py, t.as_datetime()),
None => Ok(py.None().into_ref(py)),
}
@@ -256,7 +261,7 @@ impl CertificateRevocationList {
fn last_update<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> {
x509::datetime_to_py(
py,
- self.raw
+ self.owned
.borrow_value()
.tbs_cert_list
.this_update
@@ -270,7 +275,7 @@ impl CertificateRevocationList {
x509::parse_and_cache_extensions(
py,
&mut self.cached_extensions,
- &self.raw.borrow_value().tbs_cert_list.crl_extensions,
+ &self.owned.borrow_value().tbs_cert_list.crl_extensions,
|oid, ext_data| match *oid {
oid::CRL_NUMBER_OID => {
let bignum = asn1::parse_single::<asn1::BigUint<'_>>(ext_data)?;
@@ -291,7 +296,7 @@ impl CertificateRevocationList {
))
}
oid::ISSUER_ALTERNATIVE_NAME_OID => {
- let gn_seq = asn1::parse_single::<asn1::SequenceOf<'_, x509::GeneralName<'_>>>(
+ let gn_seq = asn1::parse_single::<asn1::SequenceOf<'_, name::GeneralName<'_>>>(
ext_data,
)?;
let ians = x509::parse_general_names(py, &gn_seq)?;
@@ -313,7 +318,7 @@ impl CertificateRevocationList {
certificate::parse_authority_key_identifier(py, ext_data)?,
)),
oid::ISSUING_DISTRIBUTION_POINT_OID => {
- let idp = asn1::parse_single::<IssuingDistributionPoint<'_>>(ext_data)?;
+ let idp = asn1::parse_single::<crl::IssuingDistributionPoint<'_>>(ext_data)?;
let (full_name, relative_name) = match idp.distribution_point {
Some(data) => certificate::parse_distribution_point_name(py, data)?,
None => (py.None(), py.None()),
@@ -359,7 +364,7 @@ impl CertificateRevocationList {
serial: &pyo3::types::PyLong,
) -> pyo3::PyResult<Option<RevokedCertificate>> {
let serial_bytes = py_uint_to_big_endian_bytes(py, serial)?;
- let owned = OwnedRawRevokedCertificate::try_new(Arc::clone(&self.raw), |v| {
+ let owned = OwnedRevokedCertificate::try_new(Arc::clone(&self.owned), |v| {
let certs = match &v.borrow_value().tbs_cert_list.revoked_certificates {
Some(certs) => certs.unwrap_read().clone(),
None => return Err(()),
@@ -375,7 +380,7 @@ impl CertificateRevocationList {
});
match owned {
Ok(o) => Ok(Some(RevokedCertificate {
- raw: o,
+ owned: o,
cached_extensions: None,
})),
Err(()) => Ok(None),
@@ -387,8 +392,8 @@ impl CertificateRevocationList {
py: pyo3::Python<'p>,
public_key: &'p pyo3::PyAny,
) -> CryptographyResult<bool> {
- if slf.raw.borrow_value().tbs_cert_list.signature
- != slf.raw.borrow_value().signature_algorithm
+ if slf.owned.borrow_value().tbs_cert_list.signature
+ != slf.owned.borrow_value().signature_algorithm
{
return Ok(false);
};
@@ -400,9 +405,9 @@ impl CertificateRevocationList {
Ok(sign::verify_signature_with_oid(
py,
public_key,
- &slf.raw.borrow_value().signature_algorithm.oid,
- slf.raw.borrow_value().signature_value.as_bytes(),
- &asn1::write_single(&slf.raw.borrow_value().tbs_cert_list)?,
+ &slf.owned.borrow_value().signature_algorithm.oid,
+ slf.owned.borrow_value().signature_value.as_bytes(),
+ &asn1::write_single(&slf.owned.borrow_value().tbs_cert_list)?,
)
.is_ok())
}
@@ -410,10 +415,10 @@ impl CertificateRevocationList {
#[ouroboros::self_referencing]
struct OwnedCRLIteratorData {
- data: Arc<OwnedRawCertificateRevocationList>,
+ data: Arc<OwnedCertificateRevocationList>,
#[borrows(data)]
#[covariant]
- value: Option<asn1::SequenceOf<'this, RawRevokedCertificate<'this>>>,
+ value: Option<asn1::SequenceOf<'this, crl::RevokedCertificate<'this>>>,
}
#[pyo3::prelude::pyclass(module = "cryptography.hazmat.bindings._rust.x509")]
@@ -424,13 +429,13 @@ struct CRLIterator {
// Open-coded implementation of the API discussed in
// https://github.com/joshua-maros/ouroboros/issues/38
fn try_map_arc_data_crl<E>(
- crl: &Arc<OwnedRawCertificateRevocationList>,
+ crl: &Arc<OwnedCertificateRevocationList>,
f: impl for<'this> FnOnce(
- &'this OwnedRawCertificateRevocationList,
- &pyo3::once_cell::GILOnceCell<Vec<RawRevokedCertificate<'this>>>,
- ) -> Result<RawRevokedCertificate<'this>, E>,
-) -> Result<OwnedRawRevokedCertificate, E> {
- OwnedRawRevokedCertificate::try_new(Arc::clone(crl), |inner_crl| {
+ &'this OwnedCertificateRevocationList,
+ &pyo3::once_cell::GILOnceCell<Vec<crl::RevokedCertificate<'this>>>,
+ ) -> Result<crl::RevokedCertificate<'this>, E>,
+) -> Result<OwnedRevokedCertificate, E> {
+ OwnedRevokedCertificate::try_new(Arc::clone(crl), |inner_crl| {
crl.with(|value| {
f(inner_crl, unsafe {
std::mem::transmute(value.revoked_certs)
@@ -441,11 +446,11 @@ fn try_map_arc_data_crl<E>(
fn try_map_arc_data_mut_crl_iterator<E>(
it: &mut OwnedCRLIteratorData,
f: impl for<'this> FnOnce(
- &'this OwnedRawCertificateRevocationList,
- &mut Option<asn1::SequenceOf<'this, RawRevokedCertificate<'this>>>,
- ) -> Result<RawRevokedCertificate<'this>, E>,
-) -> Result<OwnedRawRevokedCertificate, E> {
- OwnedRawRevokedCertificate::try_new(Arc::clone(it.borrow_data()), |inner_it| {
+ &'this OwnedCertificateRevocationList,
+ &mut Option<asn1::SequenceOf<'this, crl::RevokedCertificate<'this>>>,
+ ) -> Result<crl::RevokedCertificate<'this>, E>,
+) -> Result<OwnedRevokedCertificate, E> {
+ OwnedRevokedCertificate::try_new(Arc::clone(it.borrow_data()), |inner_it| {
it.with_value_mut(|value| f(inner_it, unsafe { std::mem::transmute(value) }))
})
}
@@ -470,57 +475,23 @@ impl CRLIterator {
})
.ok()?;
Some(RevokedCertificate {
- raw: revoked,
+ owned: revoked,
cached_extensions: None,
})
}
}
-#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash)]
-struct RawCertificateRevocationList<'a> {
- tbs_cert_list: TBSCertList<'a>,
- signature_algorithm: x509::AlgorithmIdentifier<'a>,
- signature_value: asn1::BitString<'a>,
-}
-
-type RevokedCertificates<'a> = Option<
- x509::Asn1ReadableOrWritable<
- 'a,
- asn1::SequenceOf<'a, RawRevokedCertificate<'a>>,
- asn1::SequenceOfWriter<'a, RawRevokedCertificate<'a>, Vec<RawRevokedCertificate<'a>>>,
- >,
->;
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash)]
-struct TBSCertList<'a> {
- version: Option<u8>,
- signature: x509::AlgorithmIdentifier<'a>,
- issuer: x509::Name<'a>,
- this_update: x509::Time,
- next_update: Option<x509::Time>,
- revoked_certificates: RevokedCertificates<'a>,
- #[explicit(0)]
- crl_extensions: Option<x509::Extensions<'a>>,
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash, Clone)]
-struct RawRevokedCertificate<'a> {
- user_certificate: asn1::BigUint<'a>,
- revocation_date: x509::Time,
- crl_entry_extensions: Option<x509::Extensions<'a>>,
-}
-
#[ouroboros::self_referencing]
-struct OwnedRawRevokedCertificate {
- data: Arc<OwnedRawCertificateRevocationList>,
+struct OwnedRevokedCertificate {
+ data: Arc<OwnedCertificateRevocationList>,
#[borrows(data)]
#[covariant]
- value: RawRevokedCertificate<'this>,
+ value: crl::RevokedCertificate<'this>,
}
#[pyo3::prelude::pyclass(module = "cryptography.hazmat.bindings._rust.x509")]
struct RevokedCertificate {
- raw: OwnedRawRevokedCertificate,
+ owned: OwnedRevokedCertificate,
cached_extensions: Option<pyo3::PyObject>,
}
@@ -528,12 +499,12 @@ struct RevokedCertificate {
impl RevokedCertificate {
#[getter]
fn serial_number<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> {
- big_byte_slice_to_py_int(py, self.raw.borrow_value().user_certificate.as_bytes())
+ big_byte_slice_to_py_int(py, self.owned.borrow_value().user_certificate.as_bytes())
}
#[getter]
fn revocation_date<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> {
- x509::datetime_to_py(py, self.raw.borrow_value().revocation_date.as_datetime())
+ x509::datetime_to_py(py, self.owned.borrow_value().revocation_date.as_datetime())
}
#[getter]
@@ -541,45 +512,15 @@ impl RevokedCertificate {
x509::parse_and_cache_extensions(
py,
&mut self.cached_extensions,
- &self.raw.borrow_value().crl_entry_extensions,
+ &self.owned.borrow_value().crl_entry_extensions,
|oid, ext_data| parse_crl_entry_ext(py, oid.clone(), ext_data),
)
}
}
-pub(crate) type ReasonFlags<'a> =
- Option<x509::Asn1ReadableOrWritable<'a, asn1::BitString<'a>, asn1::OwnedBitString>>;
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) struct IssuingDistributionPoint<'a> {
- #[explicit(0)]
- pub distribution_point: Option<certificate::DistributionPointName<'a>>,
-
- #[implicit(1)]
- #[default(false)]
- pub only_contains_user_certs: bool,
-
- #[implicit(2)]
- #[default(false)]
- pub only_contains_ca_certs: bool,
-
- #[implicit(3)]
- pub only_some_reasons: ReasonFlags<'a>,
-
- #[implicit(4)]
- #[default(false)]
- pub indirect_crl: bool,
-
- #[implicit(5)]
- #[default(false)]
- pub only_contains_attribute_certs: bool,
-}
-
-pub(crate) type CRLReason = asn1::Enumerated;
-
pub(crate) fn parse_crl_reason_flags<'p>(
py: pyo3::Python<'p>,
- reason: &CRLReason,
+ reason: &crl::CRLReason,
) -> CryptographyResult<&'p pyo3::PyAny> {
let x509_module = py.import(pyo3::intern!(py, "cryptography.x509"))?;
let flag_name = match reason.value() {
@@ -615,7 +556,7 @@ pub fn parse_crl_entry_ext<'p>(
let x509_module = py.import(pyo3::intern!(py, "cryptography.x509"))?;
match oid {
oid::CRL_REASON_OID => {
- let flags = parse_crl_reason_flags(py, &asn1::parse_single::<CRLReason>(data)?)?;
+ let flags = parse_crl_reason_flags(py, &asn1::parse_single::<crl::CRLReason>(data)?)?;
Ok(Some(
x509_module
.getattr(pyo3::intern!(py, "CRLReason"))?
@@ -623,7 +564,7 @@ pub fn parse_crl_entry_ext<'p>(
))
}
oid::CERTIFICATE_ISSUER_OID => {
- let gn_seq = asn1::parse_single::<asn1::SequenceOf<'_, x509::GeneralName<'_>>>(data)?;
+ let gn_seq = asn1::parse_single::<asn1::SequenceOf<'_, name::GeneralName<'_>>>(data)?;
let gns = x509::parse_general_names(py, &gn_seq)?;
Ok(Some(
x509_module
@@ -663,7 +604,7 @@ fn create_x509_crl(
.getattr(pyo3::intern!(py, "serial_number"))?
.extract()?;
let py_revocation_date = py_revoked_cert.getattr(pyo3::intern!(py, "revocation_date"))?;
- revoked_certs.push(RawRevokedCertificate {
+ revoked_certs.push(crl::RevokedCertificate {
user_certificate: asn1::BigUint::new(py_uint_to_big_endian_bytes(py, serial_number)?)
.unwrap(),
revocation_date: x509::certificate::time_from_py(py, py_revocation_date)?,
@@ -678,7 +619,7 @@ fn create_x509_crl(
let py_issuer_name = builder.getattr(pyo3::intern!(py, "_issuer_name"))?;
let py_this_update = builder.getattr(pyo3::intern!(py, "_last_update"))?;
let py_next_update = builder.getattr(pyo3::intern!(py, "_next_update"))?;
- let tbs_cert_list = TBSCertList {
+ let tbs_cert_list = crl::TBSCertList {
version: Some(1),
signature: sigalg.clone(),
issuer: x509::common::encode_name(py, py_issuer_name)?,
@@ -687,7 +628,7 @@ fn create_x509_crl(
revoked_certificates: if revoked_certs.is_empty() {
None
} else {
- Some(x509::Asn1ReadableOrWritable::new_write(
+ Some(common::Asn1ReadableOrWritable::new_write(
asn1::SequenceOfWriter::new(revoked_certs),
))
},
@@ -700,7 +641,7 @@ fn create_x509_crl(
let tbs_bytes = asn1::write_single(&tbs_cert_list)?;
let signature = x509::sign::sign_data(py, private_key, hash_algorithm, &tbs_bytes)?;
- let data = asn1::write_single(&RawCertificateRevocationList {
+ let data = asn1::write_single(&crl::CertificateRevocationList {
tbs_cert_list,
signature_algorithm: sigalg,
signature_value: asn1::BitString::new(signature, 0).unwrap(),
diff --git a/src/rust/src/x509/csr.rs b/src/rust/src/x509/csr.rs
index 2122018e0..6de3667ae 100644
--- a/src/rust/src/x509/csr.rs
+++ b/src/rust/src/x509/csr.rs
@@ -5,83 +5,25 @@
use crate::asn1::{encode_der_data, oid_to_py_oid, py_oid_to_oid};
use crate::error::{CryptographyError, CryptographyResult};
use crate::x509;
-use crate::x509::{certificate, oid, sign};
+use crate::x509::{certificate, sign};
use asn1::SimpleAsn1Readable;
+use cryptography_x509::csr::{check_attribute_length, Attribute, CertificationRequestInfo, Csr};
+use cryptography_x509::{common, oid};
use pyo3::IntoPy;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-struct RawCsr<'a> {
- csr_info: CertificationRequestInfo<'a>,
- signature_alg: x509::AlgorithmIdentifier<'a>,
- signature: asn1::BitString<'a>,
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-struct CertificationRequestInfo<'a> {
- version: u8,
- subject: x509::Name<'a>,
- spki: certificate::SubjectPublicKeyInfo<'a>,
- #[implicit(0, required)]
- attributes: Attributes<'a>,
-}
-
-pub(crate) type Attributes<'a> = x509::Asn1ReadableOrWritable<
- 'a,
- asn1::SetOf<'a, Attribute<'a>>,
- asn1::SetOfWriter<'a, Attribute<'a>, Vec<Attribute<'a>>>,
->;
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) struct Attribute<'a> {
- pub(crate) type_id: asn1::ObjectIdentifier,
- pub(crate) values: x509::Asn1ReadableOrWritable<
- 'a,
- asn1::SetOf<'a, asn1::Tlv<'a>>,
- asn1::SetOfWriter<'a, x509::common::RawTlv<'a>, [x509::common::RawTlv<'a>; 1]>,
- >,
-}
-
-fn check_attribute_length<'a>(
- values: asn1::SetOf<'a, asn1::Tlv<'a>>,
-) -> Result<(), CryptographyError> {
- if values.count() > 1 {
- Err(CryptographyError::from(
- pyo3::exceptions::PyValueError::new_err("Only single-valued attributes are supported"),
- ))
- } else {
- Ok(())
- }
-}
-
-impl CertificationRequestInfo<'_> {
- fn get_extension_attribute(&self) -> Result<Option<x509::Extensions<'_>>, CryptographyError> {
- for attribute in self.attributes.unwrap_read().clone() {
- if attribute.type_id == oid::EXTENSION_REQUEST
- || attribute.type_id == oid::MS_EXTENSION_REQUEST
- {
- check_attribute_length(attribute.values.unwrap_read().clone())?;
- let val = attribute.values.unwrap_read().clone().next().unwrap();
- let exts = asn1::parse_single(val.full_data())?;
- return Ok(Some(exts));
- }
- }
- Ok(None)
- }
-}
-
#[ouroboros::self_referencing]
-struct OwnedRawCsr {
+struct OwnedCsr {
data: pyo3::Py<pyo3::types::PyBytes>,
#[borrows(data)]
#[covariant]
- value: RawCsr<'this>,
+ value: Csr<'this>,
}
#[pyo3::prelude::pyclass(module = "cryptography.hazmat.bindings._rust.x509")]
struct CertificateSigningRequest {
- raw: OwnedRawCsr,
+ raw: OwnedCsr,
cached_extensions: Option<pyo3::PyObject>,
}
@@ -212,7 +154,11 @@ impl CertificateSigningRequest {
.clone()
{
if rust_oid == attribute.type_id {
- check_attribute_length(attribute.values.unwrap_read().clone())?;
+ check_attribute_length(attribute.values.unwrap_read().clone()).map_err(|_| {
+ pyo3::exceptions::PyValueError::new_err(
+ "Only single-valued attributes are supported",
+ )
+ })?;
let val = attribute.values.unwrap_read().clone().next().unwrap();
// We allow utf8string, printablestring, and ia5string at this time
if val.tag() == asn1::Utf8String::TAG
@@ -248,7 +194,11 @@ impl CertificateSigningRequest {
.unwrap_read()
.clone()
{
- check_attribute_length(attribute.values.unwrap_read().clone())?;
+ check_attribute_length(attribute.values.unwrap_read().clone()).map_err(|_| {
+ pyo3::exceptions::PyValueError::new_err(
+ "Only single-valued attributes are supported",
+ )
+ })?;
let oid = oid_to_py_oid(py, &attribute.type_id)?;
let val = attribute.values.unwrap_read().clone().next().unwrap();
let serialized = pyo3::types::PyBytes::new(py, val.data());
@@ -268,7 +218,16 @@ impl CertificateSigningRequest {
#[getter]
fn extensions(&mut self, py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::PyObject> {
- let exts = self.raw.borrow_value().csr_info.get_extension_attribute()?;
+ let exts = self
+ .raw
+ .borrow_value()
+ .csr_info
+ .get_extension_attribute()
+ .map_err(|_| {
+ pyo3::exceptions::PyValueError::new_err(
+ "Only single-valued attributes are supported",
+ )
+ })?;
x509::parse_and_cache_extensions(py, &mut self.cached_extensions, &exts, |oid, ext_data| {
certificate::parse_cert_ext(py, oid.clone(), ext_data)
@@ -314,7 +273,7 @@ fn load_der_x509_csr(
py: pyo3::Python<'_>,
data: pyo3::Py<pyo3::types::PyBytes>,
) -> CryptographyResult<CertificateSigningRequest> {
- let raw = OwnedRawCsr::try_new(data, |data| asn1::parse_single(data.as_bytes(py)))?;
+ let raw = OwnedCsr::try_new(data, |data| asn1::parse_single(data.as_bytes(py)))?;
let version = raw.borrow_value().csr_info.version;
if version != 0 {
@@ -369,7 +328,7 @@ fn create_x509_csr(
ext_bytes = asn1::write_single(&exts)?;
attrs.push(Attribute {
type_id: (oid::EXTENSION_REQUEST).clone(),
- values: x509::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([
+ values: common::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([
asn1::parse_single(&ext_bytes)?,
])),
})
@@ -393,8 +352,8 @@ fn create_x509_csr(
attrs.push(Attribute {
type_id: oid,
- values: x509::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([
- x509::common::RawTlv::new(tag, value),
+ values: common::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([
+ common::RawTlv::new(tag, value),
])),
})
}
@@ -405,12 +364,12 @@ fn create_x509_csr(
version: 0,
subject: x509::common::encode_name(py, py_subject_name)?,
spki: asn1::parse_single(spki_bytes)?,
- attributes: x509::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new(attrs)),
+ attributes: common::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new(attrs)),
};
let tbs_bytes = asn1::write_single(&csr_info)?;
let signature = x509::sign::sign_data(py, private_key, hash_algorithm, &tbs_bytes)?;
- let data = asn1::write_single(&RawCsr {
+ let data = asn1::write_single(&Csr {
csr_info,
signature_alg: sigalg,
signature: asn1::BitString::new(signature, 0).unwrap(),
diff --git a/src/rust/src/x509/extensions.rs b/src/rust/src/x509/extensions.rs
index 84009b0c7..08e112cbb 100644
--- a/src/rust/src/x509/extensions.rs
+++ b/src/rust/src/x509/extensions.rs
@@ -5,25 +5,26 @@
use crate::asn1::{py_oid_to_oid, py_uint_to_big_endian_bytes};
use crate::error::{CryptographyError, CryptographyResult};
use crate::x509;
-use crate::x509::{certificate, crl, oid, sct};
+use crate::x509::{certificate, sct};
+use cryptography_x509::{common, crl, extensions, oid};
fn encode_general_subtrees<'a>(
py: pyo3::Python<'a>,
subtrees: &'a pyo3::PyAny,
-) -> Result<Option<certificate::SequenceOfSubtrees<'a>>, CryptographyError> {
+) -> Result<Option<extensions::SequenceOfSubtrees<'a>>, CryptographyError> {
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(certificate::GeneralSubtree {
+ subtree_seq.push(extensions::GeneralSubtree {
base: gn,
minimum: 0,
maximum: None,
});
}
- Ok(Some(x509::Asn1ReadableOrWritable::new_write(
+ Ok(Some(common::Asn1ReadableOrWritable::new_write(
asn1::SequenceOfWriter::new(subtree_seq),
)))
}
@@ -32,7 +33,7 @@ fn encode_general_subtrees<'a>(
pub(crate) fn encode_authority_key_identifier<'a>(
py: pyo3::Python<'a>,
py_aki: &'a pyo3::PyAny,
-) -> pyo3::PyResult<certificate::AuthorityKeyIdentifier<'a>> {
+) -> pyo3::PyResult<extensions::AuthorityKeyIdentifier<'a>> {
#[derive(pyo3::prelude::FromPyObject)]
struct PyAuthorityKeyIdentifier<'a> {
key_identifier: Option<&'a [u8]>,
@@ -42,7 +43,7 @@ pub(crate) fn encode_authority_key_identifier<'a>(
let aki = py_aki.extract::<PyAuthorityKeyIdentifier<'_>>()?;
let authority_cert_issuer = if let Some(authority_cert_issuer) = aki.authority_cert_issuer {
let gns = x509::common::encode_general_names(py, authority_cert_issuer)?;
- Some(x509::Asn1ReadableOrWritable::new_write(
+ Some(common::Asn1ReadableOrWritable::new_write(
asn1::SequenceOfWriter::new(gns),
))
} else {
@@ -55,7 +56,7 @@ pub(crate) fn encode_authority_key_identifier<'a>(
} else {
None
};
- Ok(certificate::AuthorityKeyIdentifier {
+ Ok(extensions::AuthorityKeyIdentifier {
authority_cert_issuer,
authority_cert_serial_number,
key_identifier: aki.key_identifier,
@@ -65,7 +66,7 @@ pub(crate) fn encode_authority_key_identifier<'a>(
pub(crate) fn encode_distribution_points<'p>(
py: pyo3::Python<'p>,
py_dps: &'p pyo3::PyAny,
-) -> pyo3::PyResult<Vec<certificate::DistributionPoint<'p>>> {
+) -> pyo3::PyResult<Vec<extensions::DistributionPoint<'p>>> {
#[derive(pyo3::prelude::FromPyObject)]
struct PyDistributionPoint<'a> {
crl_issuer: Option<&'a pyo3::PyAny>,
@@ -80,7 +81,7 @@ pub(crate) fn encode_distribution_points<'p>(
let crl_issuer = if let Some(py_crl_issuer) = py_dp.crl_issuer {
let gns = x509::common::encode_general_names(py, py_crl_issuer)?;
- Some(x509::Asn1ReadableOrWritable::new_write(
+ Some(common::Asn1ReadableOrWritable::new_write(
asn1::SequenceOfWriter::new(gns),
))
} else {
@@ -88,27 +89,27 @@ pub(crate) fn encode_distribution_points<'p>(
};
let distribution_point = if let Some(py_full_name) = py_dp.full_name {
let gns = x509::common::encode_general_names(py, py_full_name)?;
- Some(certificate::DistributionPointName::FullName(
- x509::Asn1ReadableOrWritable::new_write(asn1::SequenceOfWriter::new(gns)),
+ Some(extensions::DistributionPointName::FullName(
+ common::Asn1ReadableOrWritable::new_write(asn1::SequenceOfWriter::new(gns)),
))
} else if let Some(py_relative_name) = py_dp.relative_name {
let mut name_entries = vec![];
for py_name_entry in py_relative_name.iter()? {
name_entries.push(x509::common::encode_name_entry(py, py_name_entry?)?);
}
- Some(certificate::DistributionPointName::NameRelativeToCRLIssuer(
- x509::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new(name_entries)),
+ Some(extensions::DistributionPointName::NameRelativeToCRLIssuer(
+ common::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new(name_entries)),
))
} else {
None
};
let reasons = if let Some(py_reasons) = py_dp.reasons {
let reasons = certificate::encode_distribution_point_reasons(py, py_reasons)?;
- Some(x509::Asn1ReadableOrWritable::new_write(reasons))
+ Some(common::Asn1ReadableOrWritable::new_write(reasons))
} else {
None
};
- dps.push(certificate::DistributionPoint {
+ dps.push(extensions::DistributionPoint {
crl_issuer,
distribution_point,
reasons,
@@ -124,7 +125,16 @@ pub(crate) fn encode_extension(
) -> CryptographyResult<Option<Vec<u8>>> {
match oid {
&oid::BASIC_CONSTRAINTS_OID => {
- let bc = ext.extract::<certificate::BasicConstraints>()?;
+ #[derive(pyo3::prelude::FromPyObject)]
+ struct PyBasicConstraints {
+ ca: bool,
+ path_length: Option<u64>,
+ }
+ let pybc = ext.extract::<PyBasicConstraints>()?;
+ let bc = extensions::BasicConstraints {
+ ca: pybc.ca,
+ path_length: pybc.path_length,
+ };
Ok(Some(asn1::write_single(&bc)?))
}
&oid::SUBJECT_KEY_IDENTIFIER_OID => {
@@ -232,9 +242,9 @@ pub(crate) fn encode_extension(
.into())
}
};
- certificate::PolicyQualifierInfo {
+ extensions::PolicyQualifierInfo {
policy_qualifier_id: (oid::CP_CPS_URI_OID).clone(),
- qualifier: certificate::Qualifier::CpsUri(cps_uri),
+ qualifier: extensions::Qualifier::CpsUri(cps_uri),
}
} else {
let py_notice =
@@ -250,15 +260,15 @@ pub(crate) fn encode_extension(
notice_numbers.push(asn1::BigUint::new(bytes).unwrap());
}
- Some(certificate::NoticeReference {
- organization: certificate::DisplayText::Utf8String(
+ Some(extensions::NoticeReference {
+ organization: extensions::DisplayText::Utf8String(
asn1::Utf8String::new(
py_notice
.getattr(pyo3::intern!(py, "organization"))?
.extract()?,
),
),
- notice_numbers: x509::Asn1ReadableOrWritable::new_write(
+ notice_numbers: common::Asn1ReadableOrWritable::new_write(
asn1::SequenceOfWriter::new(notice_numbers),
),
})
@@ -268,17 +278,17 @@ pub(crate) fn encode_extension(
let py_explicit_text =
py_qualifier.getattr(pyo3::intern!(py, "explicit_text"))?;
let explicit_text = if py_explicit_text.is_true()? {
- Some(certificate::DisplayText::Utf8String(asn1::Utf8String::new(
+ Some(extensions::DisplayText::Utf8String(asn1::Utf8String::new(
py_explicit_text.extract()?,
)))
} else {
None
};
- certificate::PolicyQualifierInfo {
+ extensions::PolicyQualifierInfo {
policy_qualifier_id: (oid::CP_USER_NOTICE_OID).clone(),
- qualifier: certificate::Qualifier::UserNotice(
- certificate::UserNotice {
+ qualifier: extensions::Qualifier::UserNotice(
+ extensions::UserNotice {
notice_ref,
explicit_text,
},
@@ -287,7 +297,7 @@ pub(crate) fn encode_extension(
};
qualifiers.push(qualifier);
}
- Some(x509::Asn1ReadableOrWritable::new_write(
+ Some(common::Asn1ReadableOrWritable::new_write(
asn1::SequenceOfWriter::new(qualifiers),
))
} else {
@@ -295,7 +305,7 @@ pub(crate) fn encode_extension(
};
let py_policy_id =
py_policy_info.getattr(pyo3::intern!(py, "policy_identifier"))?;
- policy_informations.push(certificate::PolicyInformation {
+ policy_informations.push(extensions::PolicyInformation {
policy_identifier: py_oid_to_oid(py_policy_id)?,
policy_qualifiers: qualifiers,
});
@@ -305,7 +315,7 @@ pub(crate) fn encode_extension(
))?))
}
&oid::POLICY_CONSTRAINTS_OID => {
- let pc = certificate::PolicyConstraints {
+ let pc = extensions::PolicyConstraints {
require_explicit_policy: ext
.getattr(pyo3::intern!(py, "require_explicit_policy"))?
.extract()?,
@@ -318,7 +328,7 @@ pub(crate) fn encode_extension(
&oid::NAME_CONSTRAINTS_OID => {
let permitted = ext.getattr(pyo3::intern!(py, "permitted_subtrees"))?;
let excluded = ext.getattr(pyo3::intern!(py, "excluded_subtrees"))?;
- let nc = certificate::NameConstraints {
+ let nc = extensions::NameConstraints {
permitted_subtrees: encode_general_subtrees(ext.py(), permitted)?,
excluded_subtrees: encode_general_subtrees(ext.py(), excluded)?,
};
@@ -412,23 +422,23 @@ pub(crate) fn encode_extension(
{
let py_reasons = ext.getattr(pyo3::intern!(py, "only_some_reasons"))?;
let reasons = certificate::encode_distribution_point_reasons(ext.py(), py_reasons)?;
- Some(x509::Asn1ReadableOrWritable::new_write(reasons))
+ Some(common::Asn1ReadableOrWritable::new_write(reasons))
} else {
None
};
let distribution_point = if ext.getattr(pyo3::intern!(py, "full_name"))?.is_true()? {
let py_full_name = ext.getattr(pyo3::intern!(py, "full_name"))?;
let gns = x509::common::encode_general_names(ext.py(), py_full_name)?;
- Some(certificate::DistributionPointName::FullName(
- x509::Asn1ReadableOrWritable::new_write(asn1::SequenceOfWriter::new(gns)),
+ Some(extensions::DistributionPointName::FullName(
+ common::Asn1ReadableOrWritable::new_write(asn1::SequenceOfWriter::new(gns)),
))
} else if ext.getattr(pyo3::intern!(py, "relative_name"))?.is_true()? {
let mut name_entries = vec![];
for py_name_entry in ext.getattr(pyo3::intern!(py, "relative_name"))?.iter()? {
name_entries.push(x509::common::encode_name_entry(ext.py(), py_name_entry?)?);
}
- Some(certificate::DistributionPointName::NameRelativeToCRLIssuer(
- x509::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new(name_entries)),
+ Some(extensions::DistributionPointName::NameRelativeToCRLIssuer(
+ common::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new(name_entries)),
))
} else {
None
@@ -458,7 +468,7 @@ pub(crate) fn encode_extension(
}
&oid::MS_CERTIFICATE_TEMPLATE => {
let py_template_id = ext.getattr(pyo3::intern!(py, "template_id"))?;
- let mstpl = certificate::MSCertificateTemplate {
+ let mstpl = extensions::MSCertificateTemplate {
template_id: py_oid_to_oid(py_template_id)?,
major_version: ext.getattr(pyo3::intern!(py, "major_version"))?.extract()?,
minor_version: ext.getattr(pyo3::intern!(py, "minor_version"))?.extract()?,
diff --git a/src/rust/src/x509/mod.rs b/src/rust/src/x509/mod.rs
index 2ad15c6e6..c43bf9023 100644
--- a/src/rust/src/x509/mod.rs
+++ b/src/rust/src/x509/mod.rs
@@ -10,13 +10,10 @@ pub(crate) mod extensions;
pub(crate) mod ocsp;
pub(crate) mod ocsp_req;
pub(crate) mod ocsp_resp;
-pub(crate) mod oid;
pub(crate) mod sct;
pub(crate) mod sign;
-pub(crate) use certificate::Certificate;
pub(crate) use common::{
datetime_to_py, find_in_pem, parse_and_cache_extensions, parse_general_name,
- parse_general_names, parse_name, parse_rdn, py_to_datetime, AlgorithmIdentifier,
- Asn1ReadableOrWritable, AttributeTypeValue, Extensions, GeneralName, Name, Time,
+ parse_general_names, parse_name, parse_rdn, py_to_datetime,
};
diff --git a/src/rust/src/x509/ocsp.rs b/src/rust/src/x509/ocsp.rs
index e3568ca9d..b362ef326 100644
--- a/src/rust/src/x509/ocsp.rs
+++ b/src/rust/src/x509/ocsp.rs
@@ -4,7 +4,9 @@
use crate::error::CryptographyResult;
use crate::x509;
-use crate::x509::oid;
+use crate::x509::certificate::Certificate;
+use cryptography_x509::ocsp_req::CertID;
+use cryptography_x509::{common, oid};
use once_cell::sync::Lazy;
use std::collections::HashMap;
@@ -28,69 +30,59 @@ pub(crate) static HASH_NAME_TO_OIDS: Lazy<HashMap<&str, &asn1::ObjectIdentifier>
h
});
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-pub(crate) struct CertID<'a> {
- pub(crate) hash_algorithm: x509::AlgorithmIdentifier<'a>,
- pub(crate) issuer_name_hash: &'a [u8],
- pub(crate) issuer_key_hash: &'a [u8],
- pub(crate) serial_number: asn1::BigInt<'a>,
-}
-
-impl CertID<'_> {
- pub(crate) fn new<'p>(
- py: pyo3::Python<'p>,
- cert: &'p x509::Certificate,
- issuer: &'p x509::Certificate,
- hash_algorithm: &'p pyo3::PyAny,
- ) -> CryptographyResult<CertID<'p>> {
- let issuer_der = asn1::write_single(&cert.raw.borrow_value_public().tbs_cert.issuer)?;
- let issuer_name_hash = hash_data(py, hash_algorithm, &issuer_der)?;
- let issuer_key_hash = hash_data(
- py,
- hash_algorithm,
- issuer
- .raw
- .borrow_value_public()
- .tbs_cert
- .spki
- .subject_public_key
- .as_bytes(),
- )?;
+pub(crate) fn certid_new<'p>(
+ py: pyo3::Python<'p>,
+ cert: &'p Certificate,
+ issuer: &'p Certificate,
+ hash_algorithm: &'p pyo3::PyAny,
+) -> CryptographyResult<CertID<'p>> {
+ let issuer_der = asn1::write_single(&cert.raw.borrow_value_public().tbs_cert.issuer)?;
+ let issuer_name_hash = hash_data(py, hash_algorithm, &issuer_der)?;
+ let issuer_key_hash = hash_data(
+ py,
+ hash_algorithm,
+ issuer
+ .raw
+ .borrow_value_public()
+ .tbs_cert
+ .spki
+ .subject_public_key
+ .as_bytes(),
+ )?;
- Ok(CertID {
- hash_algorithm: x509::AlgorithmIdentifier {
- oid: HASH_NAME_TO_OIDS[hash_algorithm
- .getattr(pyo3::intern!(py, "name"))?
- .extract::<&str>()?]
- .clone(),
- params: Some(*x509::sign::NULL_TLV),
- },
- issuer_name_hash,
- issuer_key_hash,
- serial_number: cert.raw.borrow_value_public().tbs_cert.serial,
- })
- }
+ Ok(CertID {
+ hash_algorithm: common::AlgorithmIdentifier {
+ oid: HASH_NAME_TO_OIDS[hash_algorithm
+ .getattr(pyo3::intern!(py, "name"))?
+ .extract::<&str>()?]
+ .clone(),
+ params: Some(*x509::sign::NULL_TLV),
+ },
+ issuer_name_hash,
+ issuer_key_hash,
+ serial_number: cert.raw.borrow_value_public().tbs_cert.serial,
+ })
+}
- pub(crate) fn new_from_hash<'p>(
- py: pyo3::Python<'p>,
- issuer_name_hash: &'p [u8],
- issuer_key_hash: &'p [u8],
- serial_number: asn1::BigInt<'p>,
- hash_algorithm: &'p pyo3::PyAny,
- ) -> CryptographyResult<CertID<'p>> {
- Ok(CertID {
- hash_algorithm: x509::AlgorithmIdentifier {
- oid: HASH_NAME_TO_OIDS[hash_algorithm
- .getattr(pyo3::intern!(py, "name"))?
- .extract::<&str>()?]
- .clone(),
- params: Some(*x509::sign::NULL_TLV),
- },
- issuer_name_hash,
- issuer_key_hash,
- serial_number,
- })
- }
+pub(crate) fn certid_new_from_hash<'p>(
+ py: pyo3::Python<'p>,
+ issuer_name_hash: &'p [u8],
+ issuer_key_hash: &'p [u8],
+ serial_number: asn1::BigInt<'p>,
+ hash_algorithm: &'p pyo3::PyAny,
+) -> CryptographyResult<CertID<'p>> {
+ Ok(CertID {
+ hash_algorithm: common::AlgorithmIdentifier {
+ oid: HASH_NAME_TO_OIDS[hash_algorithm
+ .getattr(pyo3::intern!(py, "name"))?
+ .extract::<&str>()?]
+ .clone(),
+ params: Some(*x509::sign::NULL_TLV),
+ },
+ issuer_name_hash,
+ issuer_key_hash,
+ serial_number,
+ })
}
pub(crate) fn hash_data<'p>(
diff --git a/src/rust/src/x509/ocsp_req.rs b/src/rust/src/x509/ocsp_req.rs
index afd939d47..856c60c93 100644
--- a/src/rust/src/x509/ocsp_req.rs
+++ b/src/rust/src/x509/ocsp_req.rs
@@ -5,15 +5,16 @@
use crate::asn1::{big_byte_slice_to_py_int, oid_to_py_oid, py_uint_to_big_endian_bytes};
use crate::error::{CryptographyError, CryptographyResult};
use crate::x509;
-use crate::x509::{extensions, ocsp, oid};
+use crate::x509::{extensions, ocsp};
+use cryptography_x509::{common, ocsp_req, oid};
use pyo3::IntoPy;
#[ouroboros::self_referencing]
-struct OwnedRawOCSPRequest {
+struct OwnedOCSPRequest {
data: pyo3::Py<pyo3::types::PyBytes>,
#[borrows(data)]
#[covariant]
- value: RawOCSPRequest<'this>,
+ value: ocsp_req::OCSPRequest<'this>,
}
#[pyo3::prelude::pyfunction]
@@ -21,7 +22,7 @@ fn load_der_ocsp_request(
py: pyo3::Python<'_>,
data: pyo3::Py<pyo3::types::PyBytes>,
) -> CryptographyResult<OCSPRequest> {
- let raw = OwnedRawOCSPRequest::try_new(data, |data| asn1::parse_single(data.as_bytes(py)))?;
+ let raw = OwnedOCSPRequest::try_new(data, |data| asn1::parse_single(data.as_bytes(py)))?;
if raw
.borrow_value()
@@ -46,13 +47,13 @@ fn load_der_ocsp_request(
#[pyo3::prelude::pyclass(module = "cryptography.hazmat.bindings._rust.ocsp")]
struct OCSPRequest {
- raw: OwnedRawOCSPRequest,
+ raw: OwnedOCSPRequest,
cached_extensions: Option<pyo3::PyObject>,
}
impl OCSPRequest {
- fn cert_id(&self) -> ocsp::CertID<'_> {
+ fn cert_id(&self) -> ocsp_req::CertID<'_> {
self.raw
.borrow_value()
.tbs_request
@@ -174,39 +175,6 @@ impl OCSPRequest {
}
}
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-struct RawOCSPRequest<'a> {
- tbs_request: TBSRequest<'a>,
- // Parsing out the full structure, which includes the entirety of a
- // certificate is more trouble than it's worth, since it's not in the
- // Python API.
- #[explicit(0)]
- optional_signature: Option<asn1::Sequence<'a>>,
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-struct TBSRequest<'a> {
- #[explicit(0)]
- #[default(0)]
- version: u8,
- #[explicit(1)]
- requestor_name: Option<x509::GeneralName<'a>>,
- request_list: x509::Asn1ReadableOrWritable<
- 'a,
- asn1::SequenceOf<'a, Request<'a>>,
- asn1::SequenceOfWriter<'a, Request<'a>>,
- >,
- #[explicit(2)]
- request_extensions: Option<x509::Extensions<'a>>,
-}
-
-#[derive(asn1::Asn1Read, asn1::Asn1Write)]
-struct Request<'a> {
- req_cert: ocsp::CertID<'a>,
- #[explicit(0)]
- single_request_extensions: Option<x509::Extensions<'a>>,
-}
-
#[pyo3::prelude::pyfunction]
fn create_ocsp_request(
py: pyo3::Python<'_>,
@@ -216,20 +184,20 @@ fn create_ocsp_request(
// Declare outside the if-block so the lifetimes are right.
let (py_cert, py_issuer, py_hash): (
- pyo3::PyRef<'_, x509::Certificate>,
- pyo3::PyRef<'_, x509::Certificate>,
+ pyo3::PyRef<'_, x509::certificate::Certificate>,
+ pyo3::PyRef<'_, x509::certificate::Certificate>,
&pyo3::PyAny,
);
let req_cert = if !builder_request.is_none() {
let tuple = builder_request.extract::<(
- pyo3::PyRef<'_, x509::Certificate>,
- pyo3::PyRef<'_, x509::Certificate>,
+ pyo3::PyRef<'_, x509::certificate::Certificate>,
+ pyo3::PyRef<'_, x509::certificate::Certificate>,
&pyo3::PyAny,
)>()?;
py_cert = tuple.0;
py_issuer = tuple.1;
py_hash = tuple.2;
- ocsp::CertID::new(py, &py_cert, &py_issuer, py_hash)?
+ ocsp::certid_new(py, &py_cert, &py_issuer, py_hash)?
} else {
let (issuer_name_hash, issuer_key_hash, py_serial, py_hash): (
&[u8],
@@ -240,7 +208,7 @@ fn create_ocsp_request(
.getattr(pyo3::intern!(py, "_request_hash"))?
.extract()?;
let serial_number = asn1::BigInt::new(py_uint_to_big_endian_bytes(py, py_serial)?).unwrap();
- ocsp::CertID::new_from_hash(
+ ocsp::certid_new_from_hash(
py,
issuer_name_hash,
issuer_key_hash,
@@ -254,15 +222,15 @@ fn create_ocsp_request(
builder.getattr(pyo3::intern!(py, "_extensions"))?,
extensions::encode_extension,
)?;
- let reqs = [Request {
+ let reqs = [ocsp_req::Request {
req_cert,
single_request_extensions: None,
}];
- let ocsp_req = RawOCSPRequest {
- tbs_request: TBSRequest {
+ let ocsp_req = ocsp_req::OCSPRequest {
+ tbs_request: ocsp_req::TBSRequest {
version: 0,
requestor_name: None,
- request_list: x509::Asn1ReadableOrWritable::new_write(asn1::SequenceOfWriter::new(
+ request_list: common::Asn1ReadableOrWritable::new_write(asn1::SequenceOfWriter::new(
&reqs,
)),
request_extensions: extensions,
diff --git a/src/rust/src/x509/ocsp_resp.rs b/src/rust/src/x509/ocsp_resp.rs
index 0b2cab5f0..ffbf9c88a 100644
--- a/src/rust/src/x509/ocsp_resp.rs
+++ b/src/rust/src/x509/ocsp_resp.rs
@@ -5,7 +5,10 @@
use crate::asn1::{big_byte_slice_to_py_int, oid_to_py_oid};
use crate::error::{CryptographyError, CryptographyResult};
use crate::x509;
-use crate::x509::{certificate, crl, extensions, ocsp, oid, py_to_datetime, sct};
+use crate::x509::{certificate, crl, extensions, ocsp, py_to_datetime, sct};
+use cryptography_x509::crl::CRLReason;
+use cryptography_x509::extensions::Extensions;
+use cryptography_x509::{common, name, ocsp_req, oid};
use pyo3::IntoPy;
use std::sync::Arc;
@@ -233,7 +236,7 @@ impl OCSPResponse {
});
py_certs.append(pyo3::PyCell::new(
py,
- x509::Certificate {
+ x509::certificate::Certificate {
raw: raw_cert,
cached_extensions: None,
},
@@ -407,9 +410,9 @@ fn map_arc_data_ocsp_response(
f: impl for<'this> FnOnce(
&'this [u8],
&RawOCSPResponse<'this>,
- ) -> certificate::RawCertificate<'this>,
-) -> certificate::OwnedRawCertificate {
- certificate::OwnedRawCertificate::new_public(it.borrow_data().clone_ref(py), |inner_it| {
+ ) -> cryptography_x509::certificate::Certificate<'this>,
+) -> certificate::OwnedCertificate {
+ certificate::OwnedCertificate::new_public(it.borrow_data().clone_ref(py), |inner_it| {
it.with(|value| {
f(inner_it.as_bytes(py), unsafe {
std::mem::transmute(value.value)
@@ -443,13 +446,13 @@ struct ResponseBytes<'a> {
}
type OCSPCerts<'a> = Option<
- x509::Asn1ReadableOrWritable<
+ common::Asn1ReadableOrWritable<
'a,
- asn1::SequenceOf<'a, certificate::RawCertificate<'a>>,
+ asn1::SequenceOf<'a, cryptography_x509::certificate::Certificate<'a>>,
asn1::SequenceOfWriter<
'a,
- certificate::RawCertificate<'a>,
- Vec<certificate::RawCertificate<'a>>,
+ cryptography_x509::certificate::Certificate<'a>,
+ Vec<cryptography_x509::certificate::Certificate<'a>>,
>,
>,
>;
@@ -457,7 +460,7 @@ type OCSPCerts<'a> = Option<
#[derive(asn1::Asn1Read, asn1::Asn1Write)]
struct BasicOCSPResponse<'a> {
tbs_response_data: ResponseData<'a>,
- signature_algorithm: x509::AlgorithmIdentifier<'a>,
+ signature_algorithm: common::AlgorithmIdentifier<'a>,
signature: asn1::BitString<'a>,
#[explicit(0)]
certs: OCSPCerts<'a>,
@@ -488,32 +491,32 @@ struct ResponseData<'a> {
version: u8,
responder_id: ResponderId<'a>,
produced_at: asn1::GeneralizedTime,
- responses: x509::Asn1ReadableOrWritable<
+ responses: common::Asn1ReadableOrWritable<
'a,
asn1::SequenceOf<'a, SingleResponse<'a>>,
asn1::SequenceOfWriter<'a, SingleResponse<'a>, Vec<SingleResponse<'a>>>,
>,
#[explicit(1)]
- response_extensions: Option<x509::Extensions<'a>>,
+ response_extensions: Option<Extensions<'a>>,
}
#[derive(asn1::Asn1Read, asn1::Asn1Write)]
enum ResponderId<'a> {
#[explicit(1)]
- ByName(x509::Name<'a>),
+ ByName(name::Name<'a>),
#[explicit(2)]
ByKey(&'a [u8]),
}
#[derive(asn1::Asn1Read, asn1::Asn1Write)]
struct SingleResponse<'a> {
- cert_id: ocsp::CertID<'a>,
+ cert_id: ocsp_req::CertID<'a>,
cert_status: CertStatus,
this_update: asn1::GeneralizedTime,
#[explicit(0)]
next_update: Option<asn1::GeneralizedTime>,
#[explicit(1)]
- single_extensions: Option<x509::Extensions<'a>>,
+ single_extensions: Option<Extensions<'a>>,
}
impl SingleResponse<'_> {
@@ -601,7 +604,7 @@ enum CertStatus {
struct RevokedInfo {
revocation_time: asn1::GeneralizedTime,
#[explicit(0)]
- revocation_reason: Option<crl::CRLReason>,
+ revocation_reason: Option<CRLReason>,
}
#[pyo3::prelude::pyfunction]
@@ -616,10 +619,10 @@ fn create_ocsp_response(
.getattr(pyo3::intern!(py, "value"))?
.extract::<u32>()?;
- let py_cert: pyo3::PyRef<'_, x509::Certificate>;
- let py_issuer: pyo3::PyRef<'_, x509::Certificate>;
+ let py_cert: pyo3::PyRef<'_, x509::certificate::Certificate>;
+ let py_issuer: pyo3::PyRef<'_, x509::certificate::Certificate>;
let borrowed_cert;
- let py_certs: Option<Vec<pyo3::PyRef<'_, x509::Certificate>>>;
+ let py_certs: Option<Vec<pyo3::PyRef<'_, x509::certificate::Certificate>>>;
let response_bytes = if response_status == SUCCESSFUL_RESPONSE {
let ocsp_mod = py.import(pyo3::intern!(py, "cryptography.x509.ocsp"))?;
@@ -631,10 +634,12 @@ fn create_ocsp_response(
.getattr(pyo3::intern!(py, "_issuer"))?
.extract()?;
let py_cert_hash_algorithm = py_single_resp.getattr(pyo3::intern!(py, "_algorithm"))?;
- let (responder_cert, responder_encoding): (&pyo3::PyCell<x509::Certificate>, &pyo3::PyAny) =
- builder
- .getattr(pyo3::intern!(py, "_responder_id"))?
- .extract()?;
+ let (responder_cert, responder_encoding): (
+ &pyo3::PyCell<x509::certificate::Certificate>,
+ &pyo3::PyAny,
+ ) = builder
+ .getattr(pyo3::intern!(py, "_responder_id"))?
+ .extract()?;
let py_cert_status = py_single_resp.getattr(pyo3::intern!(py, "_cert_status"))?;
let cert_status = if py_cert_status.is(ocsp_mod
@@ -690,7 +695,7 @@ fn create_ocsp_response(
let this_update = asn1::GeneralizedTime::new(py_to_datetime(py, py_this_update)?)?;
let responses = vec![SingleResponse {
- cert_id: ocsp::CertID::new(py, &py_cert, &py_issuer, py_cert_hash_algorithm)?,
+ cert_id: ocsp::certid_new(py, &py_cert, &py_issuer, py_cert_hash_algorithm)?,
cert_status,
next_update,
this_update,
@@ -732,7 +737,7 @@ fn create_ocsp_response(
version: 0,
produced_at: asn1::GeneralizedTime::new(x509::common::datetime_now(py)?)?,
responder_id,
- responses: x509::Asn1ReadableOrWritable::new_write(asn1::SequenceOfWriter::new(
+ responses: common::Asn1ReadableOrWritable::new_write(asn1::SequenceOfWriter::new(
responses,
)),
response_extensions: x509::common::encode_extensions(
@@ -759,7 +764,7 @@ fn create_ocsp_response(
py_certs = builder.getattr(pyo3::intern!(py, "_certs"))?.extract()?;
let certs = py_certs.as_ref().map(|py_certs| {
- x509::Asn1ReadableOrWritable::new_write(asn1::SequenceOfWriter::new(
+ common::Asn1ReadableOrWritable::new_write(asn1::SequenceOfWriter::new(
py_certs
.iter()
.map(|c| c.raw.borrow_value_public().clone())
diff --git a/src/rust/src/x509/oid.rs b/src/rust/src/x509/oid.rs
deleted file mode 100644
index b2e3a36ac..000000000
--- a/src/rust/src/x509/oid.rs
+++ /dev/null
@@ -1,101 +0,0 @@
-// This file is dual licensed under the terms of the Apache License, Version
-// 2.0, and the BSD License. See the LICENSE file in the root of this repository
-// for complete details.
-
-pub(crate) const EXTENSION_REQUEST: asn1::ObjectIdentifier =
- asn1::oid!(1, 2, 840, 113549, 1, 9, 14);
-pub(crate) const MS_EXTENSION_REQUEST: asn1::ObjectIdentifier =
- asn1::oid!(1, 3, 6, 1, 4, 1, 311, 2, 1, 14);
-pub(crate) const MS_CERTIFICATE_TEMPLATE: asn1::ObjectIdentifier =
- asn1::oid!(1, 3, 6, 1, 4, 1, 311, 21, 7);
-pub(crate) const PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS_OID: asn1::ObjectIdentifier =
- asn1::oid!(1, 3, 6, 1, 4, 1, 11129, 2, 4, 2);
-pub(crate) const PRECERT_POISON_OID: asn1::ObjectIdentifier =
- asn1::oid!(1, 3, 6, 1, 4, 1, 11129, 2, 4, 3);
-pub(crate) const SIGNED_CERTIFICATE_TIMESTAMPS_OID: asn1::ObjectIdentifier =
- asn1::oid!(1, 3, 6, 1, 4, 1, 11129, 2, 4, 5);
-pub(crate) const AUTHORITY_INFORMATION_ACCESS_OID: asn1::ObjectIdentifier =
- asn1::oid!(1, 3, 6, 1, 5, 5, 7, 1, 1);
-pub(crate) const SUBJECT_INFORMATION_ACCESS_OID: asn1::ObjectIdentifier =
- asn1::oid!(1, 3, 6, 1, 5, 5, 7, 1, 11);
-pub(crate) const TLS_FEATURE_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 6, 1, 5, 5, 7, 1, 24);
-pub(crate) const CP_CPS_URI_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 6, 1, 5, 5, 7, 2, 1);
-pub(crate) const CP_USER_NOTICE_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 6, 1, 5, 5, 7, 2, 2);
-pub(crate) const NONCE_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 6, 1, 5, 5, 7, 48, 1, 2);
-pub(crate) const OCSP_NO_CHECK_OID: asn1::ObjectIdentifier =
- asn1::oid!(1, 3, 6, 1, 5, 5, 7, 48, 1, 5);
-pub(crate) const SUBJECT_KEY_IDENTIFIER_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 14);
-pub(crate) const KEY_USAGE_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 15);
-pub(crate) const SUBJECT_ALTERNATIVE_NAME_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 17);
-pub(crate) const ISSUER_ALTERNATIVE_NAME_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 18);
-pub(crate) const BASIC_CONSTRAINTS_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 19);
-pub(crate) const CRL_NUMBER_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 20);
-pub(crate) const CRL_REASON_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 21);
-pub(crate) const INVALIDITY_DATE_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 24);
-pub(crate) const DELTA_CRL_INDICATOR_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 27);
-pub(crate) const ISSUING_DISTRIBUTION_POINT_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 28);
-pub(crate) const CERTIFICATE_ISSUER_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 29);
-pub(crate) const NAME_CONSTRAINTS_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 30);
-pub(crate) const CRL_DISTRIBUTION_POINTS_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 31);
-pub(crate) const CERTIFICATE_POLICIES_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 32);
-pub(crate) const AUTHORITY_KEY_IDENTIFIER_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 35);
-pub(crate) const POLICY_CONSTRAINTS_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 36);
-pub(crate) const EXTENDED_KEY_USAGE_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 37);
-pub(crate) const FRESHEST_CRL_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 46);
-pub(crate) const INHIBIT_ANY_POLICY_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 54);
-pub(crate) const ACCEPTABLE_RESPONSES_OID: asn1::ObjectIdentifier =
- asn1::oid!(1, 3, 6, 1, 5, 5, 7, 48, 1, 4);
-
-// Signing methods
-pub(crate) const ECDSA_WITH_SHA224_OID: asn1::ObjectIdentifier =
- asn1::oid!(1, 2, 840, 10045, 4, 3, 1);
-pub(crate) const ECDSA_WITH_SHA256_OID: asn1::ObjectIdentifier =
- asn1::oid!(1, 2, 840, 10045, 4, 3, 2);
-pub(crate) const ECDSA_WITH_SHA384_OID: asn1::ObjectIdentifier =
- asn1::oid!(1, 2, 840, 10045, 4, 3, 3);
-pub(crate) const ECDSA_WITH_SHA512_OID: asn1::ObjectIdentifier =
- asn1::oid!(1, 2, 840, 10045, 4, 3, 4);
-pub(crate) const ECDSA_WITH_SHA3_224_OID: asn1::ObjectIdentifier =
- asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 9);
-pub(crate) const ECDSA_WITH_SHA3_256_OID: asn1::ObjectIdentifier =
- asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 10);
-pub(crate) const ECDSA_WITH_SHA3_384_OID: asn1::ObjectIdentifier =
- asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 11);
-pub(crate) const ECDSA_WITH_SHA3_512_OID: asn1::ObjectIdentifier =
- asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 12);
-
-pub(crate) const RSA_WITH_SHA224_OID: asn1::ObjectIdentifier =
- asn1::oid!(1, 2, 840, 113549, 1, 1, 14);
-pub(crate) const RSA_WITH_SHA256_OID: asn1::ObjectIdentifier =
- asn1::oid!(1, 2, 840, 113549, 1, 1, 11);
-pub(crate) const RSA_WITH_SHA384_OID: asn1::ObjectIdentifier =
- asn1::oid!(1, 2, 840, 113549, 1, 1, 12);
-pub(crate) const RSA_WITH_SHA512_OID: asn1::ObjectIdentifier =
- asn1::oid!(1, 2, 840, 113549, 1, 1, 13);
-pub(crate) const RSA_WITH_SHA3_224_OID: asn1::ObjectIdentifier =
- asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 13);
-pub(crate) const RSA_WITH_SHA3_256_OID: asn1::ObjectIdentifier =
- asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 14);
-pub(crate) const RSA_WITH_SHA3_384_OID: asn1::ObjectIdentifier =
- asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 15);
-pub(crate) const RSA_WITH_SHA3_512_OID: asn1::ObjectIdentifier =
- asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 16);
-
-pub(crate) const DSA_WITH_SHA224_OID: asn1::ObjectIdentifier =
- asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 1);
-pub(crate) const DSA_WITH_SHA256_OID: asn1::ObjectIdentifier =
- asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 2);
-pub(crate) const DSA_WITH_SHA384_OID: asn1::ObjectIdentifier =
- asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 3);
-pub(crate) const DSA_WITH_SHA512_OID: asn1::ObjectIdentifier =
- asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 4);
-
-pub(crate) const ED25519_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 101, 112);
-pub(crate) const ED448_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 101, 113);
-
-// Hashes
-pub(crate) const SHA1_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 14, 3, 2, 26);
-pub(crate) const SHA224_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 2, 4);
-pub(crate) const SHA256_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 2, 1);
-pub(crate) const SHA384_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 2, 2);
-pub(crate) const SHA512_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 2, 3);
diff --git a/src/rust/src/x509/sign.rs b/src/rust/src/x509/sign.rs
index 4be023bb2..12579b35e 100644
--- a/src/rust/src/x509/sign.rs
+++ b/src/rust/src/x509/sign.rs
@@ -3,8 +3,7 @@
// for complete details.
use crate::error::{CryptographyError, CryptographyResult};
-use crate::x509;
-use crate::x509::oid;
+use cryptography_x509::{common, oid};
use once_cell::sync::Lazy;
@@ -138,16 +137,16 @@ pub(crate) fn compute_signature_algorithm<'p>(
py: pyo3::Python<'p>,
private_key: &'p pyo3::PyAny,
hash_algorithm: &'p pyo3::PyAny,
-) -> pyo3::PyResult<x509::AlgorithmIdentifier<'static>> {
+) -> pyo3::PyResult<common::AlgorithmIdentifier<'static>> {
let key_type = identify_key_type(py, private_key)?;
let hash_type = identify_hash_type(py, hash_algorithm)?;
match (key_type, hash_type) {
- (KeyType::Ed25519, HashType::None) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Ed25519, HashType::None) => Ok(common::AlgorithmIdentifier {
oid: (oid::ED25519_OID).clone(),
params: None,
}),
- (KeyType::Ed448, HashType::None) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Ed448, HashType::None) => Ok(common::AlgorithmIdentifier {
oid: (oid::ED448_OID).clone(),
params: None,
}),
@@ -155,85 +154,85 @@ pub(crate) fn compute_signature_algorithm<'p>(
"Algorithm must be None when signing via ed25519 or ed448",
)),
- (KeyType::Ec, HashType::Sha224) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Ec, HashType::Sha224) => Ok(common::AlgorithmIdentifier {
oid: (oid::ECDSA_WITH_SHA224_OID).clone(),
params: None,
}),
- (KeyType::Ec, HashType::Sha256) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Ec, HashType::Sha256) => Ok(common::AlgorithmIdentifier {
oid: (oid::ECDSA_WITH_SHA256_OID).clone(),
params: None,
}),
- (KeyType::Ec, HashType::Sha384) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Ec, HashType::Sha384) => Ok(common::AlgorithmIdentifier {
oid: (oid::ECDSA_WITH_SHA384_OID).clone(),
params: None,
}),
- (KeyType::Ec, HashType::Sha512) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Ec, HashType::Sha512) => Ok(common::AlgorithmIdentifier {
oid: (oid::ECDSA_WITH_SHA512_OID).clone(),
params: None,
}),
- (KeyType::Ec, HashType::Sha3_224) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Ec, HashType::Sha3_224) => Ok(common::AlgorithmIdentifier {
oid: (oid::ECDSA_WITH_SHA3_224_OID).clone(),
params: None,
}),
- (KeyType::Ec, HashType::Sha3_256) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Ec, HashType::Sha3_256) => Ok(common::AlgorithmIdentifier {
oid: (oid::ECDSA_WITH_SHA3_256_OID).clone(),
params: None,
}),
- (KeyType::Ec, HashType::Sha3_384) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Ec, HashType::Sha3_384) => Ok(common::AlgorithmIdentifier {
oid: (oid::ECDSA_WITH_SHA3_384_OID).clone(),
params: None,
}),
- (KeyType::Ec, HashType::Sha3_512) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Ec, HashType::Sha3_512) => Ok(common::AlgorithmIdentifier {
oid: (oid::ECDSA_WITH_SHA3_512_OID).clone(),
params: None,
}),
- (KeyType::Rsa, HashType::Sha224) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Rsa, HashType::Sha224) => Ok(common::AlgorithmIdentifier {
oid: (oid::RSA_WITH_SHA224_OID).clone(),
params: Some(*NULL_TLV),
}),
- (KeyType::Rsa, HashType::Sha256) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Rsa, HashType::Sha256) => Ok(common::AlgorithmIdentifier {
oid: (oid::RSA_WITH_SHA256_OID).clone(),
params: Some(*NULL_TLV),
}),
- (KeyType::Rsa, HashType::Sha384) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Rsa, HashType::Sha384) => Ok(common::AlgorithmIdentifier {
oid: (oid::RSA_WITH_SHA384_OID).clone(),
params: Some(*NULL_TLV),
}),
- (KeyType::Rsa, HashType::Sha512) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Rsa, HashType::Sha512) => Ok(common::AlgorithmIdentifier {
oid: (oid::RSA_WITH_SHA512_OID).clone(),
params: Some(*NULL_TLV),
}),
- (KeyType::Rsa, HashType::Sha3_224) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Rsa, HashType::Sha3_224) => Ok(common::AlgorithmIdentifier {
oid: (oid::RSA_WITH_SHA3_224_OID).clone(),
params: Some(*NULL_TLV),
}),
- (KeyType::Rsa, HashType::Sha3_256) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Rsa, HashType::Sha3_256) => Ok(common::AlgorithmIdentifier {
oid: (oid::RSA_WITH_SHA3_256_OID).clone(),
params: Some(*NULL_TLV),
}),
- (KeyType::Rsa, HashType::Sha3_384) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Rsa, HashType::Sha3_384) => Ok(common::AlgorithmIdentifier {
oid: (oid::RSA_WITH_SHA3_384_OID).clone(),
params: Some(*NULL_TLV),
}),
- (KeyType::Rsa, HashType::Sha3_512) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Rsa, HashType::Sha3_512) => Ok(common::AlgorithmIdentifier {
oid: (oid::RSA_WITH_SHA3_512_OID).clone(),
params: Some(*NULL_TLV),
}),
- (KeyType::Dsa, HashType::Sha224) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Dsa, HashType::Sha224) => Ok(common::AlgorithmIdentifier {
oid: (oid::DSA_WITH_SHA224_OID).clone(),
params: None,
}),
- (KeyType::Dsa, HashType::Sha256) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Dsa, HashType::Sha256) => Ok(common::AlgorithmIdentifier {
oid: (oid::DSA_WITH_SHA256_OID).clone(),
params: None,
}),
- (KeyType::Dsa, HashType::Sha384) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Dsa, HashType::Sha384) => Ok(common::AlgorithmIdentifier {
oid: (oid::DSA_WITH_SHA384_OID).clone(),
params: None,
}),
- (KeyType::Dsa, HashType::Sha512) => Ok(x509::AlgorithmIdentifier {
+ (KeyType::Dsa, HashType::Sha512) => Ok(common::AlgorithmIdentifier {
oid: (oid::DSA_WITH_SHA512_OID).clone(),
params: None,
}),
@@ -456,7 +455,7 @@ fn identify_key_hash_type_for_oid(
#[cfg(test)]
mod tests {
use super::{identify_key_hash_type_for_oid, py_hash_name_from_hash_type, HashType, KeyType};
- use crate::x509::oid;
+ use cryptography_x509::oid;
#[test]
fn test_identify_key_hash_type_for_oid() {