Skip to content

Commit

Permalink
Convert PKCS#7 types to GATs
Browse files Browse the repository at this point in the history
This does not currently work because rust-asn1 doesn't handle Asn1Definedby{Readable,Writable} correctly
  • Loading branch information
alex committed Nov 26, 2024
1 parent e201c87 commit 4ab1565
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 63 deletions.
11 changes: 11 additions & 0 deletions src/rust/cryptography-x509/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,9 @@ impl<T: asn1::SimpleAsn1Writable, U: asn1::SimpleAsn1Writable> asn1::SimpleAsn1W

pub trait Asn1Operation {
type SequenceOfVec<'a, T>
where
T: 'a;
type SetOf<'a, T>
where
T: 'a;
type SetOfVec<'a, T>
Expand All @@ -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
Expand All @@ -292,6 +299,10 @@ impl Asn1Operation for Asn1Write {
= asn1::SequenceOfWriter<'a, T, Vec<T>>
where
T: 'a;
type SetOf<'a, T>
= asn1::SetOfWriter<'a, T>
where
T: 'a;
type SetOfVec<'a, T>
= asn1::SetOfWriter<'a, T, Vec<T>>
where
Expand Down
6 changes: 3 additions & 3 deletions src/rust/cryptography-x509/src/pkcs12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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<MacData<'a>>,
}

Expand Down
48 changes: 15 additions & 33 deletions src/rust/cryptography-x509/src/pkcs7.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -10,54 +11,38 @@ 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<asn1::ObjectIdentifier>,

#[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<Box<EnvelopedData<'a>>, 0>),
EnvelopedData(asn1::Explicit<Box<EnvelopedData<'a, Op>>, 0>),
#[defined_by(PKCS7_SIGNED_DATA_OID)]
SignedData(asn1::Explicit<Box<SignedData<'a>>, 0>),
SignedData(asn1::Explicit<Box<SignedData<'a, Op>>, 0>),
#[defined_by(PKCS7_DATA_OID)]
Data(Option<asn1::Explicit<&'a [u8], 0>>),
#[defined_by(PKCS7_ENCRYPTED_DATA_OID)]
EncryptedData(asn1::Explicit<EncryptedData<'a>, 0>),
}

#[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<Op::SetOf<'a, certificate::Certificate<'a>>>,

// 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<Op::SetOf<'a, asn1::Sequence<'a>>>,

pub signer_infos: Op::SetOf<'a, SignerInfo<'a>>,
}

#[derive(asn1::Asn1Write, asn1::Asn1Read)]
Expand All @@ -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>,
}

Expand Down
6 changes: 3 additions & 3 deletions src/rust/src/pkcs12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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::<Asn1Write> {
_content_type: asn1::DefinedByMarker::marker(),
content: cryptography_x509::pkcs7::Content::EncryptedData(asn1::Explicit::new(
cryptography_x509::pkcs7::EncryptedData {
Expand All @@ -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::<Asn1Write> {
_content_type: asn1::DefinedByMarker::marker(),
content: cryptography_x509::pkcs7::Content::Data(Some(asn1::Explicit::new(
&cert_bag_contents,
Expand Down
37 changes: 13 additions & 24 deletions src/rust/src/pkcs7.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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::<Asn1Write> {
_content_type: asn1::DefinedByMarker::marker(),
content: pkcs7::Content::SignedData(asn1::Explicit::new(Box::new(signed_data))),
};
Expand Down Expand Up @@ -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,
Expand All @@ -149,7 +145,7 @@ fn encrypt_and_serialize<'p>(
},
};

let content_info = pkcs7::ContentInfo {
let content_info = pkcs7::ContentInfo::<Asn1Write> {
_content_type: asn1::DefinedByMarker::marker(),
content: pkcs7::Content::EnvelopedData(asn1::Explicit::new(Box::new(enveloped_data))),
};
Expand Down Expand Up @@ -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::<pkcs7::ContentInfo<'_>>(data)?;
let content_info = asn1::parse_single::<pkcs7::ContentInfo<'_, Asn1Read>>(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
});
Expand Down Expand Up @@ -580,27 +575,21 @@ 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)),
},
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::<Asn1Write> {
_content_type: asn1::DefinedByMarker::marker(),
content: pkcs7::Content::SignedData(asn1::Explicit::new(Box::new(signed_data))),
};
Expand Down

0 comments on commit 4ab1565

Please sign in to comment.