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