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#[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 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 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 AlgorithmIdentifierParameters::None
340 }
341 oids::EC_PUBLIC_KEY => AlgorithmIdentifierParameters::Ec(seq_next_element!(
344 seq,
345 EcParameters,
346 AlgorithmIdentifier,
347 "elliptic curves parameters"
348 )),
349 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 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#[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 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#[derive(Clone, Copy, PartialEq, Eq, Debug)]
496#[allow(non_camel_case_types)]
497pub enum HashAlgorithm {
498 SHA224,
502 SHA256,
503 SHA384,
504 SHA512,
505}
506
507impl HashAlgorithm {
508 pub fn len(&self) -> usize {
509 use HashAlgorithm::*;
510 match self {
511 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 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::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 }
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 .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)] pub enum ShaVariant {
894 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#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
972pub struct DigestInfo {
973 pub oid: AlgorithmIdentifier,
974 pub digest: OctetStringAsn1,
975}
976
977#[derive(Debug, Clone, PartialEq, Eq)]
979pub struct RawAlgorithmIdentifier {
980 algorithm: ObjectIdentifier,
981 parameters: Option<Asn1RawDer>,
987}
988
989impl RawAlgorithmIdentifier {
990 pub fn from_parts(algorithm: ObjectIdentifier, parameters: Option<Asn1RawDer>) -> Self {
992 let parameters = parameters.and_then(|raw| {
993 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 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 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}