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