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