1#![cfg(feature = "builder")]
2
3use crate::cert::CertificateChoices;
6use crate::content_info::{CmsVersion, ContentInfo};
7use crate::enveloped_data::{
8 EncryptedContentInfo, EncryptedKey, EnvelopedData, KekIdentifier, KeyTransRecipientInfo,
9 OriginatorIdentifierOrKey, OriginatorInfo, RecipientIdentifier, RecipientInfo, RecipientInfos,
10 UserKeyingMaterial,
11};
12use crate::revocation::{RevocationInfoChoice, RevocationInfoChoices};
13use crate::signed_data::{
14 CertificateSet, DigestAlgorithmIdentifiers, EncapsulatedContentInfo, SignatureValue,
15 SignedAttributes, SignedData, SignerIdentifier, SignerInfo, SignerInfos, UnsignedAttributes,
16};
17use aes::{Aes128, Aes192, Aes256};
18use alloc::borrow::ToOwned;
19use alloc::boxed::Box;
20use alloc::string::String;
21use alloc::vec::Vec;
22use cipher::block_padding::Pkcs7;
23use cipher::rand_core::{CryptoRng, CryptoRngCore, RngCore};
24use cipher::BlockEncryptMut;
25use cipher::{Key, KeyIvInit, KeySizeUser};
26use const_oid::ObjectIdentifier;
27use core::cmp::Ordering;
28use core::fmt;
29use der::asn1::{BitString, OctetStringRef, SetOfVec};
30use der::oid::db::DB;
31use der::Tag::OctetString;
32use der::{Any, AnyRef, DateTime, Decode, Encode, ErrorKind, Tag};
33use digest::Digest;
34use rsa::Pkcs1v15Encrypt;
35use sha2::digest;
36use signature::digest::DynDigest;
37use signature::{Keypair, Signer};
38use spki::{AlgorithmIdentifierOwned, DynSignatureAlgorithmIdentifier, SignatureBitStringEncoding};
39use std::time::SystemTime;
40use std::vec;
41use x509_cert::attr::{Attribute, AttributeValue, Attributes};
42use x509_cert::builder::Builder;
43use zeroize::Zeroize;
44
45#[derive(Debug)]
47#[non_exhaustive]
48pub enum Error {
49 Asn1(der::Error),
51
52 PublicKey(spki::Error),
54
55 Signature(signature::Error),
57
58 Builder(String),
60}
61
62impl fmt::Display for Error {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 match self {
65 Error::Asn1(err) => write!(f, "ASN.1 error: {}", err),
66 Error::PublicKey(err) => write!(f, "public key error: {}", err),
67 Error::Signature(err) => write!(f, "signature error: {}", err),
68 Error::Builder(message) => write!(f, "builder error: {message}"),
69 }
70 }
71}
72
73impl From<der::Error> for Error {
74 fn from(err: der::Error) -> Error {
75 Error::Asn1(err)
76 }
77}
78
79impl From<spki::Error> for Error {
80 fn from(err: spki::Error) -> Error {
81 Error::PublicKey(err)
82 }
83}
84
85impl From<signature::Error> for Error {
86 fn from(err: signature::Error) -> Error {
87 Error::Signature(err)
88 }
89}
90
91type Result<T> = core::result::Result<T, Error>;
92
93pub struct SignerInfoBuilder<'s, S> {
100 signer: &'s S,
101 sid: SignerIdentifier,
102 digest_algorithm: AlgorithmIdentifierOwned,
103 signed_attributes: Option<Vec<Attribute>>,
104 unsigned_attributes: Option<Vec<Attribute>>,
105 encapsulated_content_info: &'s EncapsulatedContentInfo,
106 external_message_digest: Option<&'s [u8]>,
107}
108
109impl<'s, S> SignerInfoBuilder<'s, S>
110where
111 S: Keypair + DynSignatureAlgorithmIdentifier,
112{
113 pub fn new(
119 signer: &'s S,
120 sid: SignerIdentifier,
121 digest_algorithm: AlgorithmIdentifierOwned,
122 encapsulated_content_info: &'s EncapsulatedContentInfo,
123 external_message_digest: Option<&'s [u8]>,
124 ) -> Result<Self> {
125 Ok(SignerInfoBuilder {
126 signer,
127 sid,
128 digest_algorithm,
129 signed_attributes: None,
130 unsigned_attributes: None,
131 encapsulated_content_info,
132 external_message_digest,
133 })
134 }
135
136 pub fn add_signed_attribute(&mut self, signed_attribute: Attribute) -> Result<&mut Self> {
139 if let Some(signed_attributes) = &mut self.signed_attributes {
140 signed_attributes.push(signed_attribute);
141 } else {
142 self.signed_attributes = Some(vec![signed_attribute]);
143 }
144 Ok(self)
145 }
146
147 pub fn add_unsigned_attribute(&mut self, unsigned_attribute: Attribute) -> Result<&mut Self> {
149 if let Some(unsigned_attributes) = &mut self.unsigned_attributes {
150 unsigned_attributes.push(unsigned_attribute);
151 } else {
152 self.unsigned_attributes = Some(vec![unsigned_attribute]);
153 }
154 Ok(self)
155 }
156
157 pub fn version(&self) -> CmsVersion {
163 match self.sid {
164 SignerIdentifier::IssuerAndSerialNumber(_) => CmsVersion::V1,
165 SignerIdentifier::SubjectKeyIdentifier(_) => CmsVersion::V3,
166 }
167 }
168}
169
170impl<'s, S> Builder for SignerInfoBuilder<'s, S>
171where
172 S: Keypair + DynSignatureAlgorithmIdentifier,
173{
174 type Signer = S;
175 type Output = SignerInfo;
176
177 fn signer(&self) -> &Self::Signer {
178 self.signer
179 }
180
181 fn finalize(&mut self) -> der::Result<Vec<u8>> {
187 let message_digest = match self.external_message_digest {
188 Some(external_content_digest) => {
189 if self.encapsulated_content_info.econtent.is_some() {
190 return Err(der::Error::from(ErrorKind::Failed));
192 }
193 Some(external_content_digest.to_vec())
194 }
195 None => match &self.encapsulated_content_info.econtent {
196 None => {
197 None
200 }
201 Some(content) => {
202 let mut hasher = get_hasher(&self.digest_algorithm).ok_or_else(|| {
203 der::Error::from(ErrorKind::Failed)
205 })?;
206 let content_value = content.value();
210 hasher.update(content_value);
211 Some(hasher.finalize_reset().to_vec())
212 }
213 },
214 };
215
216 if self.signed_attributes.is_none() {
218 self.signed_attributes = Some(vec![]);
219 }
220
221 let signed_attributes = self
222 .signed_attributes
223 .as_mut()
224 .expect("Signed attributes must be present.");
225
226 if let Some(message_digest) = message_digest {
227 signed_attributes.push(
229 create_message_digest_attribute(&message_digest)
230 .map_err(|_| der::Error::from(ErrorKind::Failed))?,
231 );
232
233 let econtent_type = self.encapsulated_content_info.econtent_type;
241 let signed_attributes_content_type = signed_attributes.iter().find(|attr| {
242 attr.oid.cmp(&const_oid::db::rfc5911::ID_CONTENT_TYPE) == Ordering::Equal
243 });
244 if let Some(signed_attributes_content_type) = signed_attributes_content_type {
245 if signed_attributes_content_type.oid != econtent_type {
247 return Err(der::Error::from(ErrorKind::Failed));
249 }
250 } else {
251 signed_attributes.push(
252 create_content_type_attribute(econtent_type)
253 .map_err(|_| der::Error::from(ErrorKind::Failed))?,
254 );
255 }
256 }
257
258 let signed_attributes = SignedAttributes::try_from(signed_attributes.to_owned())
260 .map_err(|_| der::Error::from(ErrorKind::Failed))?;
261 let mut signed_attributes_der = Vec::new();
262 signed_attributes.encode_to_vec(&mut signed_attributes_der)?;
263
264 Ok(signed_attributes_der)
265 }
266
267 fn assemble(
268 self,
269 signature: BitString,
270 ) -> core::result::Result<Self::Output, x509_cert::builder::Error> {
271 let signed_attrs = self.signed_attributes.as_ref().map(|signed_attributes| {
272 SignedAttributes::try_from(signed_attributes.to_owned()).unwrap()
273 });
274 let unsigned_attrs = self
275 .unsigned_attributes
276 .as_ref()
277 .map(|unsigned_attributes| {
278 UnsignedAttributes::try_from(unsigned_attributes.to_owned()).unwrap()
279 });
280
281 let signature_value =
282 SignatureValue::new(signature.raw_bytes()).map_err(x509_cert::builder::Error::from)?;
283
284 let signature_algorithm = self.signer.signature_algorithm_identifier()?;
285
286 Ok(SignerInfo {
287 version: self.version(),
288 sid: self.sid.clone(),
289 digest_alg: self.digest_algorithm,
290 signed_attrs,
291 signature_algorithm,
292 signature: signature_value,
293 unsigned_attrs,
294 })
295 }
296}
297
298pub struct SignedDataBuilder<'s> {
300 digest_algorithms: Vec<AlgorithmIdentifierOwned>,
301 encapsulated_content_info: &'s EncapsulatedContentInfo,
302 certificates: Option<Vec<CertificateChoices>>,
303 crls: Option<Vec<RevocationInfoChoice>>,
304 signer_infos: Vec<SignerInfo>,
305}
306
307impl<'s> SignedDataBuilder<'s> {
308 pub fn new(encapsulated_content_info: &'s EncapsulatedContentInfo) -> SignedDataBuilder<'s> {
310 Self {
311 digest_algorithms: Vec::new(),
312 encapsulated_content_info,
313 certificates: None,
314 crls: None,
315 signer_infos: Vec::new(),
316 }
317 }
318
319 pub fn add_digest_algorithm(
328 &mut self,
329 digest_algorithm: AlgorithmIdentifierOwned,
330 ) -> Result<&mut Self> {
331 self.digest_algorithms.push(digest_algorithm);
332 Ok(self)
333 }
334
335 pub fn add_certificate(&mut self, certificate: CertificateChoices) -> Result<&mut Self> {
350 if self.certificates.is_none() {
351 self.certificates = Some(Vec::new());
352 }
353 if let Some(certificates) = &mut self.certificates {
354 certificates.push(certificate);
355 }
356 Ok(self)
357 }
358
359 pub fn add_crl(&mut self, crl: RevocationInfoChoice) -> Result<&mut Self> {
369 if self.crls.is_none() {
370 self.crls = Some(Vec::new());
371 }
372 if let Some(crls) = &mut self.crls {
373 crls.push(crl);
374 }
375 Ok(self)
376 }
377
378 pub fn add_signer_info<S, Signature>(
381 &mut self,
382 signer_info_builder: SignerInfoBuilder<'_, S>,
383 ) -> Result<&mut Self>
384 where
385 S: Keypair + DynSignatureAlgorithmIdentifier,
386 S: Signer<Signature>,
387 Signature: SignatureBitStringEncoding,
388 {
389 let signer_info = signer_info_builder
390 .build::<Signature>()
391 .map_err(|_| der::Error::from(ErrorKind::Failed))?;
392 self.signer_infos.push(signer_info);
393
394 Ok(self)
395 }
396
397 pub fn build(&mut self) -> Result<ContentInfo> {
399 let digest_algorithms =
400 DigestAlgorithmIdentifiers::try_from(self.digest_algorithms.to_owned()).unwrap();
401
402 let encap_content_info = self.encapsulated_content_info.clone();
403
404 let certificates = self
405 .certificates
406 .as_mut()
407 .map(|certificates| CertificateSet::try_from(certificates.to_owned()).unwrap());
408
409 let crls = self
410 .crls
411 .as_mut()
412 .map(|crls| RevocationInfoChoices::try_from(crls.to_owned()).unwrap());
413
414 let signer_infos = SignerInfos::try_from(self.signer_infos.clone()).unwrap();
415
416 let signed_data = SignedData {
417 version: self.calculate_version(),
418 digest_algorithms,
419 encap_content_info,
420 certificates,
421 crls,
422 signer_infos,
423 };
424
425 let signed_data_der = signed_data.to_der()?;
426 let content = AnyRef::try_from(signed_data_der.as_slice())?;
427
428 let signed_data = ContentInfo {
429 content_type: const_oid::db::rfc5911::ID_SIGNED_DATA,
430 content: Any::from(content),
431 };
432
433 Ok(signed_data)
434 }
435
436 fn calculate_version(&self) -> CmsVersion {
437 let other_certificates_are_present = if let Some(certificates) = &self.certificates {
455 certificates
456 .iter()
457 .any(|certificate| matches!(certificate, CertificateChoices::Other(_)))
458 } else {
459 false
460 };
461 let v2_certificates_are_present = false;
479 let v1_certificates_are_present = false;
480 let other_crls_are_present = if let Some(crls) = &self.crls {
481 crls.iter().any(|revocation_info_choice| {
482 matches!(revocation_info_choice, RevocationInfoChoice::Other(_))
483 })
484 } else {
485 false
486 };
487 let v3_signer_infos_present = self
488 .signer_infos
489 .iter()
490 .any(|signer_info| signer_info.version == CmsVersion::V3);
491 let content_not_data =
492 self.encapsulated_content_info.econtent_type != const_oid::db::rfc5911::ID_DATA;
493
494 if other_certificates_are_present || other_crls_are_present {
495 CmsVersion::V5
496 } else if v2_certificates_are_present {
497 CmsVersion::V4
498 } else if v1_certificates_are_present || v3_signer_infos_present || content_not_data {
499 CmsVersion::V3
500 } else {
501 CmsVersion::V1
502 }
503 }
504}
505
506pub trait RecipientInfoBuilder {
509 fn recipient_info_type(&self) -> RecipientInfoType;
511
512 fn recipient_info_version(&self) -> CmsVersion;
514
515 fn build(&mut self, content_encryption_key: &[u8]) -> Result<RecipientInfo>;
518}
519
520#[derive(Clone, Debug, Eq, PartialEq)]
523pub enum RecipientInfoType {
524 Ktri,
526 Kari,
528 Kekri,
530 Pwri,
532 Ori,
534}
535
536#[derive(Clone, Debug, Eq, PartialEq)]
538pub enum KeyEncryptionInfo {
539 Rsa(rsa::RsaPublicKey),
541 }
543
544pub struct KeyTransRecipientInfoBuilder<'a, R>
547where
548 R: CryptoRngCore,
549{
550 pub rid: RecipientIdentifier,
552 pub key_encryption_info: KeyEncryptionInfo,
554 rng: &'a mut R,
556}
557
558impl<'a, R> KeyTransRecipientInfoBuilder<'a, R>
559where
560 R: CryptoRngCore,
561{
562 pub fn new(
564 rid: RecipientIdentifier,
565 key_encryption_info: KeyEncryptionInfo,
566 rng: &'a mut R,
567 ) -> Result<KeyTransRecipientInfoBuilder<'a, R>> {
568 Ok(KeyTransRecipientInfoBuilder {
569 rid,
570 key_encryption_info,
571 rng,
572 })
573 }
574}
575
576impl<'a, R> RecipientInfoBuilder for KeyTransRecipientInfoBuilder<'a, R>
577where
578 R: CryptoRngCore,
579{
580 fn recipient_info_type(&self) -> RecipientInfoType {
581 RecipientInfoType::Ktri
582 }
583
584 fn recipient_info_version(&self) -> CmsVersion {
585 match self.rid {
586 RecipientIdentifier::IssuerAndSerialNumber(_) => CmsVersion::V0,
587 RecipientIdentifier::SubjectKeyIdentifier(_) => CmsVersion::V2,
588 }
589 }
590
591 fn build(&mut self, content_encryption_key: &[u8]) -> Result<RecipientInfo> {
594 let (encrypted_key, key_enc_alg) = match &self.key_encryption_info {
596 KeyEncryptionInfo::Rsa(recipient_public_key) => (
598 recipient_public_key
599 .encrypt(self.rng, Pkcs1v15Encrypt, content_encryption_key)
600 .map_err(|_| Error::Builder(String::from("Could not encrypt key")))?,
601 AlgorithmIdentifierOwned {
602 oid: const_oid::db::rfc5912::RSA_ENCRYPTION,
603 parameters: None,
604 },
605 ),
606 };
607 let enc_key = EncryptedKey::new(encrypted_key)?;
608
609 Ok(RecipientInfo::Ktri(KeyTransRecipientInfo {
610 version: self.recipient_info_version(),
611 rid: self.rid.clone(),
612 key_enc_alg,
613 enc_key,
614 }))
615 }
616}
617
618pub struct KeyAgreeRecipientInfoBuilder {
623 pub originator: OriginatorIdentifierOrKey,
625 pub ukm: Option<UserKeyingMaterial>,
627 pub key_enc_alg: AlgorithmIdentifierOwned,
629}
630
631impl KeyAgreeRecipientInfoBuilder {
632 pub fn new(
634 originator: OriginatorIdentifierOrKey,
635 ukm: Option<UserKeyingMaterial>,
636 key_enc_alg: AlgorithmIdentifierOwned,
637 ) -> Result<KeyAgreeRecipientInfoBuilder> {
638 Ok(KeyAgreeRecipientInfoBuilder {
639 originator,
640 ukm,
641 key_enc_alg,
642 })
643 }
644}
645
646impl RecipientInfoBuilder for KeyAgreeRecipientInfoBuilder {
647 fn recipient_info_type(&self) -> RecipientInfoType {
649 RecipientInfoType::Kari
650 }
651
652 fn recipient_info_version(&self) -> CmsVersion {
654 CmsVersion::V3
655 }
656
657 fn build(&mut self, _content_encryption_key: &[u8]) -> Result<RecipientInfo> {
659 Err(Error::Builder(String::from(
660 "Building KeyAgreeRecipientInfo is not implemented, yet.",
661 )))
662 }
663}
664
665pub struct KekRecipientInfoBuilder {
669 pub kek_id: KekIdentifier,
672 pub key_enc_alg: AlgorithmIdentifierOwned,
674}
675
676impl KekRecipientInfoBuilder {
677 pub fn new(
679 kek_id: KekIdentifier,
680 key_enc_alg: AlgorithmIdentifierOwned,
681 ) -> Result<KekRecipientInfoBuilder> {
682 Ok(KekRecipientInfoBuilder {
683 kek_id,
684 key_enc_alg,
685 })
686 }
687}
688
689impl RecipientInfoBuilder for KekRecipientInfoBuilder {
690 fn recipient_info_type(&self) -> RecipientInfoType {
692 RecipientInfoType::Kekri
693 }
694
695 fn recipient_info_version(&self) -> CmsVersion {
697 CmsVersion::V4
698 }
699
700 fn build(&mut self, _content_encryption_key: &[u8]) -> Result<RecipientInfo> {
702 Err(Error::Builder(String::from(
703 "Building KekRecipientInfo is not implemented, yet.",
704 )))
705 }
706}
707
708pub struct PasswordRecipientInfoBuilder {
711 pub key_derivation_alg: Option<AlgorithmIdentifierOwned>,
716 pub key_enc_alg: AlgorithmIdentifierOwned,
718}
719
720impl PasswordRecipientInfoBuilder {
721 pub fn new(
723 key_derivation_alg: Option<AlgorithmIdentifierOwned>,
724 key_enc_alg: AlgorithmIdentifierOwned,
725 ) -> Result<PasswordRecipientInfoBuilder> {
726 Ok(PasswordRecipientInfoBuilder {
727 key_derivation_alg,
728 key_enc_alg,
729 })
730 }
731}
732
733impl RecipientInfoBuilder for PasswordRecipientInfoBuilder {
734 fn recipient_info_type(&self) -> RecipientInfoType {
736 RecipientInfoType::Pwri
737 }
738
739 fn recipient_info_version(&self) -> CmsVersion {
741 CmsVersion::V0
742 }
743
744 fn build(&mut self, _content_encryption_key: &[u8]) -> Result<RecipientInfo> {
746 Err(Error::Builder(String::from(
747 "Building PasswordRecipientInfo is not implemented, yet.",
748 )))
749 }
750}
751
752pub struct OtherRecipientInfoBuilder {
755 pub ori_type: ObjectIdentifier,
757 pub ori_value: Any,
760}
761
762impl OtherRecipientInfoBuilder {
763 pub fn new(ori_type: ObjectIdentifier, ori_value: Any) -> Result<OtherRecipientInfoBuilder> {
765 Ok(OtherRecipientInfoBuilder {
766 ori_type,
767 ori_value,
768 })
769 }
770}
771
772impl RecipientInfoBuilder for OtherRecipientInfoBuilder {
773 fn recipient_info_type(&self) -> RecipientInfoType {
775 RecipientInfoType::Ori
776 }
777
778 fn recipient_info_version(&self) -> CmsVersion {
780 panic!("Ori has no CMSVersion")
781 }
782
783 fn build(&mut self, _content_encryption_key: &[u8]) -> Result<RecipientInfo> {
785 panic!("Ori has no common build method.")
786 }
787}
788
789#[derive(Clone, Debug, Eq, PartialEq)]
791pub enum ContentEncryptionAlgorithm {
792 Aes128Cbc,
794 Aes192Cbc,
796 Aes256Cbc,
798}
799
800impl ContentEncryptionAlgorithm {
801 pub fn oid(&self) -> ObjectIdentifier {
803 match self {
804 ContentEncryptionAlgorithm::Aes128Cbc => const_oid::db::rfc5911::ID_AES_128_CBC,
805 ContentEncryptionAlgorithm::Aes192Cbc => const_oid::db::rfc5911::ID_AES_192_CBC,
806 ContentEncryptionAlgorithm::Aes256Cbc => const_oid::db::rfc5911::ID_AES_256_CBC,
807 }
808 }
809}
810
811pub struct EnvelopedDataBuilder<'c> {
813 originator_info: Option<OriginatorInfo>,
814 recipient_infos: Vec<Box<dyn RecipientInfoBuilder + 'c>>,
815 unencrypted_content: &'c [u8],
816 content_encryption_algorithm: ContentEncryptionAlgorithm,
826 unprotected_attributes: Option<Attributes>,
827}
828
829impl<'c> EnvelopedDataBuilder<'c> {
830 pub fn new(
832 originator_info: Option<OriginatorInfo>,
833 unencrypted_content: &'c [u8],
834 content_encryption_algorithm: ContentEncryptionAlgorithm,
835 unprotected_attributes: Option<Attributes>,
836 ) -> Result<EnvelopedDataBuilder<'c>> {
837 Ok(EnvelopedDataBuilder {
838 originator_info,
839 recipient_infos: Vec::new(),
840 unencrypted_content,
841 content_encryption_algorithm,
842 unprotected_attributes,
843 })
844 }
845
846 pub fn add_recipient_info(
849 &mut self,
850 recipient_info_builder: impl RecipientInfoBuilder + 'c,
851 ) -> Result<&mut Self> {
852 self.recipient_infos.push(Box::new(recipient_info_builder));
853
854 Ok(self)
855 }
856
857 pub fn build_with_rng(&mut self, rng: &mut impl CryptoRngCore) -> Result<EnvelopedData> {
860 let (encrypted_content, mut content_encryption_key, content_enc_alg) = encrypt_data(
865 self.unencrypted_content,
866 &self.content_encryption_algorithm,
867 None,
868 rng,
869 )?;
870 let encrypted_content_octetstring = der::asn1::OctetString::new(encrypted_content)?;
871 let encrypted_content_info = EncryptedContentInfo {
872 content_type: const_oid::db::rfc5911::ID_DATA, content_enc_alg,
874 encrypted_content: Some(encrypted_content_octetstring), };
876
877 let recipient_infos_vec = self
878 .recipient_infos
879 .iter_mut()
880 .map(|ri| ri.build(&content_encryption_key))
881 .collect::<Result<Vec<RecipientInfo>>>()?;
882 content_encryption_key.zeroize();
883 let recip_infos = RecipientInfos::try_from(recipient_infos_vec).unwrap();
884
885 Ok(EnvelopedData {
886 version: self.calculate_version(),
887 originator_info: self.originator_info.clone(),
888 recip_infos,
889 encrypted_content: encrypted_content_info,
890 unprotected_attrs: self.unprotected_attributes.clone(),
891 })
892 }
893
894 fn calculate_version(&self) -> CmsVersion {
896 let originator_info_present = self.originator_info.is_some();
913 let other_certificates_present = if let Some(originator_info) = &self.originator_info {
914 if let Some(certificates) = &originator_info.certs {
915 certificates
916 .0
917 .iter()
918 .any(|certificate| matches!(certificate, CertificateChoices::Other(_)))
919 } else {
920 false
921 }
922 } else {
923 false
924 };
925 let other_crls_present = if let Some(originator_info) = &self.originator_info {
926 if let Some(crls) = &originator_info.crls {
927 crls.0
928 .iter()
929 .any(|crl| matches!(crl, RevocationInfoChoice::Other(_)))
930 } else {
931 false
932 }
933 } else {
934 false
935 };
936 let v2_certificates_present = false;
949 let pwri_recipient_info_present = self.recipient_infos.iter().any(|recipient_info| {
950 matches!(
951 recipient_info.recipient_info_type(),
952 RecipientInfoType::Pwri
953 )
954 });
955 let ori_recipient_info_present = self.recipient_infos.iter().any(|recipient_info| {
956 matches!(recipient_info.recipient_info_type(), RecipientInfoType::Ori)
957 });
958 let unprotected_attributes_present = self.unprotected_attributes.is_some();
959 let all_recipient_infos_are_v0 = self
960 .recipient_infos
961 .iter()
962 .all(|ri| ri.recipient_info_version() == CmsVersion::V0);
963
964 if originator_info_present && (other_certificates_present || other_crls_present) {
965 CmsVersion::V4
966 } else if (originator_info_present && v2_certificates_present)
967 || pwri_recipient_info_present
968 || ori_recipient_info_present
969 {
970 CmsVersion::V3
971 } else if !originator_info_present
972 && !unprotected_attributes_present
973 && all_recipient_infos_are_v0
974 {
975 CmsVersion::V0
976 } else {
977 CmsVersion::V2
978 }
979 }
980}
981
982fn get_hasher(
984 digest_algorithm_identifier: &AlgorithmIdentifierOwned,
985) -> Option<Box<dyn DynDigest>> {
986 let digest_name = DB.by_oid(&digest_algorithm_identifier.oid)?;
987 match digest_name {
988 "id-sha1" => Some(Box::new(sha1::Sha1::new())),
989 "id-sha256" => Some(Box::new(sha2::Sha256::new())),
990 "id-sha384" => Some(Box::new(sha2::Sha384::new())),
991 "id-sha512" => Some(Box::new(sha2::Sha512::new())),
992 "id-sha224" => Some(Box::new(sha2::Sha224::new())),
993 "id-sha-3-224" => Some(Box::new(sha3::Sha3_224::new())),
994 "id-sha-3-256" => Some(Box::new(sha3::Sha3_256::new())),
995 "id-sha-3-384" => Some(Box::new(sha3::Sha3_384::new())),
996 "id-sha-3-512" => Some(Box::new(sha3::Sha3_512::new())),
997 _ => None,
998 }
999}
1000
1001macro_rules! encrypt_block_mode {
1003 ($data:expr, $block_mode:ident::$typ:ident<$alg:ident>, $key:expr, $rng:expr, $oid:expr) => {{
1004 let (key, iv) = match $key {
1005 None => $block_mode::$typ::<$alg>::generate_key_iv($rng),
1006 Some(key) => {
1007 if key.len() != $alg::key_size() {
1008 return Err(Error::Builder(String::from(
1009 "Invalid key size for chosen algorithm",
1010 )));
1011 }
1012 (
1013 Key::<$block_mode::$typ<$alg>>::from_slice(key).to_owned(),
1014 $block_mode::$typ::<$alg>::generate_iv($rng),
1015 )
1016 }
1017 };
1018 let encryptor = $block_mode::$typ::<$alg>::new(&key.into(), &iv.into());
1019 Ok((
1020 encryptor.encrypt_padded_vec_mut::<Pkcs7>($data),
1021 key.to_vec(),
1022 AlgorithmIdentifierOwned {
1023 oid: $oid,
1024 parameters: Some(Any::new(OctetString, iv.to_vec())?),
1025 },
1026 ))
1027 }};
1028}
1029
1030fn encrypt_data<R>(
1036 data: &[u8],
1037 encryption_algorithm_identifier: &ContentEncryptionAlgorithm,
1038 key: Option<&[u8]>,
1039 rng: &mut R,
1040) -> Result<(Vec<u8>, Vec<u8>, AlgorithmIdentifierOwned)>
1041where
1042 R: CryptoRng + RngCore,
1043{
1044 match encryption_algorithm_identifier {
1045 ContentEncryptionAlgorithm::Aes128Cbc => encrypt_block_mode!(
1046 data,
1047 cbc::Encryptor<Aes128>,
1048 key,
1049 rng,
1050 encryption_algorithm_identifier.oid()
1051 ),
1052 ContentEncryptionAlgorithm::Aes192Cbc => encrypt_block_mode!(
1053 data,
1054 cbc::Encryptor<Aes192>,
1055 key,
1056 rng,
1057 encryption_algorithm_identifier.oid()
1058 ),
1059 ContentEncryptionAlgorithm::Aes256Cbc => encrypt_block_mode!(
1060 data,
1061 cbc::Encryptor<Aes256>,
1062 key,
1063 rng,
1064 encryption_algorithm_identifier.oid()
1065 ),
1066 }
1067}
1068
1069pub fn create_content_type_attribute(content_type: ObjectIdentifier) -> Result<Attribute> {
1072 let content_type_attribute_value =
1073 AttributeValue::new(Tag::ObjectIdentifier, content_type.as_bytes())?;
1074 let mut values = SetOfVec::new();
1075 values.insert(content_type_attribute_value)?;
1076 let attribute = Attribute {
1077 oid: const_oid::db::rfc5911::ID_CONTENT_TYPE,
1078 values,
1079 };
1080 Ok(attribute)
1081}
1082
1083pub fn create_message_digest_attribute(message_digest: &[u8]) -> Result<Attribute> {
1086 let message_digest_der = OctetStringRef::new(message_digest)?;
1087 let message_digest_attribute_value =
1088 AttributeValue::new(OctetString, message_digest_der.as_bytes())?;
1089 let mut values = SetOfVec::new();
1090 values.insert(message_digest_attribute_value)?;
1091 let attribute = Attribute {
1092 oid: const_oid::db::rfc5911::ID_MESSAGE_DIGEST,
1093 values,
1094 };
1095 Ok(attribute)
1096}
1097
1098pub fn create_signing_time_attribute() -> Result<Attribute> {
1104 let now = DateTime::from_system_time(SystemTime::now())?;
1105 let tag = if now.year() < 1950 || now.year() > 2049 {
1106 Tag::GeneralizedTime
1107 } else {
1108 Tag::UtcTime
1109 };
1110 let time_der = if tag == Tag::GeneralizedTime {
1112 der::asn1::GeneralizedTime::from_date_time(now).to_der()?
1114 } else {
1115 der::asn1::UtcTime::from_date_time(now)?.to_der()?
1117 };
1118 let signing_time_attribute_value = AttributeValue::from_der(&time_der)?;
1119 let mut values = SetOfVec::<AttributeValue>::new();
1120 values.insert(signing_time_attribute_value)?;
1121 let attribute = Attribute {
1122 oid: const_oid::db::rfc5911::ID_SIGNING_TIME,
1123 values,
1124 };
1125 Ok(attribute)
1126}