picky_asn1_x509/
algorithm_identifier.rs

1use crate::oids;
2use oid::ObjectIdentifier;
3use picky_asn1::tag::{Tag, TagPeeker};
4use picky_asn1::wrapper::{
5    ExplicitContextTag0, ExplicitContextTag1, ExplicitContextTag2, IntegerAsn1, ObjectIdentifierAsn1, OctetStringAsn1,
6};
7use picky_asn1_der::Asn1RawDer;
8use serde::{de, ser, Deserialize, Serialize};
9use std::cmp::Ordering;
10use std::error::Error;
11use std::fmt;
12
13/// unsupported algorithm
14#[derive(Debug)]
15pub struct UnsupportedAlgorithmError {
16    pub algorithm: String,
17}
18
19impl fmt::Display for UnsupportedAlgorithmError {
20    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21        write!(f, "unsupported algorithm:  {}", self.algorithm)
22    }
23}
24
25impl Error for UnsupportedAlgorithmError {}
26
27#[derive(Debug, PartialEq, Eq, Clone)]
28pub struct AlgorithmIdentifier {
29    algorithm: ObjectIdentifierAsn1,
30    parameters: AlgorithmIdentifierParameters,
31}
32
33impl AlgorithmIdentifier {
34    pub fn oid(&self) -> &ObjectIdentifier {
35        &self.algorithm.0
36    }
37
38    pub fn oid_asn1(&self) -> &ObjectIdentifierAsn1 {
39        &self.algorithm
40    }
41
42    pub fn parameters(&self) -> &AlgorithmIdentifierParameters {
43        &self.parameters
44    }
45
46    pub fn is_a(&self, algorithm: ObjectIdentifier) -> bool {
47        algorithm.eq(&self.algorithm.0)
48    }
49
50    pub fn is_one_of(&self, algorithms: impl IntoIterator<Item = ObjectIdentifier>) -> bool {
51        algorithms.into_iter().any(|oid| self.is_a(oid))
52    }
53
54    pub fn new_md5_with_rsa_encryption() -> Self {
55        Self {
56            algorithm: oids::md5_with_rsa_encryption().into(),
57            parameters: AlgorithmIdentifierParameters::Null,
58        }
59    }
60
61    pub fn new_sha1_with_rsa_encryption() -> Self {
62        Self {
63            algorithm: oids::sha1_with_rsa_encryption().into(),
64            parameters: AlgorithmIdentifierParameters::Null,
65        }
66    }
67
68    pub fn new_sha1() -> Self {
69        Self {
70            algorithm: oids::sha1().into(),
71            parameters: AlgorithmIdentifierParameters::Null,
72        }
73    }
74
75    pub fn new_sha224_with_rsa_encryption() -> Self {
76        Self {
77            algorithm: oids::sha224_with_rsa_encryption().into(),
78            parameters: AlgorithmIdentifierParameters::Null,
79        }
80    }
81
82    pub fn new_sha256_with_rsa_encryption() -> Self {
83        Self {
84            algorithm: oids::sha256_with_rsa_encryption().into(),
85            parameters: AlgorithmIdentifierParameters::Null,
86        }
87    }
88
89    pub fn new_sha384_with_rsa_encryption() -> Self {
90        Self {
91            algorithm: oids::sha384_with_rsa_encryption().into(),
92            parameters: AlgorithmIdentifierParameters::Null,
93        }
94    }
95
96    pub fn new_sha512_with_rsa_encryption() -> Self {
97        Self {
98            algorithm: oids::sha512_with_rsa_encryption().into(),
99            parameters: AlgorithmIdentifierParameters::Null,
100        }
101    }
102
103    pub fn new_sha3_384_with_rsa_encryption() -> Self {
104        Self {
105            algorithm: oids::id_rsassa_pkcs1_v1_5_with_sha3_384().into(),
106            parameters: AlgorithmIdentifierParameters::Null,
107        }
108    }
109
110    pub fn new_sha3_512_with_rsa_encryption() -> Self {
111        Self {
112            algorithm: oids::id_rsassa_pkcs1_v1_5_with_sha3_512().into(),
113            parameters: AlgorithmIdentifierParameters::Null,
114        }
115    }
116
117    pub fn new_rsassa_pss(parameters: RsassaPssParams) -> Self {
118        Self {
119            algorithm: oids::rsassa_pss().into(),
120            parameters: AlgorithmIdentifierParameters::RsassaPss(parameters),
121        }
122    }
123
124    pub fn new_rsa_encryption() -> Self {
125        Self {
126            algorithm: oids::rsa_encryption().into(),
127            parameters: AlgorithmIdentifierParameters::Null,
128        }
129    }
130
131    pub fn new_rsa_encryption_with_sha(variant: ShaVariant) -> Result<Self, UnsupportedAlgorithmError> {
132        let algorithm = match variant {
133            ShaVariant::SHA2_224 => oids::sha224_with_rsa_encryption(),
134            ShaVariant::SHA2_256 => oids::sha256_with_rsa_encryption(),
135            ShaVariant::SHA2_384 => oids::sha384_with_rsa_encryption(),
136            ShaVariant::SHA2_512 => oids::sha512_with_rsa_encryption(),
137            ShaVariant::SHA3_384 => oids::id_rsassa_pkcs1_v1_5_with_sha3_384(),
138            ShaVariant::SHA3_512 => oids::id_rsassa_pkcs1_v1_5_with_sha3_512(),
139            _ => {
140                return Err(UnsupportedAlgorithmError {
141                    algorithm: format!("{:?}", variant),
142                })
143            }
144        };
145
146        Ok(Self {
147            algorithm: algorithm.into(),
148            parameters: AlgorithmIdentifierParameters::Null,
149        })
150    }
151
152    pub fn new_dsa_with_sha1() -> Self {
153        Self {
154            algorithm: oids::dsa_with_sha1().into(),
155            parameters: AlgorithmIdentifierParameters::Null,
156        }
157    }
158
159    pub fn new_ecdsa_with_sha512() -> Self {
160        Self {
161            algorithm: oids::ecdsa_with_sha512().into(),
162            parameters: AlgorithmIdentifierParameters::None,
163        }
164    }
165
166    pub fn new_ecdsa_with_sha384() -> Self {
167        Self {
168            algorithm: oids::ecdsa_with_sha384().into(),
169            parameters: AlgorithmIdentifierParameters::None,
170        }
171    }
172
173    pub fn new_ecdsa_with_sha256() -> Self {
174        Self {
175            algorithm: oids::ecdsa_with_sha256().into(),
176            parameters: AlgorithmIdentifierParameters::None,
177        }
178    }
179
180    pub fn new_elliptic_curve(ec_params: EcParameters) -> Self {
181        Self {
182            algorithm: oids::ec_public_key().into(),
183            parameters: AlgorithmIdentifierParameters::Ec(ec_params),
184        }
185    }
186
187    /// Create new algorithm identifier without checking if the algorithm parameters are valid for
188    /// the given algorithm.
189    pub(crate) fn new_unchecked(algorithm: ObjectIdentifier, parameters: AlgorithmIdentifierParameters) -> Self {
190        Self {
191            algorithm: algorithm.into(),
192            parameters,
193        }
194    }
195
196    pub fn new_ed25519() -> Self {
197        Self {
198            algorithm: oids::ed25519().into(),
199            parameters: AlgorithmIdentifierParameters::None,
200        }
201    }
202
203    pub fn new_x25519() -> Self {
204        Self {
205            algorithm: oids::x25519().into(),
206            parameters: AlgorithmIdentifierParameters::None,
207        }
208    }
209
210    pub fn new_ed448() -> Self {
211        Self {
212            algorithm: oids::ed448().into(),
213            parameters: AlgorithmIdentifierParameters::None,
214        }
215    }
216
217    pub fn new_x448() -> Self {
218        Self {
219            algorithm: oids::x448().into(),
220            parameters: AlgorithmIdentifierParameters::None,
221        }
222    }
223
224    pub fn new_aes128(mode: AesMode, params: AesParameters) -> Self {
225        Self {
226            algorithm: mode.to_128bit_oid(),
227            parameters: AlgorithmIdentifierParameters::Aes(params),
228        }
229    }
230
231    pub fn new_aes192(mode: AesMode, params: AesParameters) -> Self {
232        Self {
233            algorithm: mode.to_192bit_oid(),
234            parameters: AlgorithmIdentifierParameters::Aes(params),
235        }
236    }
237
238    pub fn new_aes256(mode: AesMode, params: AesParameters) -> Self {
239        Self {
240            algorithm: mode.to_256bit_oid(),
241            parameters: AlgorithmIdentifierParameters::Aes(params),
242        }
243    }
244
245    pub fn new_aes256_empty(mode: AesMode) -> Self {
246        Self {
247            algorithm: mode.to_256bit_oid(),
248            parameters: AlgorithmIdentifierParameters::None,
249        }
250    }
251
252    pub fn new_sha(variant: ShaVariant) -> Self {
253        Self {
254            algorithm: variant.into(),
255            parameters: AlgorithmIdentifierParameters::Null,
256        }
257    }
258}
259
260impl ser::Serialize for AlgorithmIdentifier {
261    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
262    where
263        S: ser::Serializer,
264    {
265        use ser::SerializeSeq;
266        let mut seq = serializer.serialize_seq(Some(2))?;
267        seq.serialize_element(&self.algorithm)?;
268        match &self.parameters {
269            AlgorithmIdentifierParameters::None => {}
270            AlgorithmIdentifierParameters::Null => {
271                seq.serialize_element(&())?;
272            }
273            AlgorithmIdentifierParameters::Ec(ec_params) => {
274                seq.serialize_element(ec_params)?;
275            }
276            AlgorithmIdentifierParameters::Aes(aes_params) => {
277                seq.serialize_element(aes_params)?;
278            }
279            AlgorithmIdentifierParameters::RsassaPss(rsa_params) => {
280                seq.serialize_element(rsa_params)?;
281            }
282        }
283        seq.end()
284    }
285}
286
287impl<'de> de::Deserialize<'de> for AlgorithmIdentifier {
288    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
289    where
290        D: de::Deserializer<'de>,
291    {
292        struct Visitor;
293
294        impl<'de> de::Visitor<'de> for Visitor {
295            type Value = AlgorithmIdentifier;
296
297            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
298                formatter.write_str("a valid DER-encoded algorithm identifier")
299            }
300
301            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
302            where
303                A: de::SeqAccess<'de>,
304            {
305                let oid: ObjectIdentifierAsn1 = seq_next_element!(seq, AlgorithmIdentifier, "algorithm oid");
306
307                let args = match Into::<String>::into(&oid.0).as_str() {
308                    oids::RSA_ENCRYPTION
309                    | oids::SHA1_WITH_RSA_ENCRYPTION
310                    | oids::SHA224_WITH_RSA_ENCRYPTION
311                    | oids::SHA256_WITH_RSA_ENCRYPTION
312                    | oids::SHA384_WITH_RSA_ENCRYPTION
313                    | oids::SHA512_WITH_RSA_ENCRYPTION => {
314                        // Try to deserialize next element in sequence.
315                        // Error is ignored because some implementations just leave no parameter at all for
316                        // RSA encryption (ie: rsa-export-0.1.1 crate) but we still want to be able
317                        // to parse their output.
318                        let _ = seq.next_element::<()>();
319                        AlgorithmIdentifierParameters::Null
320                    }
321                    oids::RSASSA_PSS => AlgorithmIdentifierParameters::RsassaPss(seq_next_element!(
322                        seq,
323                        RsassaPssParams,
324                        "RSASSA-PSS parameters"
325                    )),
326                    oids::ECDSA_WITH_SHA384
327                    | oids::ECDSA_WITH_SHA256
328                    | oids::ECDSA_WITH_SHA512
329                    | oids::ED25519
330                    | oids::ED448
331                    | oids::X25519
332                    | oids::X448 => AlgorithmIdentifierParameters::None,
333                    oids::DSA_WITH_SHA1 => {
334                        // A note from [RFC 3927](https://www.ietf.org/rfc/rfc3279.txt)
335                        // When the id-dsa-with-sha1 algorithm identifier appears as the
336                        // algorithm field in an AlgorithmIdentifier, the encoding SHALL omit
337                        // the parameters field.  That is, the AlgorithmIdentifier SHALL be a
338                        // SEQUENCE of one component: the OBJECT IDENTIFIER id-dsa-with-sha1.
339                        AlgorithmIdentifierParameters::None
340                    }
341                    // A note from [RFC 5480](https://tools.ietf.org/html/rfc5480#section-2.1.1)
342                    // The parameter for id-ecPublicKey is as follows and MUST always be present
343                    oids::EC_PUBLIC_KEY => AlgorithmIdentifierParameters::Ec(seq_next_element!(
344                        seq,
345                        EcParameters,
346                        AlgorithmIdentifier,
347                        "elliptic curves parameters"
348                    )),
349                    // AES
350                    x if x.starts_with("2.16.840.1.101.3.4.1.") => {
351                        if let Some(aes_parameters) = seq.next_element()? {
352                            AlgorithmIdentifierParameters::Aes(aes_parameters)
353                        } else {
354                            AlgorithmIdentifierParameters::None
355                        }
356                    }
357                    // SHA
358                    x if x.starts_with("2.16.840.1.101.3.4.2.") || x == oids::SHA1 => {
359                        type Unit = ();
360                        seq_next_element!(seq, Unit, AlgorithmIdentifier, "sha algorithm identifier");
361                        AlgorithmIdentifierParameters::Null
362                    }
363                    _ => {
364                        return Err(serde_invalid_value!(
365                            AlgorithmIdentifier,
366                            "unsupported algorithm (unknown oid)",
367                            "a supported algorithm"
368                        ));
369                    }
370                };
371
372                Ok(AlgorithmIdentifier {
373                    algorithm: oid,
374                    parameters: args,
375                })
376            }
377        }
378
379        deserializer.deserialize_seq(Visitor)
380    }
381}
382
383#[derive(Debug, PartialEq, Eq, Clone)]
384pub enum AlgorithmIdentifierParameters {
385    None,
386    Null,
387    Aes(AesParameters),
388    Ec(EcParameters),
389    RsassaPss(RsassaPssParams),
390}
391
392/// [RFC 4055 #3.1](https://www.rfc-editor.org/rfc/rfc4055#section-3.1)
393///
394/// ```not_rust
395///       RSASSA-PSS-params  ::=  SEQUENCE  {
396///           hashAlgorithm      [0] HashAlgorithm DEFAULT
397///                                     sha1Identifier,
398///           maskGenAlgorithm   [1] MaskGenAlgorithm DEFAULT
399///                                     mgf1SHA1Identifier,
400///           saltLength         [2] INTEGER DEFAULT 20,
401///           trailerField       [3] INTEGER DEFAULT 1  }
402/// ```
403///
404/// Implementations that perform signature generation MUST omit the trailerField
405/// field, indicating that the default trailer field value was used... thus the
406/// reason no trailer field is specified in this structure.
407#[derive(Clone, Debug, Eq, PartialEq)]
408pub struct RsassaPssParams {
409    pub hash_algorithm: HashAlgorithm,
410    pub mask_gen_algorithm: MaskGenAlgorithm,
411    pub salt_length: usize,
412}
413
414impl RsassaPssParams {
415    pub fn new(hash_algorithm: HashAlgorithm) -> Self {
416        Self {
417            hash_algorithm,
418            mask_gen_algorithm: MaskGenAlgorithm::new(hash_algorithm),
419            salt_length: hash_algorithm.len(),
420        }
421    }
422}
423
424impl ser::Serialize for RsassaPssParams {
425    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
426    where
427        S: ser::Serializer,
428    {
429        use ser::SerializeSeq;
430        let mut seq = serializer.serialize_seq(Some(3))?;
431        seq.serialize_element(&ExplicitContextTag0(&self.hash_algorithm))?;
432        seq.serialize_element(&ExplicitContextTag1(&self.mask_gen_algorithm))?;
433        seq.serialize_element(&ExplicitContextTag2(&IntegerAsn1::from_bytes_be_signed(
434            self.salt_length.to_be_bytes().to_vec(),
435        )))?;
436        seq.end()
437    }
438}
439
440fn usize_from_be_bytes(asn1: &IntegerAsn1) -> usize {
441    let bytes = asn1.as_unsigned_bytes_be();
442    match bytes.len().cmp(&8) {
443        Ordering::Greater => usize::MAX,
444        Ordering::Less => {
445            const USIZE_SIZE: usize = std::mem::size_of::<usize>();
446
447            let mut tmp = [0; USIZE_SIZE];
448            tmp[(USIZE_SIZE - bytes.len())..USIZE_SIZE].clone_from_slice(bytes);
449            usize::from_be_bytes(tmp)
450        }
451        // unwrap is safe since we know this is exactly 8 bytes.
452        Ordering::Equal => usize::from_be_bytes(bytes.try_into().unwrap()),
453    }
454}
455
456impl<'de> de::Deserialize<'de> for RsassaPssParams {
457    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
458    where
459        D: de::Deserializer<'de>,
460    {
461        struct Visitor;
462
463        impl<'de> de::Visitor<'de> for Visitor {
464            type Value = RsassaPssParams;
465
466            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
467                formatter.write_str("a valid DER-encoded RsassaPssParams")
468            }
469
470            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
471            where
472                A: de::SeqAccess<'de>,
473            {
474                let hash = seq_next_element!(seq, ExplicitContextTag0<HashAlgorithm>, HashAlgorithm, "cont [0]");
475                let mask_gen = seq_next_element!(
476                    seq,
477                    ExplicitContextTag1<MaskGenAlgorithm>,
478                    MaskGenAlgorithm,
479                    "maskGenAlgorithm"
480                );
481                let salt = seq_next_element!(seq, ExplicitContextTag2<IntegerAsn1>, IntegerAsn1, "saltLength");
482                Ok(RsassaPssParams {
483                    hash_algorithm: hash.0,
484                    mask_gen_algorithm: mask_gen.0,
485                    salt_length: usize_from_be_bytes(&salt.0),
486                })
487            }
488        }
489
490        deserializer.deserialize_seq(Visitor)
491    }
492}
493
494// https://www.rfc-editor.org/rfc/rfc4055#section-2.1
495#[derive(Clone, Copy, PartialEq, Eq, Debug)]
496#[allow(non_camel_case_types)]
497pub enum HashAlgorithm {
498    // Nobody should be using SHA1 in 2023, it is completely broken... and the RFC for RsassaPssParams
499    // adds needless complexity in regard to requiring the omission of parameters if SHA1 is used.
500    //SHA1,
501    SHA224,
502    SHA256,
503    SHA384,
504    SHA512,
505}
506
507impl HashAlgorithm {
508    pub fn len(&self) -> usize {
509        use HashAlgorithm::*;
510        match self {
511            //SHA1 => 20,
512            SHA224 => 28,
513            SHA256 => 32,
514            SHA384 => 48,
515            SHA512 => 64,
516        }
517    }
518    pub fn is_empty(&self) -> bool {
519        false
520    }
521}
522impl From<&HashAlgorithm> for ObjectIdentifierAsn1 {
523    fn from(variant: &HashAlgorithm) -> Self {
524        use HashAlgorithm::*;
525        match variant {
526            //SHA1 => oids::sha1().into(),
527            SHA224 => oids::sha224().into(),
528            SHA256 => oids::sha256().into(),
529            SHA384 => oids::sha384().into(),
530            SHA512 => oids::sha512().into(),
531        }
532    }
533}
534
535impl TryFrom<ObjectIdentifierAsn1> for HashAlgorithm {
536    type Error = UnsupportedAlgorithmError;
537
538    fn try_from(oid: ObjectIdentifierAsn1) -> Result<Self, Self::Error> {
539        match Into::<String>::into(oid.0).as_str() {
540            //oids::SHA1 => Ok(HashAlgorithm::SHA1),
541            oids::SHA224 => Ok(HashAlgorithm::SHA224),
542            oids::SHA256 => Ok(HashAlgorithm::SHA256),
543            oids::SHA384 => Ok(HashAlgorithm::SHA384),
544            oids::SHA512 => Ok(HashAlgorithm::SHA512),
545            unsupported => Err(UnsupportedAlgorithmError {
546                algorithm: unsupported.to_string(),
547            }),
548        }
549    }
550}
551
552impl ser::Serialize for HashAlgorithm {
553    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
554    where
555        S: ser::Serializer,
556    {
557        use ser::SerializeSeq;
558        let mut seq = serializer.serialize_seq(Some(2))?;
559        seq.serialize_element(&ObjectIdentifierAsn1::from(self))?;
560        seq.serialize_element(&())?;
561        seq.end()
562    }
563}
564
565impl<'de> de::Deserialize<'de> for HashAlgorithm {
566    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
567    where
568        D: de::Deserializer<'de>,
569    {
570        struct Visitor;
571
572        impl<'de> de::Visitor<'de> for Visitor {
573            type Value = HashAlgorithm;
574
575            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
576                formatter.write_str("a valid DER-encoded HashAlgorithm")
577            }
578
579            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
580            where
581                A: de::SeqAccess<'de>,
582            {
583                let oid: ObjectIdentifierAsn1 = seq_next_element!(seq, ObjectIdentifierAsn1, "oid of hashAlgorithm");
584                let _: Option<()> = seq.next_element()?;
585                oid.try_into().map_err(|_| {
586                    serde_invalid_value!(
587                        HashAlgorithm,
588                        "unsupported or unknown hash algorithm",
589                        "a supported hash algorithm"
590                    )
591                })
592            }
593        }
594
595        deserializer.deserialize_seq(Visitor)
596    }
597}
598
599#[derive(Clone, Debug, Eq, PartialEq)]
600pub struct MaskGenAlgorithm {
601    pub mask_gen_algorithm: ObjectIdentifierAsn1,
602    pub hash_algorithm: HashAlgorithm,
603}
604
605impl MaskGenAlgorithm {
606    pub fn new(hash_algorithm: HashAlgorithm) -> Self {
607        Self {
608            mask_gen_algorithm: ObjectIdentifierAsn1::from(oids::id_mgf1()),
609            hash_algorithm,
610        }
611    }
612}
613
614impl ser::Serialize for MaskGenAlgorithm {
615    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
616    where
617        S: ser::Serializer,
618    {
619        use ser::SerializeSeq;
620        let mut seq = serializer.serialize_seq(Some(2))?;
621        seq.serialize_element(&self.mask_gen_algorithm)?;
622        seq.serialize_element(&self.hash_algorithm)?;
623        seq.end()
624    }
625}
626
627impl<'de> de::Deserialize<'de> for MaskGenAlgorithm {
628    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
629    where
630        D: de::Deserializer<'de>,
631    {
632        struct Visitor;
633
634        impl<'de> de::Visitor<'de> for Visitor {
635            type Value = MaskGenAlgorithm;
636
637            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
638                formatter.write_str("a valid DER-encoded MaskGenAlgorithm")
639            }
640
641            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
642            where
643                A: de::SeqAccess<'de>,
644            {
645                let mask_gen_algorithm: ObjectIdentifierAsn1 =
646                    seq_next_element!(seq, ObjectIdentifierAsn1, "oid of maskGenAlgorithm");
647                let hash_algorithm: HashAlgorithm = seq_next_element!(seq, HashAlgorithm, "hashAlgorithm");
648                Ok(MaskGenAlgorithm {
649                    mask_gen_algorithm,
650                    hash_algorithm,
651                })
652            }
653        }
654
655        deserializer.deserialize_seq(Visitor)
656    }
657}
658
659#[derive(Debug, PartialEq, Eq, Clone)]
660pub enum EcParameters {
661    NamedCurve(ObjectIdentifierAsn1),
662    // -- implicitCurve and specifiedCurve MUST NOT be used in PKIX.
663    // ImplicitCurve,
664    // SpecifiedCurve(SpecifiedECDomain)
665}
666
667impl EcParameters {
668    pub fn curve_oid(&self) -> &ObjectIdentifier {
669        match self {
670            EcParameters::NamedCurve(oid) => &oid.0,
671        }
672    }
673}
674
675impl From<ObjectIdentifierAsn1> for EcParameters {
676    fn from(oid: ObjectIdentifierAsn1) -> Self {
677        Self::NamedCurve(oid)
678    }
679}
680
681impl From<ObjectIdentifier> for EcParameters {
682    fn from(oid: ObjectIdentifier) -> Self {
683        Self::NamedCurve(oid.into())
684    }
685}
686
687impl ser::Serialize for EcParameters {
688    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
689    where
690        S: ser::Serializer,
691    {
692        match &self {
693            EcParameters::NamedCurve(oid) => oid.serialize(serializer),
694        }
695    }
696}
697
698impl<'de> de::Deserialize<'de> for EcParameters {
699    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
700    where
701        D: de::Deserializer<'de>,
702    {
703        struct Visitor;
704
705        impl<'de> de::Visitor<'de> for Visitor {
706            type Value = EcParameters;
707
708            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
709                formatter.write_str("a valid DER-encoded DirectoryString")
710            }
711
712            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
713            where
714                A: de::SeqAccess<'de>,
715            {
716                let tag_peeker: TagPeeker = seq_next_element!(seq, EcParameters, "choice tag");
717
718                let curve_oid = match tag_peeker.next_tag {
719                    Tag::OID => seq_next_element!(seq, ObjectIdentifierAsn1, "NamedCurve object identifier"),
720                    _ => {
721                        return Err(serde_invalid_value!(
722                            EcParameters,
723                            "unsupported or unknown elliptic curve parameter",
724                            "a supported elliptic curve parameter"
725                        ))
726                    }
727                };
728
729                Ok(EcParameters::NamedCurve(curve_oid))
730            }
731        }
732
733        deserializer.deserialize_enum("DirectoryString", &["NamedCurve", "ImplicitCurve"], Visitor)
734    }
735}
736
737#[derive(Clone, Copy, PartialEq, Eq, Debug)]
738pub enum AesMode {
739    Ecb,
740    Cbc,
741    Ofb,
742    Cfb,
743    Wrap,
744    Gcm,
745    Ccm,
746    WrapPad,
747}
748
749#[derive(Debug, PartialEq, Eq, Clone)]
750pub enum AesParameters {
751    Null,
752    InitializationVector(OctetStringAsn1),
753    AuthenticatedEncryptionParameters(AesAuthEncParams),
754}
755
756#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
757pub struct AesAuthEncParams {
758    pub(crate) nonce: OctetStringAsn1,
759    pub(crate) icv_len: IntegerAsn1,
760}
761
762impl AesAuthEncParams {
763    pub fn new(nonce: Vec<u8>, icv_len: usize) -> Self {
764        Self {
765            nonce: OctetStringAsn1::from(nonce),
766            icv_len: IntegerAsn1::from(
767                icv_len
768                    .to_be_bytes()
769                    // Remove leading zeroes.
770                    .into_iter()
771                    .skip_while(|n| *n == 0)
772                    .collect::<Vec<_>>(),
773            ),
774        }
775    }
776
777    pub fn nonce(&self) -> &[u8] {
778        &self.nonce.0
779    }
780
781    pub fn icv_len(&self) -> &[u8] {
782        &self.icv_len.0
783    }
784}
785
786impl AesMode {
787    fn to_128bit_oid(self) -> ObjectIdentifierAsn1 {
788        match self {
789            AesMode::Ecb => oids::aes128_ecb().into(),
790            AesMode::Cbc => oids::aes128_cbc().into(),
791            AesMode::Ofb => oids::aes128_ofb().into(),
792            AesMode::Cfb => oids::aes128_cfb().into(),
793            AesMode::Wrap => oids::aes128_wrap().into(),
794            AesMode::Gcm => oids::aes128_gcm().into(),
795            AesMode::Ccm => oids::aes128_ccm().into(),
796            AesMode::WrapPad => oids::aes128_wrap_pad().into(),
797        }
798    }
799
800    fn to_192bit_oid(self) -> ObjectIdentifierAsn1 {
801        match self {
802            AesMode::Ecb => oids::aes192_ecb().into(),
803            AesMode::Cbc => oids::aes192_cbc().into(),
804            AesMode::Ofb => oids::aes192_ofb().into(),
805            AesMode::Cfb => oids::aes192_cfb().into(),
806            AesMode::Wrap => oids::aes192_wrap().into(),
807            AesMode::Gcm => oids::aes192_gcm().into(),
808            AesMode::Ccm => oids::aes192_ccm().into(),
809            AesMode::WrapPad => oids::aes192_wrap_pad().into(),
810        }
811    }
812
813    fn to_256bit_oid(self) -> ObjectIdentifierAsn1 {
814        match self {
815            AesMode::Ecb => oids::aes256_ecb().into(),
816            AesMode::Cbc => oids::aes256_cbc().into(),
817            AesMode::Ofb => oids::aes256_ofb().into(),
818            AesMode::Cfb => oids::aes256_cfb().into(),
819            AesMode::Wrap => oids::aes256_wrap().into(),
820            AesMode::Gcm => oids::aes256_gcm().into(),
821            AesMode::Ccm => oids::aes256_ccm().into(),
822            AesMode::WrapPad => oids::aes256_wrap_pad().into(),
823        }
824    }
825}
826
827impl ser::Serialize for AesParameters {
828    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
829    where
830        S: ser::Serializer,
831    {
832        match self {
833            AesParameters::Null => ().serialize(serializer),
834            AesParameters::InitializationVector(iv) => iv.serialize(serializer),
835            AesParameters::AuthenticatedEncryptionParameters(params) => params.serialize(serializer),
836        }
837    }
838}
839
840impl<'de> de::Deserialize<'de> for AesParameters {
841    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
842    where
843        D: de::Deserializer<'de>,
844    {
845        struct Visitor;
846
847        impl<'de> de::Visitor<'de> for Visitor {
848            type Value = AesParameters;
849
850            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
851                formatter.write_str("a valid DER-encoded DirectoryString")
852            }
853
854            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
855            where
856                A: de::SeqAccess<'de>,
857            {
858                let tag_peeker: TagPeeker = seq_next_element!(seq, AesParameters, "choice tag");
859                match tag_peeker.next_tag {
860                    Tag::OCTET_STRING => Ok(AesParameters::InitializationVector(seq_next_element!(
861                        seq,
862                        AesParameters,
863                        "Object Identifier"
864                    ))),
865                    Tag::NULL => {
866                        seq.next_element::<()>()?.expect("should not panic");
867                        Ok(AesParameters::Null)
868                    }
869                    Tag::SEQUENCE => Ok(AesParameters::AuthenticatedEncryptionParameters(seq_next_element!(
870                        seq,
871                        AesAuthEncParams,
872                        "AES Authenticated Encryption parameters"
873                    ))),
874                    _ => Err(serde_invalid_value!(
875                        AesParameters,
876                        "unsupported or unknown AES parameter",
877                        "a supported AES parameter"
878                    )),
879                }
880            }
881        }
882
883        deserializer.deserialize_enum(
884            "DirectoryString",
885            &["Null", "InitializationVector", "AuthenticatedEncryptionParameters"],
886            Visitor,
887        )
888    }
889}
890
891#[derive(Clone, Copy, PartialEq, Eq, Debug)]
892#[allow(non_camel_case_types)] // 'SHA2_512_224' is clearer than 'SHA2512224' or 'Sha2512224' imo
893pub enum ShaVariant {
894    // TODO: rename enum (breaking)
895    MD5,
896    SHA1,
897    SHA2_224,
898    SHA2_256,
899    SHA2_384,
900    SHA2_512,
901    SHA2_512_224,
902    SHA2_512_256,
903    SHA3_224,
904    SHA3_256,
905    SHA3_384,
906    SHA3_512,
907    SHAKE128,
908    SHAKE256,
909}
910
911impl From<ShaVariant> for ObjectIdentifierAsn1 {
912    fn from(variant: ShaVariant) -> Self {
913        match variant {
914            ShaVariant::MD5 => oids::md5().into(),
915            ShaVariant::SHA1 => oids::sha1().into(),
916            ShaVariant::SHA2_224 => oids::sha224().into(),
917            ShaVariant::SHA2_256 => oids::sha256().into(),
918            ShaVariant::SHA2_384 => oids::sha384().into(),
919            ShaVariant::SHA2_512 => oids::sha512().into(),
920            ShaVariant::SHA2_512_224 => oids::sha512_224().into(),
921            ShaVariant::SHA2_512_256 => oids::sha512_256().into(),
922            ShaVariant::SHA3_224 => oids::sha3_224().into(),
923            ShaVariant::SHA3_256 => oids::sha3_256().into(),
924            ShaVariant::SHA3_384 => oids::sha3_384().into(),
925            ShaVariant::SHA3_512 => oids::sha3_512().into(),
926            ShaVariant::SHAKE128 => oids::shake128().into(),
927            ShaVariant::SHAKE256 => oids::shake256().into(),
928        }
929    }
930}
931
932impl TryFrom<ObjectIdentifierAsn1> for ShaVariant {
933    type Error = UnsupportedAlgorithmError;
934
935    fn try_from(oid: ObjectIdentifierAsn1) -> Result<Self, Self::Error> {
936        match Into::<String>::into(oid.0).as_str() {
937            oids::MD5 => Ok(ShaVariant::MD5),
938            oids::SHA1 => Ok(ShaVariant::SHA1),
939            oids::SHA224 => Ok(ShaVariant::SHA2_224),
940            oids::SHA256 => Ok(ShaVariant::SHA2_256),
941            oids::SHA384 => Ok(ShaVariant::SHA2_384),
942            oids::SHA512 => Ok(ShaVariant::SHA2_512),
943            oids::SHA512_224 => Ok(ShaVariant::SHA2_512_224),
944            oids::SHA512_256 => Ok(ShaVariant::SHA2_512_256),
945            oids::SHA3_224 => Ok(ShaVariant::SHA3_224),
946            oids::SHA3_256 => Ok(ShaVariant::SHA3_256),
947            oids::SHA3_384 => Ok(ShaVariant::SHA3_384),
948            oids::SHA3_512 => Ok(ShaVariant::SHA3_512),
949            oids::SHAKE128 => Ok(ShaVariant::SHAKE128),
950            oids::SHAKE256 => Ok(ShaVariant::SHAKE256),
951            unsupported => Err(UnsupportedAlgorithmError {
952                algorithm: unsupported.to_string(),
953            }),
954        }
955    }
956}
957
958/// [PKCS #1: RSA Cryptography Specifications Version
959/// 2.2](https://tools.ietf.org/html/rfc8017.html#section-9.2)
960///
961/// # Section 9.2
962///
963/// The type DigestInfo has the syntax:
964///
965/// ```not_rust
966///    DigestInfo ::= SEQUENCE {
967///        digestAlgorithm AlgorithmIdentifier,
968///        digest OCTET STRING
969///    }
970/// ```
971#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
972pub struct DigestInfo {
973    pub oid: AlgorithmIdentifier,
974    pub digest: OctetStringAsn1,
975}
976
977/// Raw representation of `AlgorithmIdentifier` ASN.1 type to allow parsing unknown algorithms.
978#[derive(Debug, Clone, PartialEq, Eq)]
979pub struct RawAlgorithmIdentifier {
980    algorithm: ObjectIdentifier,
981    /// Parameters here are defined in X509 as follows:
982    /// ```not_rust
983    /// parameters ANY DEFINED BY algorithm OPTIONAL
984    /// ```
985    /// therefore we will parse it as raw DER and allow user to parse it later.
986    parameters: Option<Asn1RawDer>,
987}
988
989impl RawAlgorithmIdentifier {
990    /// Create new `RawAlgorithmIdentifier` from algorithm OID and optional parameters.
991    pub fn from_parts(algorithm: ObjectIdentifier, parameters: Option<Asn1RawDer>) -> Self {
992        let parameters = parameters.and_then(|raw| {
993            // `params` field is always present and set to NULL if no parameters are needed.
994            // therefore, we need special handling to show absence of parameters in
995            // `RawAlgorithmIdentifier` API
996            if raw.0 == [0x05, 0x00] {
997                None
998            } else {
999                Some(raw)
1000            }
1001        });
1002
1003        Self { algorithm, parameters }
1004    }
1005
1006    pub fn algorithm(&self) -> &ObjectIdentifier {
1007        &self.algorithm
1008    }
1009
1010    pub fn parameters(&self) -> Option<&Asn1RawDer> {
1011        self.parameters.as_ref()
1012    }
1013}
1014
1015impl ser::Serialize for RawAlgorithmIdentifier {
1016    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1017    where
1018        S: ser::Serializer,
1019    {
1020        use ser::SerializeSeq;
1021
1022        let mut seq = serializer.serialize_seq(Some(2))?;
1023        let oid = ObjectIdentifierAsn1(self.algorithm.clone());
1024        seq.serialize_element(&oid)?;
1025        if let Some(parameters) = &self.parameters {
1026            seq.serialize_element(parameters)?;
1027        } else {
1028            // NULL should be still serialized to AlgortihmIdentifier even if params are absent
1029            seq.serialize_element(&())?;
1030        }
1031        seq.end()
1032    }
1033}
1034
1035impl<'de> de::Deserialize<'de> for RawAlgorithmIdentifier {
1036    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1037    where
1038        D: de::Deserializer<'de>,
1039    {
1040        struct RawAlgorithmIdentifierVisitor;
1041
1042        impl<'de> de::Visitor<'de> for RawAlgorithmIdentifierVisitor {
1043            type Value = RawAlgorithmIdentifier;
1044
1045            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1046                formatter.write_str("a valid DER-encoded RawAlgorithmIdentifier")
1047            }
1048
1049            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1050            where
1051                A: de::SeqAccess<'de>,
1052            {
1053                let oid: ObjectIdentifierAsn1 = seq_next_element!(seq, RawAlgorithmIdentifier, "raw algorithm oid");
1054
1055                let algorithm = oid.0;
1056                let parameters: Option<Asn1RawDer> = seq.next_element::<Asn1RawDer>()?;
1057                Ok(RawAlgorithmIdentifier::from_parts(algorithm, parameters))
1058            }
1059        }
1060
1061        deserializer.deserialize_seq(RawAlgorithmIdentifierVisitor)
1062    }
1063}
1064
1065#[cfg(test)]
1066mod tests {
1067    use super::*;
1068    use base64::engine::general_purpose;
1069    use base64::Engine as _;
1070
1071    #[test]
1072    fn aes_null_params() {
1073        let expected = [48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 1, 1, 5, 0];
1074        let aes_id = AlgorithmIdentifier::new_aes128(AesMode::Ecb, AesParameters::Null);
1075        check_serde!(aes_id: AlgorithmIdentifier in expected);
1076    }
1077
1078    #[test]
1079    fn aes_iv_params() {
1080        let expected = [
1081            48, 25, 6, 9, 96, 134, 72, 1, 101, 3, 4, 1, 1, 4, 12, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
1082            165, 165,
1083        ];
1084        let aes_id =
1085            AlgorithmIdentifier::new_aes128(AesMode::Ecb, AesParameters::InitializationVector(vec![0xA5; 12].into()));
1086        check_serde!(aes_id: AlgorithmIdentifier in expected);
1087    }
1088
1089    #[test]
1090    fn aes_ae_params() {
1091        let expected = [
1092            48, 30, 6, 9, 96, 134, 72, 1, 101, 3, 4, 1, 1, 48, 17, 4, 12, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1093            255, 255, 255, 2, 1, 12,
1094        ];
1095        let aes_id = AlgorithmIdentifier::new_aes128(
1096            AesMode::Ecb,
1097            AesParameters::AuthenticatedEncryptionParameters(AesAuthEncParams {
1098                nonce: vec![0xff; 12].into(),
1099                icv_len: vec![12].into(),
1100            }),
1101        );
1102        check_serde!(aes_id: AlgorithmIdentifier in expected);
1103    }
1104
1105    #[test]
1106    fn sha256() {
1107        let expected = [48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 5, 0];
1108        let sha = AlgorithmIdentifier::new_sha(ShaVariant::SHA2_256);
1109        check_serde!(sha: AlgorithmIdentifier in expected);
1110    }
1111
1112    #[test]
1113    fn ec_params() {
1114        let expected = [
1115            48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2,
1116        ];
1117        let ec_params =
1118            AlgorithmIdentifier::new_elliptic_curve(EcParameters::NamedCurve(oids::ecdsa_with_sha256().into()));
1119        check_serde!(ec_params: AlgorithmIdentifier in expected);
1120    }
1121
1122    #[test]
1123    fn digest_info() {
1124        let digest = picky_asn1_der::to_vec(&DigestInfo {
1125            oid: AlgorithmIdentifier::new_sha(ShaVariant::SHA2_256),
1126            // Random 32 bytes generated for a SHA256 hash
1127            digest: vec![
1128                0xf4, 0x12, 0x6b, 0x55, 0xbf, 0xcf, 0x8c, 0xc4, 0xe9, 0xe0, 0xbe, 0x5a, 0x9c, 0x16, 0x88, 0x55, 0x0f,
1129                0x26, 0x00, 0x8c, 0x2c, 0xa5, 0xf6, 0xaf, 0xbd, 0xe7, 0x9c, 0x42, 0x22, 0xe9, 0x25, 0xed,
1130            ]
1131            .into(),
1132        })
1133        .unwrap();
1134
1135        let expected = vec![
1136            0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04,
1137            0x20, 0xf4, 0x12, 0x6b, 0x55, 0xbf, 0xcf, 0x8c, 0xc4, 0xe9, 0xe0, 0xbe, 0x5a, 0x9c, 0x16, 0x88, 0x55, 0x0f,
1138            0x26, 0x00, 0x8c, 0x2c, 0xa5, 0xf6, 0xaf, 0xbd, 0xe7, 0x9c, 0x42, 0x22, 0xe9, 0x25, 0xed,
1139        ];
1140
1141        assert_eq!(digest, expected);
1142    }
1143
1144    #[test]
1145    fn rsa_pss_params_sha256() {
1146        let expected = [
1147            0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
1148            0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d,
1149            0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x20,
1150        ];
1151        let structure = RsassaPssParams::new(HashAlgorithm::SHA256);
1152        check_serde!(structure: RsassaPssParams in expected);
1153    }
1154
1155    #[test]
1156    fn rsa_pss_params_sha384() {
1157        let expected = [
1158            0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
1159            0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d,
1160            0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x30,
1161        ];
1162        let structure = RsassaPssParams::new(HashAlgorithm::SHA384);
1163        check_serde!(structure: RsassaPssParams in expected);
1164    }
1165
1166    #[test]
1167    fn rsa_pss_params_sha512() {
1168        let expected = [
1169            0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
1170            0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d,
1171            0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x40,
1172        ];
1173        let structure = RsassaPssParams::new(HashAlgorithm::SHA512);
1174        check_serde!(structure: RsassaPssParams in expected);
1175    }
1176
1177    #[test]
1178    fn rsa_pss_encryption() {
1179        let expected = [
1180            0x30, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0A, 0x30, 0x34, 0xa0, 0x0f, 0x30,
1181            0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa1, 0x1c, 0x30, 0x1a,
1182            0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
1183            0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x20,
1184        ];
1185        let structure = AlgorithmIdentifier::new_rsassa_pss(RsassaPssParams::new(HashAlgorithm::SHA256));
1186        check_serde!(structure: AlgorithmIdentifier in expected);
1187    }
1188
1189    #[test]
1190    fn rsa_encryption() {
1191        let expected = [
1192            0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00,
1193        ];
1194        let rsa_encryption = AlgorithmIdentifier::new_rsa_encryption();
1195        check_serde!(rsa_encryption: AlgorithmIdentifier in expected);
1196    }
1197
1198    #[test]
1199    fn rsa_encryption_with_missing_params() {
1200        let encoded = [
1201            0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
1202        ];
1203        let deserialized: AlgorithmIdentifier =
1204            picky_asn1_der::from_bytes(&encoded).expect("failed AlgorithmIdentifier deserialization");
1205        pretty_assertions::assert_eq!(
1206            deserialized,
1207            AlgorithmIdentifier::new_rsa_encryption(),
1208            concat!("deserialized ", stringify!($item), " doesn't match")
1209        );
1210    }
1211
1212    #[test]
1213    fn raw_algorithm_roundtrip_no_params() {
1214        let encoded = [
1215            0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x09, 0x05, 0x00,
1216        ];
1217        let decoded: RawAlgorithmIdentifier = picky_asn1_der::from_bytes(&encoded).unwrap();
1218        let expected = RawAlgorithmIdentifier::from_parts(oids::hmac_with_sha256(), None);
1219        pretty_assertions::assert_eq!(decoded, expected);
1220        check_serde!(decoded: RawAlgorithmIdentifier in encoded);
1221    }
1222
1223    #[test]
1224    fn raw_algorithm_roundtrip() {
1225        let encoded = [
1226            0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64, 0x69,
1227            0x61, 0x74, 0x65, 0x5F, 0x63, 0x61,
1228        ];
1229        let decoded: RawAlgorithmIdentifier = picky_asn1_der::from_bytes(&encoded).unwrap();
1230        let oid: ObjectIdentifier = "2.5.4.3".to_string().try_into().unwrap();
1231        let params = Asn1RawDer(vec![
1232            0x0C, 0x0F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x5F, 0x63, 0x61,
1233        ]);
1234        let expected = RawAlgorithmIdentifier::from_parts(oid, Some(params));
1235        pretty_assertions::assert_eq!(decoded, expected);
1236        check_serde!(decoded: RawAlgorithmIdentifier in encoded);
1237    }
1238}