rasn_cms/
lib.rs

1#![doc = include_str!("../README.md")]
2#![no_std]
3
4extern crate alloc;
5
6pub mod algorithms;
7pub mod authenticode;
8pub mod firmware_wrapper;
9pub mod pkcs7_compat;
10pub mod tsp;
11
12use alloc::boxed::Box;
13use rasn::error::InnerSubtypeConstraintError;
14use rasn::prelude::*;
15pub use rasn_pkix::{
16    AlgorithmIdentifier, Attribute, Certificate, CertificateList, CertificateSerialNumber, Name,
17    SubjectKeyIdentifier,
18};
19
20/// OID of top-level CMS ContentInfo
21pub const CONTENT_INFO: &Oid = Oid::ISO_MEMBER_BODY_US_RSADSI_PKCS9_SMIME_CT_CONTENTINFO;
22
23/// OID of CMS ContentType
24pub const CONTENT_TYPE: &Oid = Oid::ISO_MEMBER_BODY_US_RSADSI_PKCS9_CONTENT_TYPE;
25
26/// OID of MessageDigest
27pub const MESSAGE_DIGEST: &Oid = Oid::ISO_MEMBER_BODY_US_RSADSI_PKCS9_MESSAGE_DIGEST;
28
29/// OID of SigningTime
30pub const SIGNING_TIME: &Oid = Oid::ISO_MEMBER_BODY_US_RSADSI_PKCS9_SIGNING_TIME;
31
32/// OID of CounterSignature
33pub const COUNTER_SIGNATURE: &Oid = Oid::ISO_MEMBER_BODY_US_RSADSI_PKCS9_COUNTER_SIGNATURE;
34
35// content types
36/// OID of Data content type
37pub const CONTENT_DATA: &Oid = Oid::ISO_MEMBER_BODY_US_RSADSI_PKCS7_DATA;
38
39/// OID of SignedData content type
40pub const CONTENT_SIGNED_DATA: &Oid = Oid::ISO_MEMBER_BODY_US_RSADSI_PKCS7_SIGNED_DATA;
41
42/// OID of EnvelopedData content type
43pub const CONTENT_ENVELOPED_DATA: &Oid = Oid::ISO_MEMBER_BODY_US_RSADSI_PKCS7_ENVELOPED_DATA;
44
45/// OID of DigestedData content type
46pub const CONTENT_DIGESTED_DATA: &Oid = Oid::ISO_MEMBER_BODY_US_RSADSI_PKCS7_DIGESTED_DATA;
47
48/// OID of EncryptedData content type
49pub const CONTENT_ENCRYPTED_DATA: &Oid = Oid::ISO_MEMBER_BODY_US_RSADSI_PKCS7_ENCRYPTED_DATA;
50
51/// OID of AuthenticatedData content type
52pub const CONTENT_AUTHENTICATED_DATA: &Oid =
53    Oid::ISO_MEMBER_BODY_US_RSADSI_PKCS9_SMIME_CT_AUTHENTICATED_DATA;
54
55pub type CmsVersion = Integer;
56pub type ContentType = ObjectIdentifier;
57pub type DigestAlgorithmIdentifier = AlgorithmIdentifier;
58pub type DigestAlgorithmIdentifiers = SetOf<DigestAlgorithmIdentifier>;
59pub type SignatureAlgorithmIdentifier = AlgorithmIdentifier;
60pub type ContentEncryptionAlgorithmIdentifier = AlgorithmIdentifier;
61pub type KeyEncryptionAlgorithmIdentifier = AlgorithmIdentifier;
62pub type KeyDerivationAlgorithmIdentifier = AlgorithmIdentifier;
63pub type MessageAuthenticationCodeAlgorithm = AlgorithmIdentifier;
64pub type CertificateSet = SetOf<CertificateChoices>;
65pub type RevocationInfoChoices = SetOf<RevocationInfoChoice>;
66pub type SignerInfos = SetOf<SignerInfo>;
67pub type SignedAttributes = SetOf<Attribute>;
68pub type UnsignedAttributes = SetOf<Attribute>;
69pub type SignatureValue = OctetString;
70pub type RecipientInfos = SetOf<RecipientInfo>;
71pub type UnprotectedAttributes = SetOf<Attribute>;
72pub type EncryptedContent = OctetString;
73pub type EncryptedKey = OctetString;
74pub type RecipientEncryptedKeys = SequenceOf<RecipientEncryptedKey>;
75pub type UserKeyingMaterial = OctetString;
76pub type Digest = OctetString;
77pub type AuthAttributes = SetOf<Attribute>;
78pub type UnauthAttributes = SetOf<Attribute>;
79pub type MessageAuthenticationCode = OctetString;
80pub type Signature = BitString;
81
82#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
83pub struct AuthEnvelopedData {
84    pub version: CmsVersion,
85    #[rasn(tag(0))]
86    pub originator_info: Option<OriginatorInfo>,
87    pub recipient_infos: RecipientInfos,
88    pub auth_encrypted_content_info: EncryptedContentInfo,
89    #[rasn(tag(1))]
90    pub auth_attrs: Option<AuthAttributes>,
91    pub mac: MessageAuthenticationCode,
92    #[rasn(tag(2))]
93    pub unauth_attrs: Option<UnauthAttributes>,
94}
95
96/// ContentInfo encapsulates a single identified content type, and the
97/// identified type may provide further encapsulation.
98#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
99pub struct ContentInfo {
100    pub content_type: ContentType,
101    #[rasn(tag(explicit(0)))]
102    pub content: Any,
103}
104
105/// SignedData represents a signed-data content type
106#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
107pub struct SignedData {
108    pub version: CmsVersion,
109    pub digest_algorithms: DigestAlgorithmIdentifiers,
110    pub encap_content_info: EncapsulatedContentInfo,
111    #[rasn(tag(0))]
112    pub certificates: Option<CertificateSet>,
113    #[rasn(tag(1))]
114    pub crls: Option<RevocationInfoChoices>,
115    pub signer_infos: SignerInfos,
116}
117
118/// EnvelopedData represents an enveloped-data content type
119#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
120pub struct EnvelopedData {
121    pub version: CmsVersion,
122    #[rasn(tag(0))]
123    pub originator_info: Option<OriginatorInfo>,
124    pub recipient_infos: RecipientInfos,
125    pub encrypted_content_info: EncryptedContentInfo,
126    #[rasn(tag(1))]
127    pub unprotected_attrs: Option<UnprotectedAttributes>,
128}
129
130/// DigestedData represents a digested-data content type
131#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
132pub struct DigestedData {
133    pub version: CmsVersion,
134    pub digest_algorithm: DigestAlgorithmIdentifier,
135    pub encap_content_info: EncapsulatedContentInfo,
136    pub digest: Digest,
137}
138
139/// EncryptedData represents an encrypted-data content type
140#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
141pub struct EncryptedData {
142    pub version: CmsVersion,
143    pub encrypted_content_info: EncryptedContentInfo,
144    #[rasn(tag(1))]
145    pub unprotected_attrs: Option<UnprotectedAttributes>,
146}
147
148/// AuthenticatedData represents an authenticated-data content type
149#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
150pub struct AuthenticatedData {
151    pub version: CmsVersion,
152    #[rasn(tag(0))]
153    pub originator_info: Option<OriginatorInfo>,
154    pub recipient_infos: RecipientInfos,
155    pub mac_algorithm: MessageAuthenticationCodeAlgorithm,
156    #[rasn(tag(1))]
157    pub digest_algorithm: Option<DigestAlgorithmIdentifier>,
158    pub encap_content_info: EncapsulatedContentInfo,
159    #[rasn(tag(2))]
160    pub auth_attrs: Option<AuthAttributes>,
161    pub mac: MessageAuthenticationCode,
162    #[rasn(tag(3))]
163    pub unauth_attrs: Option<UnauthAttributes>,
164}
165
166/// The `CertificateChoices`` type contains options for certificate formats.
167///
168/// It gives either a PKCS #6 extended
169/// certificate, an X.509 certificate, a version 1 X.509
170///  attribute certificate (ACv1) [X.509-97], a version 2 X.509 attribute
171/// certificate (ACv2) [X.509-00], or any other certificate format.
172#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
173#[rasn(choice)]
174pub enum CertificateChoices {
175    Certificate(Box<Certificate>),
176    #[rasn(tag(0))]
177    ExtendedCertificate(Box<ExtendedCertificate>),
178    #[rasn(tag(2))]
179    V2AttributeCertificate(Box<rasn_pkix::attribute_certificate::AttributeCertificate>),
180    #[rasn(tag(3))]
181    Other(OtherCertificateFormat),
182}
183
184/// OtherCertificateFormat represents a custom certificate format
185#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
186pub struct OtherCertificateFormat {
187    pub other_cert_format: ObjectIdentifier,
188    pub other_cert: Any,
189}
190
191/// The RevocationInfoChoice type gives a revocation status information alternatives.
192///
193/// It is intended that the set contain
194/// information sufficient to determine whether the certificates and
195/// attribute certificates with which the set is associated are revoked.
196#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
197#[rasn(choice)]
198pub enum RevocationInfoChoice {
199    Crl(CertificateList),
200    #[rasn(tag(1))]
201    Other(OtherRevocationInfoFormat),
202}
203
204/// The OtherRevocationInfoFormat alternative is provided to support any
205/// other revocation information format without further modifications to
206/// the CMS.
207#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
208pub struct OtherRevocationInfoFormat {
209    pub other_rev_info_format: ObjectIdentifier,
210    pub other_rev_info: Any,
211}
212
213/// The content is represented in the type EncapsulatedContentInfo
214#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
215pub struct EncapsulatedContentInfo {
216    pub content_type: ContentType,
217    #[rasn(tag(explicit(0)))]
218    pub content: Option<OctetString>,
219}
220
221/// Per-signer information is represented in the type SignerInfo
222#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
223pub struct SignerInfo {
224    pub version: CmsVersion,
225    pub sid: SignerIdentifier,
226    pub digest_algorithm: DigestAlgorithmIdentifier,
227    #[rasn(tag(0))]
228    pub signed_attrs: Option<SignedAttributes>,
229    pub signature_algorithm: SignatureAlgorithmIdentifier,
230    pub signature: SignatureValue,
231    #[rasn(tag(1))]
232    pub unsigned_attrs: Option<UnsignedAttributes>,
233}
234
235/// SignerIdentifier data type represents the choice of signer identifications
236#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
237#[rasn(choice)]
238pub enum SignerIdentifier {
239    IssuerAndSerialNumber(IssuerAndSerialNumber),
240    #[rasn(tag(0))]
241    SubjectKeyIdentifier(SubjectKeyIdentifier),
242}
243
244/// The IssuerAndSerialNumber type identifies a certificate, and thereby
245/// an entity and a public key, by the distinguished name of the
246/// certificate issuer and an issuer-specific certificate serial number.
247#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
248pub struct IssuerAndSerialNumber {
249    pub issuer: Name,
250    pub serial_number: CertificateSerialNumber,
251}
252
253/// OriginatorInfo optionally provides information about the
254/// originator. It is present only if required by the key management algorithm.
255#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
256pub struct OriginatorInfo {
257    #[rasn(tag(0))]
258    pub certs: Option<CertificateSet>,
259    #[rasn(tag(1))]
260    pub crls: Option<RevocationInfoChoices>,
261}
262
263/// EncryptedContentInfo is the encrypted content information
264#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
265pub struct EncryptedContentInfo {
266    pub content_type: ContentType,
267    pub content_encryption_algorithm: ContentEncryptionAlgorithmIdentifier,
268    #[rasn(tag(0))]
269    pub encrypted_content: Option<EncryptedContent>,
270}
271
272/// RecipientInfo is a per-recipient information.
273#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
274#[rasn(choice)]
275pub enum RecipientInfo {
276    KeyTransRecipientInfo(KeyTransRecipientInfo),
277    #[rasn(tag(1))]
278    KeyAgreeRecipientInfo(KeyAgreeRecipientInfo),
279    #[rasn(tag(2))]
280    KekRecipientInfo(KekRecipientInfo),
281    #[rasn(tag(3))]
282    PasswordRecipientInfo(PasswordRecipientInfo),
283    #[rasn(tag(4))]
284    OtherRecipientInfo(OtherRecipientInfo),
285}
286
287/// Per-recipient information using key transport is represented in the
288/// type KeyTransRecipientInfo.  Each instance of KeyTransRecipientInfo
289/// transfers the content-encryption key to one recipient.
290#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
291pub struct KeyTransRecipientInfo {
292    pub version: CmsVersion,
293    pub rid: RecipientIdentifier,
294    pub key_encryption_algorithm: KeyEncryptionAlgorithmIdentifier,
295    pub encrypted_key: EncryptedKey,
296}
297
298/// RecipientIdentifier specifies the recipient's certificate or key that was used by
299/// the sender to protect the content-encryption key.
300#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
301#[rasn(choice)]
302pub enum RecipientIdentifier {
303    IssuerAndSerialNumber(IssuerAndSerialNumber),
304    #[rasn(tag(0))]
305    SubjectKeyIdentifier(SubjectKeyIdentifier),
306}
307
308/// Recipient information using key agreement is represented in the type
309/// KeyAgreeRecipientInfo.
310#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
311pub struct KeyAgreeRecipientInfo {
312    pub version: CmsVersion,
313    #[rasn(tag(explicit(0)))]
314    pub originator: OriginatorIdentifierOrKey,
315    #[rasn(tag(explicit(1)))]
316    pub user_keying_material: Option<UserKeyingMaterial>,
317    pub key_encryption_algorithm: KeyEncryptionAlgorithmIdentifier,
318    pub recipient_encrypted_keys: RecipientEncryptedKeys,
319}
320
321/// RecipientEncryptedKey includes a recipient identifier and
322/// encrypted key for one or more recipients.
323#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
324pub struct RecipientEncryptedKey {
325    pub key_agree_recipient_identifier: KeyAgreeRecipientIdentifier,
326    pub encrypted_key: EncryptedKey,
327}
328
329/// KeyAgreeRecipientIdentifier is a CHOICE with two alternatives.
330///
331/// Alternatives specify the recipient's certificate, and thereby the
332/// recipient's public key, that was used by the sender to generate a
333/// pairwise key-encryption key.
334#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
335#[rasn(choice)]
336pub enum KeyAgreeRecipientIdentifier {
337    IssuerAndSerialNumber(IssuerAndSerialNumber),
338    #[rasn(tag(0))]
339    RecipientKeyIdentifier(RecipientKeyIdentifier),
340}
341
342/// RecipientKeyIdentifier identifies the recipient's key.
343#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
344pub struct RecipientKeyIdentifier {
345    pub subject_key_identifier: SubjectKeyIdentifier,
346    pub date: Option<GeneralizedTime>,
347    pub other: Option<OtherKeyAttribute>,
348}
349
350/// Additional information used by the recipient to determine
351/// the key-encryption key used by the sender.
352#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
353pub struct OtherKeyAttribute {
354    pub key_attr_id: ObjectIdentifier,
355    pub key_attr: Option<Any>,
356}
357
358/// OriginatorIdentifierOrKey is a CHOICE with three alternatives specifying the
359/// sender's key agreement public key.
360#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
361#[rasn(choice)]
362pub enum OriginatorIdentifierOrKey {
363    IssuerAndSerialNumber(IssuerAndSerialNumber),
364    #[rasn(tag(0))]
365    SubjectKeyIdentifier(SubjectKeyIdentifier),
366    #[rasn(tag(1))]
367    OriginatorPublicKey(OriginatorPublicKey),
368}
369
370/// The OriginatorPublicKey alternative
371/// includes the algorithm identifier and sender's key agreement
372/// public key.
373#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
374pub struct OriginatorPublicKey {
375    pub algorithm: AlgorithmIdentifier,
376    pub public_key: BitString,
377}
378
379/// Recipient information using previously distributed symmetric keys is
380/// represented in the type KEKRecipientInfo.
381#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
382pub struct KekRecipientInfo {
383    pub version: CmsVersion,
384    pub kek_id: KekIdentifier,
385    pub key_encryption_algorithm: KeyEncryptionAlgorithmIdentifier,
386    pub encrypted_key: EncryptedKey,
387}
388
389/// KekIdentifier specifies a symmetric key-encryption key that was previously
390/// distributed to the sender and one or more recipients.
391#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
392pub struct KekIdentifier {
393    pub key_identifier: OctetString,
394    pub date: Option<GeneralizedTime>,
395    pub other: Option<OtherKeyAttribute>,
396}
397
398/// Recipient information using a password or shared secret value is
399/// represented in the type PasswordRecipientInfo.
400#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
401pub struct PasswordRecipientInfo {
402    pub version: CmsVersion,
403    #[rasn(tag(0))]
404    pub key_derivation_algorithm: Option<KeyDerivationAlgorithmIdentifier>,
405    pub key_encryption_algorithm: KeyEncryptionAlgorithmIdentifier,
406    pub encrypted_eey: EncryptedKey,
407}
408
409/// Recipient information for additional key management techniques are
410/// represented in the type OtherRecipientInfo.
411#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
412pub struct OtherRecipientInfo {
413    pub ori_type: ObjectIdentifier,
414    pub ori_value: Any,
415}
416
417#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
418#[rasn(choice)]
419pub enum ExtendedCertificateOrCertificate {
420    Certificate(Certificate),
421    #[rasn(tag(0))]
422    ExtendedCertificate(ExtendedCertificate),
423}
424
425#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
426pub struct ExtendedCertificate {
427    pub extended_certificate_info: ExtendedCertificateInfo,
428    pub signature_algorithm: SignatureAlgorithmIdentifier,
429    pub signature: Signature,
430}
431
432#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, Hash)]
433pub struct ExtendedCertificateInfo {
434    pub version: CmsVersion,
435    pub certificate: Certificate,
436    pub attributes: UnauthAttributes,
437}
438
439/** CMSAlgorithmProtection
440
441[RFC 6211](https://www.rfc-editor.org/rfc/rfc6211#section-2):
442
443```text
444   aa-cmsAlgorithmProtection ATTRIBUTE ::= {
445       TYPE CMSAlgorithmProtection
446       IDENTIFIED BY { id-aa-CMSAlgorithmProtection }
447   }
448
449   id-aa-CMSAlgorithmProtection OBJECT IDENTIFIER ::= { iso(1)
450        member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9) 52 }
451
452   CMSAlgorithmProtection ::= SEQUENCE {
453       digestAlgorithm         DigestAlgorithmIdentifier,
454       signatureAlgorithm  [1] SignatureAlgorithmIdentifier OPTIONAL,
455       macAlgorithm        [2] MessageAuthenticationCodeAlgorithm
456                                        OPTIONAL
457   }
458   (WITH COMPONENTS { signatureAlgorithm PRESENT,
459                      macAlgorithm ABSENT } |
460    WITH COMPONENTS { signatureAlgorithm ABSENT,
461                      macAlgorithm PRESENT })
462```
463
464Please note that `signatureAlgorithm` and `macAlgorithm` are mutually exclusive.
465*/
466#[allow(missing_docs)]
467#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
468pub struct CmsAlgorithmProtection {
469    pub digest_algorithm: DigestAlgorithmIdentifier,
470    #[rasn(tag(1))]
471    pub signature_algorithm: Option<SignatureAlgorithmIdentifier>,
472    #[rasn(tag(2))]
473    pub mac_algorithm: Option<MessageAuthenticationCodeAlgorithm>,
474}
475
476impl CmsAlgorithmProtection {
477    pub fn with_signature_algorithm(
478        digest_algorithm: DigestAlgorithmIdentifier,
479        signature_algorithm: SignatureAlgorithmIdentifier,
480    ) -> Result<Self, InnerSubtypeConstraintError> {
481        Self {
482            digest_algorithm,
483            signature_algorithm: Some(signature_algorithm),
484            mac_algorithm: None,
485        }
486        .validate_components()
487    }
488
489    pub fn with_mac_algorithm(
490        digest_algorithm: DigestAlgorithmIdentifier,
491        mac_algorithm: MessageAuthenticationCodeAlgorithm,
492    ) -> Result<Self, InnerSubtypeConstraintError> {
493        Self {
494            digest_algorithm,
495            signature_algorithm: None,
496            mac_algorithm: Some(mac_algorithm),
497        }
498        .validate_components()
499    }
500}
501
502impl InnerSubtypeConstraint for CmsAlgorithmProtection {
503    fn validate_and_decode_containing(
504        self,
505        _: Option<rasn::Codec>,
506    ) -> Result<Self, rasn::error::InnerSubtypeConstraintError> {
507        if self.signature_algorithm.is_some() != self.mac_algorithm.is_some() {
508            return Err(InnerSubtypeConstraintError::MissingRequiredComponent {
509                component_path: "CmsAlgorithmProtection",
510                components: &["digest_algorithm", "signature_algorithm", "mac_algorithm"],
511            });
512        }
513        Ok(self)
514    }
515}