From 7d3da0465a175cf7447391fb2dd039bc741dc97a 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 | 10 ++--- src/rust/src/pkcs7.rs | 37 +++++++----------- 5 files changed, 47 insertions(+), 65 deletions(-) diff --git a/src/rust/cryptography-x509/src/common.rs b/src/rust/cryptography-x509/src/common.rs index 5e73a6bb29e0..4ba463d8cada 100644 --- a/src/rust/cryptography-x509/src/common.rs +++ b/src/rust/cryptography-x509/src/common.rs @@ -268,6 +268,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> @@ -284,6 +287,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 @@ -295,6 +302,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 f0da7ad28983..3d237dde17ac 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::Utf8StoredBMPString; +use crate::common::{Asn1Operation, Utf8StoredBMPString}; use crate::{pkcs7, pkcs8}; 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, asn1::Asn1Read)] -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 4fcd98cb40be..2d0d8b82f107 100644 --- a/src/rust/src/pkcs12.rs +++ b/src/rust/src/pkcs12.rs @@ -3,11 +3,11 @@ // for complete details. use std::collections::hash_map::DefaultHasher; -use std::hash::{Hash, Hasher}; +use std::hash::{Hash, Hash, Hasher, Hasher}; -use cryptography_x509::common::Utf8StoredBMPString; +use cryptography_x509::common::{Asn1Write, Utf8StoredBMPString, Utf8StoredBMPString}; use pyo3::types::{PyAnyMethods, PyBytesMethods, PyListMethods}; -use pyo3::{IntoPyObject, PyTypeInfo}; +use pyo3::{IntoPyObject, IntoPyObject, PyTypeInfo, PyTypeInfo}; use crate::backend::{ciphers, hashes, hmac, kdf, keys}; use crate::buf::CffiBuf; @@ -479,7 +479,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 { @@ -497,7 +497,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 f2f41b95135d..be3d01c7fe2e 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}; @@ -63,19 +63,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))), }; @@ -157,9 +155,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, @@ -171,7 +167,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))), }; @@ -240,18 +236,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 }); @@ -610,9 +605,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)), @@ -620,17 +613,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))), };