1use {
8 crate::{
9 X509CertificateError as Error,
10 rfc3447::DigestInfo,
11 rfc5280::{AlgorithmIdentifier, AlgorithmParameter},
12 },
13 aws_lc_rs::{digest, signature},
14 bcder::{ConstOid, OctetString, Oid, encode::Values},
15 spki::ObjectIdentifier,
16 std::fmt::{Display, Formatter},
17};
18
19const OID_SHA1: ConstOid = Oid(&[43, 14, 3, 2, 26]);
23
24const OID_SHA256: ConstOid = Oid(&[96, 134, 72, 1, 101, 3, 4, 2, 1]);
28
29const OID_SHA384: ConstOid = Oid(&[96, 134, 72, 1, 101, 3, 4, 2, 2]);
33
34const OID_SHA512: ConstOid = Oid(&[96, 134, 72, 1, 101, 3, 4, 2, 3]);
38
39const OID_SHA1_RSA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 1, 5]);
43
44const OID_SHA256_RSA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 1, 11]);
48
49const OID_SHA384_RSA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 1, 12]);
53
54const OID_SHA512_RSA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 1, 13]);
58
59const OID_RSA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 1, 1]);
63
64pub(crate) const OID_ECDSA_SHA256: ConstOid = Oid(&[42, 134, 72, 206, 61, 4, 3, 2]);
68
69pub(crate) const OID_ECDSA_SHA384: ConstOid = Oid(&[42, 134, 72, 206, 61, 4, 3, 3]);
73
74pub(crate) const OID_EC_PUBLIC_KEY: ConstOid = Oid(&[42, 134, 72, 206, 61, 2, 1]);
78
79const OID_ED25519_KEY_AGREEMENT: ConstOid = Oid(&[43, 101, 110]);
83
84const OID_ED25519_SIGNATURE_ALGORITHM: ConstOid = Oid(&[43, 101, 112]);
88
89pub(crate) const OID_EC_SECP256R1: ConstOid = Oid(&[42, 134, 72, 206, 61, 3, 1, 7]);
93
94pub(crate) const OID_EC_SECP384R1: ConstOid = Oid(&[43, 129, 4, 0, 34]);
98
99pub(crate) const OID_NO_SIGNATURE_ALGORITHM: ConstOid = Oid(&[43, 6, 1, 5, 5, 7, 6, 2]);
103
104#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
115pub enum DigestAlgorithm {
116 Sha1,
120
121 Sha256,
125
126 Sha384,
130
131 Sha512,
135}
136
137impl Display for DigestAlgorithm {
138 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
139 match self {
140 DigestAlgorithm::Sha1 => f.write_str("SHA-1"),
141 DigestAlgorithm::Sha256 => f.write_str("SHA-256"),
142 DigestAlgorithm::Sha384 => f.write_str("SHA-384"),
143 DigestAlgorithm::Sha512 => f.write_str("SHA-512"),
144 }
145 }
146}
147
148impl From<DigestAlgorithm> for Oid {
149 fn from(alg: DigestAlgorithm) -> Self {
150 Oid(match alg {
151 DigestAlgorithm::Sha1 => OID_SHA1.as_ref(),
152 DigestAlgorithm::Sha256 => OID_SHA256.as_ref(),
153 DigestAlgorithm::Sha384 => OID_SHA384.as_ref(),
154 DigestAlgorithm::Sha512 => OID_SHA512.as_ref(),
155 }
156 .into())
157 }
158}
159
160impl TryFrom<&Oid> for DigestAlgorithm {
161 type Error = Error;
162
163 fn try_from(v: &Oid) -> Result<Self, Self::Error> {
164 if v == &OID_SHA1 {
165 Ok(Self::Sha1)
166 } else if v == &OID_SHA256 {
167 Ok(Self::Sha256)
168 } else if v == &OID_SHA384 {
169 Ok(Self::Sha384)
170 } else if v == &OID_SHA512 {
171 Ok(Self::Sha512)
172 } else {
173 Err(Error::UnknownDigestAlgorithm(format!("{}", v)))
174 }
175 }
176}
177
178impl TryFrom<&AlgorithmIdentifier> for DigestAlgorithm {
179 type Error = Error;
180
181 fn try_from(v: &AlgorithmIdentifier) -> Result<Self, Self::Error> {
182 Self::try_from(&v.algorithm)
183 }
184}
185
186impl From<DigestAlgorithm> for AlgorithmIdentifier {
187 fn from(alg: DigestAlgorithm) -> Self {
188 Self {
189 algorithm: alg.into(),
190 parameters: None,
191 }
192 }
193}
194
195impl From<DigestAlgorithm> for digest::Context {
196 fn from(alg: DigestAlgorithm) -> Self {
197 digest::Context::new(match alg {
198 DigestAlgorithm::Sha1 => &digest::SHA1_FOR_LEGACY_USE_ONLY,
199 DigestAlgorithm::Sha256 => &digest::SHA256,
200 DigestAlgorithm::Sha384 => &digest::SHA384,
201 DigestAlgorithm::Sha512 => &digest::SHA512,
202 })
203 }
204}
205
206impl DigestAlgorithm {
207 pub fn digester(&self) -> digest::Context {
209 digest::Context::from(*self)
210 }
211
212 pub fn digest_data(&self, data: &[u8]) -> Vec<u8> {
214 let mut h = self.digester();
215 h.update(data);
216 h.finish().as_ref().to_vec()
217 }
218
219 pub fn digest_reader<R: std::io::Read>(&self, fh: &mut R) -> Result<Vec<u8>, std::io::Error> {
221 let mut h = self.digester();
222
223 loop {
224 let mut buffer = [0u8; 16384];
225 let count = fh.read(&mut buffer)?;
226
227 h.update(&buffer[0..count]);
228
229 if count < buffer.len() {
230 break;
231 }
232 }
233
234 Ok(h.finish().as_ref().to_vec())
235 }
236
237 pub fn digest_path(&self, path: &std::path::Path) -> Result<Vec<u8>, std::io::Error> {
239 self.digest_reader(&mut std::fs::File::open(path)?)
240 }
241
242 pub fn rsa_pkcs1_encode(
251 &self,
252 message: &[u8],
253 target_length_in_bytes: usize,
254 ) -> Result<Vec<u8>, Error> {
255 let digest = self.digest_data(message);
256
257 let digest_info = DigestInfo {
258 algorithm: (*self).into(),
259 digest: OctetString::new(digest.into()),
260 };
261 let mut digest_info_der = vec![];
262 digest_info.write_encoded(bcder::Mode::Der, &mut digest_info_der)?;
263
264 let encoded_digest_len = digest_info_der.len();
265
266 if encoded_digest_len + 11 > target_length_in_bytes {
270 return Err(Error::PkcsEncodeTooShort);
271 }
272
273 let pad_len = target_length_in_bytes - encoded_digest_len - 3;
274
275 let mut res = vec![0xff; target_length_in_bytes];
276 res[0] = 0x00;
278 res[1] = 0x01;
280 res[2 + pad_len] = 0x00;
283
284 let digest_destination = &mut res[3 + pad_len..];
285 digest_destination.copy_from_slice(&digest_info_der);
286
287 Ok(res)
288 }
289}
290
291#[derive(Copy, Clone, Debug, Eq, PartialEq)]
302pub enum SignatureAlgorithm {
303 RsaSha1,
307
308 RsaSha256,
312
313 RsaSha384,
317
318 RsaSha512,
322
323 EcdsaSha256,
327
328 EcdsaSha384,
332
333 Ed25519,
337
338 NoSignature(DigestAlgorithm),
342}
343
344impl SignatureAlgorithm {
345 pub fn from_oid_and_digest_algorithm(
358 oid: &Oid,
359 digest_algorithm: DigestAlgorithm,
360 ) -> Result<Self, Error> {
361 match Self::try_from(oid) {
362 Ok(alg) => Ok(alg),
363 _ => match KeyAlgorithm::try_from(oid) {
364 Ok(key_alg) => match key_alg {
365 KeyAlgorithm::Rsa => match digest_algorithm {
366 DigestAlgorithm::Sha1 => Ok(Self::RsaSha1),
367 DigestAlgorithm::Sha256 => Ok(Self::RsaSha256),
368 DigestAlgorithm::Sha384 => Ok(Self::RsaSha384),
369 DigestAlgorithm::Sha512 => Ok(Self::RsaSha512),
370 },
371 KeyAlgorithm::Ed25519 => Ok(Self::Ed25519),
372 KeyAlgorithm::Ecdsa(_) => match digest_algorithm {
373 DigestAlgorithm::Sha256 => Ok(Self::EcdsaSha256),
374 DigestAlgorithm::Sha384 => Ok(Self::EcdsaSha384),
375 DigestAlgorithm::Sha1 | DigestAlgorithm::Sha512 => {
376 Err(Error::UnknownSignatureAlgorithm(format!(
377 "cannot use digest {:?} with ECDSA",
378 digest_algorithm
379 )))
380 }
381 },
382 },
383 _ => {
384 if oid == &OID_NO_SIGNATURE_ALGORITHM {
385 Ok(Self::NoSignature(digest_algorithm))
386 } else {
387 Err(Error::UnknownSignatureAlgorithm(format!(
388 "do not know how to resolve {} to a signature algorithm",
389 oid
390 )))
391 }
392 }
393 },
394 }
395 }
396
397 pub fn from_digest_algorithm(digest_algorithm: DigestAlgorithm) -> Self {
399 Self::NoSignature(digest_algorithm)
400 }
401
402 pub fn resolve_verification_algorithm(
407 &self,
408 key_algorithm: KeyAlgorithm,
409 ) -> Result<&'static dyn signature::VerificationAlgorithm, Error> {
410 match key_algorithm {
411 KeyAlgorithm::Rsa => match self {
412 Self::RsaSha1 => Ok(&signature::RSA_PKCS1_2048_8192_SHA1_FOR_LEGACY_USE_ONLY),
413 Self::RsaSha256 => Ok(&signature::RSA_PKCS1_2048_8192_SHA256),
414 Self::RsaSha384 => Ok(&signature::RSA_PKCS1_2048_8192_SHA384),
415 Self::RsaSha512 => Ok(&signature::RSA_PKCS1_2048_8192_SHA512),
416 alg => Err(Error::UnsupportedSignatureVerification(key_algorithm, *alg)),
417 },
418 KeyAlgorithm::Ed25519 => match self {
419 Self::Ed25519 => Ok(&signature::ED25519),
420 alg => Err(Error::UnsupportedSignatureVerification(key_algorithm, *alg)),
421 },
422 KeyAlgorithm::Ecdsa(curve) => match curve {
423 EcdsaCurve::Secp256r1 => match self {
424 Self::EcdsaSha256 => Ok(&signature::ECDSA_P256_SHA256_ASN1),
425 Self::EcdsaSha384 => Ok(&signature::ECDSA_P256_SHA384_ASN1),
426 alg => Err(Error::UnsupportedSignatureVerification(key_algorithm, *alg)),
427 },
428 EcdsaCurve::Secp384r1 => match self {
429 Self::EcdsaSha256 => Ok(&signature::ECDSA_P384_SHA256_ASN1),
430 Self::EcdsaSha384 => Ok(&signature::ECDSA_P384_SHA384_ASN1),
431 alg => Err(Error::UnsupportedSignatureVerification(key_algorithm, *alg)),
432 },
433 },
434 }
435 }
436
437 pub fn digest_algorithm(&self) -> Option<DigestAlgorithm> {
439 match self {
440 SignatureAlgorithm::RsaSha1 => Some(DigestAlgorithm::Sha1),
441 SignatureAlgorithm::RsaSha256 => Some(DigestAlgorithm::Sha256),
442 SignatureAlgorithm::RsaSha384 => Some(DigestAlgorithm::Sha384),
443 SignatureAlgorithm::RsaSha512 => Some(DigestAlgorithm::Sha512),
444 SignatureAlgorithm::EcdsaSha256 => Some(DigestAlgorithm::Sha256),
445 SignatureAlgorithm::EcdsaSha384 => Some(DigestAlgorithm::Sha384),
446 SignatureAlgorithm::Ed25519 => None,
448 SignatureAlgorithm::NoSignature(digest_algorithm) => Some(*digest_algorithm),
449 }
450 }
451}
452
453impl Display for SignatureAlgorithm {
454 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
455 match self {
456 SignatureAlgorithm::RsaSha1 => f.write_str("SHA-1 with RSA encryption"),
457 SignatureAlgorithm::RsaSha256 => f.write_str("SHA-256 with RSA encryption"),
458 SignatureAlgorithm::RsaSha384 => f.write_str("SHA-384 with RSA encryption"),
459 SignatureAlgorithm::RsaSha512 => f.write_str("SHA-512 with RSA encryption"),
460 SignatureAlgorithm::EcdsaSha256 => f.write_str("ECDSA with SHA-256"),
461 SignatureAlgorithm::EcdsaSha384 => f.write_str("ECDSA with SHA-384"),
462 SignatureAlgorithm::Ed25519 => f.write_str("ED25519"),
463 SignatureAlgorithm::NoSignature(digest_algorithm) => {
464 f.write_fmt(format_args!("No signature with {}", digest_algorithm))
465 }
466 }
467 }
468}
469
470impl From<SignatureAlgorithm> for Oid {
471 fn from(alg: SignatureAlgorithm) -> Self {
472 Oid(match alg {
473 SignatureAlgorithm::RsaSha1 => OID_SHA1_RSA.as_ref(),
474 SignatureAlgorithm::RsaSha256 => OID_SHA256_RSA.as_ref(),
475 SignatureAlgorithm::RsaSha384 => OID_SHA384_RSA.as_ref(),
476 SignatureAlgorithm::RsaSha512 => OID_SHA512_RSA.as_ref(),
477 SignatureAlgorithm::EcdsaSha256 => OID_ECDSA_SHA256.as_ref(),
478 SignatureAlgorithm::EcdsaSha384 => OID_ECDSA_SHA384.as_ref(),
479 SignatureAlgorithm::Ed25519 => OID_ED25519_SIGNATURE_ALGORITHM.as_ref(),
480 SignatureAlgorithm::NoSignature(_) => OID_NO_SIGNATURE_ALGORITHM.as_ref(),
481 }
482 .into())
483 }
484}
485
486impl TryFrom<&Oid> for SignatureAlgorithm {
487 type Error = Error;
488
489 fn try_from(v: &Oid) -> Result<Self, Self::Error> {
490 if v == &OID_SHA1_RSA {
491 Ok(Self::RsaSha1)
492 } else if v == &OID_SHA256_RSA {
493 Ok(Self::RsaSha256)
494 } else if v == &OID_SHA384_RSA {
495 Ok(Self::RsaSha384)
496 } else if v == &OID_SHA512_RSA {
497 Ok(Self::RsaSha512)
498 } else if v == &OID_ECDSA_SHA256 {
499 Ok(Self::EcdsaSha256)
500 } else if v == &OID_ECDSA_SHA384 {
501 Ok(Self::EcdsaSha384)
502 } else if v == &OID_ED25519_SIGNATURE_ALGORITHM {
503 Ok(Self::Ed25519)
504 } else {
505 Err(Error::UnknownSignatureAlgorithm(format!("{}", v)))
506 }
507 }
508}
509
510impl TryFrom<&AlgorithmIdentifier> for SignatureAlgorithm {
511 type Error = Error;
512
513 fn try_from(v: &AlgorithmIdentifier) -> Result<Self, Self::Error> {
514 Self::try_from(&v.algorithm)
515 }
516}
517
518impl From<SignatureAlgorithm> for AlgorithmIdentifier {
519 fn from(alg: SignatureAlgorithm) -> Self {
520 Self {
521 algorithm: alg.into(),
522 parameters: None,
523 }
524 }
525}
526
527#[derive(Copy, Clone, Debug, Eq, PartialEq)]
529pub enum EcdsaCurve {
530 Secp256r1,
531 Secp384r1,
532}
533
534impl EcdsaCurve {
535 pub fn all() -> &'static [Self] {
537 &[Self::Secp256r1, Self::Secp384r1]
538 }
539
540 pub fn as_signature_oid(&self) -> Oid {
542 Oid(match self {
543 Self::Secp256r1 => OID_EC_SECP256R1.as_ref().into(),
544 Self::Secp384r1 => OID_EC_SECP384R1.as_ref().into(),
545 })
546 }
547}
548
549impl TryFrom<&Oid> for EcdsaCurve {
550 type Error = Error;
551
552 fn try_from(v: &Oid) -> Result<Self, Self::Error> {
553 if v == &OID_EC_SECP256R1 {
554 Ok(Self::Secp256r1)
555 } else if v == &OID_EC_SECP384R1 {
556 Ok(Self::Secp384r1)
557 } else {
558 Err(Error::UnknownEllipticCurve(format!("{}", v)))
559 }
560 }
561}
562
563impl From<EcdsaCurve> for &'static signature::EcdsaSigningAlgorithm {
564 fn from(curve: EcdsaCurve) -> Self {
565 match curve {
566 EcdsaCurve::Secp256r1 => &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
567 EcdsaCurve::Secp384r1 => &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
568 }
569 }
570}
571
572#[derive(Copy, Clone, Debug, Eq, PartialEq)]
577pub enum KeyAlgorithm {
578 Rsa,
582
583 Ecdsa(EcdsaCurve),
587
588 Ed25519,
590}
591
592impl Display for KeyAlgorithm {
593 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
594 match self {
595 Self::Rsa => f.write_str("RSA"),
596 Self::Ecdsa(_) => f.write_str("ECDSA"),
597 Self::Ed25519 => f.write_str("ED25519"),
598 }
599 }
600}
601
602impl TryFrom<&Oid> for KeyAlgorithm {
603 type Error = Error;
604
605 fn try_from(v: &Oid) -> Result<Self, Self::Error> {
606 if v == &OID_RSA {
607 Ok(Self::Rsa)
608 } else if v == &OID_EC_PUBLIC_KEY {
609 Ok(Self::Ecdsa(EcdsaCurve::Secp384r1))
611 } else if v == &OID_ED25519_KEY_AGREEMENT || v == &OID_ED25519_SIGNATURE_ALGORITHM {
614 Ok(Self::Ed25519)
615 } else {
616 Err(Error::UnknownKeyAlgorithm(format!("{}", v)))
617 }
618 }
619}
620
621impl TryFrom<&ObjectIdentifier> for KeyAlgorithm {
622 type Error = Error;
623
624 fn try_from(v: &ObjectIdentifier) -> Result<Self, Self::Error> {
625 match v.as_bytes() {
627 x if x == OID_RSA.as_ref() => Ok(Self::Rsa),
628 x if x == OID_EC_PUBLIC_KEY.as_ref() => Ok(Self::Ecdsa(EcdsaCurve::Secp384r1)),
629 x if x == OID_ED25519_KEY_AGREEMENT.as_ref()
630 || x == OID_ED25519_SIGNATURE_ALGORITHM.as_ref() =>
631 {
632 Ok(Self::Ed25519)
633 }
634 _ => Err(Error::UnknownKeyAlgorithm(v.to_string())),
635 }
636 }
637}
638
639impl From<KeyAlgorithm> for Oid {
640 fn from(alg: KeyAlgorithm) -> Self {
641 Oid(match alg {
642 KeyAlgorithm::Rsa => OID_RSA.as_ref(),
643 KeyAlgorithm::Ecdsa(_) => OID_EC_PUBLIC_KEY.as_ref(),
644 KeyAlgorithm::Ed25519 => OID_ED25519_KEY_AGREEMENT.as_ref(),
645 }
646 .into())
647 }
648}
649
650impl From<KeyAlgorithm> for ObjectIdentifier {
651 fn from(alg: KeyAlgorithm) -> Self {
652 let bytes = match alg {
653 KeyAlgorithm::Rsa => OID_RSA.as_ref(),
654 KeyAlgorithm::Ecdsa(_) => OID_EC_PUBLIC_KEY.as_ref(),
655 KeyAlgorithm::Ed25519 => OID_ED25519_KEY_AGREEMENT.as_ref(),
656 };
657
658 ObjectIdentifier::from_bytes(bytes).expect("OID bytes should be valid")
659 }
660}
661
662impl TryFrom<&AlgorithmIdentifier> for KeyAlgorithm {
663 type Error = Error;
664
665 fn try_from(v: &AlgorithmIdentifier) -> Result<Self, Self::Error> {
666 let ka = Self::try_from(&v.algorithm)?;
669
670 let ka = if let Some(params) = &v.parameters {
671 match ka {
672 Self::Ecdsa(_) => {
673 let curve_oid = params.decode_oid()?;
674 let curve = EcdsaCurve::try_from(&curve_oid)?;
675
676 Ok(Self::Ecdsa(curve))
677 }
678 Self::Ed25519 => {
679 if params.as_slice() == [0x05, 0x00] {
681 Ok(ka)
682 } else {
683 Err(Error::UnhandledKeyAlgorithmParameters("on ED25519"))
684 }
685 }
686 Self::Rsa => {
687 if params.as_slice() == [0x05, 0x00] {
689 Ok(ka)
690 } else {
691 Err(Error::UnhandledKeyAlgorithmParameters("on RSA"))
692 }
693 }
694 }?
695 } else {
696 ka
697 };
698
699 Ok(ka)
700 }
701}
702
703impl From<KeyAlgorithm> for AlgorithmIdentifier {
704 fn from(alg: KeyAlgorithm) -> Self {
705 let parameters = match alg {
706 KeyAlgorithm::Ed25519 => None,
707 KeyAlgorithm::Rsa => None,
708 KeyAlgorithm::Ecdsa(curve) => {
709 Some(AlgorithmParameter::from_oid(curve.as_signature_oid()))
710 }
711 };
712
713 Self {
714 algorithm: alg.into(),
715 parameters,
716 }
717 }
718}
719
720#[cfg(test)]
721mod test {
722 use super::*;
723
724 #[test]
725 fn digest_pkcs1() -> Result<(), Error> {
726 let message = b"deadbeef";
727 let raw_digest = DigestAlgorithm::Sha256.digest_data(message);
728
729 let encoded = DigestAlgorithm::Sha256.rsa_pkcs1_encode(message, 128)?;
731 assert_eq!(&encoded[0..3], &[0x00, 0x01, 0xff]);
732 assert_eq!(&encoded[96..], &raw_digest);
733
734 Ok(())
735 }
736
737 #[test]
738 fn key_algorithm_oids() -> Result<(), Error> {
739 let oid = ObjectIdentifier::from(KeyAlgorithm::Rsa);
740 assert_eq!(oid.to_string(), "1.2.840.113549.1.1.1");
741 let oid = ObjectIdentifier::new("1.2.840.113549.1.1.1").unwrap();
742 assert_eq!(KeyAlgorithm::try_from(&oid)?, KeyAlgorithm::Rsa);
743
744 let oid = ObjectIdentifier::from(KeyAlgorithm::Ecdsa(EcdsaCurve::Secp256r1));
745 assert_eq!(oid.to_string(), "1.2.840.10045.2.1");
746 let oid = ObjectIdentifier::new("1.2.840.10045.2.1").unwrap();
747 assert_eq!(
748 KeyAlgorithm::try_from(&oid)?,
749 KeyAlgorithm::Ecdsa(EcdsaCurve::Secp384r1)
750 );
751
752 let oid = ObjectIdentifier::from(KeyAlgorithm::Ed25519);
753 assert_eq!(oid.to_string(), "1.3.101.110");
754 let oid = ObjectIdentifier::new("1.3.101.110").unwrap();
755 assert_eq!(KeyAlgorithm::try_from(&oid)?, KeyAlgorithm::Ed25519);
756
757 Ok(())
758 }
759}