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