diff --git a/pkcs7/Cargo.toml b/pkcs7/Cargo.toml index 57e80f87f..0f620df81 100644 --- a/pkcs7/Cargo.toml +++ b/pkcs7/Cargo.toml @@ -20,7 +20,9 @@ spki = { version = "0.7" } x509-cert = { version = "0.2", default-features = false } [dev-dependencies] +der = { version = "0.7", features = ["oid", "pem"] } hex-literal = "0.4" +x509-cert = { version = "0.2", default-features = false, features = ["pem"] } [package.metadata.docs.rs] all-features = true diff --git a/pkcs7/src/algorithm_identifier_types.rs b/pkcs7/src/algorithm_identifier_types.rs new file mode 100644 index 000000000..3d1cc7d9a --- /dev/null +++ b/pkcs7/src/algorithm_identifier_types.rs @@ -0,0 +1,21 @@ +//! `Algorithm Identifier Types` [RFC 5652 § 10.1](https://datatracker.ietf.org/doc/html/rfc5652#section-10.1) + +use der::asn1::SetOfVec; +use spki::AlgorithmIdentifierRef; + +/// ```text +/// DigestAlgorithmIdentifier ::= AlgorithmIdentifier +/// ``` +/// See [RFC 5652 10.1.1](https://datatracker.ietf.org/doc/html/rfc5652#section-10.1.1). +pub type DigestAlgorithmIdentifier<'a> = AlgorithmIdentifierRef<'a>; + +/// ```text +/// DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier +/// ``` +pub type DigestAlgorithmIdentifiers<'a> = SetOfVec>; + +/// ```text +/// SignatureAlgorithmIdentifier ::= AlgorithmIdentifier +/// ``` +/// See [RFC 5652 10.1.2](https://datatracker.ietf.org/doc/html/rfc5652#section-10.1.2). +pub type SignatureAlgorithmIdentifier<'a> = AlgorithmIdentifierRef<'a>; diff --git a/pkcs7/src/lib.rs b/pkcs7/src/lib.rs index 3755540fb..e0beebc58 100644 --- a/pkcs7/src/lib.rs +++ b/pkcs7/src/lib.rs @@ -15,6 +15,7 @@ unused_qualifications )] +pub mod algorithm_identifier_types; pub mod certificate_choices; pub mod cms_version; pub mod data_content; diff --git a/pkcs7/src/signed_data_content.rs b/pkcs7/src/signed_data_content.rs index ed55b5988..43ccf170c 100644 --- a/pkcs7/src/signed_data_content.rs +++ b/pkcs7/src/signed_data_content.rs @@ -1,27 +1,17 @@ //! `signed-data` content type [RFC 5652 § 5](https://datatracker.ietf.org/doc/html/rfc5652#section-5) use crate::{ + algorithm_identifier_types::DigestAlgorithmIdentifiers, certificate_choices::CertificateChoices, cms_version::CmsVersion, encapsulated_content_info::EncapsulatedContentInfo, revocation_info_choices::RevocationInfoChoices, signer_info::SignerInfos, }; use der::{asn1::SetOfVec, Sequence}; -use spki::AlgorithmIdentifierRef; - -/// ```text -/// DigestAlgorithmIdentifier ::= AlgorithmIdentifier -/// ``` -type DigestAlgorithmIdentifier<'a> = AlgorithmIdentifierRef<'a>; - -/// ```text -/// DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier -/// ``` -type DigestAlgorithmIdentifiers<'a> = SetOfVec>; /// ```text /// CertificateSet ::= SET OF CertificateChoices /// ``` -type CertificateSet<'a> = SetOfVec>; +pub type CertificateSet<'a> = SetOfVec>; /// Signed-data content type [RFC 5652 § 5](https://datatracker.ietf.org/doc/html/rfc5652#section-5) /// diff --git a/pkcs7/src/signer_info.rs b/pkcs7/src/signer_info.rs index 3f71769d6..fc53f09f1 100644 --- a/pkcs7/src/signer_info.rs +++ b/pkcs7/src/signer_info.rs @@ -1,25 +1,17 @@ //! `SignerInfo` data type [RFC 5652 § 5.3](https://datatracker.ietf.org/doc/html/rfc5652#section-5.3) -use crate::cms_version::CmsVersion; +use crate::{ + algorithm_identifier_types::{DigestAlgorithmIdentifier, SignatureAlgorithmIdentifier}, + cms_version::CmsVersion, +}; use der::{ asn1::{OctetStringRef, SetOfVec}, Choice, Sequence, ValueOrd, }; -use spki::AlgorithmIdentifierRef; use x509_cert::{ attr::Attribute, ext::pkix::SubjectKeyIdentifier, name::Name, serial_number::SerialNumber, }; -/// ```text -/// DigestAlgorithmIdentifier ::= AlgorithmIdentifier -/// ``` -type DigestAlgorithmIdentifier<'a> = AlgorithmIdentifierRef<'a>; - -/// ```text -/// SignatureAlgorithmIdentifier ::= AlgorithmIdentifier -/// ``` -type SignatureAlgorithmIdentifier<'a> = AlgorithmIdentifierRef<'a>; - /// ```text /// SignedAttributes ::= SET SIZE (1..MAX) OF Attribute /// ``` diff --git a/pkcs7/tests/content_tests.rs b/pkcs7/tests/content_tests.rs index 195c7f1ac..2e1483d9c 100644 --- a/pkcs7/tests/content_tests.rs +++ b/pkcs7/tests/content_tests.rs @@ -2,9 +2,13 @@ use der::{ asn1::{ObjectIdentifier, OctetStringRef, SequenceRef}, - Decode, SliceWriter, + Decode, DecodePem, SliceWriter, }; use hex_literal::hex; +use pkcs7::algorithm_identifier_types::{DigestAlgorithmIdentifier, DigestAlgorithmIdentifiers}; +use pkcs7::certificate_choices::CertificateChoices; +use pkcs7::signed_data_content::CertificateSet; +use pkcs7::signer_info::SignerInfos; use pkcs7::{ cms_version::CmsVersion, encapsulated_content_info::EncapsulatedContentInfo, encrypted_data_content::EncryptedDataContent, enveloped_data_content::EncryptedContentInfo, @@ -139,6 +143,9 @@ fn decode_signed_scep_example() { } _ => panic!("expected ContentInfo::SignedData(Some(_))"), } + + let mut buf = vec![0u8; bytes.len()]; + encode_content_info(&content, &mut buf); } // TODO(tarcieri): BER support @@ -186,3 +193,54 @@ fn decode_signed_der() { 10034 ); } + +#[test] +fn create_pkcs7_signed_data() { + // {iso(1) identified-organization(3) thawte(101) id-Ed25519(112)} + const OID_ED25519: &str = "1.3.101.112"; + // {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-7(7) signedData(2)} + const OID_PKCS7_SIGNED_DATA: &str = "1.2.840.113549.1.7.2"; + + let digest_algorithms = { + let digest_algorithm = DigestAlgorithmIdentifier { + oid: der::asn1::ObjectIdentifier::new(OID_ED25519).unwrap(), + parameters: None, + }; + let mut digest_algorithms = DigestAlgorithmIdentifiers::new(); + digest_algorithms.add(digest_algorithm).unwrap(); + digest_algorithms + }; + + let encap_content_info = { + EncapsulatedContentInfo { + e_content_type: der::asn1::ObjectIdentifier::new(OID_PKCS7_SIGNED_DATA).unwrap(), + e_content: None, + } + }; + + let certificates = { + let cert_pem = include_bytes!("../tests/examples/cert.pem"); + let cert: x509_cert::Certificate = x509_cert::Certificate::from_pem(cert_pem).unwrap(); + let cert_choice = CertificateChoices::Certificate(cert); + let mut certs = CertificateSet::new(); + certs.add(cert_choice).unwrap(); + Some(certs) + }; + + fn get_signer_infos<'a>() -> SignerInfos<'a> { + let signer_infos = SignerInfos::new(); + signer_infos + } + + let content_info = ContentInfo::SignedData(SignedDataContent { + version: pkcs7::cms_version::CmsVersion::V1, + digest_algorithms, + encap_content_info, + certificates, + crls: None, + signer_infos: get_signer_infos(), + }); + + let mut buf = vec![0u8; 10000]; // buffer length must be guessed in advance :| + encode_content_info(&content_info, &mut buf); +}