1#[cfg(feature = "xmlenc")]
9use std::borrow::Cow;
10
11#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
12use getrandom::rand_core::TryCryptoRng;
13use getrandom::{SysRng, rand_core::TryRng};
14
15#[cfg(feature = "xmldsig")]
16use crate::xmldsig::DigestAlgorithm;
17#[cfg(feature = "xmlenc")]
18use crate::xmlenc::{DataEncryptionAlgorithm, KeyWrapAlgorithm, RsaOaepParameters};
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22#[non_exhaustive]
23pub enum ProviderOperation {
24 Digest,
26 Sign,
28 Verify,
30 VerifyCertificate,
32 Encrypt,
34 Decrypt,
36 KeyWrap,
38 KeyUnwrap,
40 KeyTransport,
42 KeyRecovery,
44 KeyAgreement,
46 Kdf,
48 Random,
50}
51
52#[derive(Debug, Clone, Copy)]
57#[non_exhaustive]
58pub enum ProviderCapability<'a> {
59 #[cfg(feature = "xmldsig")]
61 Digest(DigestAlgorithm),
62 #[cfg(feature = "xmldsig")]
64 Sign(crate::xmldsig::SignatureAlgorithm),
65 #[cfg(feature = "xmldsig")]
67 Verify(crate::xmldsig::SignatureAlgorithm),
68 #[cfg(feature = "xmldsig")]
70 VerifyCertificate(X509SignatureAlgorithm),
71 #[cfg(feature = "xmlenc")]
73 Encrypt(DataEncryptionAlgorithm),
74 #[cfg(feature = "xmlenc")]
76 Decrypt(DataEncryptionAlgorithm),
77 #[cfg(feature = "xmlenc")]
79 KeyWrap(KeyWrapAlgorithm),
80 #[cfg(feature = "xmlenc")]
82 KeyUnwrap(KeyWrapAlgorithm),
83 #[cfg(feature = "xmlenc")]
85 KeyTransport(&'a RsaOaepParameters),
86 #[cfg(feature = "xmlenc")]
88 KeyRecovery(&'a RsaOaepParameters),
89 KeyAgreement(&'a KeyAgreementParameters<'a>),
91 Kdf(&'a KdfParameters<'a>),
93 Random,
95}
96
97impl ProviderCapability<'_> {
98 #[must_use]
100 pub const fn operation(&self) -> ProviderOperation {
101 match self {
102 #[cfg(feature = "xmldsig")]
103 Self::Digest(_) => ProviderOperation::Digest,
104 #[cfg(feature = "xmldsig")]
105 Self::Sign(_) => ProviderOperation::Sign,
106 #[cfg(feature = "xmldsig")]
107 Self::Verify(_) => ProviderOperation::Verify,
108 #[cfg(feature = "xmldsig")]
109 Self::VerifyCertificate(_) => ProviderOperation::VerifyCertificate,
110 #[cfg(feature = "xmlenc")]
111 Self::Encrypt(_) => ProviderOperation::Encrypt,
112 #[cfg(feature = "xmlenc")]
113 Self::Decrypt(_) => ProviderOperation::Decrypt,
114 #[cfg(feature = "xmlenc")]
115 Self::KeyWrap(_) => ProviderOperation::KeyWrap,
116 #[cfg(feature = "xmlenc")]
117 Self::KeyUnwrap(_) => ProviderOperation::KeyUnwrap,
118 #[cfg(feature = "xmlenc")]
119 Self::KeyTransport(_) => ProviderOperation::KeyTransport,
120 #[cfg(feature = "xmlenc")]
121 Self::KeyRecovery(_) => ProviderOperation::KeyRecovery,
122 Self::KeyAgreement(_) => ProviderOperation::KeyAgreement,
123 Self::Kdf(_) => ProviderOperation::Kdf,
124 Self::Random => ProviderOperation::Random,
125 }
126 }
127
128 #[must_use]
130 pub fn algorithm(&self) -> Option<&str> {
131 match self {
132 #[cfg(feature = "xmldsig")]
133 Self::Digest(algorithm) => Some(algorithm.uri()),
134 #[cfg(feature = "xmldsig")]
135 Self::Sign(algorithm) | Self::Verify(algorithm) => Some(algorithm.uri()),
136 #[cfg(feature = "xmldsig")]
137 Self::VerifyCertificate(algorithm) => Some(algorithm.oid()),
138 #[cfg(feature = "xmlenc")]
139 Self::Encrypt(algorithm) | Self::Decrypt(algorithm) => Some(algorithm.uri()),
140 #[cfg(feature = "xmlenc")]
141 Self::KeyWrap(algorithm) | Self::KeyUnwrap(algorithm) => Some(algorithm.uri()),
142 #[cfg(feature = "xmlenc")]
143 Self::KeyTransport(parameters) | Self::KeyRecovery(parameters) => {
144 Some(parameters.algorithm.uri())
145 }
146 Self::KeyAgreement(parameters) => Some(parameters.algorithm),
147 Self::Kdf(parameters) => Some(parameters.algorithm),
148 Self::Random => None,
149 }
150 }
151}
152
153#[derive(Debug, Clone, Copy, PartialEq, Eq)]
155pub struct KeyAgreementParameters<'a> {
156 pub algorithm: &'a str,
158 pub peer_public_key: &'a [u8],
160}
161
162#[derive(Debug, Clone, Copy, PartialEq, Eq)]
164pub struct KdfParameters<'a> {
165 pub algorithm: &'a str,
167 pub digest: Option<&'a str>,
169 pub salt: &'a [u8],
171 pub info: &'a [u8],
173 pub iterations: u64,
175 pub output_len: usize,
177}
178
179#[cfg(feature = "xmldsig")]
181#[derive(Debug, Clone, Copy, PartialEq, Eq)]
182#[non_exhaustive]
183pub enum X509SignatureAlgorithm {
184 Dsa(DigestAlgorithm),
186 RsaPkcs1v15(DigestAlgorithm),
188 RsaPss {
190 digest: DigestAlgorithm,
192 mgf_digest: DigestAlgorithm,
194 salt_len: usize,
196 },
197 Ecdsa(DigestAlgorithm),
199 Ed25519,
201}
202
203#[cfg(feature = "xmldsig")]
204impl X509SignatureAlgorithm {
205 #[must_use]
207 pub const fn oid(self) -> &'static str {
208 match self {
209 Self::Dsa(DigestAlgorithm::Sha1) => "1.2.840.10040.4.3",
210 Self::Dsa(DigestAlgorithm::Sha256) => "2.16.840.1.101.3.4.3.2",
211 Self::Dsa(DigestAlgorithm::Sha384) => "2.16.840.1.101.3.4.3.3",
212 Self::Dsa(DigestAlgorithm::Sha512) => "2.16.840.1.101.3.4.3.4",
213 Self::RsaPkcs1v15(DigestAlgorithm::Sha1) => "1.2.840.113549.1.1.5",
214 Self::RsaPkcs1v15(DigestAlgorithm::Sha256) => "1.2.840.113549.1.1.11",
215 Self::RsaPkcs1v15(DigestAlgorithm::Sha384) => "1.2.840.113549.1.1.12",
216 Self::RsaPkcs1v15(DigestAlgorithm::Sha512) => "1.2.840.113549.1.1.13",
217 Self::RsaPss { .. } => "1.2.840.113549.1.1.10",
218 Self::Ecdsa(DigestAlgorithm::Sha1) => "1.2.840.10045.4.1",
219 Self::Ecdsa(DigestAlgorithm::Sha256) => "1.2.840.10045.4.3.2",
220 Self::Ecdsa(DigestAlgorithm::Sha384) => "1.2.840.10045.4.3.3",
221 Self::Ecdsa(DigestAlgorithm::Sha512) => "1.2.840.10045.4.3.4",
222 Self::Ed25519 => "1.3.101.112",
223 }
224 }
225}
226
227#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
229#[non_exhaustive]
230pub enum ProviderInputError {
231 #[error("failed to initialize {0}")]
233 PrimitiveInitialization(&'static str),
234 #[error("invalid AES-CBC framing")]
236 AesCbcFraming,
237 #[error("invalid AES-CBC ciphertext")]
239 AesCbcCiphertext,
240 #[error("invalid AES-GCM framing")]
242 AesGcmFraming,
243 #[error("invalid AES key-wrap framing")]
245 AesKeyWrapFraming,
246 #[error("legacy RSA-OAEP requires MGF1-SHA1")]
248 LegacyRsaOaepMgf,
249}
250
251#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
253#[non_exhaustive]
254pub enum ProviderError {
255 #[error("provider does not support {operation:?} with algorithm {algorithm:?}")]
257 Unsupported {
258 operation: ProviderOperation,
260 algorithm: Option<String>,
262 },
263 #[error("invalid key size: expected {expected} bytes, got {actual}")]
265 InvalidKeySize {
266 expected: usize,
268 actual: usize,
270 },
271 #[error(
274 "invalid provider output size for {operation:?}: expected {expected} bytes, got {actual}"
275 )]
276 InvalidOutputSize {
277 operation: ProviderOperation,
279 expected: usize,
281 actual: usize,
283 },
284 #[error(
287 "invalid provider output size for {operation:?}: expected {minimum}..={maximum} bytes, got {actual}"
288 )]
289 InvalidOutputSizeRange {
290 operation: ProviderOperation,
292 minimum: usize,
294 maximum: usize,
296 actual: usize,
298 },
299 #[error("invalid cryptographic input: {0}")]
301 InvalidInput(ProviderInputError),
302 #[error("cryptographic authentication failed")]
304 AuthenticationFailed,
305 #[error("operating-system random number generation failed: {0}")]
307 Random(String),
308}
309
310#[cfg(feature = "xmlenc")]
316pub trait KeyTransportKey: Send + Sync {
317 fn rsa_modulus(&self) -> Cow<'_, [u8]>;
323
324 fn rsa_exponent(&self) -> Cow<'_, [u8]>;
326
327 fn transport_with_provider(
329 &self,
330 provider: &dyn CryptoProvider,
331 parameters: &RsaOaepParameters,
332 plaintext: &[u8],
333 ) -> Result<Vec<u8>, ProviderError>;
334}
335
336#[cfg(feature = "xmlenc")]
341pub trait KeyRecoveryKey: Send + Sync {
342 fn ciphertext_len(&self) -> usize;
345
346 fn recover_with_provider(
348 &self,
349 provider: &dyn CryptoProvider,
350 parameters: &RsaOaepParameters,
351 ciphertext: &[u8],
352 ) -> Result<Vec<u8>, ProviderError>;
353}
354
355pub trait KeyAgreementKey: Send + Sync {
357 fn agree(&self, parameters: &KeyAgreementParameters<'_>) -> Result<Vec<u8>, ProviderError>;
359}
360
361pub trait CryptoProvider: Send + Sync {
363 fn name(&self) -> &'static str;
365
366 fn supports(&self, capability: ProviderCapability<'_>) -> bool;
368
369 fn fill_random(&self, output: &mut [u8]) -> Result<(), ProviderError>;
371
372 #[cfg(feature = "xmldsig")]
374 fn digest(&self, algorithm: DigestAlgorithm, data: &[u8]) -> Result<Vec<u8>, ProviderError>;
375
376 #[cfg(feature = "xmldsig")]
382 fn sign(
383 &self,
384 key: &dyn crate::xmldsig::SigningKey,
385 algorithm: crate::xmldsig::SignatureAlgorithm,
386 data: &[u8],
387 ) -> Result<Vec<u8>, crate::xmldsig::SigningKeyError>;
388
389 #[cfg(feature = "xmldsig")]
394 fn verify(
395 &self,
396 key: &dyn crate::xmldsig::VerifyingKey,
397 algorithm: crate::xmldsig::SignatureAlgorithm,
398 data: &[u8],
399 signature: &[u8],
400 ) -> Result<bool, crate::xmldsig::DsigError>;
401
402 #[cfg(feature = "xmldsig")]
404 fn verify_x509_signature(
405 &self,
406 algorithm: X509SignatureAlgorithm,
407 signed_data: &[u8],
408 signature: &[u8],
409 issuer_spki_der: &[u8],
410 ) -> Result<bool, ProviderError> {
411 let _ = (signed_data, signature, issuer_spki_der);
412 Err(ProviderError::Unsupported {
413 operation: ProviderOperation::VerifyCertificate,
414 algorithm: Some(algorithm.oid().to_owned()),
415 })
416 }
417
418 #[cfg(feature = "xmlenc")]
420 fn encrypt_data(
421 &self,
422 algorithm: DataEncryptionAlgorithm,
423 key: &[u8],
424 plaintext: &[u8],
425 ) -> Result<Vec<u8>, ProviderError>;
426
427 #[cfg(feature = "xmlenc")]
429 fn decrypt_data(
430 &self,
431 algorithm: DataEncryptionAlgorithm,
432 key: &[u8],
433 ciphertext: &[u8],
434 ) -> Result<Vec<u8>, ProviderError>;
435
436 #[cfg(feature = "xmlenc")]
442 fn wrap_key(
443 &self,
444 algorithm: KeyWrapAlgorithm,
445 kek: &[u8],
446 key: &[u8],
447 ) -> Result<Vec<u8>, ProviderError>;
448
449 #[cfg(feature = "xmlenc")]
451 fn unwrap_key(
452 &self,
453 algorithm: KeyWrapAlgorithm,
454 kek: &[u8],
455 wrapped: &[u8],
456 ) -> Result<Vec<u8>, ProviderError>;
457
458 #[cfg(feature = "xmlenc")]
460 fn transport_key(
461 &self,
462 key: &dyn KeyTransportKey,
463 parameters: &RsaOaepParameters,
464 plaintext: &[u8],
465 ) -> Result<Vec<u8>, ProviderError>;
466
467 #[cfg(feature = "xmlenc")]
469 fn recover_key(
470 &self,
471 key: &dyn KeyRecoveryKey,
472 parameters: &RsaOaepParameters,
473 ciphertext: &[u8],
474 ) -> Result<Vec<u8>, ProviderError>;
475
476 fn agree_key(
478 &self,
479 key: &dyn KeyAgreementKey,
480 parameters: &KeyAgreementParameters<'_>,
481 ) -> Result<Vec<u8>, ProviderError> {
482 self.require_capability(ProviderCapability::KeyAgreement(parameters))?;
483 key.agree(parameters)
484 }
485
486 fn derive_key(
492 &self,
493 parameters: &KdfParameters<'_>,
494 secret: &[u8],
495 ) -> Result<Vec<u8>, ProviderError>;
496
497 fn require_capability(&self, capability: ProviderCapability<'_>) -> Result<(), ProviderError> {
499 if self.supports(capability) {
500 Ok(())
501 } else {
502 Err(ProviderError::Unsupported {
503 operation: capability.operation(),
504 algorithm: capability.algorithm().map(str::to_owned),
505 })
506 }
507 }
508}
509
510#[derive(Debug, Clone, Copy, Default)]
512pub struct RustCryptoProvider;
513
514#[cfg(feature = "xmlenc")]
516#[derive(Clone)]
517pub struct RustCryptoRsaPublicKey {
518 key: rsa::RsaPublicKey,
519 modulus: Vec<u8>,
520 exponent: Vec<u8>,
521}
522
523#[cfg(feature = "xmlenc")]
524impl RustCryptoRsaPublicKey {
525 #[must_use]
527 pub fn new(key: rsa::RsaPublicKey) -> Self {
528 use rsa::traits::PublicKeyParts as _;
529 let modulus = key.n().to_be_bytes_trimmed_vartime().into_vec();
530 let exponent = key.e().to_be_bytes_trimmed_vartime().into_vec();
531 Self {
532 key,
533 modulus,
534 exponent,
535 }
536 }
537}
538
539#[cfg(feature = "xmlenc")]
540impl From<rsa::RsaPublicKey> for RustCryptoRsaPublicKey {
541 fn from(key: rsa::RsaPublicKey) -> Self {
542 Self::new(key)
543 }
544}
545
546#[cfg(feature = "xmlenc")]
547impl KeyTransportKey for RustCryptoRsaPublicKey {
548 fn rsa_modulus(&self) -> Cow<'_, [u8]> {
549 Cow::Borrowed(&self.modulus)
550 }
551
552 fn rsa_exponent(&self) -> Cow<'_, [u8]> {
553 Cow::Borrowed(&self.exponent)
554 }
555
556 fn transport_with_provider(
557 &self,
558 provider: &dyn CryptoProvider,
559 parameters: &RsaOaepParameters,
560 plaintext: &[u8],
561 ) -> Result<Vec<u8>, ProviderError> {
562 rustcrypto::transport_key(provider, &self.key, parameters, plaintext)
563 }
564}
565
566#[cfg(feature = "xmlenc")]
567impl KeyTransportKey for rsa::RsaPublicKey {
568 fn rsa_modulus(&self) -> Cow<'_, [u8]> {
569 use rsa::traits::PublicKeyParts as _;
570 Cow::Owned(self.n().to_be_bytes_trimmed_vartime().into_vec())
571 }
572
573 fn rsa_exponent(&self) -> Cow<'_, [u8]> {
574 use rsa::traits::PublicKeyParts as _;
575 Cow::Owned(self.e().to_be_bytes_trimmed_vartime().into_vec())
576 }
577
578 fn transport_with_provider(
579 &self,
580 provider: &dyn CryptoProvider,
581 parameters: &RsaOaepParameters,
582 plaintext: &[u8],
583 ) -> Result<Vec<u8>, ProviderError> {
584 rustcrypto::transport_key(provider, self, parameters, plaintext)
585 }
586}
587
588#[cfg(feature = "xmlenc")]
590#[derive(Clone)]
591pub struct RustCryptoRsaPrivateKey {
592 key: rsa::RsaPrivateKey,
593 ciphertext_len: usize,
594}
595
596#[cfg(feature = "xmlenc")]
597impl RustCryptoRsaPrivateKey {
598 #[must_use]
600 pub fn new(key: rsa::RsaPrivateKey) -> Self {
601 use rsa::traits::PublicKeyParts as _;
602 let ciphertext_len = key.size();
603 Self {
604 key,
605 ciphertext_len,
606 }
607 }
608}
609
610#[cfg(feature = "xmlenc")]
611impl From<rsa::RsaPrivateKey> for RustCryptoRsaPrivateKey {
612 fn from(key: rsa::RsaPrivateKey) -> Self {
613 Self::new(key)
614 }
615}
616
617#[cfg(feature = "xmlenc")]
618impl KeyRecoveryKey for RustCryptoRsaPrivateKey {
619 fn ciphertext_len(&self) -> usize {
620 self.ciphertext_len
621 }
622
623 fn recover_with_provider(
624 &self,
625 provider: &dyn CryptoProvider,
626 parameters: &RsaOaepParameters,
627 ciphertext: &[u8],
628 ) -> Result<Vec<u8>, ProviderError> {
629 rustcrypto::recover_key(provider, &self.key, parameters, ciphertext)
630 }
631}
632
633#[cfg(feature = "xmlenc")]
634impl KeyRecoveryKey for rsa::RsaPrivateKey {
635 fn ciphertext_len(&self) -> usize {
636 use rsa::traits::PublicKeyParts as _;
637 self.size()
638 }
639
640 fn recover_with_provider(
641 &self,
642 provider: &dyn CryptoProvider,
643 parameters: &RsaOaepParameters,
644 ciphertext: &[u8],
645 ) -> Result<Vec<u8>, ProviderError> {
646 rustcrypto::recover_key(provider, self, parameters, ciphertext)
647 }
648}
649
650pub static RUST_CRYPTO_PROVIDER: RustCryptoProvider = RustCryptoProvider;
652
653#[must_use]
655pub fn default_provider() -> &'static dyn CryptoProvider {
656 &RUST_CRYPTO_PROVIDER
657}
658
659#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
661pub(crate) struct ProviderRng<'a>(pub(crate) &'a dyn CryptoProvider);
662
663#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
664impl TryRng for ProviderRng<'_> {
665 type Error = ProviderError;
666
667 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
668 let mut bytes = [0_u8; 4];
669 self.try_fill_bytes(&mut bytes)?;
670 Ok(u32::from_le_bytes(bytes))
671 }
672
673 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
674 let mut bytes = [0_u8; 8];
675 self.try_fill_bytes(&mut bytes)?;
676 Ok(u64::from_le_bytes(bytes))
677 }
678
679 fn try_fill_bytes(&mut self, output: &mut [u8]) -> Result<(), Self::Error> {
680 self.0.fill_random(output)
681 }
682}
683
684#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
685impl TryCryptoRng for ProviderRng<'_> {}
686
687impl CryptoProvider for RustCryptoProvider {
688 fn name(&self) -> &'static str {
689 "rustcrypto"
690 }
691
692 fn supports(&self, capability: ProviderCapability<'_>) -> bool {
693 match capability {
694 #[cfg(feature = "xmldsig")]
695 ProviderCapability::Digest(_) => true,
696 #[cfg(feature = "xmldsig")]
697 ProviderCapability::Sign(algorithm) => is_supported_signing_uri(algorithm.uri()),
698 #[cfg(feature = "xmldsig")]
699 ProviderCapability::Verify(algorithm) => is_supported_signature_uri(algorithm.uri()),
700 #[cfg(feature = "xmldsig")]
701 ProviderCapability::VerifyCertificate(algorithm) => {
702 is_supported_x509_signature(algorithm)
703 }
704 #[cfg(feature = "xmlenc")]
705 ProviderCapability::Encrypt(_) | ProviderCapability::Decrypt(_) => true,
706 #[cfg(feature = "xmlenc")]
707 ProviderCapability::KeyWrap(_) | ProviderCapability::KeyUnwrap(_) => true,
708 #[cfg(feature = "xmlenc")]
709 ProviderCapability::KeyTransport(parameters)
710 | ProviderCapability::KeyRecovery(parameters) => legacy_oaep_mgf_is_valid(parameters),
711 ProviderCapability::Random => true,
712 ProviderCapability::KeyAgreement(_) | ProviderCapability::Kdf(_) => false,
713 }
714 }
715
716 fn fill_random(&self, output: &mut [u8]) -> Result<(), ProviderError> {
717 SysRng
718 .try_fill_bytes(output)
719 .map_err(|error| ProviderError::Random(error.to_string()))
720 }
721
722 fn derive_key(
723 &self,
724 parameters: &KdfParameters<'_>,
725 _secret: &[u8],
726 ) -> Result<Vec<u8>, ProviderError> {
727 self.require_capability(ProviderCapability::Kdf(parameters))?;
728 Err(ProviderError::Unsupported {
729 operation: ProviderOperation::Kdf,
730 algorithm: Some(parameters.algorithm.to_owned()),
731 })
732 }
733
734 #[cfg(feature = "xmldsig")]
735 fn digest(&self, algorithm: DigestAlgorithm, data: &[u8]) -> Result<Vec<u8>, ProviderError> {
736 use sha1::Sha1;
737 use sha2::{Digest, Sha256, Sha384, Sha512};
738 Ok(match algorithm {
739 DigestAlgorithm::Sha1 => Sha1::digest(data).to_vec(),
740 DigestAlgorithm::Sha256 => Sha256::digest(data).to_vec(),
741 DigestAlgorithm::Sha384 => Sha384::digest(data).to_vec(),
742 DigestAlgorithm::Sha512 => Sha512::digest(data).to_vec(),
743 })
744 }
745
746 #[cfg(feature = "xmldsig")]
747 fn sign(
748 &self,
749 key: &dyn crate::xmldsig::SigningKey,
750 algorithm: crate::xmldsig::SignatureAlgorithm,
751 data: &[u8],
752 ) -> Result<Vec<u8>, crate::xmldsig::SigningKeyError> {
753 self.require_capability(ProviderCapability::Sign(algorithm))?;
754 key.sign_with_provider(self, algorithm, data)
755 }
756
757 #[cfg(feature = "xmldsig")]
758 fn verify(
759 &self,
760 key: &dyn crate::xmldsig::VerifyingKey,
761 algorithm: crate::xmldsig::SignatureAlgorithm,
762 data: &[u8],
763 signature: &[u8],
764 ) -> Result<bool, crate::xmldsig::DsigError> {
765 self.require_capability(ProviderCapability::Verify(algorithm))?;
766 key.verify(algorithm, data, signature)
767 }
768
769 #[cfg(feature = "xmldsig")]
770 fn verify_x509_signature(
771 &self,
772 algorithm: X509SignatureAlgorithm,
773 signed_data: &[u8],
774 signature: &[u8],
775 issuer_spki_der: &[u8],
776 ) -> Result<bool, ProviderError> {
777 rustcrypto_x509::verify_signature(algorithm, signed_data, signature, issuer_spki_der)
778 }
779
780 #[cfg(feature = "xmlenc")]
781 fn encrypt_data(
782 &self,
783 algorithm: DataEncryptionAlgorithm,
784 key: &[u8],
785 plaintext: &[u8],
786 ) -> Result<Vec<u8>, ProviderError> {
787 rustcrypto::encrypt_data(self, algorithm, key, plaintext)
788 }
789
790 #[cfg(feature = "xmlenc")]
791 fn decrypt_data(
792 &self,
793 algorithm: DataEncryptionAlgorithm,
794 key: &[u8],
795 ciphertext: &[u8],
796 ) -> Result<Vec<u8>, ProviderError> {
797 rustcrypto::decrypt_data(algorithm, key, ciphertext)
798 }
799
800 #[cfg(feature = "xmlenc")]
801 fn wrap_key(
802 &self,
803 algorithm: KeyWrapAlgorithm,
804 kek: &[u8],
805 key: &[u8],
806 ) -> Result<Vec<u8>, ProviderError> {
807 rustcrypto::wrap_key(algorithm, kek, key)
808 }
809
810 #[cfg(feature = "xmlenc")]
811 fn unwrap_key(
812 &self,
813 algorithm: KeyWrapAlgorithm,
814 kek: &[u8],
815 wrapped: &[u8],
816 ) -> Result<Vec<u8>, ProviderError> {
817 rustcrypto::unwrap_key(algorithm, kek, wrapped)
818 }
819
820 #[cfg(feature = "xmlenc")]
821 fn transport_key(
822 &self,
823 key: &dyn KeyTransportKey,
824 parameters: &RsaOaepParameters,
825 plaintext: &[u8],
826 ) -> Result<Vec<u8>, ProviderError> {
827 validate_oaep_parameters(parameters)?;
828 self.require_capability(ProviderCapability::KeyTransport(parameters))?;
829 key.transport_with_provider(self, parameters, plaintext)
830 }
831
832 #[cfg(feature = "xmlenc")]
833 fn recover_key(
834 &self,
835 key: &dyn KeyRecoveryKey,
836 parameters: &RsaOaepParameters,
837 ciphertext: &[u8],
838 ) -> Result<Vec<u8>, ProviderError> {
839 validate_oaep_parameters(parameters)?;
840 self.require_capability(ProviderCapability::KeyRecovery(parameters))?;
841 key.recover_with_provider(self, parameters, ciphertext)
842 }
843}
844
845#[cfg(feature = "xmlenc")]
846fn legacy_oaep_mgf_is_valid(parameters: &RsaOaepParameters) -> bool {
847 parameters.algorithm != crate::xmlenc::KeyTransportAlgorithm::RsaOaepMgf1p
848 || parameters.mgf_digest == crate::xmlenc::OaepDigestAlgorithm::Sha1
849}
850
851#[cfg(feature = "xmlenc")]
852fn validate_oaep_parameters(parameters: &RsaOaepParameters) -> Result<(), ProviderError> {
853 if legacy_oaep_mgf_is_valid(parameters) {
854 Ok(())
855 } else {
856 Err(ProviderError::InvalidInput(
857 ProviderInputError::LegacyRsaOaepMgf,
858 ))
859 }
860}
861
862#[cfg(feature = "xmldsig")]
863fn is_supported_signature_uri(algorithm: &str) -> bool {
864 matches!(
865 algorithm,
866 "http://www.w3.org/2000/09/xmldsig#dsa-sha1"
867 | "http://www.w3.org/2000/09/xmldsig#hmac-sha1"
868 | "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
869 | "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
870 | "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"
871 | "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"
872 | "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"
873 | "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384"
874 )
875}
876
877#[cfg(feature = "xmldsig")]
878fn is_supported_signing_uri(algorithm: &str) -> bool {
879 matches!(
880 algorithm,
881 "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
882 | "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"
883 | "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"
884 | "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"
885 | "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384"
886 )
887}
888
889#[cfg(feature = "xmldsig")]
890fn is_supported_x509_signature(algorithm: X509SignatureAlgorithm) -> bool {
891 match algorithm {
892 X509SignatureAlgorithm::Dsa(DigestAlgorithm::Sha1)
893 | X509SignatureAlgorithm::RsaPkcs1v15(_)
894 | X509SignatureAlgorithm::Ecdsa(DigestAlgorithm::Sha256 | DigestAlgorithm::Sha384)
895 | X509SignatureAlgorithm::Ed25519 => true,
896 X509SignatureAlgorithm::RsaPss {
897 digest, mgf_digest, ..
898 } => {
899 matches!(
900 digest,
901 DigestAlgorithm::Sha256 | DigestAlgorithm::Sha384 | DigestAlgorithm::Sha512
902 ) && digest == mgf_digest
903 }
904 X509SignatureAlgorithm::Dsa(_)
905 | X509SignatureAlgorithm::Ecdsa(DigestAlgorithm::Sha1 | DigestAlgorithm::Sha512) => false,
906 }
907}
908
909#[cfg(feature = "xmldsig")]
910mod rustcrypto_x509 {
911 use der::Decode as _;
912 use dsa::pkcs8::DecodePublicKey as _;
913 use rsa::{
914 RsaPublicKey,
915 pkcs1::DecodeRsaPublicKey as _,
916 pss::{Signature as RsaPssSignature, VerifyingKey as RsaPssVerifyingKey},
917 traits::PublicKeyParts as _,
918 };
919 use sha1::Digest as _;
920 use sha2::{Sha256, Sha384, Sha512};
921 use signature::{Verifier as _, hazmat::PrehashVerifier as _};
922 use x509_parser::prelude::FromDer as _;
923
924 use super::{ProviderError, X509SignatureAlgorithm};
925 use crate::xmldsig::{
926 DigestAlgorithm, DsigError, SignatureAlgorithm, VerificationKey, VerifyingKey as _,
927 };
928
929 pub(super) fn verify_signature(
930 algorithm: X509SignatureAlgorithm,
931 signed_data: &[u8],
932 signature: &[u8],
933 issuer_spki_der: &[u8],
934 ) -> Result<bool, ProviderError> {
935 match algorithm {
936 X509SignatureAlgorithm::Dsa(DigestAlgorithm::Sha1) => {
937 let Ok(key) = dsa::VerifyingKey::from_public_key_der(issuer_spki_der) else {
941 return Ok(false);
942 };
943 let Ok(signature) = dsa::Signature::from_der(signature) else {
944 return Ok(false);
945 };
946 let digest = sha1::Sha1::digest(signed_data);
947 Ok(key.verify_prehash(&digest, &signature).is_ok())
948 }
949 X509SignatureAlgorithm::RsaPkcs1v15(digest) => {
950 let Some(algorithm) = rsa_pkcs1_algorithm(digest) else {
951 return unsupported(X509SignatureAlgorithm::RsaPkcs1v15(digest));
952 };
953 verify_xml_signature(algorithm, signed_data, signature, issuer_spki_der)
954 }
955 X509SignatureAlgorithm::Ecdsa(digest) => {
956 let Some(algorithm) = ecdsa_algorithm(digest) else {
957 return unsupported(X509SignatureAlgorithm::Ecdsa(digest));
958 };
959 verify_xml_signature(algorithm, signed_data, signature, issuer_spki_der)
960 }
961 X509SignatureAlgorithm::RsaPss {
962 digest,
963 mgf_digest,
964 salt_len,
965 } => {
966 let Some(key) = compatible_rsa_pss_public_key_from_spki(issuer_spki_der, algorithm)
970 else {
971 return Ok(false);
972 };
973 if digest != mgf_digest {
974 return unsupported(algorithm);
975 }
976 verify_rsa_pss(digest, salt_len, signed_data, signature, key)
977 }
978 X509SignatureAlgorithm::Ed25519 => {
979 let Ok(key) = ed25519_dalek::VerifyingKey::from_public_key_der(issuer_spki_der)
980 else {
981 return Ok(false);
982 };
983 let Ok(signature) = ed25519_dalek::Signature::try_from(signature) else {
984 return Ok(false);
985 };
986 Ok(key.verify_strict(signed_data, &signature).is_ok())
987 }
988 _ => unsupported(algorithm),
989 }
990 }
991
992 fn verify_xml_signature(
993 algorithm: SignatureAlgorithm,
994 signed_data: &[u8],
995 signature: &[u8],
996 issuer_spki_der: &[u8],
997 ) -> Result<bool, ProviderError> {
998 let key = VerificationKey {
999 algorithm,
1000 public_key_bytes: issuer_spki_der.to_vec(),
1001 certificate_der: None,
1002 name: None,
1003 };
1004 match key.verify(algorithm, signed_data, signature) {
1005 Ok(verified) => Ok(verified),
1006 Err(DsigError::Provider(error)) => Err(error),
1007 Err(_) => Ok(false),
1008 }
1009 }
1010
1011 fn verify_rsa_pss(
1012 digest: DigestAlgorithm,
1013 salt_len: usize,
1014 signed_data: &[u8],
1015 signature: &[u8],
1016 key: RsaPublicKey,
1017 ) -> Result<bool, ProviderError> {
1018 if !rsa_pss_salt_fits_key(&key, digest, salt_len) {
1019 return Ok(false);
1020 }
1021 let Ok(signature) = RsaPssSignature::try_from(signature) else {
1022 return Ok(false);
1023 };
1024 let verified = match digest {
1025 DigestAlgorithm::Sha256 => {
1026 RsaPssVerifyingKey::<Sha256>::new_with_salt_len(key, salt_len)
1027 .verify(signed_data, &signature)
1028 }
1029 DigestAlgorithm::Sha384 => {
1030 RsaPssVerifyingKey::<Sha384>::new_with_salt_len(key, salt_len)
1031 .verify(signed_data, &signature)
1032 }
1033 DigestAlgorithm::Sha512 => {
1034 RsaPssVerifyingKey::<Sha512>::new_with_salt_len(key, salt_len)
1035 .verify(signed_data, &signature)
1036 }
1037 DigestAlgorithm::Sha1 => {
1038 return unsupported(X509SignatureAlgorithm::RsaPss {
1039 digest,
1040 mgf_digest: digest,
1041 salt_len,
1042 });
1043 }
1044 };
1045 Ok(verified.is_ok())
1046 }
1047
1048 pub(super) fn rsa_pss_salt_fits_key(
1049 key: &RsaPublicKey,
1050 digest: DigestAlgorithm,
1051 salt_len: usize,
1052 ) -> bool {
1053 let Some(em_bits) = key.n().bits().checked_sub(1) else {
1054 return false;
1055 };
1056 let Ok(em_len) = usize::try_from(em_bits.div_ceil(8)) else {
1057 return false;
1058 };
1059 digest
1060 .output_len()
1061 .checked_add(salt_len)
1062 .and_then(|length| length.checked_add(2))
1063 .is_some_and(|required| required <= em_len)
1064 }
1065
1066 fn compatible_rsa_pss_public_key_from_spki(
1067 spki_der: &[u8],
1068 signature_algorithm: X509SignatureAlgorithm,
1069 ) -> Option<RsaPublicKey> {
1070 let (_, spki) = x509_parser::x509::SubjectPublicKeyInfo::from_der(spki_der).ok()?;
1071 match spki.algorithm.algorithm.to_id_string().as_str() {
1072 "1.2.840.113549.1.1.1" => RsaPublicKey::from_public_key_der(spki_der).ok(),
1073 "1.2.840.113549.1.1.10" => {
1074 if spki
1077 .algorithm
1078 .parameters
1079 .as_ref()
1080 .is_some_and(|parameters| {
1081 !rsa_pss_key_parameters_allow(parameters, signature_algorithm)
1082 })
1083 {
1084 return None;
1085 }
1086 RsaPublicKey::from_pkcs1_der(&spki.subject_public_key.data).ok()
1087 }
1088 _ => None,
1089 }
1090 }
1091
1092 fn rsa_pss_key_parameters_allow(
1093 parameters: &x509_parser::asn1_rs::Any<'_>,
1094 signature_algorithm: X509SignatureAlgorithm,
1095 ) -> bool {
1096 let X509SignatureAlgorithm::RsaPss {
1097 digest,
1098 mgf_digest,
1099 salt_len,
1100 } = signature_algorithm
1101 else {
1102 return false;
1103 };
1104 let Ok(parameters) =
1105 x509_parser::signature_algorithm::RsaSsaPssParams::try_from(parameters)
1106 else {
1107 return false;
1108 };
1109 let Ok(mask) = parameters.mask_gen_algorithm() else {
1110 return false;
1111 };
1112 parameters.trailer_field() == 1
1113 && x509_digest_from_oid(¶meters.hash_algorithm_oid().to_id_string()) == Some(digest)
1114 && mask.mgf.to_id_string() == "1.2.840.113549.1.1.8"
1115 && x509_digest_from_oid(&mask.hash.to_id_string()) == Some(mgf_digest)
1116 && usize::try_from(parameters.salt_length()).is_ok_and(|minimum| salt_len >= minimum)
1117 }
1118
1119 fn x509_digest_from_oid(oid: &str) -> Option<DigestAlgorithm> {
1120 match oid {
1121 "1.3.14.3.2.26" => Some(DigestAlgorithm::Sha1),
1122 "2.16.840.1.101.3.4.2.1" => Some(DigestAlgorithm::Sha256),
1123 "2.16.840.1.101.3.4.2.2" => Some(DigestAlgorithm::Sha384),
1124 "2.16.840.1.101.3.4.2.3" => Some(DigestAlgorithm::Sha512),
1125 _ => None,
1126 }
1127 }
1128
1129 const fn rsa_pkcs1_algorithm(digest: DigestAlgorithm) -> Option<SignatureAlgorithm> {
1130 match digest {
1131 DigestAlgorithm::Sha1 => Some(SignatureAlgorithm::RsaSha1),
1132 DigestAlgorithm::Sha256 => Some(SignatureAlgorithm::RsaSha256),
1133 DigestAlgorithm::Sha384 => Some(SignatureAlgorithm::RsaSha384),
1134 DigestAlgorithm::Sha512 => Some(SignatureAlgorithm::RsaSha512),
1135 }
1136 }
1137
1138 const fn ecdsa_algorithm(digest: DigestAlgorithm) -> Option<SignatureAlgorithm> {
1139 match digest {
1140 DigestAlgorithm::Sha256 => Some(SignatureAlgorithm::EcdsaSha256),
1141 DigestAlgorithm::Sha384 => Some(SignatureAlgorithm::EcdsaSha384),
1142 DigestAlgorithm::Sha1 | DigestAlgorithm::Sha512 => None,
1143 }
1144 }
1145
1146 fn unsupported<T>(algorithm: X509SignatureAlgorithm) -> Result<T, ProviderError> {
1147 Err(ProviderError::Unsupported {
1148 operation: super::ProviderOperation::VerifyCertificate,
1149 algorithm: Some(algorithm.oid().to_owned()),
1150 })
1151 }
1152}
1153
1154#[cfg(feature = "xmlenc")]
1155mod rustcrypto {
1156 use aes::{
1157 Aes128, Aes256,
1158 cipher::{BlockModeDecrypt, BlockModeEncrypt, KeyIvInit, block_padding::NoPadding},
1159 };
1160 use aes_gcm::{
1161 Aes128Gcm, Aes256Gcm, Nonce,
1162 aead::{AeadInOut, KeyInit},
1163 };
1164 use aes_kw::{KwAes128, KwAes256};
1165 use cbc::{Decryptor, Encryptor};
1166 use rsa::{Oaep, traits::PaddingScheme};
1167 use sha1::Sha1;
1168 use sha2::{Sha256, Sha384, Sha512};
1169
1170 use super::{CryptoProvider, ProviderError, ProviderInputError};
1171 use crate::xmlenc::{
1172 DataEncryptionAlgorithm, KeyWrapAlgorithm, OaepDigestAlgorithm, RsaOaepParameters,
1173 };
1174
1175 pub(super) fn encrypt_data(
1176 provider: &dyn CryptoProvider,
1177 algorithm: DataEncryptionAlgorithm,
1178 key: &[u8],
1179 plaintext: &[u8],
1180 ) -> Result<Vec<u8>, ProviderError> {
1181 check_key(algorithm.key_len(), key)?;
1182 match algorithm {
1183 DataEncryptionAlgorithm::Aes128Cbc => encrypt_cbc::<Aes128>(provider, key, plaintext),
1184 DataEncryptionAlgorithm::Aes256Cbc => encrypt_cbc::<Aes256>(provider, key, plaintext),
1185 DataEncryptionAlgorithm::Aes128Gcm => {
1186 encrypt_gcm::<Aes128Gcm>(provider, key, plaintext)
1187 }
1188 DataEncryptionAlgorithm::Aes256Gcm => {
1189 encrypt_gcm::<Aes256Gcm>(provider, key, plaintext)
1190 }
1191 }
1192 }
1193
1194 pub(super) fn decrypt_data(
1195 algorithm: DataEncryptionAlgorithm,
1196 key: &[u8],
1197 ciphertext: &[u8],
1198 ) -> Result<Vec<u8>, ProviderError> {
1199 check_key(algorithm.key_len(), key)?;
1200 match algorithm {
1201 DataEncryptionAlgorithm::Aes128Cbc => decrypt_cbc::<Aes128>(key, ciphertext),
1202 DataEncryptionAlgorithm::Aes256Cbc => decrypt_cbc::<Aes256>(key, ciphertext),
1203 DataEncryptionAlgorithm::Aes128Gcm => decrypt_gcm::<Aes128Gcm>(key, ciphertext),
1204 DataEncryptionAlgorithm::Aes256Gcm => decrypt_gcm::<Aes256Gcm>(key, ciphertext),
1205 }
1206 }
1207
1208 fn check_key(expected: usize, key: &[u8]) -> Result<(), ProviderError> {
1209 if key.len() == expected {
1210 Ok(())
1211 } else {
1212 Err(ProviderError::InvalidKeySize {
1213 expected,
1214 actual: key.len(),
1215 })
1216 }
1217 }
1218
1219 fn encrypt_cbc<C>(
1220 provider: &dyn CryptoProvider,
1221 key: &[u8],
1222 plaintext: &[u8],
1223 ) -> Result<Vec<u8>, ProviderError>
1224 where
1225 C: aes::cipher::BlockCipherEncrypt + aes::cipher::KeyInit,
1226 {
1227 let mut iv = [0_u8; 16];
1228 provider.fill_random(&mut iv)?;
1229 let pad_len = 16 - (plaintext.len() % 16);
1230 let mut padded = vec![0_u8; plaintext.len() + pad_len];
1231 padded[..plaintext.len()].copy_from_slice(plaintext);
1232 if pad_len > 1 {
1233 let last = padded.len() - 1;
1234 provider.fill_random(&mut padded[plaintext.len()..last])?;
1235 }
1236 *padded.last_mut().expect("padding is non-empty") = pad_len as u8;
1237 Encryptor::<C>::new_from_slices(key, &iv)
1238 .map_err(|_| {
1239 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization("AES-CBC"))
1240 })?
1241 .encrypt_padded::<NoPadding>(&mut padded, plaintext.len() + pad_len)
1242 .map_err(|_| {
1243 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization(
1244 "AES-CBC padding",
1245 ))
1246 })?;
1247 let mut output = Vec::with_capacity(16 + padded.len());
1248 output.extend_from_slice(&iv);
1249 output.extend_from_slice(&padded);
1250 Ok(output)
1251 }
1252
1253 fn decrypt_cbc<C>(key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, ProviderError>
1254 where
1255 C: aes::cipher::BlockCipherDecrypt + aes::cipher::KeyInit,
1256 {
1257 if ciphertext.len() < 32 || !(ciphertext.len() - 16).is_multiple_of(16) {
1258 return Err(ProviderError::InvalidInput(
1259 ProviderInputError::AesCbcFraming,
1260 ));
1261 }
1262 let (iv, body) = ciphertext.split_at(16);
1263 let mut plaintext = body.to_vec();
1264 Decryptor::<C>::new_from_slices(key, iv)
1265 .map_err(|_| {
1266 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization("AES-CBC"))
1267 })?
1268 .decrypt_padded::<NoPadding>(&mut plaintext)
1269 .map_err(|_| ProviderError::InvalidInput(ProviderInputError::AesCbcCiphertext))?;
1270 let pad_len = *plaintext.last().ok_or(ProviderError::InvalidInput(
1271 ProviderInputError::AesCbcCiphertext,
1272 ))?;
1273 let padding_bytes = usize::from(pad_len);
1274 if !(1..=16).contains(&padding_bytes) || padding_bytes > plaintext.len() {
1275 return Err(ProviderError::InvalidInput(
1276 ProviderInputError::AesCbcCiphertext,
1277 ));
1278 }
1279 plaintext.truncate(plaintext.len() - padding_bytes);
1280 Ok(plaintext)
1281 }
1282
1283 fn encrypt_gcm<C>(
1284 provider: &dyn CryptoProvider,
1285 key: &[u8],
1286 plaintext: &[u8],
1287 ) -> Result<Vec<u8>, ProviderError>
1288 where
1289 C: AeadInOut + KeyInit,
1290 {
1291 let mut nonce = [0_u8; 12];
1292 provider.fill_random(&mut nonce)?;
1293 let cipher = C::new_from_slice(key).map_err(|_| {
1294 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization("AES-GCM"))
1295 })?;
1296 let mut output = plaintext.to_vec();
1297 let nonce = Nonce::try_from(nonce.as_slice()).map_err(|_| {
1298 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization(
1299 "AES-GCM nonce",
1300 ))
1301 })?;
1302 cipher
1303 .encrypt_in_place(&nonce, &[], &mut output)
1304 .map_err(|_| ProviderError::AuthenticationFailed)?;
1305 let mut framed = Vec::with_capacity(12 + output.len());
1306 framed.extend_from_slice(&nonce);
1307 framed.extend_from_slice(&output);
1308 Ok(framed)
1309 }
1310
1311 fn decrypt_gcm<C>(key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, ProviderError>
1312 where
1313 C: AeadInOut + KeyInit,
1314 {
1315 if ciphertext.len() < 28 {
1316 return Err(ProviderError::InvalidInput(
1317 ProviderInputError::AesGcmFraming,
1318 ));
1319 }
1320 let (nonce, body) = ciphertext.split_at(12);
1321 let cipher = C::new_from_slice(key).map_err(|_| {
1322 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization("AES-GCM"))
1323 })?;
1324 let mut plaintext = body.to_vec();
1325 let nonce = Nonce::try_from(nonce).map_err(|_| {
1326 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization(
1327 "AES-GCM nonce",
1328 ))
1329 })?;
1330 cipher
1331 .decrypt_in_place(&nonce, &[], &mut plaintext)
1332 .map_err(|_| ProviderError::AuthenticationFailed)?;
1333 Ok(plaintext)
1334 }
1335
1336 pub(super) fn wrap_key(
1337 algorithm: KeyWrapAlgorithm,
1338 kek: &[u8],
1339 key: &[u8],
1340 ) -> Result<Vec<u8>, ProviderError> {
1341 check_key(algorithm.key_len(), kek)?;
1342 let mut output = vec![0_u8; key.len() + 8];
1343 match algorithm {
1344 KeyWrapAlgorithm::AesKw128 => KwAes128::new_from_slice(kek)
1345 .map_err(|_| ProviderError::InvalidKeySize {
1346 expected: 16,
1347 actual: kek.len(),
1348 })?
1349 .wrap_key(key, &mut output),
1350 KeyWrapAlgorithm::AesKw256 => KwAes256::new_from_slice(kek)
1351 .map_err(|_| ProviderError::InvalidKeySize {
1352 expected: 32,
1353 actual: kek.len(),
1354 })?
1355 .wrap_key(key, &mut output),
1356 }
1357 .map_err(|_| ProviderError::InvalidInput(ProviderInputError::AesKeyWrapFraming))?;
1358 Ok(output)
1359 }
1360
1361 pub(super) fn unwrap_key(
1362 algorithm: KeyWrapAlgorithm,
1363 kek: &[u8],
1364 wrapped: &[u8],
1365 ) -> Result<Vec<u8>, ProviderError> {
1366 check_key(algorithm.key_len(), kek)?;
1367 if wrapped.len() < 16 || !wrapped.len().is_multiple_of(8) {
1368 return Err(ProviderError::InvalidInput(
1369 ProviderInputError::AesKeyWrapFraming,
1370 ));
1371 }
1372 let mut output = vec![0_u8; wrapped.len() - 8];
1373 let key = match algorithm {
1374 KeyWrapAlgorithm::AesKw128 => KwAes128::new_from_slice(kek)
1375 .map_err(|_| ProviderError::InvalidKeySize {
1376 expected: 16,
1377 actual: kek.len(),
1378 })?
1379 .unwrap_key(wrapped, &mut output),
1380 KeyWrapAlgorithm::AesKw256 => KwAes256::new_from_slice(kek)
1381 .map_err(|_| ProviderError::InvalidKeySize {
1382 expected: 32,
1383 actual: kek.len(),
1384 })?
1385 .unwrap_key(wrapped, &mut output),
1386 }
1387 .map_err(|_| ProviderError::AuthenticationFailed)?;
1388 Ok(key.to_vec())
1389 }
1390
1391 pub(super) fn transport_key(
1392 provider: &dyn CryptoProvider,
1393 key: &rsa::RsaPublicKey,
1394 parameters: &RsaOaepParameters,
1395 plaintext: &[u8],
1396 ) -> Result<Vec<u8>, ProviderError> {
1397 super::validate_oaep_parameters(parameters)?;
1398 let mut rng = super::ProviderRng(provider);
1399 macro_rules! encrypt_with {
1400 ($digest:ty, $mgf:ty) => {
1401 Oaep::<$digest, $mgf>::new_with_mgf_hash_and_label(parameters.label.clone())
1402 .encrypt(&mut rng, key, plaintext)
1403 };
1404 }
1405 let result = match (parameters.digest, parameters.mgf_digest) {
1406 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha1) => {
1407 encrypt_with!(Sha1, Sha1)
1408 }
1409 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha256) => {
1410 encrypt_with!(Sha1, Sha256)
1411 }
1412 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha384) => {
1413 encrypt_with!(Sha1, Sha384)
1414 }
1415 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha512) => {
1416 encrypt_with!(Sha1, Sha512)
1417 }
1418 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha1) => {
1419 encrypt_with!(Sha256, Sha1)
1420 }
1421 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha256) => {
1422 encrypt_with!(Sha256, Sha256)
1423 }
1424 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha384) => {
1425 encrypt_with!(Sha256, Sha384)
1426 }
1427 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha512) => {
1428 encrypt_with!(Sha256, Sha512)
1429 }
1430 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha1) => {
1431 encrypt_with!(Sha384, Sha1)
1432 }
1433 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha256) => {
1434 encrypt_with!(Sha384, Sha256)
1435 }
1436 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha384) => {
1437 encrypt_with!(Sha384, Sha384)
1438 }
1439 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha512) => {
1440 encrypt_with!(Sha384, Sha512)
1441 }
1442 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha1) => {
1443 encrypt_with!(Sha512, Sha1)
1444 }
1445 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha256) => {
1446 encrypt_with!(Sha512, Sha256)
1447 }
1448 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha384) => {
1449 encrypt_with!(Sha512, Sha384)
1450 }
1451 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha512) => {
1452 encrypt_with!(Sha512, Sha512)
1453 }
1454 };
1455 result.map_err(map_rsa_error)
1456 }
1457
1458 pub(super) fn recover_key(
1459 provider: &dyn CryptoProvider,
1460 key: &rsa::RsaPrivateKey,
1461 parameters: &RsaOaepParameters,
1462 ciphertext: &[u8],
1463 ) -> Result<Vec<u8>, ProviderError> {
1464 super::validate_oaep_parameters(parameters)?;
1465 let mut rng = super::ProviderRng(provider);
1466 macro_rules! decrypt_with {
1467 ($digest:ty, $mgf:ty) => {
1468 Oaep::<$digest, $mgf>::new_with_mgf_hash_and_label(parameters.label.clone())
1469 .decrypt(Some(&mut rng), key, ciphertext)
1470 };
1471 }
1472 let result = match (parameters.digest, parameters.mgf_digest) {
1473 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha1) => {
1474 decrypt_with!(Sha1, Sha1)
1475 }
1476 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha256) => {
1477 decrypt_with!(Sha1, Sha256)
1478 }
1479 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha384) => {
1480 decrypt_with!(Sha1, Sha384)
1481 }
1482 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha512) => {
1483 decrypt_with!(Sha1, Sha512)
1484 }
1485 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha1) => {
1486 decrypt_with!(Sha256, Sha1)
1487 }
1488 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha256) => {
1489 decrypt_with!(Sha256, Sha256)
1490 }
1491 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha384) => {
1492 decrypt_with!(Sha256, Sha384)
1493 }
1494 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha512) => {
1495 decrypt_with!(Sha256, Sha512)
1496 }
1497 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha1) => {
1498 decrypt_with!(Sha384, Sha1)
1499 }
1500 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha256) => {
1501 decrypt_with!(Sha384, Sha256)
1502 }
1503 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha384) => {
1504 decrypt_with!(Sha384, Sha384)
1505 }
1506 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha512) => {
1507 decrypt_with!(Sha384, Sha512)
1508 }
1509 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha1) => {
1510 decrypt_with!(Sha512, Sha1)
1511 }
1512 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha256) => {
1513 decrypt_with!(Sha512, Sha256)
1514 }
1515 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha384) => {
1516 decrypt_with!(Sha512, Sha384)
1517 }
1518 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha512) => {
1519 decrypt_with!(Sha512, Sha512)
1520 }
1521 };
1522 result.map_err(map_rsa_error)
1523 }
1524
1525 fn map_rsa_error(error: rsa::Error) -> ProviderError {
1526 match error {
1527 rsa::Error::Rng => ProviderError::Random("RSA-OAEP randomness failed".into()),
1528 _ => ProviderError::AuthenticationFailed,
1529 }
1530 }
1531}
1532
1533#[cfg(test)]
1534mod tests {
1535 #[cfg(feature = "xmldsig")]
1536 use std::sync::atomic::AtomicUsize;
1537 use std::sync::atomic::{AtomicBool, Ordering};
1538
1539 use super::*;
1540
1541 #[cfg(feature = "xmldsig")]
1542 struct CountingRandomProvider {
1543 random_calls: AtomicUsize,
1544 reject_digest: Option<DigestAlgorithm>,
1545 extra_digest_byte: bool,
1546 accept_signatures: bool,
1547 }
1548
1549 #[cfg(feature = "xmldsig")]
1550 impl CryptoProvider for CountingRandomProvider {
1551 fn name(&self) -> &'static str {
1552 "counting-random"
1553 }
1554
1555 fn supports(&self, capability: ProviderCapability<'_>) -> bool {
1556 RUST_CRYPTO_PROVIDER.supports(capability)
1557 }
1558
1559 fn fill_random(&self, output: &mut [u8]) -> Result<(), ProviderError> {
1560 self.random_calls.fetch_add(1, Ordering::Relaxed);
1561 RUST_CRYPTO_PROVIDER.fill_random(output)
1562 }
1563
1564 fn derive_key(
1565 &self,
1566 parameters: &KdfParameters<'_>,
1567 secret: &[u8],
1568 ) -> Result<Vec<u8>, ProviderError> {
1569 RUST_CRYPTO_PROVIDER.derive_key(parameters, secret)
1570 }
1571
1572 fn digest(
1573 &self,
1574 algorithm: DigestAlgorithm,
1575 data: &[u8],
1576 ) -> Result<Vec<u8>, ProviderError> {
1577 if self.reject_digest == Some(algorithm) {
1578 return Err(ProviderError::Unsupported {
1579 operation: ProviderOperation::Digest,
1580 algorithm: Some(algorithm.uri().to_owned()),
1581 });
1582 }
1583 let mut digest = RUST_CRYPTO_PROVIDER.digest(algorithm, data)?;
1584 if self.extra_digest_byte {
1585 digest.push(0);
1586 }
1587 Ok(digest)
1588 }
1589
1590 fn sign(
1591 &self,
1592 key: &dyn crate::xmldsig::SigningKey,
1593 algorithm: crate::xmldsig::SignatureAlgorithm,
1594 data: &[u8],
1595 ) -> Result<Vec<u8>, crate::xmldsig::SigningKeyError> {
1596 key.sign_with_provider(self, algorithm, data)
1597 }
1598
1599 fn verify(
1600 &self,
1601 key: &dyn crate::xmldsig::VerifyingKey,
1602 algorithm: crate::xmldsig::SignatureAlgorithm,
1603 data: &[u8],
1604 signature: &[u8],
1605 ) -> Result<bool, crate::xmldsig::DsigError> {
1606 if self.accept_signatures {
1607 return Ok(true);
1608 }
1609 RUST_CRYPTO_PROVIDER.verify(key, algorithm, data, signature)
1610 }
1611
1612 #[cfg(feature = "xmlenc")]
1613 fn encrypt_data(
1614 &self,
1615 algorithm: DataEncryptionAlgorithm,
1616 key: &[u8],
1617 plaintext: &[u8],
1618 ) -> Result<Vec<u8>, ProviderError> {
1619 RUST_CRYPTO_PROVIDER.encrypt_data(algorithm, key, plaintext)
1620 }
1621
1622 #[cfg(feature = "xmlenc")]
1623 fn decrypt_data(
1624 &self,
1625 algorithm: DataEncryptionAlgorithm,
1626 key: &[u8],
1627 ciphertext: &[u8],
1628 ) -> Result<Vec<u8>, ProviderError> {
1629 RUST_CRYPTO_PROVIDER.decrypt_data(algorithm, key, ciphertext)
1630 }
1631
1632 #[cfg(feature = "xmlenc")]
1633 fn wrap_key(
1634 &self,
1635 algorithm: KeyWrapAlgorithm,
1636 kek: &[u8],
1637 key: &[u8],
1638 ) -> Result<Vec<u8>, ProviderError> {
1639 RUST_CRYPTO_PROVIDER.wrap_key(algorithm, kek, key)
1640 }
1641
1642 #[cfg(feature = "xmlenc")]
1643 fn unwrap_key(
1644 &self,
1645 algorithm: KeyWrapAlgorithm,
1646 kek: &[u8],
1647 wrapped: &[u8],
1648 ) -> Result<Vec<u8>, ProviderError> {
1649 RUST_CRYPTO_PROVIDER.unwrap_key(algorithm, kek, wrapped)
1650 }
1651
1652 #[cfg(feature = "xmlenc")]
1653 fn transport_key(
1654 &self,
1655 key: &dyn KeyTransportKey,
1656 parameters: &RsaOaepParameters,
1657 plaintext: &[u8],
1658 ) -> Result<Vec<u8>, ProviderError> {
1659 RUST_CRYPTO_PROVIDER.transport_key(key, parameters, plaintext)
1660 }
1661
1662 #[cfg(feature = "xmlenc")]
1663 fn recover_key(
1664 &self,
1665 key: &dyn KeyRecoveryKey,
1666 parameters: &RsaOaepParameters,
1667 ciphertext: &[u8],
1668 ) -> Result<Vec<u8>, ProviderError> {
1669 RUST_CRYPTO_PROVIDER.recover_key(key, parameters, ciphertext)
1670 }
1671 }
1672
1673 #[cfg(feature = "xmldsig")]
1674 #[test]
1675 fn capability_query_is_explicit_about_unimplemented_operations() {
1676 assert!(RUST_CRYPTO_PROVIDER.supports(ProviderCapability::Digest(DigestAlgorithm::Sha256)));
1677 let agreement = KeyAgreementParameters {
1678 algorithm: "urn:unsupported:agreement",
1679 peer_public_key: &[],
1680 };
1681 assert!(!RUST_CRYPTO_PROVIDER.supports(ProviderCapability::KeyAgreement(&agreement)));
1682 assert!(!RUST_CRYPTO_PROVIDER.supports(ProviderCapability::Sign(
1683 crate::xmldsig::SignatureAlgorithm::RsaSha1
1684 )));
1685 assert!(RUST_CRYPTO_PROVIDER.supports(ProviderCapability::Verify(
1686 crate::xmldsig::SignatureAlgorithm::RsaSha1
1687 )));
1688 }
1689
1690 #[cfg(all(feature = "xmldsig", feature = "xmlenc"))]
1691 #[test]
1692 fn capability_queries_include_oaep_and_pss_parameters() {
1693 use crate::xmlenc::{KeyTransportAlgorithm, OaepDigestAlgorithm};
1694
1695 let invalid_legacy = RsaOaepParameters {
1696 algorithm: KeyTransportAlgorithm::RsaOaepMgf1p,
1697 digest: OaepDigestAlgorithm::Sha256,
1698 mgf_digest: OaepDigestAlgorithm::Sha256,
1699 label: Vec::new(),
1700 };
1701 assert!(!RUST_CRYPTO_PROVIDER.supports(ProviderCapability::KeyTransport(&invalid_legacy)));
1702 let modern =
1703 RsaOaepParameters::xmlenc11(OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha512)
1704 .label(b"label".to_vec());
1705 assert!(RUST_CRYPTO_PROVIDER.supports(ProviderCapability::KeyTransport(&modern)));
1706
1707 let supported_pss = X509SignatureAlgorithm::RsaPss {
1708 digest: DigestAlgorithm::Sha256,
1709 mgf_digest: DigestAlgorithm::Sha256,
1710 salt_len: 32,
1711 };
1712 assert!(
1713 RUST_CRYPTO_PROVIDER.supports(ProviderCapability::VerifyCertificate(supported_pss))
1714 );
1715 let unsupported_pss = X509SignatureAlgorithm::RsaPss {
1716 digest: DigestAlgorithm::Sha256,
1717 mgf_digest: DigestAlgorithm::Sha384,
1718 salt_len: 32,
1719 };
1720 assert!(
1721 !RUST_CRYPTO_PROVIDER.supports(ProviderCapability::VerifyCertificate(unsupported_pss))
1722 );
1723 }
1724
1725 struct RecordingAgreementKey(AtomicBool);
1726
1727 impl KeyAgreementKey for RecordingAgreementKey {
1728 fn agree(
1729 &self,
1730 _parameters: &KeyAgreementParameters<'_>,
1731 ) -> Result<Vec<u8>, ProviderError> {
1732 self.0.store(true, Ordering::Relaxed);
1733 Ok(vec![0x42])
1734 }
1735 }
1736
1737 #[test]
1738 fn unsupported_agreement_and_kdf_fail_without_dispatch_or_fallback() {
1739 let agreement = KeyAgreementParameters {
1740 algorithm: "urn:example:agreement",
1741 peer_public_key: b"peer",
1742 };
1743 let key = RecordingAgreementKey(AtomicBool::new(false));
1744 let error = RUST_CRYPTO_PROVIDER
1745 .agree_key(&key, &agreement)
1746 .expect_err("unsupported agreement must fail closed");
1747 assert!(matches!(
1748 error,
1749 ProviderError::Unsupported {
1750 operation: ProviderOperation::KeyAgreement,
1751 algorithm: Some(ref algorithm),
1752 } if algorithm == agreement.algorithm
1753 ));
1754 assert!(!key.0.load(Ordering::Relaxed));
1755
1756 let kdf = KdfParameters {
1757 algorithm: "urn:example:kdf",
1758 digest: Some("urn:example:digest"),
1759 salt: b"salt",
1760 info: b"info",
1761 iterations: 1,
1762 output_len: 32,
1763 };
1764 assert!(matches!(
1765 RUST_CRYPTO_PROVIDER.derive_key(&kdf, b"secret"),
1766 Err(ProviderError::Unsupported {
1767 operation: ProviderOperation::Kdf,
1768 algorithm: Some(ref algorithm),
1769 }) if algorithm == kdf.algorithm
1770 ));
1771 }
1772
1773 #[cfg(feature = "xmldsig")]
1774 #[test]
1775 fn rsa_signing_uses_the_selected_providers_randomness() {
1776 use crate::xmldsig::{RsaSigningKey, SignatureAlgorithm};
1777
1778 let key = RsaSigningKey::from_pkcs8_pem(include_str!(
1781 "../tests/fixtures/keys/rsa/rsa-2048-key.pem"
1782 ))
1783 .expect("RSA fixture must parse");
1784 let provider = CountingRandomProvider {
1785 random_calls: AtomicUsize::new(0),
1786 reject_digest: None,
1787 extra_digest_byte: false,
1788 accept_signatures: false,
1789 };
1790
1791 let signature = provider
1792 .sign(&key, SignatureAlgorithm::RsaSha256, b"signed info")
1793 .expect("RSA signing must succeed");
1794
1795 assert!(!signature.is_empty());
1796 assert!(provider.random_calls.load(Ordering::Relaxed) > 0);
1797 }
1798
1799 #[cfg(feature = "xmldsig")]
1800 #[test]
1801 fn ecdsa_signing_uses_the_selected_providers_digest() {
1802 use crate::xmldsig::{
1803 EcdsaP256SigningKey, EcdsaP384SigningKey, SignatureAlgorithm, SigningKeyError,
1804 };
1805
1806 let cases: [(
1810 Box<dyn crate::xmldsig::SigningKey>,
1811 SignatureAlgorithm,
1812 DigestAlgorithm,
1813 ); 2] = [
1814 (
1815 Box::new(
1816 EcdsaP256SigningKey::from_pkcs8_pem(include_str!(
1817 "../tests/fixtures/keys/ec/ec-prime256v1-key.pem"
1818 ))
1819 .expect("P-256 fixture must parse"),
1820 ),
1821 SignatureAlgorithm::EcdsaSha384,
1822 DigestAlgorithm::Sha384,
1823 ),
1824 (
1825 Box::new(
1826 EcdsaP384SigningKey::from_pkcs8_pem(include_str!(
1827 "../tests/fixtures/keys/ec/ec-prime384v1-key.pem"
1828 ))
1829 .expect("P-384 fixture must parse"),
1830 ),
1831 SignatureAlgorithm::EcdsaSha256,
1832 DigestAlgorithm::Sha256,
1833 ),
1834 ];
1835
1836 for (key, signature_algorithm, digest_algorithm) in cases {
1837 let provider = CountingRandomProvider {
1838 random_calls: AtomicUsize::new(0),
1839 reject_digest: Some(digest_algorithm),
1840 extra_digest_byte: false,
1841 accept_signatures: false,
1842 };
1843 let error = provider
1844 .sign(key.as_ref(), signature_algorithm, b"signed info")
1845 .expect_err("provider digest rejection must stop ECDSA signing");
1846
1847 assert!(matches!(
1848 error,
1849 SigningKeyError::Provider(ProviderError::Unsupported {
1850 operation: ProviderOperation::Digest,
1851 algorithm: Some(ref uri),
1852 }) if uri == digest_algorithm.uri()
1853 ));
1854 }
1855 }
1856
1857 #[cfg(feature = "xmldsig")]
1858 #[test]
1859 fn ecdsa_signing_rejects_provider_digests_with_the_wrong_length() {
1860 use crate::xmldsig::{
1861 EcdsaP256SigningKey, EcdsaP384SigningKey, SignatureAlgorithm, SigningKeyError,
1862 };
1863
1864 let cases: [(
1867 Box<dyn crate::xmldsig::SigningKey>,
1868 SignatureAlgorithm,
1869 usize,
1870 ); 2] = [
1871 (
1872 Box::new(
1873 EcdsaP256SigningKey::from_pkcs8_pem(include_str!(
1874 "../tests/fixtures/keys/ec/ec-prime256v1-key.pem"
1875 ))
1876 .expect("P-256 fixture must parse"),
1877 ),
1878 SignatureAlgorithm::EcdsaSha256,
1879 32,
1880 ),
1881 (
1882 Box::new(
1883 EcdsaP384SigningKey::from_pkcs8_pem(include_str!(
1884 "../tests/fixtures/keys/ec/ec-prime384v1-key.pem"
1885 ))
1886 .expect("P-384 fixture must parse"),
1887 ),
1888 SignatureAlgorithm::EcdsaSha384,
1889 48,
1890 ),
1891 ];
1892
1893 for (key, algorithm, expected) in cases {
1894 let provider = CountingRandomProvider {
1895 random_calls: AtomicUsize::new(0),
1896 reject_digest: None,
1897 extra_digest_byte: true,
1898 accept_signatures: false,
1899 };
1900 let error = provider
1901 .sign(key.as_ref(), algorithm, b"signed info")
1902 .expect_err("an oversized provider digest must not reach ECDSA prehash signing");
1903
1904 assert!(matches!(
1905 error,
1906 SigningKeyError::Provider(ProviderError::InvalidOutputSize {
1907 operation: ProviderOperation::Digest,
1908 expected: actual_expected,
1909 actual,
1910 }) if actual_expected == expected && actual == expected + 1
1911 ));
1912 }
1913 }
1914
1915 #[cfg(feature = "xmldsig")]
1916 #[test]
1917 fn verification_facade_rejects_malformed_dsa_before_provider_dispatch() {
1918 use crate::xmldsig::{
1919 DefaultKeyResolver, DsigStatus, FailureReason, SignatureAlgorithm, VerifyContext,
1920 };
1921
1922 let original = include_str!(
1923 "../tests/fixtures/xmldsig/merlin-xmldsig-twenty-three/signature-enveloping-dsa.xml"
1924 );
1925 let value_start = original
1926 .find("<SignatureValue>")
1927 .expect("Merlin fixture must contain SignatureValue")
1928 + "<SignatureValue>".len();
1929 let value_end = original[value_start..]
1930 .find("</SignatureValue>")
1931 .map(|offset| value_start + offset)
1932 .expect("Merlin fixture must close SignatureValue");
1933 let mut malformed = original.to_owned();
1934 malformed.replace_range(value_start..value_end, "AQ==");
1935 let provider = CountingRandomProvider {
1936 random_calls: AtomicUsize::new(0),
1937 reject_digest: None,
1938 extra_digest_byte: false,
1939 accept_signatures: true,
1940 };
1941
1942 let mut policy = crate::policy::VerificationPolicy::default();
1943 policy
1944 .key_trust
1945 .allowed_legacy_signature_algorithms
1946 .insert(SignatureAlgorithm::DsaSha1);
1947 policy.key_trust.dsa_keys.minimum_modulus_bits = 1024;
1948 let result = VerifyContext::new()
1949 .policy(policy)
1950 .provider(&provider)
1951 .key_resolver(&DefaultKeyResolver::default())
1952 .verify(&malformed)
1953 .expect("malformed framing must be a verification miss");
1954
1955 assert_eq!(
1956 result.status,
1957 DsigStatus::Invalid(FailureReason::SignatureMismatch)
1958 );
1959 }
1960
1961 #[cfg(feature = "xmldsig")]
1962 #[test]
1963 fn rustcrypto_provider_verifies_parameterized_rsa_pss_certificates() {
1964 use der::{Decode as _, Encode as _};
1965 use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng};
1966 use rsa::{RsaPrivateKey, pkcs8::EncodePublicKey, pss::SigningKey as RsaPssSigningKey};
1967 use sha2::Sha256;
1968 use signature::{RandomizedSigner, SignatureEncoding};
1969 use x509_cert::spki::{AlgorithmIdentifierOwned, ObjectIdentifier};
1970
1971 let mut rng = ChaCha20Rng::from_seed([0x5a; 32]);
1974 let private_key =
1975 RsaPrivateKey::new(&mut rng, 2048).expect("deterministic RSA key generation");
1976 let public_key = private_key
1977 .to_public_key()
1978 .to_public_key_der()
1979 .expect("RSA public key must encode as SPKI");
1980 let signing_key = RsaPssSigningKey::<Sha256>::new_with_salt_len(private_key, 32);
1981 let signed_data = b"certificate tbs bytes";
1982 let signature = signing_key
1983 .try_sign_with_rng(&mut rng, signed_data)
1984 .expect("RSA-PSS signing must succeed")
1985 .to_vec();
1986
1987 assert!(
1988 RUST_CRYPTO_PROVIDER
1989 .verify_x509_signature(
1990 X509SignatureAlgorithm::RsaPss {
1991 digest: DigestAlgorithm::Sha256,
1992 mgf_digest: DigestAlgorithm::Sha256,
1993 salt_len: 32,
1994 },
1995 signed_data,
1996 &signature,
1997 public_key.as_bytes(),
1998 )
1999 .expect("standard RSA-PSS parameters must be supported")
2000 );
2001
2002 let mut parameterless_pss_spki =
2003 x509_cert::SubjectPublicKeyInfo::from_der(public_key.as_bytes())
2004 .expect("RSA SPKI must decode");
2005 parameterless_pss_spki.algorithm = AlgorithmIdentifierOwned {
2006 oid: ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10"),
2007 parameters: None,
2008 };
2009 let parameterless_pss_spki = parameterless_pss_spki
2010 .to_der()
2011 .expect("parameterless PSS SPKI must encode");
2012 assert!(
2013 RUST_CRYPTO_PROVIDER
2014 .verify_x509_signature(
2015 X509SignatureAlgorithm::RsaPss {
2016 digest: DigestAlgorithm::Sha256,
2017 mgf_digest: DigestAlgorithm::Sha256,
2018 salt_len: 32,
2019 },
2020 signed_data,
2021 &signature,
2022 ¶meterless_pss_spki,
2023 )
2024 .expect("parameterless PSS keys impose no signature restrictions")
2025 );
2026
2027 let mut pss_spki = x509_cert::SubjectPublicKeyInfo::from_der(public_key.as_bytes())
2028 .expect("RSA SPKI must decode");
2029 let pss_parameters = der::asn1::Any::from_der(&[
2030 0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
2031 0x04, 0x02, 0x01, 0x05, 0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48,
2032 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
2033 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x20,
2034 ])
2035 .expect("standard SHA-256 PSS parameters must decode");
2036 pss_spki.algorithm = AlgorithmIdentifierOwned {
2037 oid: ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10"),
2038 parameters: Some(pss_parameters),
2039 };
2040 let pss_spki = pss_spki.to_der().expect("PSS SPKI must encode");
2041
2042 assert!(
2043 RUST_CRYPTO_PROVIDER
2044 .verify_x509_signature(
2045 X509SignatureAlgorithm::RsaPss {
2046 digest: DigestAlgorithm::Sha256,
2047 mgf_digest: DigestAlgorithm::Sha256,
2048 salt_len: 32,
2049 },
2050 signed_data,
2051 &signature,
2052 &pss_spki,
2053 )
2054 .expect("RFC 4055 PSS SubjectPublicKeyInfo must be supported")
2055 );
2056
2057 for incompatible in [
2058 X509SignatureAlgorithm::RsaPss {
2059 digest: DigestAlgorithm::Sha384,
2060 mgf_digest: DigestAlgorithm::Sha256,
2061 salt_len: 32,
2062 },
2063 X509SignatureAlgorithm::RsaPss {
2064 digest: DigestAlgorithm::Sha256,
2065 mgf_digest: DigestAlgorithm::Sha384,
2066 salt_len: 32,
2067 },
2068 X509SignatureAlgorithm::RsaPss {
2069 digest: DigestAlgorithm::Sha256,
2070 mgf_digest: DigestAlgorithm::Sha256,
2071 salt_len: 16,
2072 },
2073 ] {
2074 assert!(
2075 !RUST_CRYPTO_PROVIDER
2076 .verify_x509_signature(incompatible, signed_data, &signature, &pss_spki,)
2077 .expect("incompatible PSS key restrictions are invalid, not unsupported")
2078 );
2079 }
2080 }
2081
2082 #[cfg(feature = "xmldsig")]
2083 #[test]
2084 fn rustcrypto_provider_verifies_dsa_certificate_signature_at_q_width() {
2085 use base64::Engine as _;
2086
2087 let spki = base64::engine::general_purpose::STANDARD
2090 .decode("MIIDQzCCAjYGByqGSM44BAEwggIpAoIBAQDEkm7mUEj1dizQRRrcU6ehyhpQ1NAkcKi9XyNcBJDZlyTdVH09XZ04UZNuXAWRL1hEDvDAvFimuwmW7k099j0PRM+WypsfOOgZPJhIVNZu9poTPGINKpbMTXFmR+qhrYM4z+NSKxuUBWZwX5HibBIG5INbx8IDHWAxZqxgHQsebDej1+yZyCTTpmDS9nKGkBRVaxsJgZt958UPNlIz1ECf4n4P4mPLAl7W5xV8VSWMqlXdkOAPbLC/mChjFoCj0jmCQpbcOvd7a6cWhcyhw/yikoVoKEPNWr9xLtdJV37f1/4q/xTvoPKWhMmgMQ/DigUnYgPzmexyS82m5HLZ/vOJAh0A/ckrg9g9PsZesUsH/4bEijeNwWGXB5e+/LCt0QKCAQEAuBGFzyjZEmvbDKbb+8tz+zqw4lK7RGwOjVM3v9xPS6LuG5L1OwCNQcUcVIsU9VxBnEx9oMnl8eVX1nq3kfdiZB2F9ESxwX5FzBt+KLjMOzBa8rPlzVcyCZ3sT3orAQ2D/q7ffDhTCUt+v8UNiAhVbaNnR/vI7AkVoP9crRjpOSV/7b5MGa0BcjIyEzTtqM58wppfSQt8jkj7WT3+Bww/Y9rOtshDE2QosaX/7xoDnzyeZ3amLjTe3/MjBcsKlbK2z4QuaI6xoQBVd/QjP8FjXpZBhXWFIAsOL/sz6uR2Er0ovdX8DBA0EJpuzlTX94Lvf+Eh+5/83ESAm97fk4pnhQOCAQUAAoIBAEwSwKuLFPeR7UJGXkWM9egyYewhqHpIXPBEWOVPqwTw3xLc3EkufpYY9wkhJS08KD+J92jMjm//0bYeVf7fXisc6PHtGY4wx5XBm1g9HKw9lwRjbk7nH495dlZdl0BXHa14TJ8myE2zOM1jsaFyz6jAFTaRnKYIj6WlKOj59d2iAXtLZRme9r+7U4G6zDUkphyIEcIGH4vhb6gm3URr1zAV5kJjTlsPAiqgeH/PgxU52tmvLphJgv/xPxsuX5W0/s7iKbphIb2YWh/gtTWXvRQHiQQ2fCncI3TAMnZ75dBY0gPOVLQJhUyffeRbk9UULux/jc8QBPgKBS7GM5DnNSw=")
2091 .expect("DSA SPKI fixture must decode");
2092 let signature = base64::engine::general_purpose::STANDARD
2093 .decode("MD0CHQChtB1c+f5BmTJCtT7Gi4cyQiR2igj0znRQYCJ3Ahw4NGg4pL5jgA8Ri07ESV9Yr90WfUmRrbRcnjsY")
2094 .expect("DSA signature fixture must decode");
2095 let message = b"certificate tbs bytes for dsa q-width regression";
2096
2097 assert!(
2098 rustcrypto_x509::verify_signature(
2099 X509SignatureAlgorithm::Dsa(DigestAlgorithm::Sha1),
2100 message,
2101 &signature,
2102 &spki,
2103 )
2104 .expect("supported DSA-SHA1 certificate signature")
2105 );
2106
2107 let mut tampered = signature;
2108 *tampered.last_mut().expect("DER signature is non-empty") ^= 1;
2109 assert!(
2110 !rustcrypto_x509::verify_signature(
2111 X509SignatureAlgorithm::Dsa(DigestAlgorithm::Sha1),
2112 message,
2113 &tampered,
2114 &spki,
2115 )
2116 .expect("tampered DSA-SHA1 certificate signature is a verification miss")
2117 );
2118 }
2119
2120 #[cfg(feature = "xmldsig")]
2121 #[test]
2122 fn primitive_provider_does_not_embed_rsa_strength_policy() {
2123 use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng};
2124 use rsa::{RsaPrivateKey, pkcs8::EncodePublicKey, pss::SigningKey as RsaPssSigningKey};
2125 use sha2::Sha256;
2126 use signature::{RandomizedSigner, SignatureEncoding};
2127
2128 let mut rng = ChaCha20Rng::from_seed([0x3c; 32]);
2129 let private_key =
2130 RsaPrivateKey::new(&mut rng, 1024).expect("deterministic weak RSA key generation");
2131 let public_key = private_key
2132 .to_public_key()
2133 .to_public_key_der()
2134 .expect("weak RSA public key must encode as SPKI");
2135 let signed_data = b"certificate tbs bytes";
2136 let signature = RsaPssSigningKey::<Sha256>::new_with_salt_len(private_key, 32)
2137 .try_sign_with_rng(&mut rng, signed_data)
2138 .expect("weak RSA-PSS key can still produce a cryptographic signature")
2139 .to_vec();
2140
2141 assert!(
2142 RUST_CRYPTO_PROVIDER
2143 .verify_x509_signature(
2144 X509SignatureAlgorithm::RsaPss {
2145 digest: DigestAlgorithm::Sha256,
2146 mgf_digest: DigestAlgorithm::Sha256,
2147 salt_len: 32,
2148 },
2149 signed_data,
2150 &signature,
2151 public_key.as_bytes(),
2152 )
2153 .expect(
2154 "provider must evaluate structurally valid RSA-PSS independently of policy"
2155 )
2156 );
2157 }
2158
2159 #[cfg(feature = "xmldsig")]
2160 #[test]
2161 fn oversized_rsa_pss_salt_is_a_verification_miss() {
2162 use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng};
2163 use rsa::{RsaPrivateKey, pkcs8::EncodePublicKey as _, traits::PublicKeyParts as _};
2164
2165 let mut rng = ChaCha20Rng::from_seed([0x55; 32]);
2168 let public_key = RsaPrivateKey::new(&mut rng, 1024)
2169 .expect("deterministic RSA key generation")
2170 .to_public_key();
2171 let spki = public_key
2172 .to_public_key_der()
2173 .expect("RSA public key must encode as SPKI");
2174
2175 assert!(rustcrypto_x509::rsa_pss_salt_fits_key(
2176 &public_key,
2177 DigestAlgorithm::Sha256,
2178 0,
2179 ));
2180 assert!(rustcrypto_x509::rsa_pss_salt_fits_key(
2181 &public_key,
2182 DigestAlgorithm::Sha256,
2183 94,
2184 ));
2185 assert!(!rustcrypto_x509::rsa_pss_salt_fits_key(
2186 &public_key,
2187 DigestAlgorithm::Sha256,
2188 95,
2189 ));
2190
2191 assert!(
2192 !RUST_CRYPTO_PROVIDER
2193 .verify_x509_signature(
2194 X509SignatureAlgorithm::RsaPss {
2195 digest: DigestAlgorithm::Sha256,
2196 mgf_digest: DigestAlgorithm::Sha256,
2197 salt_len: usize::MAX,
2198 },
2199 b"certificate tbs bytes",
2200 &vec![0_u8; public_key.size()],
2201 spki.as_bytes(),
2202 )
2203 .expect("oversized PSS salt must fail without panicking")
2204 );
2205 }
2206
2207 #[cfg(feature = "xmlenc")]
2208 #[test]
2209 fn legacy_oaep_mgf_constraint_is_symmetric() {
2210 use rsa::pkcs8::DecodePrivateKey;
2211
2212 let key = rsa::RsaPrivateKey::from_pkcs8_pem(include_str!(
2215 "../tests/fixtures/keys/rsa/rsa-2048-key.pem"
2216 ))
2217 .expect("RSA fixture must parse");
2218 let parameters = crate::xmlenc::RsaOaepParameters {
2219 algorithm: crate::xmlenc::KeyTransportAlgorithm::RsaOaepMgf1p,
2220 digest: crate::xmlenc::OaepDigestAlgorithm::Sha256,
2221 mgf_digest: crate::xmlenc::OaepDigestAlgorithm::Sha256,
2222 label: Vec::new(),
2223 };
2224
2225 assert!(matches!(
2226 RUST_CRYPTO_PROVIDER.recover_key(&key, ¶meters, &[0_u8; 256]),
2227 Err(ProviderError::InvalidInput(
2228 ProviderInputError::LegacyRsaOaepMgf
2229 ))
2230 ));
2231 assert!(matches!(
2232 RUST_CRYPTO_PROVIDER.transport_key(&key.to_public_key(), ¶meters, &[0_u8; 16]),
2233 Err(ProviderError::InvalidInput(
2234 ProviderInputError::LegacyRsaOaepMgf
2235 ))
2236 ));
2237 }
2238}