From 4ab1565e8d24a977ad0ea4a94551097d7b0a2646 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 22 Nov 2024 14:17:58 -0500 Subject: [PATCH] Convert PKCS#7 types to GATs This does not currently work because rust-asn1 doesn't handle Asn1Definedby{Readable,Writable} correctly --- src/rust/cryptography-x509/src/common.rs | 11 ++++++ src/rust/cryptography-x509/src/pkcs12.rs | 6 +-- src/rust/cryptography-x509/src/pkcs7.rs | 48 ++++++++---------------- src/rust/src/pkcs12.rs | 6 +-- src/rust/src/pkcs7.rs | 37 +++++++----------- 5 files changed, 45 insertions(+), 63 deletions(-) diff --git a/src/rust/cryptography-x509/src/common.rs b/src/rust/cryptography-x509/src/common.rs index 77ccd011a85e..d96e690cc21a 100644 --- a/src/rust/cryptography-x509/src/common.rs +++ b/src/rust/cryptography-x509/src/common.rs @@ -265,6 +265,9 @@ impl asn1::SimpleAsn1W pub trait Asn1Operation { type SequenceOfVec<'a, T> + where + T: 'a; + type SetOf<'a, T> where T: 'a; type SetOfVec<'a, T> @@ -281,6 +284,10 @@ impl Asn1Operation for Asn1Read { = asn1::SequenceOf<'a, T> where T: 'a; + type SetOf<'a, T> + = asn1::SetOf<'a, T> + where + T: 'a; type SetOfVec<'a, T> = asn1::SetOf<'a, T> where @@ -292,6 +299,10 @@ impl Asn1Operation for Asn1Write { = asn1::SequenceOfWriter<'a, T, Vec> where T: 'a; + type SetOf<'a, T> + = asn1::SetOfWriter<'a, T> + where + T: 'a; type SetOfVec<'a, T> = asn1::SetOfWriter<'a, T, Vec> where diff --git a/src/rust/cryptography-x509/src/pkcs12.rs b/src/rust/cryptography-x509/src/pkcs12.rs index f8f518a4b615..4e6da594228c 100644 --- a/src/rust/cryptography-x509/src/pkcs12.rs +++ b/src/rust/cryptography-x509/src/pkcs12.rs @@ -2,7 +2,7 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. -use crate::common::{AlgorithmIdentifier, Utf8StoredBMPString}; +use crate::common::{AlgorithmIdentifier, Asn1Operation, Utf8StoredBMPString}; use crate::pkcs7; pub const CERT_BAG_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 12, 10, 1, 3); @@ -14,9 +14,9 @@ pub const FRIENDLY_NAME_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 1135 pub const LOCAL_KEY_ID_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 9, 21); #[derive(asn1::Asn1Write)] -pub struct Pfx<'a> { +pub struct Pfx<'a, Op: Asn1Operation> { pub version: u8, - pub auth_safe: pkcs7::ContentInfo<'a>, + pub auth_safe: pkcs7::ContentInfo<'a, Op>, pub mac_data: Option>, } diff --git a/src/rust/cryptography-x509/src/pkcs7.rs b/src/rust/cryptography-x509/src/pkcs7.rs index 7a55d48b473b..a2e46fe6678e 100644 --- a/src/rust/cryptography-x509/src/pkcs7.rs +++ b/src/rust/cryptography-x509/src/pkcs7.rs @@ -2,6 +2,7 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. +use crate::common::Asn1Operation; use crate::{certificate, common, csr, name}; pub const PKCS7_DATA_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 7, 1); @@ -10,19 +11,19 @@ pub const PKCS7_ENVELOPED_DATA_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 84 pub const PKCS7_ENCRYPTED_DATA_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 7, 6); #[derive(asn1::Asn1Write, asn1::Asn1Read)] -pub struct ContentInfo<'a> { +pub struct ContentInfo<'a, Op: Asn1Operation> { pub _content_type: asn1::DefinedByMarker, #[defined_by(_content_type)] - pub content: Content<'a>, + pub content: Content<'a, Op>, } #[derive(asn1::Asn1DefinedByWrite, asn1::Asn1DefinedByRead)] -pub enum Content<'a> { +pub enum Content<'a, Op: Asn1Operation> { #[defined_by(PKCS7_ENVELOPED_DATA_OID)] - EnvelopedData(asn1::Explicit>, 0>), + EnvelopedData(asn1::Explicit>, 0>), #[defined_by(PKCS7_SIGNED_DATA_OID)] - SignedData(asn1::Explicit>, 0>), + SignedData(asn1::Explicit>, 0>), #[defined_by(PKCS7_DATA_OID)] Data(Option>), #[defined_by(PKCS7_ENCRYPTED_DATA_OID)] @@ -30,34 +31,18 @@ pub enum Content<'a> { } #[derive(asn1::Asn1Write, asn1::Asn1Read)] -pub struct SignedData<'a> { +pub struct SignedData<'a, Op: Asn1Operation> { pub version: u8, - pub digest_algorithms: common::Asn1ReadableOrWritable< - asn1::SetOf<'a, common::AlgorithmIdentifier<'a>>, - asn1::SetOfWriter<'a, common::AlgorithmIdentifier<'a>>, - >, - pub content_info: ContentInfo<'a>, + pub digest_algorithms: Op::SetOf<'a, common::AlgorithmIdentifier<'a>>, + pub content_info: ContentInfo<'a, Op>, #[implicit(0)] - pub certificates: Option< - common::Asn1ReadableOrWritable< - asn1::SetOf<'a, certificate::Certificate<'a>>, - asn1::SetOfWriter<'a, certificate::Certificate<'a>>, - >, - >, + pub certificates: Option>>, // We don't ever supply any of these, so for now, don't fill out the fields. #[implicit(1)] - pub crls: Option< - common::Asn1ReadableOrWritable< - asn1::SetOf<'a, asn1::Sequence<'a>>, - asn1::SetOfWriter<'a, asn1::Sequence<'a>>, - >, - >, - - pub signer_infos: common::Asn1ReadableOrWritable< - asn1::SetOf<'a, SignerInfo<'a>>, - asn1::SetOfWriter<'a, SignerInfo<'a>>, - >, + pub crls: Option>>, + + pub signer_infos: Op::SetOf<'a, SignerInfo<'a>>, } #[derive(asn1::Asn1Write, asn1::Asn1Read)] @@ -76,12 +61,9 @@ pub struct SignerInfo<'a> { } #[derive(asn1::Asn1Write, asn1::Asn1Read)] -pub struct EnvelopedData<'a> { +pub struct EnvelopedData<'a, Op: Asn1Operation> { pub version: u8, - pub recipient_infos: common::Asn1ReadableOrWritable< - asn1::SetOf<'a, RecipientInfo<'a>>, - asn1::SetOfWriter<'a, RecipientInfo<'a>>, - >, + pub recipient_infos: Op::SetOf<'a, RecipientInfo<'a>>, pub encrypted_content_info: EncryptedContentInfo<'a>, } diff --git a/src/rust/src/pkcs12.rs b/src/rust/src/pkcs12.rs index 3de031a22b38..49c37bbda165 100644 --- a/src/rust/src/pkcs12.rs +++ b/src/rust/src/pkcs12.rs @@ -8,7 +8,7 @@ use crate::error::{CryptographyError, CryptographyResult}; use crate::padding::PKCS7PaddingContext; use crate::x509::certificate::Certificate; use crate::{types, x509}; -use cryptography_x509::common::Utf8StoredBMPString; +use cryptography_x509::common::{Asn1Write, Utf8StoredBMPString}; use pyo3::types::{PyAnyMethods, PyBytesMethods, PyListMethods}; use pyo3::IntoPyObject; use std::collections::hash_map::DefaultHasher; @@ -577,7 +577,7 @@ fn serialize_key_and_certificates<'p>( &cert_bag_contents, )?; - auth_safe_contents.push(cryptography_x509::pkcs7::ContentInfo { + auth_safe_contents.push(cryptography_x509::pkcs7::ContentInfo:: { _content_type: asn1::DefinedByMarker::marker(), content: cryptography_x509::pkcs7::Content::EncryptedData(asn1::Explicit::new( cryptography_x509::pkcs7::EncryptedData { @@ -595,7 +595,7 @@ fn serialize_key_and_certificates<'p>( )), }) } else { - auth_safe_contents.push(cryptography_x509::pkcs7::ContentInfo { + auth_safe_contents.push(cryptography_x509::pkcs7::ContentInfo:: { _content_type: asn1::DefinedByMarker::marker(), content: cryptography_x509::pkcs7::Content::Data(Some(asn1::Explicit::new( &cert_bag_contents, diff --git a/src/rust/src/pkcs7.rs b/src/rust/src/pkcs7.rs index 90cd063f8b6a..7d4ce04ecff3 100644 --- a/src/rust/src/pkcs7.rs +++ b/src/rust/src/pkcs7.rs @@ -6,7 +6,7 @@ use std::borrow::Cow; use std::collections::HashMap; use std::ops::Deref; -use cryptography_x509::common::{AlgorithmIdentifier, AlgorithmParameters}; +use cryptography_x509::common::{AlgorithmIdentifier, AlgorithmParameters, Asn1Read, Asn1Write}; use cryptography_x509::csr::Attribute; use cryptography_x509::pkcs7::PKCS7_DATA_OID; use cryptography_x509::{common, oid, pkcs7}; @@ -59,19 +59,17 @@ fn serialize_certificates<'p>( let signed_data = pkcs7::SignedData { version: 1, - digest_algorithms: common::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new(&[])), + digest_algorithms: asn1::SetOfWriter::new([].as_slice()), content_info: pkcs7::ContentInfo { _content_type: asn1::DefinedByMarker::marker(), content: pkcs7::Content::Data(None), }, - certificates: Some(common::Asn1ReadableOrWritable::new_write( - asn1::SetOfWriter::new(&raw_certs), - )), + certificates: Some(asn1::SetOfWriter::new(raw_certs.as_slice())), crls: None, - signer_infos: common::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new(&[])), + signer_infos: asn1::SetOfWriter::new([].as_slice()), }; - let content_info = pkcs7::ContentInfo { + let content_info = pkcs7::ContentInfo:: { _content_type: asn1::DefinedByMarker::marker(), content: pkcs7::Content::SignedData(asn1::Explicit::new(Box::new(signed_data))), }; @@ -135,9 +133,7 @@ fn encrypt_and_serialize<'p>( let enveloped_data = pkcs7::EnvelopedData { version: 0, - recipient_infos: common::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new( - &recipient_infos, - )), + recipient_infos: asn1::SetOfWriter::new(recipient_infos.as_slice()), encrypted_content_info: pkcs7::EncryptedContentInfo { content_type: PKCS7_DATA_OID, @@ -149,7 +145,7 @@ fn encrypt_and_serialize<'p>( }, }; - let content_info = pkcs7::ContentInfo { + let content_info = pkcs7::ContentInfo:: { _content_type: asn1::DefinedByMarker::marker(), content: pkcs7::Content::EnvelopedData(asn1::Explicit::new(Box::new(enveloped_data))), }; @@ -218,18 +214,17 @@ fn decrypt_der<'p>( check_decrypt_parameters(py, &certificate, &private_key, options)?; // Decrypt the data - let content_info = asn1::parse_single::>(data)?; + let content_info = asn1::parse_single::>(data)?; let plain_content = match content_info.content { pkcs7::Content::EnvelopedData(data) => { // Extract enveloped data let enveloped_data = data.into_inner(); // Get recipients, and the one matching with the given certificate (if any) - let mut recipient_infos = enveloped_data.recipient_infos.unwrap_read().clone(); let recipient_certificate = certificate.get().raw.borrow_dependent(); let recipient_serial_number = recipient_certificate.tbs_cert.serial; let recipient_issuer = recipient_certificate.tbs_cert.issuer.clone(); - let found_recipient_info = recipient_infos.find(|info| { + let found_recipient_info = enveloped_data.recipient_infos.find(|info| { info.issuer_and_serial_number.serial_number == recipient_serial_number && info.issuer_and_serial_number.issuer == recipient_issuer }); @@ -580,9 +575,7 @@ fn sign_and_serialize<'p>( let signed_data = pkcs7::SignedData { version: 1, - digest_algorithms: common::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new( - &digest_algs, - )), + digest_algorithms: asn1::SetOfWriter::new(digest_algs.as_slice()), content_info: pkcs7::ContentInfo { _content_type: asn1::DefinedByMarker::marker(), content: pkcs7::Content::Data(content.map(asn1::Explicit::new)), @@ -590,17 +583,13 @@ fn sign_and_serialize<'p>( certificates: if options.contains(types::PKCS7_NO_CERTS.get(py)?)? { None } else { - Some(common::Asn1ReadableOrWritable::new_write( - asn1::SetOfWriter::new(&certs), - )) + Some(asn1::SetOfWriter::new(certs.as_slice())) }, crls: None, - signer_infos: common::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new( - &signer_infos, - )), + signer_infos: asn1::SetOfWriter::new(signer_infos.as_slice()), }; - let content_info = pkcs7::ContentInfo { + let content_info = pkcs7::ContentInfo:: { _content_type: asn1::DefinedByMarker::marker(), content: pkcs7::Content::SignedData(asn1::Explicit::new(Box::new(signed_data))), };