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::signature::verify_ecdsa_signature_spki_asn1_der;
926 use crate::xmldsig::{
927 DigestAlgorithm, DsigError, SignatureAlgorithm, VerificationKey, VerifyingKey as _,
928 };
929
930 pub(super) fn verify_signature(
931 algorithm: X509SignatureAlgorithm,
932 signed_data: &[u8],
933 signature: &[u8],
934 issuer_spki_der: &[u8],
935 ) -> Result<bool, ProviderError> {
936 match algorithm {
937 X509SignatureAlgorithm::Dsa(DigestAlgorithm::Sha1) => {
938 let Ok(key) = dsa::VerifyingKey::from_public_key_der(issuer_spki_der) else {
942 return Ok(false);
943 };
944 let Ok(signature) = dsa::Signature::from_der(signature) else {
945 return Ok(false);
946 };
947 let digest = sha1::Sha1::digest(signed_data);
948 Ok(key.verify_prehash(&digest, &signature).is_ok())
949 }
950 X509SignatureAlgorithm::RsaPkcs1v15(digest) => {
951 let Some(algorithm) = rsa_pkcs1_algorithm(digest) else {
952 return unsupported(X509SignatureAlgorithm::RsaPkcs1v15(digest));
953 };
954 verify_xml_signature(algorithm, signed_data, signature, issuer_spki_der)
955 }
956 X509SignatureAlgorithm::Ecdsa(digest) => {
957 let Some(algorithm) = ecdsa_algorithm(digest) else {
958 return unsupported(X509SignatureAlgorithm::Ecdsa(digest));
959 };
960 match verify_ecdsa_signature_spki_asn1_der(
963 algorithm,
964 issuer_spki_der,
965 signed_data,
966 signature,
967 ) {
968 Ok(verified) => Ok(verified),
969 Err(_) => Ok(false),
970 }
971 }
972 X509SignatureAlgorithm::RsaPss {
973 digest,
974 mgf_digest,
975 salt_len,
976 } => {
977 let Some(key) = compatible_rsa_pss_public_key_from_spki(issuer_spki_der, algorithm)
981 else {
982 return Ok(false);
983 };
984 if digest != mgf_digest {
985 return unsupported(algorithm);
986 }
987 verify_rsa_pss(digest, salt_len, signed_data, signature, key)
988 }
989 X509SignatureAlgorithm::Ed25519 => {
990 let Ok(key) = ed25519_dalek::VerifyingKey::from_public_key_der(issuer_spki_der)
991 else {
992 return Ok(false);
993 };
994 let Ok(signature) = ed25519_dalek::Signature::try_from(signature) else {
995 return Ok(false);
996 };
997 Ok(key.verify_strict(signed_data, &signature).is_ok())
998 }
999 _ => unsupported(algorithm),
1000 }
1001 }
1002
1003 fn verify_xml_signature(
1004 algorithm: SignatureAlgorithm,
1005 signed_data: &[u8],
1006 signature: &[u8],
1007 issuer_spki_der: &[u8],
1008 ) -> Result<bool, ProviderError> {
1009 let key = VerificationKey {
1010 algorithm,
1011 public_key_bytes: issuer_spki_der.to_vec(),
1012 certificate_der: None,
1013 name: None,
1014 };
1015 match key.verify(algorithm, signed_data, signature) {
1016 Ok(verified) => Ok(verified),
1017 Err(DsigError::Provider(error)) => Err(error),
1018 Err(_) => Ok(false),
1019 }
1020 }
1021
1022 fn verify_rsa_pss(
1023 digest: DigestAlgorithm,
1024 salt_len: usize,
1025 signed_data: &[u8],
1026 signature: &[u8],
1027 key: RsaPublicKey,
1028 ) -> Result<bool, ProviderError> {
1029 if !rsa_pss_salt_fits_key(&key, digest, salt_len) {
1030 return Ok(false);
1031 }
1032 let Ok(signature) = RsaPssSignature::try_from(signature) else {
1033 return Ok(false);
1034 };
1035 let verified = match digest {
1036 DigestAlgorithm::Sha256 => {
1037 RsaPssVerifyingKey::<Sha256>::new_with_salt_len(key, salt_len)
1038 .verify(signed_data, &signature)
1039 }
1040 DigestAlgorithm::Sha384 => {
1041 RsaPssVerifyingKey::<Sha384>::new_with_salt_len(key, salt_len)
1042 .verify(signed_data, &signature)
1043 }
1044 DigestAlgorithm::Sha512 => {
1045 RsaPssVerifyingKey::<Sha512>::new_with_salt_len(key, salt_len)
1046 .verify(signed_data, &signature)
1047 }
1048 DigestAlgorithm::Sha1 => {
1049 return unsupported(X509SignatureAlgorithm::RsaPss {
1050 digest,
1051 mgf_digest: digest,
1052 salt_len,
1053 });
1054 }
1055 };
1056 Ok(verified.is_ok())
1057 }
1058
1059 pub(super) fn rsa_pss_salt_fits_key(
1060 key: &RsaPublicKey,
1061 digest: DigestAlgorithm,
1062 salt_len: usize,
1063 ) -> bool {
1064 let Some(em_bits) = key.n().bits().checked_sub(1) else {
1065 return false;
1066 };
1067 let Ok(em_len) = usize::try_from(em_bits.div_ceil(8)) else {
1068 return false;
1069 };
1070 digest
1071 .output_len()
1072 .checked_add(salt_len)
1073 .and_then(|length| length.checked_add(2))
1074 .is_some_and(|required| required <= em_len)
1075 }
1076
1077 fn compatible_rsa_pss_public_key_from_spki(
1078 spki_der: &[u8],
1079 signature_algorithm: X509SignatureAlgorithm,
1080 ) -> Option<RsaPublicKey> {
1081 let (_, spki) = x509_parser::x509::SubjectPublicKeyInfo::from_der(spki_der).ok()?;
1082 match spki.algorithm.algorithm.to_id_string().as_str() {
1083 "1.2.840.113549.1.1.1" => RsaPublicKey::from_public_key_der(spki_der).ok(),
1084 "1.2.840.113549.1.1.10" => {
1085 if spki
1088 .algorithm
1089 .parameters
1090 .as_ref()
1091 .is_some_and(|parameters| {
1092 !rsa_pss_key_parameters_allow(parameters, signature_algorithm)
1093 })
1094 {
1095 return None;
1096 }
1097 RsaPublicKey::from_pkcs1_der(&spki.subject_public_key.data).ok()
1098 }
1099 _ => None,
1100 }
1101 }
1102
1103 fn rsa_pss_key_parameters_allow(
1104 parameters: &x509_parser::asn1_rs::Any<'_>,
1105 signature_algorithm: X509SignatureAlgorithm,
1106 ) -> bool {
1107 let X509SignatureAlgorithm::RsaPss {
1108 digest,
1109 mgf_digest,
1110 salt_len,
1111 } = signature_algorithm
1112 else {
1113 return false;
1114 };
1115 let Ok(parameters) =
1116 x509_parser::signature_algorithm::RsaSsaPssParams::try_from(parameters)
1117 else {
1118 return false;
1119 };
1120 let Ok(mask) = parameters.mask_gen_algorithm() else {
1121 return false;
1122 };
1123 parameters.trailer_field() == 1
1124 && x509_digest_from_oid(¶meters.hash_algorithm_oid().to_id_string()) == Some(digest)
1125 && mask.mgf.to_id_string() == "1.2.840.113549.1.1.8"
1126 && x509_digest_from_oid(&mask.hash.to_id_string()) == Some(mgf_digest)
1127 && usize::try_from(parameters.salt_length()).is_ok_and(|minimum| salt_len >= minimum)
1128 }
1129
1130 fn x509_digest_from_oid(oid: &str) -> Option<DigestAlgorithm> {
1131 match oid {
1132 "1.3.14.3.2.26" => Some(DigestAlgorithm::Sha1),
1133 "2.16.840.1.101.3.4.2.1" => Some(DigestAlgorithm::Sha256),
1134 "2.16.840.1.101.3.4.2.2" => Some(DigestAlgorithm::Sha384),
1135 "2.16.840.1.101.3.4.2.3" => Some(DigestAlgorithm::Sha512),
1136 _ => None,
1137 }
1138 }
1139
1140 const fn rsa_pkcs1_algorithm(digest: DigestAlgorithm) -> Option<SignatureAlgorithm> {
1141 match digest {
1142 DigestAlgorithm::Sha1 => Some(SignatureAlgorithm::RsaSha1),
1143 DigestAlgorithm::Sha256 => Some(SignatureAlgorithm::RsaSha256),
1144 DigestAlgorithm::Sha384 => Some(SignatureAlgorithm::RsaSha384),
1145 DigestAlgorithm::Sha512 => Some(SignatureAlgorithm::RsaSha512),
1146 }
1147 }
1148
1149 const fn ecdsa_algorithm(digest: DigestAlgorithm) -> Option<SignatureAlgorithm> {
1150 match digest {
1151 DigestAlgorithm::Sha256 => Some(SignatureAlgorithm::EcdsaSha256),
1152 DigestAlgorithm::Sha384 => Some(SignatureAlgorithm::EcdsaSha384),
1153 DigestAlgorithm::Sha1 | DigestAlgorithm::Sha512 => None,
1154 }
1155 }
1156
1157 fn unsupported<T>(algorithm: X509SignatureAlgorithm) -> Result<T, ProviderError> {
1158 Err(ProviderError::Unsupported {
1159 operation: super::ProviderOperation::VerifyCertificate,
1160 algorithm: Some(algorithm.oid().to_owned()),
1161 })
1162 }
1163}
1164
1165#[cfg(feature = "xmlenc")]
1166mod rustcrypto {
1167 use aes::{
1168 Aes128, Aes256,
1169 cipher::{BlockModeDecrypt, BlockModeEncrypt, KeyIvInit, block_padding::NoPadding},
1170 };
1171 use aes_gcm::{
1172 Aes128Gcm, Aes256Gcm, Nonce,
1173 aead::{AeadInOut, KeyInit},
1174 };
1175 use aes_kw::{KwAes128, KwAes256};
1176 use cbc::{Decryptor, Encryptor};
1177 use rsa::{Oaep, traits::PaddingScheme};
1178 use sha1::Sha1;
1179 use sha2::{Sha256, Sha384, Sha512};
1180
1181 use super::{CryptoProvider, ProviderError, ProviderInputError};
1182 use crate::xmlenc::{
1183 DataEncryptionAlgorithm, KeyWrapAlgorithm, OaepDigestAlgorithm, RsaOaepParameters,
1184 };
1185
1186 pub(super) fn encrypt_data(
1187 provider: &dyn CryptoProvider,
1188 algorithm: DataEncryptionAlgorithm,
1189 key: &[u8],
1190 plaintext: &[u8],
1191 ) -> Result<Vec<u8>, ProviderError> {
1192 check_key(algorithm.key_len(), key)?;
1193 match algorithm {
1194 DataEncryptionAlgorithm::Aes128Cbc => encrypt_cbc::<Aes128>(provider, key, plaintext),
1195 DataEncryptionAlgorithm::Aes256Cbc => encrypt_cbc::<Aes256>(provider, key, plaintext),
1196 DataEncryptionAlgorithm::Aes128Gcm => {
1197 encrypt_gcm::<Aes128Gcm>(provider, key, plaintext)
1198 }
1199 DataEncryptionAlgorithm::Aes256Gcm => {
1200 encrypt_gcm::<Aes256Gcm>(provider, key, plaintext)
1201 }
1202 }
1203 }
1204
1205 pub(super) fn decrypt_data(
1206 algorithm: DataEncryptionAlgorithm,
1207 key: &[u8],
1208 ciphertext: &[u8],
1209 ) -> Result<Vec<u8>, ProviderError> {
1210 check_key(algorithm.key_len(), key)?;
1211 match algorithm {
1212 DataEncryptionAlgorithm::Aes128Cbc => decrypt_cbc::<Aes128>(key, ciphertext),
1213 DataEncryptionAlgorithm::Aes256Cbc => decrypt_cbc::<Aes256>(key, ciphertext),
1214 DataEncryptionAlgorithm::Aes128Gcm => decrypt_gcm::<Aes128Gcm>(key, ciphertext),
1215 DataEncryptionAlgorithm::Aes256Gcm => decrypt_gcm::<Aes256Gcm>(key, ciphertext),
1216 }
1217 }
1218
1219 fn check_key(expected: usize, key: &[u8]) -> Result<(), ProviderError> {
1220 if key.len() == expected {
1221 Ok(())
1222 } else {
1223 Err(ProviderError::InvalidKeySize {
1224 expected,
1225 actual: key.len(),
1226 })
1227 }
1228 }
1229
1230 fn encrypt_cbc<C>(
1231 provider: &dyn CryptoProvider,
1232 key: &[u8],
1233 plaintext: &[u8],
1234 ) -> Result<Vec<u8>, ProviderError>
1235 where
1236 C: aes::cipher::BlockCipherEncrypt + aes::cipher::KeyInit,
1237 {
1238 let mut iv = [0_u8; 16];
1239 provider.fill_random(&mut iv)?;
1240 let pad_len = 16 - (plaintext.len() % 16);
1241 let mut padded = vec![0_u8; plaintext.len() + pad_len];
1242 padded[..plaintext.len()].copy_from_slice(plaintext);
1243 if pad_len > 1 {
1244 let last = padded.len() - 1;
1245 provider.fill_random(&mut padded[plaintext.len()..last])?;
1246 }
1247 *padded.last_mut().expect("padding is non-empty") = pad_len as u8;
1248 Encryptor::<C>::new_from_slices(key, &iv)
1249 .map_err(|_| {
1250 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization("AES-CBC"))
1251 })?
1252 .encrypt_padded::<NoPadding>(&mut padded, plaintext.len() + pad_len)
1253 .map_err(|_| {
1254 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization(
1255 "AES-CBC padding",
1256 ))
1257 })?;
1258 let mut output = Vec::with_capacity(16 + padded.len());
1259 output.extend_from_slice(&iv);
1260 output.extend_from_slice(&padded);
1261 Ok(output)
1262 }
1263
1264 fn decrypt_cbc<C>(key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, ProviderError>
1265 where
1266 C: aes::cipher::BlockCipherDecrypt + aes::cipher::KeyInit,
1267 {
1268 if ciphertext.len() < 32 || !(ciphertext.len() - 16).is_multiple_of(16) {
1269 return Err(ProviderError::InvalidInput(
1270 ProviderInputError::AesCbcFraming,
1271 ));
1272 }
1273 let (iv, body) = ciphertext.split_at(16);
1274 let mut plaintext = body.to_vec();
1275 Decryptor::<C>::new_from_slices(key, iv)
1276 .map_err(|_| {
1277 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization("AES-CBC"))
1278 })?
1279 .decrypt_padded::<NoPadding>(&mut plaintext)
1280 .map_err(|_| ProviderError::InvalidInput(ProviderInputError::AesCbcCiphertext))?;
1281 let pad_len = *plaintext.last().ok_or(ProviderError::InvalidInput(
1282 ProviderInputError::AesCbcCiphertext,
1283 ))?;
1284 let padding_bytes = usize::from(pad_len);
1285 if !(1..=16).contains(&padding_bytes) || padding_bytes > plaintext.len() {
1286 return Err(ProviderError::InvalidInput(
1287 ProviderInputError::AesCbcCiphertext,
1288 ));
1289 }
1290 plaintext.truncate(plaintext.len() - padding_bytes);
1291 Ok(plaintext)
1292 }
1293
1294 fn encrypt_gcm<C>(
1295 provider: &dyn CryptoProvider,
1296 key: &[u8],
1297 plaintext: &[u8],
1298 ) -> Result<Vec<u8>, ProviderError>
1299 where
1300 C: AeadInOut + KeyInit,
1301 {
1302 let mut nonce = [0_u8; 12];
1303 provider.fill_random(&mut nonce)?;
1304 let cipher = C::new_from_slice(key).map_err(|_| {
1305 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization("AES-GCM"))
1306 })?;
1307 let mut output = plaintext.to_vec();
1308 let nonce = Nonce::try_from(nonce.as_slice()).map_err(|_| {
1309 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization(
1310 "AES-GCM nonce",
1311 ))
1312 })?;
1313 cipher
1314 .encrypt_in_place(&nonce, &[], &mut output)
1315 .map_err(|_| ProviderError::AuthenticationFailed)?;
1316 let mut framed = Vec::with_capacity(12 + output.len());
1317 framed.extend_from_slice(&nonce);
1318 framed.extend_from_slice(&output);
1319 Ok(framed)
1320 }
1321
1322 fn decrypt_gcm<C>(key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, ProviderError>
1323 where
1324 C: AeadInOut + KeyInit,
1325 {
1326 if ciphertext.len() < 28 {
1327 return Err(ProviderError::InvalidInput(
1328 ProviderInputError::AesGcmFraming,
1329 ));
1330 }
1331 let (nonce, body) = ciphertext.split_at(12);
1332 let cipher = C::new_from_slice(key).map_err(|_| {
1333 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization("AES-GCM"))
1334 })?;
1335 let mut plaintext = body.to_vec();
1336 let nonce = Nonce::try_from(nonce).map_err(|_| {
1337 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization(
1338 "AES-GCM nonce",
1339 ))
1340 })?;
1341 cipher
1342 .decrypt_in_place(&nonce, &[], &mut plaintext)
1343 .map_err(|_| ProviderError::AuthenticationFailed)?;
1344 Ok(plaintext)
1345 }
1346
1347 pub(super) fn wrap_key(
1348 algorithm: KeyWrapAlgorithm,
1349 kek: &[u8],
1350 key: &[u8],
1351 ) -> Result<Vec<u8>, ProviderError> {
1352 check_key(algorithm.key_len(), kek)?;
1353 let mut output = vec![0_u8; key.len() + 8];
1354 match algorithm {
1355 KeyWrapAlgorithm::AesKw128 => KwAes128::new_from_slice(kek)
1356 .map_err(|_| ProviderError::InvalidKeySize {
1357 expected: 16,
1358 actual: kek.len(),
1359 })?
1360 .wrap_key(key, &mut output),
1361 KeyWrapAlgorithm::AesKw256 => KwAes256::new_from_slice(kek)
1362 .map_err(|_| ProviderError::InvalidKeySize {
1363 expected: 32,
1364 actual: kek.len(),
1365 })?
1366 .wrap_key(key, &mut output),
1367 }
1368 .map_err(|_| ProviderError::InvalidInput(ProviderInputError::AesKeyWrapFraming))?;
1369 Ok(output)
1370 }
1371
1372 pub(super) fn unwrap_key(
1373 algorithm: KeyWrapAlgorithm,
1374 kek: &[u8],
1375 wrapped: &[u8],
1376 ) -> Result<Vec<u8>, ProviderError> {
1377 check_key(algorithm.key_len(), kek)?;
1378 if wrapped.len() < 16 || !wrapped.len().is_multiple_of(8) {
1379 return Err(ProviderError::InvalidInput(
1380 ProviderInputError::AesKeyWrapFraming,
1381 ));
1382 }
1383 let mut output = vec![0_u8; wrapped.len() - 8];
1384 let key = match algorithm {
1385 KeyWrapAlgorithm::AesKw128 => KwAes128::new_from_slice(kek)
1386 .map_err(|_| ProviderError::InvalidKeySize {
1387 expected: 16,
1388 actual: kek.len(),
1389 })?
1390 .unwrap_key(wrapped, &mut output),
1391 KeyWrapAlgorithm::AesKw256 => KwAes256::new_from_slice(kek)
1392 .map_err(|_| ProviderError::InvalidKeySize {
1393 expected: 32,
1394 actual: kek.len(),
1395 })?
1396 .unwrap_key(wrapped, &mut output),
1397 }
1398 .map_err(|_| ProviderError::AuthenticationFailed)?;
1399 Ok(key.to_vec())
1400 }
1401
1402 pub(super) fn transport_key(
1403 provider: &dyn CryptoProvider,
1404 key: &rsa::RsaPublicKey,
1405 parameters: &RsaOaepParameters,
1406 plaintext: &[u8],
1407 ) -> Result<Vec<u8>, ProviderError> {
1408 super::validate_oaep_parameters(parameters)?;
1409 let mut rng = super::ProviderRng(provider);
1410 macro_rules! encrypt_with {
1411 ($digest:ty, $mgf:ty) => {
1412 Oaep::<$digest, $mgf>::new_with_mgf_hash_and_label(parameters.label.clone())
1413 .encrypt(&mut rng, key, plaintext)
1414 };
1415 }
1416 let result = match (parameters.digest, parameters.mgf_digest) {
1417 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha1) => {
1418 encrypt_with!(Sha1, Sha1)
1419 }
1420 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha256) => {
1421 encrypt_with!(Sha1, Sha256)
1422 }
1423 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha384) => {
1424 encrypt_with!(Sha1, Sha384)
1425 }
1426 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha512) => {
1427 encrypt_with!(Sha1, Sha512)
1428 }
1429 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha1) => {
1430 encrypt_with!(Sha256, Sha1)
1431 }
1432 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha256) => {
1433 encrypt_with!(Sha256, Sha256)
1434 }
1435 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha384) => {
1436 encrypt_with!(Sha256, Sha384)
1437 }
1438 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha512) => {
1439 encrypt_with!(Sha256, Sha512)
1440 }
1441 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha1) => {
1442 encrypt_with!(Sha384, Sha1)
1443 }
1444 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha256) => {
1445 encrypt_with!(Sha384, Sha256)
1446 }
1447 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha384) => {
1448 encrypt_with!(Sha384, Sha384)
1449 }
1450 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha512) => {
1451 encrypt_with!(Sha384, Sha512)
1452 }
1453 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha1) => {
1454 encrypt_with!(Sha512, Sha1)
1455 }
1456 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha256) => {
1457 encrypt_with!(Sha512, Sha256)
1458 }
1459 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha384) => {
1460 encrypt_with!(Sha512, Sha384)
1461 }
1462 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha512) => {
1463 encrypt_with!(Sha512, Sha512)
1464 }
1465 };
1466 result.map_err(map_rsa_error)
1467 }
1468
1469 pub(super) fn recover_key(
1470 provider: &dyn CryptoProvider,
1471 key: &rsa::RsaPrivateKey,
1472 parameters: &RsaOaepParameters,
1473 ciphertext: &[u8],
1474 ) -> Result<Vec<u8>, ProviderError> {
1475 super::validate_oaep_parameters(parameters)?;
1476 let mut rng = super::ProviderRng(provider);
1477 macro_rules! decrypt_with {
1478 ($digest:ty, $mgf:ty) => {
1479 Oaep::<$digest, $mgf>::new_with_mgf_hash_and_label(parameters.label.clone())
1480 .decrypt(Some(&mut rng), key, ciphertext)
1481 };
1482 }
1483 let result = match (parameters.digest, parameters.mgf_digest) {
1484 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha1) => {
1485 decrypt_with!(Sha1, Sha1)
1486 }
1487 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha256) => {
1488 decrypt_with!(Sha1, Sha256)
1489 }
1490 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha384) => {
1491 decrypt_with!(Sha1, Sha384)
1492 }
1493 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha512) => {
1494 decrypt_with!(Sha1, Sha512)
1495 }
1496 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha1) => {
1497 decrypt_with!(Sha256, Sha1)
1498 }
1499 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha256) => {
1500 decrypt_with!(Sha256, Sha256)
1501 }
1502 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha384) => {
1503 decrypt_with!(Sha256, Sha384)
1504 }
1505 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha512) => {
1506 decrypt_with!(Sha256, Sha512)
1507 }
1508 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha1) => {
1509 decrypt_with!(Sha384, Sha1)
1510 }
1511 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha256) => {
1512 decrypt_with!(Sha384, Sha256)
1513 }
1514 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha384) => {
1515 decrypt_with!(Sha384, Sha384)
1516 }
1517 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha512) => {
1518 decrypt_with!(Sha384, Sha512)
1519 }
1520 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha1) => {
1521 decrypt_with!(Sha512, Sha1)
1522 }
1523 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha256) => {
1524 decrypt_with!(Sha512, Sha256)
1525 }
1526 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha384) => {
1527 decrypt_with!(Sha512, Sha384)
1528 }
1529 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha512) => {
1530 decrypt_with!(Sha512, Sha512)
1531 }
1532 };
1533 result.map_err(map_rsa_error)
1534 }
1535
1536 fn map_rsa_error(error: rsa::Error) -> ProviderError {
1537 match error {
1538 rsa::Error::Rng => ProviderError::Random("RSA-OAEP randomness failed".into()),
1539 _ => ProviderError::AuthenticationFailed,
1540 }
1541 }
1542}
1543
1544#[cfg(test)]
1545mod tests {
1546 #[cfg(feature = "xmldsig")]
1547 use std::sync::atomic::AtomicUsize;
1548 use std::sync::atomic::{AtomicBool, Ordering};
1549
1550 use super::*;
1551
1552 #[cfg(feature = "xmldsig")]
1553 struct CountingRandomProvider {
1554 random_calls: AtomicUsize,
1555 reject_digest: Option<DigestAlgorithm>,
1556 extra_digest_byte: bool,
1557 accept_signatures: bool,
1558 }
1559
1560 #[cfg(feature = "xmldsig")]
1561 impl CryptoProvider for CountingRandomProvider {
1562 fn name(&self) -> &'static str {
1563 "counting-random"
1564 }
1565
1566 fn supports(&self, capability: ProviderCapability<'_>) -> bool {
1567 RUST_CRYPTO_PROVIDER.supports(capability)
1568 }
1569
1570 fn fill_random(&self, output: &mut [u8]) -> Result<(), ProviderError> {
1571 self.random_calls.fetch_add(1, Ordering::Relaxed);
1572 RUST_CRYPTO_PROVIDER.fill_random(output)
1573 }
1574
1575 fn derive_key(
1576 &self,
1577 parameters: &KdfParameters<'_>,
1578 secret: &[u8],
1579 ) -> Result<Vec<u8>, ProviderError> {
1580 RUST_CRYPTO_PROVIDER.derive_key(parameters, secret)
1581 }
1582
1583 fn digest(
1584 &self,
1585 algorithm: DigestAlgorithm,
1586 data: &[u8],
1587 ) -> Result<Vec<u8>, ProviderError> {
1588 if self.reject_digest == Some(algorithm) {
1589 return Err(ProviderError::Unsupported {
1590 operation: ProviderOperation::Digest,
1591 algorithm: Some(algorithm.uri().to_owned()),
1592 });
1593 }
1594 let mut digest = RUST_CRYPTO_PROVIDER.digest(algorithm, data)?;
1595 if self.extra_digest_byte {
1596 digest.push(0);
1597 }
1598 Ok(digest)
1599 }
1600
1601 fn sign(
1602 &self,
1603 key: &dyn crate::xmldsig::SigningKey,
1604 algorithm: crate::xmldsig::SignatureAlgorithm,
1605 data: &[u8],
1606 ) -> Result<Vec<u8>, crate::xmldsig::SigningKeyError> {
1607 key.sign_with_provider(self, algorithm, data)
1608 }
1609
1610 fn verify(
1611 &self,
1612 key: &dyn crate::xmldsig::VerifyingKey,
1613 algorithm: crate::xmldsig::SignatureAlgorithm,
1614 data: &[u8],
1615 signature: &[u8],
1616 ) -> Result<bool, crate::xmldsig::DsigError> {
1617 if self.accept_signatures {
1618 return Ok(true);
1619 }
1620 RUST_CRYPTO_PROVIDER.verify(key, algorithm, data, signature)
1621 }
1622
1623 #[cfg(feature = "xmlenc")]
1624 fn encrypt_data(
1625 &self,
1626 algorithm: DataEncryptionAlgorithm,
1627 key: &[u8],
1628 plaintext: &[u8],
1629 ) -> Result<Vec<u8>, ProviderError> {
1630 RUST_CRYPTO_PROVIDER.encrypt_data(algorithm, key, plaintext)
1631 }
1632
1633 #[cfg(feature = "xmlenc")]
1634 fn decrypt_data(
1635 &self,
1636 algorithm: DataEncryptionAlgorithm,
1637 key: &[u8],
1638 ciphertext: &[u8],
1639 ) -> Result<Vec<u8>, ProviderError> {
1640 RUST_CRYPTO_PROVIDER.decrypt_data(algorithm, key, ciphertext)
1641 }
1642
1643 #[cfg(feature = "xmlenc")]
1644 fn wrap_key(
1645 &self,
1646 algorithm: KeyWrapAlgorithm,
1647 kek: &[u8],
1648 key: &[u8],
1649 ) -> Result<Vec<u8>, ProviderError> {
1650 RUST_CRYPTO_PROVIDER.wrap_key(algorithm, kek, key)
1651 }
1652
1653 #[cfg(feature = "xmlenc")]
1654 fn unwrap_key(
1655 &self,
1656 algorithm: KeyWrapAlgorithm,
1657 kek: &[u8],
1658 wrapped: &[u8],
1659 ) -> Result<Vec<u8>, ProviderError> {
1660 RUST_CRYPTO_PROVIDER.unwrap_key(algorithm, kek, wrapped)
1661 }
1662
1663 #[cfg(feature = "xmlenc")]
1664 fn transport_key(
1665 &self,
1666 key: &dyn KeyTransportKey,
1667 parameters: &RsaOaepParameters,
1668 plaintext: &[u8],
1669 ) -> Result<Vec<u8>, ProviderError> {
1670 RUST_CRYPTO_PROVIDER.transport_key(key, parameters, plaintext)
1671 }
1672
1673 #[cfg(feature = "xmlenc")]
1674 fn recover_key(
1675 &self,
1676 key: &dyn KeyRecoveryKey,
1677 parameters: &RsaOaepParameters,
1678 ciphertext: &[u8],
1679 ) -> Result<Vec<u8>, ProviderError> {
1680 RUST_CRYPTO_PROVIDER.recover_key(key, parameters, ciphertext)
1681 }
1682 }
1683
1684 #[cfg(feature = "xmldsig")]
1685 #[test]
1686 fn capability_query_is_explicit_about_unimplemented_operations() {
1687 assert!(RUST_CRYPTO_PROVIDER.supports(ProviderCapability::Digest(DigestAlgorithm::Sha256)));
1688 let agreement = KeyAgreementParameters {
1689 algorithm: "urn:unsupported:agreement",
1690 peer_public_key: &[],
1691 };
1692 assert!(!RUST_CRYPTO_PROVIDER.supports(ProviderCapability::KeyAgreement(&agreement)));
1693 assert!(!RUST_CRYPTO_PROVIDER.supports(ProviderCapability::Sign(
1694 crate::xmldsig::SignatureAlgorithm::RsaSha1
1695 )));
1696 assert!(RUST_CRYPTO_PROVIDER.supports(ProviderCapability::Verify(
1697 crate::xmldsig::SignatureAlgorithm::RsaSha1
1698 )));
1699 }
1700
1701 #[cfg(all(feature = "xmldsig", feature = "xmlenc"))]
1702 #[test]
1703 fn capability_queries_include_oaep_and_pss_parameters() {
1704 use crate::xmlenc::{KeyTransportAlgorithm, OaepDigestAlgorithm};
1705
1706 let invalid_legacy = RsaOaepParameters {
1707 algorithm: KeyTransportAlgorithm::RsaOaepMgf1p,
1708 digest: OaepDigestAlgorithm::Sha256,
1709 mgf_digest: OaepDigestAlgorithm::Sha256,
1710 label: Vec::new(),
1711 };
1712 assert!(!RUST_CRYPTO_PROVIDER.supports(ProviderCapability::KeyTransport(&invalid_legacy)));
1713 let modern =
1714 RsaOaepParameters::xmlenc11(OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha512)
1715 .label(b"label".to_vec());
1716 assert!(RUST_CRYPTO_PROVIDER.supports(ProviderCapability::KeyTransport(&modern)));
1717
1718 let supported_pss = X509SignatureAlgorithm::RsaPss {
1719 digest: DigestAlgorithm::Sha256,
1720 mgf_digest: DigestAlgorithm::Sha256,
1721 salt_len: 32,
1722 };
1723 assert!(
1724 RUST_CRYPTO_PROVIDER.supports(ProviderCapability::VerifyCertificate(supported_pss))
1725 );
1726 let unsupported_pss = X509SignatureAlgorithm::RsaPss {
1727 digest: DigestAlgorithm::Sha256,
1728 mgf_digest: DigestAlgorithm::Sha384,
1729 salt_len: 32,
1730 };
1731 assert!(
1732 !RUST_CRYPTO_PROVIDER.supports(ProviderCapability::VerifyCertificate(unsupported_pss))
1733 );
1734 }
1735
1736 struct RecordingAgreementKey(AtomicBool);
1737
1738 impl KeyAgreementKey for RecordingAgreementKey {
1739 fn agree(
1740 &self,
1741 _parameters: &KeyAgreementParameters<'_>,
1742 ) -> Result<Vec<u8>, ProviderError> {
1743 self.0.store(true, Ordering::Relaxed);
1744 Ok(vec![0x42])
1745 }
1746 }
1747
1748 #[test]
1749 fn unsupported_agreement_and_kdf_fail_without_dispatch_or_fallback() {
1750 let agreement = KeyAgreementParameters {
1751 algorithm: "urn:example:agreement",
1752 peer_public_key: b"peer",
1753 };
1754 let key = RecordingAgreementKey(AtomicBool::new(false));
1755 let error = RUST_CRYPTO_PROVIDER
1756 .agree_key(&key, &agreement)
1757 .expect_err("unsupported agreement must fail closed");
1758 assert!(matches!(
1759 error,
1760 ProviderError::Unsupported {
1761 operation: ProviderOperation::KeyAgreement,
1762 algorithm: Some(ref algorithm),
1763 } if algorithm == agreement.algorithm
1764 ));
1765 assert!(!key.0.load(Ordering::Relaxed));
1766
1767 let kdf = KdfParameters {
1768 algorithm: "urn:example:kdf",
1769 digest: Some("urn:example:digest"),
1770 salt: b"salt",
1771 info: b"info",
1772 iterations: 1,
1773 output_len: 32,
1774 };
1775 assert!(matches!(
1776 RUST_CRYPTO_PROVIDER.derive_key(&kdf, b"secret"),
1777 Err(ProviderError::Unsupported {
1778 operation: ProviderOperation::Kdf,
1779 algorithm: Some(ref algorithm),
1780 }) if algorithm == kdf.algorithm
1781 ));
1782 }
1783
1784 #[cfg(feature = "xmldsig")]
1785 #[test]
1786 fn rsa_signing_uses_the_selected_providers_randomness() {
1787 use crate::xmldsig::{RsaSigningKey, SignatureAlgorithm};
1788
1789 let key = RsaSigningKey::from_pkcs8_pem(include_str!(
1792 "../tests/fixtures/keys/rsa/rsa-2048-key.pem"
1793 ))
1794 .expect("RSA fixture must parse");
1795 let provider = CountingRandomProvider {
1796 random_calls: AtomicUsize::new(0),
1797 reject_digest: None,
1798 extra_digest_byte: false,
1799 accept_signatures: false,
1800 };
1801
1802 let signature = provider
1803 .sign(&key, SignatureAlgorithm::RsaSha256, b"signed info")
1804 .expect("RSA signing must succeed");
1805
1806 assert!(!signature.is_empty());
1807 assert!(provider.random_calls.load(Ordering::Relaxed) > 0);
1808 }
1809
1810 #[cfg(feature = "xmldsig")]
1811 #[test]
1812 fn ecdsa_signing_uses_the_selected_providers_digest() {
1813 use crate::xmldsig::{
1814 EcdsaP256SigningKey, EcdsaP384SigningKey, SignatureAlgorithm, SigningKeyError,
1815 };
1816
1817 let cases: [(
1821 Box<dyn crate::xmldsig::SigningKey>,
1822 SignatureAlgorithm,
1823 DigestAlgorithm,
1824 ); 2] = [
1825 (
1826 Box::new(
1827 EcdsaP256SigningKey::from_pkcs8_pem(include_str!(
1828 "../tests/fixtures/keys/ec/ec-prime256v1-key.pem"
1829 ))
1830 .expect("P-256 fixture must parse"),
1831 ),
1832 SignatureAlgorithm::EcdsaSha384,
1833 DigestAlgorithm::Sha384,
1834 ),
1835 (
1836 Box::new(
1837 EcdsaP384SigningKey::from_pkcs8_pem(include_str!(
1838 "../tests/fixtures/keys/ec/ec-prime384v1-key.pem"
1839 ))
1840 .expect("P-384 fixture must parse"),
1841 ),
1842 SignatureAlgorithm::EcdsaSha256,
1843 DigestAlgorithm::Sha256,
1844 ),
1845 ];
1846
1847 for (key, signature_algorithm, digest_algorithm) in cases {
1848 let provider = CountingRandomProvider {
1849 random_calls: AtomicUsize::new(0),
1850 reject_digest: Some(digest_algorithm),
1851 extra_digest_byte: false,
1852 accept_signatures: false,
1853 };
1854 let error = provider
1855 .sign(key.as_ref(), signature_algorithm, b"signed info")
1856 .expect_err("provider digest rejection must stop ECDSA signing");
1857
1858 assert!(matches!(
1859 error,
1860 SigningKeyError::Provider(ProviderError::Unsupported {
1861 operation: ProviderOperation::Digest,
1862 algorithm: Some(ref uri),
1863 }) if uri == digest_algorithm.uri()
1864 ));
1865 }
1866 }
1867
1868 #[cfg(feature = "xmldsig")]
1869 #[test]
1870 fn ecdsa_signing_rejects_provider_digests_with_the_wrong_length() {
1871 use crate::xmldsig::{
1872 EcdsaP256SigningKey, EcdsaP384SigningKey, SignatureAlgorithm, SigningKeyError,
1873 };
1874
1875 let cases: [(
1878 Box<dyn crate::xmldsig::SigningKey>,
1879 SignatureAlgorithm,
1880 usize,
1881 ); 2] = [
1882 (
1883 Box::new(
1884 EcdsaP256SigningKey::from_pkcs8_pem(include_str!(
1885 "../tests/fixtures/keys/ec/ec-prime256v1-key.pem"
1886 ))
1887 .expect("P-256 fixture must parse"),
1888 ),
1889 SignatureAlgorithm::EcdsaSha256,
1890 32,
1891 ),
1892 (
1893 Box::new(
1894 EcdsaP384SigningKey::from_pkcs8_pem(include_str!(
1895 "../tests/fixtures/keys/ec/ec-prime384v1-key.pem"
1896 ))
1897 .expect("P-384 fixture must parse"),
1898 ),
1899 SignatureAlgorithm::EcdsaSha384,
1900 48,
1901 ),
1902 ];
1903
1904 for (key, algorithm, expected) in cases {
1905 let provider = CountingRandomProvider {
1906 random_calls: AtomicUsize::new(0),
1907 reject_digest: None,
1908 extra_digest_byte: true,
1909 accept_signatures: false,
1910 };
1911 let error = provider
1912 .sign(key.as_ref(), algorithm, b"signed info")
1913 .expect_err("an oversized provider digest must not reach ECDSA prehash signing");
1914
1915 assert!(matches!(
1916 error,
1917 SigningKeyError::Provider(ProviderError::InvalidOutputSize {
1918 operation: ProviderOperation::Digest,
1919 expected: actual_expected,
1920 actual,
1921 }) if actual_expected == expected && actual == expected + 1
1922 ));
1923 }
1924 }
1925
1926 #[cfg(feature = "xmldsig")]
1927 #[test]
1928 fn verification_facade_rejects_malformed_dsa_before_provider_dispatch() {
1929 use crate::xmldsig::{
1930 DefaultKeyResolver, DsigStatus, FailureReason, SignatureAlgorithm, VerifyContext,
1931 };
1932
1933 let original = include_str!(
1934 "../tests/fixtures/xmldsig/merlin-xmldsig-twenty-three/signature-enveloping-dsa.xml"
1935 );
1936 let value_start = original
1937 .find("<SignatureValue>")
1938 .expect("Merlin fixture must contain SignatureValue")
1939 + "<SignatureValue>".len();
1940 let value_end = original[value_start..]
1941 .find("</SignatureValue>")
1942 .map(|offset| value_start + offset)
1943 .expect("Merlin fixture must close SignatureValue");
1944 let mut malformed = original.to_owned();
1945 malformed.replace_range(value_start..value_end, "AQ==");
1946 let provider = CountingRandomProvider {
1947 random_calls: AtomicUsize::new(0),
1948 reject_digest: None,
1949 extra_digest_byte: false,
1950 accept_signatures: true,
1951 };
1952
1953 let mut policy = crate::policy::VerificationPolicy::default();
1954 policy
1955 .key_trust
1956 .allowed_legacy_signature_algorithms
1957 .insert(SignatureAlgorithm::DsaSha1);
1958 policy.key_trust.dsa_keys.minimum_modulus_bits = 1024;
1959 let result = VerifyContext::new()
1960 .policy(policy)
1961 .provider(&provider)
1962 .key_resolver(&DefaultKeyResolver::default())
1963 .verify(&malformed)
1964 .expect("malformed framing must be a verification miss");
1965
1966 assert_eq!(
1967 result.status,
1968 DsigStatus::Invalid(FailureReason::SignatureMismatch)
1969 );
1970 }
1971
1972 #[cfg(feature = "xmldsig")]
1973 #[test]
1974 fn rustcrypto_provider_verifies_parameterized_rsa_pss_certificates() {
1975 use der::{Decode as _, Encode as _};
1976 use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng};
1977 use rsa::{RsaPrivateKey, pkcs8::EncodePublicKey, pss::SigningKey as RsaPssSigningKey};
1978 use sha2::Sha256;
1979 use signature::{RandomizedSigner, SignatureEncoding};
1980 use x509_cert::spki::{AlgorithmIdentifierOwned, ObjectIdentifier};
1981
1982 let mut rng = ChaCha20Rng::from_seed([0x5a; 32]);
1985 let private_key =
1986 RsaPrivateKey::new(&mut rng, 2048).expect("deterministic RSA key generation");
1987 let public_key = private_key
1988 .to_public_key()
1989 .to_public_key_der()
1990 .expect("RSA public key must encode as SPKI");
1991 let signing_key = RsaPssSigningKey::<Sha256>::new_with_salt_len(private_key, 32);
1992 let signed_data = b"certificate tbs bytes";
1993 let signature = signing_key
1994 .try_sign_with_rng(&mut rng, signed_data)
1995 .expect("RSA-PSS signing must succeed")
1996 .to_vec();
1997
1998 assert!(
1999 RUST_CRYPTO_PROVIDER
2000 .verify_x509_signature(
2001 X509SignatureAlgorithm::RsaPss {
2002 digest: DigestAlgorithm::Sha256,
2003 mgf_digest: DigestAlgorithm::Sha256,
2004 salt_len: 32,
2005 },
2006 signed_data,
2007 &signature,
2008 public_key.as_bytes(),
2009 )
2010 .expect("standard RSA-PSS parameters must be supported")
2011 );
2012
2013 let mut parameterless_pss_spki =
2014 x509_cert::SubjectPublicKeyInfo::from_der(public_key.as_bytes())
2015 .expect("RSA SPKI must decode");
2016 parameterless_pss_spki.algorithm = AlgorithmIdentifierOwned {
2017 oid: ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10"),
2018 parameters: None,
2019 };
2020 let parameterless_pss_spki = parameterless_pss_spki
2021 .to_der()
2022 .expect("parameterless PSS SPKI must encode");
2023 assert!(
2024 RUST_CRYPTO_PROVIDER
2025 .verify_x509_signature(
2026 X509SignatureAlgorithm::RsaPss {
2027 digest: DigestAlgorithm::Sha256,
2028 mgf_digest: DigestAlgorithm::Sha256,
2029 salt_len: 32,
2030 },
2031 signed_data,
2032 &signature,
2033 ¶meterless_pss_spki,
2034 )
2035 .expect("parameterless PSS keys impose no signature restrictions")
2036 );
2037
2038 let mut pss_spki = x509_cert::SubjectPublicKeyInfo::from_der(public_key.as_bytes())
2039 .expect("RSA SPKI must decode");
2040 let pss_parameters = der::asn1::Any::from_der(&[
2041 0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
2042 0x04, 0x02, 0x01, 0x05, 0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48,
2043 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
2044 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x20,
2045 ])
2046 .expect("standard SHA-256 PSS parameters must decode");
2047 pss_spki.algorithm = AlgorithmIdentifierOwned {
2048 oid: ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10"),
2049 parameters: Some(pss_parameters),
2050 };
2051 let pss_spki = pss_spki.to_der().expect("PSS SPKI must encode");
2052
2053 assert!(
2054 RUST_CRYPTO_PROVIDER
2055 .verify_x509_signature(
2056 X509SignatureAlgorithm::RsaPss {
2057 digest: DigestAlgorithm::Sha256,
2058 mgf_digest: DigestAlgorithm::Sha256,
2059 salt_len: 32,
2060 },
2061 signed_data,
2062 &signature,
2063 &pss_spki,
2064 )
2065 .expect("RFC 4055 PSS SubjectPublicKeyInfo must be supported")
2066 );
2067
2068 for incompatible in [
2069 X509SignatureAlgorithm::RsaPss {
2070 digest: DigestAlgorithm::Sha384,
2071 mgf_digest: DigestAlgorithm::Sha256,
2072 salt_len: 32,
2073 },
2074 X509SignatureAlgorithm::RsaPss {
2075 digest: DigestAlgorithm::Sha256,
2076 mgf_digest: DigestAlgorithm::Sha384,
2077 salt_len: 32,
2078 },
2079 X509SignatureAlgorithm::RsaPss {
2080 digest: DigestAlgorithm::Sha256,
2081 mgf_digest: DigestAlgorithm::Sha256,
2082 salt_len: 16,
2083 },
2084 ] {
2085 assert!(
2086 !RUST_CRYPTO_PROVIDER
2087 .verify_x509_signature(incompatible, signed_data, &signature, &pss_spki,)
2088 .expect("incompatible PSS key restrictions are invalid, not unsupported")
2089 );
2090 }
2091 }
2092
2093 #[cfg(feature = "xmldsig")]
2094 #[test]
2095 fn rustcrypto_provider_verifies_dsa_certificate_signature_at_q_width() {
2096 use base64::Engine as _;
2097
2098 let spki = base64::engine::general_purpose::STANDARD
2101 .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=")
2102 .expect("DSA SPKI fixture must decode");
2103 let signature = base64::engine::general_purpose::STANDARD
2104 .decode("MD0CHQChtB1c+f5BmTJCtT7Gi4cyQiR2igj0znRQYCJ3Ahw4NGg4pL5jgA8Ri07ESV9Yr90WfUmRrbRcnjsY")
2105 .expect("DSA signature fixture must decode");
2106 let message = b"certificate tbs bytes for dsa q-width regression";
2107
2108 assert!(
2109 rustcrypto_x509::verify_signature(
2110 X509SignatureAlgorithm::Dsa(DigestAlgorithm::Sha1),
2111 message,
2112 &signature,
2113 &spki,
2114 )
2115 .expect("supported DSA-SHA1 certificate signature")
2116 );
2117
2118 let mut tampered = signature;
2119 *tampered.last_mut().expect("DER signature is non-empty") ^= 1;
2120 assert!(
2121 !rustcrypto_x509::verify_signature(
2122 X509SignatureAlgorithm::Dsa(DigestAlgorithm::Sha1),
2123 message,
2124 &tampered,
2125 &spki,
2126 )
2127 .expect("tampered DSA-SHA1 certificate signature is a verification miss")
2128 );
2129 }
2130
2131 #[cfg(feature = "xmldsig")]
2132 #[test]
2133 fn primitive_provider_does_not_embed_rsa_strength_policy() {
2134 use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng};
2135 use rsa::{RsaPrivateKey, pkcs8::EncodePublicKey, pss::SigningKey as RsaPssSigningKey};
2136 use sha2::Sha256;
2137 use signature::{RandomizedSigner, SignatureEncoding};
2138
2139 let mut rng = ChaCha20Rng::from_seed([0x3c; 32]);
2140 let private_key =
2141 RsaPrivateKey::new(&mut rng, 1024).expect("deterministic weak RSA key generation");
2142 let public_key = private_key
2143 .to_public_key()
2144 .to_public_key_der()
2145 .expect("weak RSA public key must encode as SPKI");
2146 let signed_data = b"certificate tbs bytes";
2147 let signature = RsaPssSigningKey::<Sha256>::new_with_salt_len(private_key, 32)
2148 .try_sign_with_rng(&mut rng, signed_data)
2149 .expect("weak RSA-PSS key can still produce a cryptographic signature")
2150 .to_vec();
2151
2152 assert!(
2153 RUST_CRYPTO_PROVIDER
2154 .verify_x509_signature(
2155 X509SignatureAlgorithm::RsaPss {
2156 digest: DigestAlgorithm::Sha256,
2157 mgf_digest: DigestAlgorithm::Sha256,
2158 salt_len: 32,
2159 },
2160 signed_data,
2161 &signature,
2162 public_key.as_bytes(),
2163 )
2164 .expect(
2165 "provider must evaluate structurally valid RSA-PSS independently of policy"
2166 )
2167 );
2168 }
2169
2170 #[cfg(feature = "xmldsig")]
2171 #[test]
2172 fn oversized_rsa_pss_salt_is_a_verification_miss() {
2173 use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng};
2174 use rsa::{RsaPrivateKey, pkcs8::EncodePublicKey as _, traits::PublicKeyParts as _};
2175
2176 let mut rng = ChaCha20Rng::from_seed([0x55; 32]);
2179 let public_key = RsaPrivateKey::new(&mut rng, 1024)
2180 .expect("deterministic RSA key generation")
2181 .to_public_key();
2182 let spki = public_key
2183 .to_public_key_der()
2184 .expect("RSA public key must encode as SPKI");
2185
2186 assert!(rustcrypto_x509::rsa_pss_salt_fits_key(
2187 &public_key,
2188 DigestAlgorithm::Sha256,
2189 0,
2190 ));
2191 assert!(rustcrypto_x509::rsa_pss_salt_fits_key(
2192 &public_key,
2193 DigestAlgorithm::Sha256,
2194 94,
2195 ));
2196 assert!(!rustcrypto_x509::rsa_pss_salt_fits_key(
2197 &public_key,
2198 DigestAlgorithm::Sha256,
2199 95,
2200 ));
2201
2202 assert!(
2203 !RUST_CRYPTO_PROVIDER
2204 .verify_x509_signature(
2205 X509SignatureAlgorithm::RsaPss {
2206 digest: DigestAlgorithm::Sha256,
2207 mgf_digest: DigestAlgorithm::Sha256,
2208 salt_len: usize::MAX,
2209 },
2210 b"certificate tbs bytes",
2211 &vec![0_u8; public_key.size()],
2212 spki.as_bytes(),
2213 )
2214 .expect("oversized PSS salt must fail without panicking")
2215 );
2216 }
2217
2218 #[cfg(feature = "xmlenc")]
2219 #[test]
2220 fn legacy_oaep_mgf_constraint_is_symmetric() {
2221 use rsa::pkcs8::DecodePrivateKey;
2222
2223 let key = rsa::RsaPrivateKey::from_pkcs8_pem(include_str!(
2226 "../tests/fixtures/keys/rsa/rsa-2048-key.pem"
2227 ))
2228 .expect("RSA fixture must parse");
2229 let parameters = crate::xmlenc::RsaOaepParameters {
2230 algorithm: crate::xmlenc::KeyTransportAlgorithm::RsaOaepMgf1p,
2231 digest: crate::xmlenc::OaepDigestAlgorithm::Sha256,
2232 mgf_digest: crate::xmlenc::OaepDigestAlgorithm::Sha256,
2233 label: Vec::new(),
2234 };
2235
2236 assert!(matches!(
2237 RUST_CRYPTO_PROVIDER.recover_key(&key, ¶meters, &[0_u8; 256]),
2238 Err(ProviderError::InvalidInput(
2239 ProviderInputError::LegacyRsaOaepMgf
2240 ))
2241 ));
2242 assert!(matches!(
2243 RUST_CRYPTO_PROVIDER.transport_key(&key.to_public_key(), ¶meters, &[0_u8; 16]),
2244 Err(ProviderError::InvalidInput(
2245 ProviderInputError::LegacyRsaOaepMgf
2246 ))
2247 ));
2248 }
2249}