Skip to main content

xml_sec/
provider.rs

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