1#[cfg(feature = "xmldsig")]
9use crate::rustcrypto_sha3 as sha3;
10
11#[cfg(feature = "aws-lc-fips")]
12mod aws_lc;
13#[cfg(feature = "xmlenc")]
14mod chacha;
15#[cfg(feature = "xmlenc")]
16mod key_establishment;
17#[cfg(feature = "pkcs11")]
18pub mod pkcs11;
19#[cfg(feature = "xmlenc")]
20pub use key_establishment::{
21 EcdhCurve, RustCryptoDhKey, RustCryptoEcdhKey, RustCryptoX448Key, RustCryptoX25519Key,
22};
23#[cfg(feature = "xmldsig")]
24mod key_encapsulation;
25#[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
26mod rsa_pkcs1v15;
27#[cfg(feature = "xmldsig")]
28pub(crate) mod rsa_pss;
29#[cfg(feature = "xmldsig")]
30pub use key_encapsulation::{
31 EncapsulatedKey, KeyDecapsulationKey, KeyEncapsulationAlgorithm, KeyEncapsulationKey,
32};
33#[cfg(feature = "experimental-pq")]
34pub use key_encapsulation::{
35 MlKemPrivateKeyEncoding, RustCryptoMlKemPrivateKey, RustCryptoMlKemPublicKey,
36};
37
38#[cfg(feature = "xmlenc")]
41pub struct RecoveredContentKey {
42 bytes: zeroize::Zeroizing<Vec<u8>>,
43 valid: subtle::Choice,
44 implicit_rejection: bool,
45 opaque: Option<std::sync::Arc<dyn ContentDecryptionKey>>,
46}
47
48#[cfg(feature = "xmlenc")]
49impl std::fmt::Debug for RecoveredContentKey {
50 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 f.debug_struct("RecoveredContentKey")
52 .finish_non_exhaustive()
53 }
54}
55
56#[cfg(feature = "xmlenc")]
57impl RecoveredContentKey {
58 pub fn confirmed(bytes: Vec<u8>) -> Self {
66 Self {
67 bytes: zeroize::Zeroizing::new(bytes),
68 valid: subtle::Choice::from(1),
69 implicit_rejection: false,
70 opaque: None,
71 }
72 }
73
74 #[cfg(feature = "legacy-algorithms")]
75 pub fn recovery(bytes: zeroize::Zeroizing<Vec<u8>>, valid: subtle::Choice) -> Self {
80 Self {
81 bytes,
82 valid,
83 implicit_rejection: true,
84 opaque: None,
85 }
86 }
87
88 pub fn opaque(key: std::sync::Arc<dyn ContentDecryptionKey>) -> Self {
90 Self {
91 bytes: zeroize::Zeroizing::new(Vec::new()),
92 valid: subtle::Choice::from(1),
93 implicit_rejection: false,
94 opaque: Some(key),
95 }
96 }
97
98 pub fn key_len(&self) -> usize {
100 self.opaque
101 .as_ref()
102 .map_or(self.bytes.len(), |key| key.key_len())
103 }
104
105 pub(crate) fn same_candidate(&self, other: &Self) -> bool {
106 match (&self.opaque, &other.opaque) {
107 (Some(a), Some(b)) => std::sync::Arc::ptr_eq(a, b),
108 (None, None) => self.bytes == other.bytes && self.valid() == other.valid(),
109 _ => false,
110 }
111 }
112
113 pub(crate) fn decrypt(
114 &self,
115 provider: &dyn CryptoProvider,
116 algorithm: DataEncryptionAlgorithm,
117 ciphertext: &[u8],
118 parameters: Option<crate::xmlenc::ChaChaParametersRef<'_>>,
119 ) -> Result<Vec<u8>, ProviderError> {
120 match &self.opaque {
121 Some(_) if parameters.is_some() => Err(ProviderError::Unsupported {
122 operation: ProviderOperation::Decrypt,
123 algorithm: Some(algorithm.uri().into()),
124 }),
125 Some(key) => provider.decrypt_content_key(algorithm, key.as_ref(), ciphertext),
126 None => provider.decrypt_data_with_parameters(
127 algorithm,
128 &self.bytes,
129 ciphertext,
130 parameters,
131 ),
132 }
133 }
134
135 #[cfg(test)]
136 pub(crate) fn bytes(&self) -> &[u8] {
137 &self.bytes
138 }
139 pub(crate) fn valid(&self) -> bool {
140 bool::from(self.valid)
141 }
142 pub(crate) fn unwrap_nested(
145 &self,
146 provider: &dyn CryptoProvider,
147 algorithm: KeyWrapAlgorithm,
148 ciphertext: &[u8],
149 output_len: usize,
150 ) -> Result<Self, ProviderError> {
151 if self.opaque.is_some() {
152 return Err(ProviderError::KeyNotExportable);
153 }
154 if self.implicit_rejection {
155 provider.require_capability(ProviderCapability::Random)?;
160 let mut fallback = zeroize::Zeroizing::new(vec![0; output_len]);
161 provider.fill_random(&mut fallback)?;
162 let mut candidate = match provider.unwrap_key(algorithm, &self.bytes, ciphertext) {
163 Ok(bytes) => zeroize::Zeroizing::new(bytes),
164 Err(ProviderError::AuthenticationFailed) => {
165 return Ok(Self {
166 bytes: fallback,
167 valid: subtle::Choice::from(0),
168 implicit_rejection: true,
169 opaque: None,
170 });
171 }
172 Err(error) => return Err(error),
173 };
174 if candidate.len() != output_len {
175 return Err(ProviderError::InvalidOutputSize {
176 operation: ProviderOperation::KeyUnwrap,
177 expected: output_len,
178 actual: candidate.len(),
179 });
180 }
181 use subtle::ConditionallySelectable;
182 for (byte, random) in candidate.iter_mut().zip(fallback.iter()) {
183 *byte = u8::conditional_select(random, byte, self.valid);
184 }
185 return Ok(Self {
186 bytes: candidate,
187 valid: self.valid,
188 implicit_rejection: true,
189 opaque: None,
190 });
191 }
192 let bytes = provider.unwrap_key(algorithm, &self.bytes, ciphertext)?;
193 Ok(Self {
194 bytes: zeroize::Zeroizing::new(bytes),
195 valid: self.valid,
196 implicit_rejection: false,
197 opaque: None,
198 })
199 }
200 pub fn into_key(mut self) -> Result<Vec<u8>, ProviderError> {
203 if self.opaque.is_some() {
204 return Err(ProviderError::KeyNotExportable);
205 }
206 if !self.valid() {
207 return Err(ProviderError::AuthenticationFailed);
208 }
209 Ok(core::mem::take(&mut *self.bytes))
210 }
211}
212#[cfg(all(feature = "aws-lc-fips", feature = "xmlenc"))]
213pub use aws_lc::AwsLcRsaPrivateKey;
214#[cfg(feature = "aws-lc-fips")]
215pub use aws_lc::{AwsLcFipsProvider, AwsLcSigningKey};
216
217#[cfg(feature = "xmlenc")]
218use std::borrow::Cow;
219
220#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
221use getrandom::rand_core::TryCryptoRng;
222use getrandom::{SysRng, rand_core::TryRng};
223
224#[cfg(feature = "xmldsig")]
225use crate::xmldsig::DigestAlgorithm;
226#[cfg(feature = "xmlenc")]
227use crate::xmlenc::{DataEncryptionAlgorithm, KeyWrapAlgorithm, RsaOaepParameters};
228
229#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
231#[non_exhaustive]
232pub enum ProviderOperation {
233 Digest,
235 Sign,
237 Verify,
239 VerifyCertificate,
241 Encrypt,
243 Decrypt,
245 KeyWrap,
247 KeyUnwrap,
249 KeyTransport,
251 KeyRecovery,
253 KeyAgreement,
255 Encapsulate,
257 Decapsulate,
259 Kdf,
261 Random,
263}
264
265#[derive(Debug, Clone, Copy)]
270#[non_exhaustive]
271pub enum ProviderCapability<'a> {
272 #[cfg(feature = "xmldsig")]
274 Encapsulate(KeyEncapsulationAlgorithm),
275 #[cfg(feature = "xmldsig")]
277 Decapsulate(KeyEncapsulationAlgorithm),
278 #[cfg(feature = "xmldsig")]
280 Digest(DigestAlgorithm),
281 #[cfg(feature = "xmldsig")]
286 Sign(crate::xmldsig::SignatureAlgorithm),
287 #[cfg(feature = "xmldsig")]
292 Verify(crate::xmldsig::SignatureAlgorithm),
293 #[cfg(feature = "xmldsig")]
295 VerifyCertificate(X509SignatureAlgorithm),
296 #[cfg(feature = "xmlenc")]
298 Encrypt(DataEncryptionAlgorithm),
299 #[cfg(feature = "xmlenc")]
301 Decrypt(DataEncryptionAlgorithm),
302 #[cfg(feature = "xmlenc")]
304 KeyWrap(KeyWrapAlgorithm),
305 #[cfg(feature = "xmlenc")]
307 KeyUnwrap(KeyWrapAlgorithm),
308 #[cfg(feature = "xmlenc")]
310 KeyTransport(&'a RsaOaepParameters),
311 #[cfg(feature = "xmlenc")]
313 KeyRecovery(&'a RsaOaepParameters),
314 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
316 Pkcs1v15Transport,
317 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
319 Pkcs1v15Recovery,
320 KeyAgreement(&'a KeyAgreementParameters<'a>),
322 Kdf(&'a KdfParameters<'a>),
324 Random,
326}
327
328impl ProviderCapability<'_> {
329 #[must_use]
331 pub const fn operation(&self) -> ProviderOperation {
332 match self {
333 #[cfg(feature = "xmldsig")]
334 Self::Encapsulate(_) => ProviderOperation::Encapsulate,
335 #[cfg(feature = "xmldsig")]
336 Self::Decapsulate(_) => ProviderOperation::Decapsulate,
337 #[cfg(feature = "xmldsig")]
338 Self::Digest(_) => ProviderOperation::Digest,
339 #[cfg(feature = "xmldsig")]
340 Self::Sign(_) => ProviderOperation::Sign,
341 #[cfg(feature = "xmldsig")]
342 Self::Verify(_) => ProviderOperation::Verify,
343 #[cfg(feature = "xmldsig")]
344 Self::VerifyCertificate(_) => ProviderOperation::VerifyCertificate,
345 #[cfg(feature = "xmlenc")]
346 Self::Encrypt(_) => ProviderOperation::Encrypt,
347 #[cfg(feature = "xmlenc")]
348 Self::Decrypt(_) => ProviderOperation::Decrypt,
349 #[cfg(feature = "xmlenc")]
350 Self::KeyWrap(_) => ProviderOperation::KeyWrap,
351 #[cfg(feature = "xmlenc")]
352 Self::KeyUnwrap(_) => ProviderOperation::KeyUnwrap,
353 #[cfg(feature = "xmlenc")]
354 Self::KeyTransport(_) => ProviderOperation::KeyTransport,
355 #[cfg(feature = "xmlenc")]
356 Self::KeyRecovery(_) => ProviderOperation::KeyRecovery,
357 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
358 Self::Pkcs1v15Transport => ProviderOperation::KeyTransport,
359 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
360 Self::Pkcs1v15Recovery => ProviderOperation::KeyRecovery,
361 Self::KeyAgreement(_) => ProviderOperation::KeyAgreement,
362 Self::Kdf(_) => ProviderOperation::Kdf,
363 Self::Random => ProviderOperation::Random,
364 }
365 }
366
367 #[must_use]
369 pub fn algorithm(&self) -> Option<&str> {
370 match self {
371 #[cfg(feature = "xmldsig")]
372 Self::Encapsulate(algorithm) | Self::Decapsulate(algorithm) => Some(algorithm.uri()),
373 #[cfg(feature = "xmldsig")]
374 Self::Digest(algorithm) => Some(algorithm.uri()),
375 #[cfg(feature = "xmldsig")]
376 Self::Sign(algorithm) | Self::Verify(algorithm) => Some(algorithm.uri()),
377 #[cfg(feature = "xmldsig")]
378 Self::VerifyCertificate(algorithm) => algorithm.oid(),
379 #[cfg(feature = "xmlenc")]
380 Self::Encrypt(algorithm) | Self::Decrypt(algorithm) => Some(algorithm.uri()),
381 #[cfg(feature = "xmlenc")]
382 Self::KeyWrap(algorithm) | Self::KeyUnwrap(algorithm) => Some(algorithm.uri()),
383 #[cfg(feature = "xmlenc")]
384 Self::KeyTransport(parameters) | Self::KeyRecovery(parameters) => {
385 Some(parameters.algorithm.uri())
386 }
387 Self::KeyAgreement(parameters) => Some(parameters.algorithm),
388 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
389 Self::Pkcs1v15Transport | Self::Pkcs1v15Recovery => {
390 Some(crate::xmlenc::KeyTransportAlgorithm::RsaPkcs1v15.uri())
391 }
392 Self::Kdf(parameters) => Some(parameters.algorithm),
393 Self::Random => None,
394 }
395 }
396}
397
398#[derive(Debug, Clone, Copy, PartialEq, Eq)]
400pub struct KeyAgreementParameters<'a> {
401 pub algorithm: &'a str,
403 pub peer_public_key: &'a [u8],
405}
406
407#[derive(Debug, Clone, Copy, PartialEq, Eq)]
409pub enum KdfContext<'a> {
410 LegacyDh {
413 encryption_algorithm: &'a str,
415 nonce: &'a [u8],
417 },
418 Octets(&'a [u8]),
420 Bits {
423 bytes: &'a [u8],
425 bit_len: usize,
427 },
428}
429
430#[derive(Debug, Clone, Copy, PartialEq, Eq)]
432pub struct KdfParameters<'a> {
433 pub algorithm: &'a str,
435 pub digest: Option<&'a str>,
437 pub salt: &'a [u8],
439 pub info: KdfContext<'a>,
441 pub iterations: u64,
443 pub output_len: usize,
445}
446
447#[cfg(feature = "xmldsig")]
449#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
450#[non_exhaustive]
451pub enum X509SignatureAlgorithm {
452 Dsa(DigestAlgorithm),
454 RsaPkcs1v15(DigestAlgorithm),
456 RsaPss {
458 digest: DigestAlgorithm,
460 mgf_digest: DigestAlgorithm,
462 salt_len: usize,
464 },
465 Ecdsa(DigestAlgorithm),
467 Ed25519,
469 Ed448,
471 PostQuantum(crate::xmldsig::PqAlgorithm),
473}
474
475#[cfg(feature = "xmldsig")]
476impl X509SignatureAlgorithm {
477 #[must_use]
479 pub const fn oid(self) -> Option<&'static str> {
480 Some(match self {
481 #[cfg(feature = "legacy-algorithms")]
482 Self::Dsa(DigestAlgorithm::Md5 | DigestAlgorithm::Ripemd160)
483 | Self::RsaPkcs1v15(DigestAlgorithm::Md5 | DigestAlgorithm::Ripemd160)
484 | Self::Ecdsa(DigestAlgorithm::Md5 | DigestAlgorithm::Ripemd160) => return None,
485 Self::Dsa(DigestAlgorithm::Sha1) => "1.2.840.10040.4.3",
486 Self::Dsa(DigestAlgorithm::Sha224) => "2.16.840.1.101.3.4.3.1",
487 Self::Dsa(DigestAlgorithm::Sha256) => "2.16.840.1.101.3.4.3.2",
488 Self::Dsa(DigestAlgorithm::Sha384) => "2.16.840.1.101.3.4.3.3",
489 Self::Dsa(DigestAlgorithm::Sha512) => "2.16.840.1.101.3.4.3.4",
490 Self::Dsa(DigestAlgorithm::Sha3_224) => "2.16.840.1.101.3.4.3.5",
491 Self::Dsa(DigestAlgorithm::Sha3_256) => "2.16.840.1.101.3.4.3.6",
492 Self::Dsa(DigestAlgorithm::Sha3_384) => "2.16.840.1.101.3.4.3.7",
493 Self::Dsa(DigestAlgorithm::Sha3_512) => "2.16.840.1.101.3.4.3.8",
494 Self::RsaPkcs1v15(DigestAlgorithm::Sha1) => "1.2.840.113549.1.1.5",
495 Self::RsaPkcs1v15(DigestAlgorithm::Sha224) => "1.2.840.113549.1.1.14",
496 Self::RsaPkcs1v15(DigestAlgorithm::Sha256) => "1.2.840.113549.1.1.11",
497 Self::RsaPkcs1v15(DigestAlgorithm::Sha384) => "1.2.840.113549.1.1.12",
498 Self::RsaPkcs1v15(DigestAlgorithm::Sha512) => "1.2.840.113549.1.1.13",
499 Self::RsaPkcs1v15(DigestAlgorithm::Sha3_224) => "2.16.840.1.101.3.4.3.13",
500 Self::RsaPkcs1v15(DigestAlgorithm::Sha3_256) => "2.16.840.1.101.3.4.3.14",
501 Self::RsaPkcs1v15(DigestAlgorithm::Sha3_384) => "2.16.840.1.101.3.4.3.15",
502 Self::RsaPkcs1v15(DigestAlgorithm::Sha3_512) => "2.16.840.1.101.3.4.3.16",
503 Self::RsaPss { .. } => "1.2.840.113549.1.1.10",
504 Self::Ecdsa(DigestAlgorithm::Sha1) => "1.2.840.10045.4.1",
505 Self::Ecdsa(DigestAlgorithm::Sha224) => "1.2.840.10045.4.3.1",
506 Self::Ecdsa(DigestAlgorithm::Sha256) => "1.2.840.10045.4.3.2",
507 Self::Ecdsa(DigestAlgorithm::Sha384) => "1.2.840.10045.4.3.3",
508 Self::Ecdsa(DigestAlgorithm::Sha512) => "1.2.840.10045.4.3.4",
509 Self::Ecdsa(DigestAlgorithm::Sha3_224) => "2.16.840.1.101.3.4.3.9",
510 Self::Ecdsa(DigestAlgorithm::Sha3_256) => "2.16.840.1.101.3.4.3.10",
511 Self::Ecdsa(DigestAlgorithm::Sha3_384) => "2.16.840.1.101.3.4.3.11",
512 Self::Ecdsa(DigestAlgorithm::Sha3_512) => "2.16.840.1.101.3.4.3.12",
513 Self::Ed25519 => "1.3.101.112",
514 Self::Ed448 => "1.3.101.113",
515 Self::PostQuantum(algorithm) => algorithm.oid(),
516 })
517 }
518}
519
520#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
522#[non_exhaustive]
523pub enum ProviderInputError {
524 #[error("invalid ML-KEM key material")]
526 MlKemKey,
527 #[error("invalid ML-KEM ciphertext length")]
529 MlKemCiphertext,
530 #[error("invalid ECDH key material")]
532 EcdhKey,
533 #[error("ECDH-ES sender key already consumed; supply a fresh key pair")]
535 ConsumedEphemeralKey,
536 #[error("invalid DH key material")]
538 DhKey,
539 #[error("invalid HKDF parameters")]
541 HkdfParameters,
542 #[error("invalid PBKDF2 parameters")]
544 Pbkdf2Parameters,
545 #[error("invalid ConcatKDF parameters")]
547 ConcatKdfParameters,
548 #[error("invalid legacy DH KDF parameters")]
550 LegacyDhKdfParameters,
551 #[error("failed to initialize {0}")]
553 PrimitiveInitialization(&'static str),
554 #[error("invalid AES-CBC framing")]
556 AesCbcFraming,
557 #[error("invalid AES-CBC ciphertext")]
559 AesCbcCiphertext,
560 #[error("invalid AES-GCM framing")]
562 AesGcmFraming,
563 #[error("invalid AES key-wrap framing")]
565 AesKeyWrapFraming,
566 #[deprecated(note = "explicit MGF parameters are supported for both RSA-OAEP URIs")]
571 #[error("legacy RSA-OAEP requires MGF1-SHA1")]
572 LegacyRsaOaepMgf,
573}
574
575#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
577#[non_exhaustive]
578pub enum ProviderError {
579 #[error("key is not exportable")]
581 KeyNotExportable,
582 #[error("external cryptographic provider failed: {0}")]
584 External(ExternalProviderError),
585 #[error("provider does not support {operation:?} with algorithm {algorithm:?}")]
587 Unsupported {
588 operation: ProviderOperation,
590 algorithm: Option<String>,
592 },
593 #[error("invalid key size: expected {expected} bytes, got {actual}")]
595 InvalidKeySize {
596 expected: usize,
598 actual: usize,
600 },
601 #[error(
604 "invalid provider output size for {operation:?}: expected {expected} bytes, got {actual}"
605 )]
606 InvalidOutputSize {
607 operation: ProviderOperation,
609 expected: usize,
611 actual: usize,
613 },
614 #[error(
617 "invalid provider output size for {operation:?}: expected {minimum}..={maximum} bytes, got {actual}"
618 )]
619 InvalidOutputSizeRange {
620 operation: ProviderOperation,
622 minimum: usize,
624 maximum: usize,
626 actual: usize,
628 },
629 #[error("invalid cryptographic input: {0}")]
631 InvalidInput(ProviderInputError),
632 #[error("cryptographic authentication failed")]
634 AuthenticationFailed,
635 #[error("operating-system random number generation failed: {0}")]
637 Random(String),
638}
639
640#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
642#[non_exhaustive]
643pub enum ExternalProviderError {
644 #[error("module or token unavailable")]
646 Unavailable,
647 #[error("authentication failed")]
649 Credentials,
650 #[error("key object unavailable or ambiguous")]
652 Object,
653 #[error("key usage denied")]
655 Usage,
656 #[error("key provider binding mismatch")]
658 Binding,
659 #[error("token operation failed")]
661 Operation,
662}
663
664#[derive(Clone, Default)]
666pub struct ProviderBinding(std::sync::Arc<()>);
667
668impl ProviderBinding {
669 pub fn matches(&self, other: &Self) -> bool {
671 std::sync::Arc::ptr_eq(&self.0, &other.0)
672 }
673}
674
675#[cfg(feature = "xmlenc")]
677pub trait ContentDecryptionKey: Send + Sync {
678 fn provider_binding(&self) -> &ProviderBinding;
680 fn key_len(&self) -> usize;
682 fn decrypt_with_provider(
684 &self,
685 provider: &dyn CryptoProvider,
686 algorithm: DataEncryptionAlgorithm,
687 ciphertext: &[u8],
688 ) -> Result<Vec<u8>, ProviderError>;
689}
690
691#[cfg(feature = "xmlenc")]
693pub trait KeyUnwrappingKey: Send + Sync {
694 fn provider_binding(&self) -> &ProviderBinding;
696 fn unwrap_with_provider(
698 &self,
699 provider: &dyn CryptoProvider,
700 algorithm: KeyWrapAlgorithm,
701 content_algorithm: DataEncryptionAlgorithm,
702 wrapped: &[u8],
703 ) -> Result<RecoveredContentKey, ProviderError>;
704}
705
706#[cfg(feature = "xmlenc")]
712pub trait KeyTransportKey: Send + Sync {
713 fn provider_binding(&self) -> Option<&ProviderBinding> {
715 None
716 }
717 #[cfg(feature = "legacy-algorithms")]
719 fn transport_pkcs1v15(
720 &self,
721 _provider: &dyn CryptoProvider,
722 _plaintext: &[u8],
723 ) -> Result<Vec<u8>, ProviderError> {
724 Err(ProviderError::Unsupported {
725 operation: ProviderOperation::KeyTransport,
726 algorithm: Some(
727 crate::xmlenc::KeyTransportAlgorithm::RsaPkcs1v15
728 .uri()
729 .into(),
730 ),
731 })
732 }
733 fn rsa_modulus(&self) -> Cow<'_, [u8]>;
739
740 fn rsa_exponent(&self) -> Cow<'_, [u8]>;
742
743 fn transport_with_provider(
745 &self,
746 provider: &dyn CryptoProvider,
747 parameters: &RsaOaepParameters,
748 plaintext: &[u8],
749 ) -> Result<Vec<u8>, ProviderError>;
750}
751
752#[cfg(feature = "xmlenc")]
757pub trait KeyRecoveryKey: Send + Sync {
758 fn recover_content_with_provider(
760 &self,
761 provider: &dyn CryptoProvider,
762 parameters: &RsaOaepParameters,
763 _content_algorithm: DataEncryptionAlgorithm,
764 ciphertext: &[u8],
765 ) -> Result<RecoveredContentKey, ProviderError> {
766 self.recover_with_provider(provider, parameters, ciphertext)
767 .map(RecoveredContentKey::confirmed)
768 }
769 #[cfg(feature = "legacy-algorithms")]
771 fn recover_pkcs1v15(
772 &self,
773 _provider: &dyn CryptoProvider,
774 _ciphertext: &[u8],
775 _key_len: usize,
776 ) -> Result<RecoveredContentKey, ProviderError> {
777 Err(ProviderError::Unsupported {
778 operation: ProviderOperation::KeyRecovery,
779 algorithm: Some(
780 crate::xmlenc::KeyTransportAlgorithm::RsaPkcs1v15
781 .uri()
782 .into(),
783 ),
784 })
785 }
786 fn provider_name(&self) -> Option<&'static str> {
788 None
789 }
790 fn public_spki(&self) -> Option<&[u8]> {
792 None
793 }
794 fn rsa_modulus_bits(&self) -> usize;
797
798 fn rsa_public_exponent(&self) -> Option<u64>;
801
802 fn ciphertext_len(&self) -> usize;
805
806 fn recover_with_provider(
808 &self,
809 provider: &dyn CryptoProvider,
810 parameters: &RsaOaepParameters,
811 ciphertext: &[u8],
812 ) -> Result<Vec<u8>, ProviderError>;
813}
814
815pub trait KeyAgreementKey: Send + Sync {
817 fn dh_domain_bits(&self) -> Option<(usize, usize)> {
820 None
821 }
822 fn provider_binding(&self) -> Option<&ProviderBinding> {
824 None
825 }
826 fn agree(&self, parameters: &KeyAgreementParameters<'_>) -> Result<Vec<u8>, ProviderError>;
828}
829
830pub trait CryptoProvider: Send + Sync {
832 fn binding(&self) -> Option<&ProviderBinding> {
834 None
835 }
836
837 #[cfg(feature = "xmlenc")]
839 fn recover_content_key(
840 &self,
841 key: &dyn KeyRecoveryKey,
842 parameters: &RsaOaepParameters,
843 _content_algorithm: DataEncryptionAlgorithm,
844 ciphertext: &[u8],
845 ) -> Result<RecoveredContentKey, ProviderError> {
846 self.recover_key(key, parameters, ciphertext)
847 .map(RecoveredContentKey::confirmed)
848 }
849
850 #[cfg(feature = "xmlenc")]
852 fn unwrap_content_key(
853 &self,
854 _key: &dyn KeyUnwrappingKey,
855 algorithm: KeyWrapAlgorithm,
856 _content_algorithm: DataEncryptionAlgorithm,
857 _wrapped: &[u8],
858 ) -> Result<RecoveredContentKey, ProviderError> {
859 Err(ProviderError::Unsupported {
860 operation: ProviderOperation::KeyUnwrap,
861 algorithm: Some(algorithm.uri().into()),
862 })
863 }
864
865 #[cfg(feature = "xmlenc")]
867 fn decrypt_content_key(
868 &self,
869 algorithm: DataEncryptionAlgorithm,
870 _key: &dyn ContentDecryptionKey,
871 _ciphertext: &[u8],
872 ) -> Result<Vec<u8>, ProviderError> {
873 Err(ProviderError::Unsupported {
874 operation: ProviderOperation::Decrypt,
875 algorithm: Some(algorithm.uri().into()),
876 })
877 }
878 fn name(&self) -> &'static str;
880
881 #[cfg(feature = "xmldsig")]
884 fn import_signing_key(
885 &self,
886 algorithm: crate::xmldsig::SignatureAlgorithm,
887 _pkcs8: &[u8],
888 ) -> Result<Box<dyn crate::xmldsig::SigningKey>, crate::xmldsig::SigningKeyError> {
889 Err(ProviderError::Unsupported {
890 operation: ProviderOperation::Sign,
891 algorithm: Some(algorithm.uri().into()),
892 }
893 .into())
894 }
895
896 #[cfg(feature = "xmlenc")]
898 fn import_recovery_key(
899 &self,
900 _pkcs8: &[u8],
901 ) -> Result<std::sync::Arc<dyn KeyRecoveryKey>, ProviderError> {
902 Err(ProviderError::Unsupported {
903 operation: ProviderOperation::KeyRecovery,
904 algorithm: None,
905 })
906 }
907
908 fn supports(&self, capability: ProviderCapability<'_>) -> bool;
914
915 #[cfg(feature = "xmldsig")]
918 fn import_encapsulation_key(
919 &self,
920 algorithm: KeyEncapsulationAlgorithm,
921 _spki: &[u8],
922 ) -> Result<std::sync::Arc<dyn KeyEncapsulationKey>, ProviderError> {
923 Err(ProviderError::Unsupported {
924 operation: ProviderOperation::Encapsulate,
925 algorithm: Some(algorithm.uri().into()),
926 })
927 }
928
929 #[cfg(feature = "xmldsig")]
932 fn import_decapsulation_key(
933 &self,
934 algorithm: KeyEncapsulationAlgorithm,
935 _pkcs8: &[u8],
936 ) -> Result<std::sync::Arc<dyn KeyDecapsulationKey>, ProviderError> {
937 Err(ProviderError::Unsupported {
938 operation: ProviderOperation::Decapsulate,
939 algorithm: Some(algorithm.uri().into()),
940 })
941 }
942
943 fn fill_random(&self, output: &mut [u8]) -> Result<(), ProviderError>;
945
946 #[cfg(feature = "xmldsig")]
948 fn encapsulate_key(
949 &self,
950 key: &dyn KeyEncapsulationKey,
951 ) -> Result<EncapsulatedKey, ProviderError> {
952 Err(ProviderError::Unsupported {
953 operation: ProviderOperation::Encapsulate,
954 algorithm: Some(key.algorithm().uri().into()),
955 })
956 }
957
958 #[cfg(feature = "xmldsig")]
960 fn decapsulate_key(
961 &self,
962 key: &dyn KeyDecapsulationKey,
963 ciphertext: &[u8],
964 ) -> Result<zeroize::Zeroizing<[u8; 32]>, ProviderError> {
965 let _ = ciphertext;
966 Err(ProviderError::Unsupported {
967 operation: ProviderOperation::Decapsulate,
968 algorithm: Some(key.algorithm().uri().into()),
969 })
970 }
971
972 #[cfg(feature = "xmldsig")]
974 fn digest(&self, algorithm: DigestAlgorithm, data: &[u8]) -> Result<Vec<u8>, ProviderError>;
975
976 #[cfg(feature = "xmldsig")]
982 fn sign(
983 &self,
984 key: &dyn crate::xmldsig::SigningKey,
985 algorithm: crate::xmldsig::SignatureAlgorithm,
986 data: &[u8],
987 ) -> Result<Vec<u8>, crate::xmldsig::SigningKeyError>;
988
989 #[cfg(feature = "xmldsig")]
994 fn verify(
995 &self,
996 key: &dyn crate::xmldsig::VerifyingKey,
997 algorithm: crate::xmldsig::SignatureAlgorithm,
998 data: &[u8],
999 signature: &[u8],
1000 ) -> Result<bool, crate::xmldsig::DsigError>;
1001
1002 #[cfg(feature = "xmldsig")]
1004 fn sign_with_context(
1005 &self,
1006 key: &dyn crate::xmldsig::SigningKey,
1007 algorithm: crate::xmldsig::SignatureAlgorithm,
1008 context: &crate::xmldsig::SignatureContext,
1009 data: &[u8],
1010 ) -> Result<Vec<u8>, crate::xmldsig::SigningKeyError> {
1011 if !context.as_bytes().is_empty() {
1012 return Err(crate::xmldsig::SigningKeyError::UnsupportedAlgorithm {
1013 uri: algorithm.uri().to_owned(),
1014 });
1015 }
1016 self.sign(key, algorithm, data)
1017 }
1018
1019 #[cfg(feature = "xmldsig")]
1021 fn verify_with_context(
1022 &self,
1023 key: &dyn crate::xmldsig::VerifyingKey,
1024 algorithm: crate::xmldsig::SignatureAlgorithm,
1025 context: &crate::xmldsig::SignatureContext,
1026 data: &[u8],
1027 signature: &[u8],
1028 ) -> Result<bool, crate::xmldsig::DsigError> {
1029 if !context.as_bytes().is_empty() {
1030 return Err(
1031 crate::xmldsig::SignatureVerificationError::UnsupportedAlgorithm {
1032 uri: algorithm.uri().to_owned(),
1033 }
1034 .into(),
1035 );
1036 }
1037 self.verify(key, algorithm, data, signature)
1038 }
1039
1040 #[cfg(feature = "xmldsig")]
1042 fn verify_x509_signature(
1043 &self,
1044 algorithm: X509SignatureAlgorithm,
1045 signed_data: &[u8],
1046 signature: &[u8],
1047 issuer_spki_der: &[u8],
1048 ) -> Result<bool, ProviderError> {
1049 let _ = (signed_data, signature, issuer_spki_der);
1050 Err(ProviderError::Unsupported {
1051 operation: ProviderOperation::VerifyCertificate,
1052 algorithm: algorithm.oid().map(str::to_owned),
1053 })
1054 }
1055
1056 #[cfg(feature = "xmlenc")]
1058 fn encrypt_data(
1059 &self,
1060 algorithm: DataEncryptionAlgorithm,
1061 key: &[u8],
1062 plaintext: &[u8],
1063 ) -> Result<Vec<u8>, ProviderError>;
1064
1065 #[cfg(feature = "xmlenc")]
1067 fn decrypt_data(
1068 &self,
1069 algorithm: DataEncryptionAlgorithm,
1070 key: &[u8],
1071 ciphertext: &[u8],
1072 ) -> Result<Vec<u8>, ProviderError>;
1073
1074 #[cfg(feature = "xmlenc")]
1077 fn encrypt_data_with_parameters(
1078 &self,
1079 algorithm: DataEncryptionAlgorithm,
1080 key: &[u8],
1081 plaintext: &[u8],
1082 parameters: Option<crate::xmlenc::ChaChaParametersRef<'_>>,
1083 ) -> Result<Vec<u8>, ProviderError> {
1084 if parameters.is_some() {
1085 return Err(ProviderError::Unsupported {
1086 operation: ProviderOperation::Encrypt,
1087 algorithm: Some(algorithm.uri().into()),
1088 });
1089 }
1090 self.encrypt_data(algorithm, key, plaintext)
1091 }
1092
1093 #[cfg(feature = "xmlenc")]
1095 fn decrypt_data_with_parameters(
1096 &self,
1097 algorithm: DataEncryptionAlgorithm,
1098 key: &[u8],
1099 ciphertext: &[u8],
1100 parameters: Option<crate::xmlenc::ChaChaParametersRef<'_>>,
1101 ) -> Result<Vec<u8>, ProviderError> {
1102 if parameters.is_some() {
1103 return Err(ProviderError::Unsupported {
1104 operation: ProviderOperation::Decrypt,
1105 algorithm: Some(algorithm.uri().into()),
1106 });
1107 }
1108 self.decrypt_data(algorithm, key, ciphertext)
1109 }
1110
1111 #[cfg(feature = "xmlenc")]
1117 fn wrap_key(
1118 &self,
1119 algorithm: KeyWrapAlgorithm,
1120 kek: &[u8],
1121 key: &[u8],
1122 ) -> Result<Vec<u8>, ProviderError>;
1123
1124 #[cfg(feature = "xmlenc")]
1126 fn unwrap_key(
1127 &self,
1128 algorithm: KeyWrapAlgorithm,
1129 kek: &[u8],
1130 wrapped: &[u8],
1131 ) -> Result<Vec<u8>, ProviderError>;
1132
1133 #[cfg(feature = "xmlenc")]
1135 fn transport_key(
1136 &self,
1137 key: &dyn KeyTransportKey,
1138 parameters: &RsaOaepParameters,
1139 plaintext: &[u8],
1140 ) -> Result<Vec<u8>, ProviderError>;
1141
1142 #[cfg(feature = "xmlenc")]
1144 fn recover_key(
1145 &self,
1146 key: &dyn KeyRecoveryKey,
1147 parameters: &RsaOaepParameters,
1148 ciphertext: &[u8],
1149 ) -> Result<Vec<u8>, ProviderError>;
1150
1151 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
1153 fn transport_pkcs1v15(
1154 &self,
1155 _key: &dyn KeyTransportKey,
1156 _plaintext: &[u8],
1157 ) -> Result<Vec<u8>, ProviderError> {
1158 Err(ProviderError::Unsupported {
1159 operation: ProviderOperation::KeyTransport,
1160 algorithm: Some(
1161 crate::xmlenc::KeyTransportAlgorithm::RsaPkcs1v15
1162 .uri()
1163 .into(),
1164 ),
1165 })
1166 }
1167
1168 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
1170 fn recover_pkcs1v15(
1171 &self,
1172 _key: &dyn KeyRecoveryKey,
1173 _ciphertext: &[u8],
1174 _key_len: usize,
1175 ) -> Result<RecoveredContentKey, ProviderError> {
1176 Err(ProviderError::Unsupported {
1177 operation: ProviderOperation::KeyRecovery,
1178 algorithm: Some(
1179 crate::xmlenc::KeyTransportAlgorithm::RsaPkcs1v15
1180 .uri()
1181 .into(),
1182 ),
1183 })
1184 }
1185
1186 fn agree_key(
1188 &self,
1189 key: &dyn KeyAgreementKey,
1190 parameters: &KeyAgreementParameters<'_>,
1191 ) -> Result<Vec<u8>, ProviderError> {
1192 self.require_capability(ProviderCapability::KeyAgreement(parameters))?;
1193 if let Some(binding) = key.provider_binding()
1194 && !self
1195 .binding()
1196 .is_some_and(|selected| selected.matches(binding))
1197 {
1198 return Err(ProviderError::External(ExternalProviderError::Binding));
1199 }
1200 key.agree(parameters)
1201 }
1202
1203 fn derive_key(
1209 &self,
1210 parameters: &KdfParameters<'_>,
1211 secret: &[u8],
1212 ) -> Result<Vec<u8>, ProviderError>;
1213
1214 fn require_capability(&self, capability: ProviderCapability<'_>) -> Result<(), ProviderError> {
1216 if self.supports(capability) {
1217 Ok(())
1218 } else {
1219 Err(ProviderError::Unsupported {
1220 operation: capability.operation(),
1221 algorithm: capability.algorithm().map(str::to_owned),
1222 })
1223 }
1224 }
1225}
1226
1227#[derive(Debug, Clone, Copy, Default)]
1229pub struct RustCryptoProvider;
1230
1231#[cfg(feature = "xmlenc")]
1233#[derive(Clone)]
1234pub struct RustCryptoRsaPublicKey {
1235 key: rsa::RsaPublicKey,
1236 modulus: Vec<u8>,
1237 exponent: Vec<u8>,
1238}
1239
1240#[cfg(feature = "xmlenc")]
1241impl RustCryptoRsaPublicKey {
1242 #[must_use]
1244 pub fn new(key: rsa::RsaPublicKey) -> Self {
1245 use rsa::traits::PublicKeyParts as _;
1246 let modulus = key.n().to_be_bytes_trimmed_vartime().into_vec();
1247 let exponent = key.e().to_be_bytes_trimmed_vartime().into_vec();
1248 Self {
1249 key,
1250 modulus,
1251 exponent,
1252 }
1253 }
1254}
1255
1256#[cfg(feature = "xmlenc")]
1257impl From<rsa::RsaPublicKey> for RustCryptoRsaPublicKey {
1258 fn from(key: rsa::RsaPublicKey) -> Self {
1259 Self::new(key)
1260 }
1261}
1262
1263#[cfg(feature = "xmlenc")]
1264impl KeyTransportKey for RustCryptoRsaPublicKey {
1265 #[cfg(feature = "legacy-algorithms")]
1266 fn transport_pkcs1v15(
1267 &self,
1268 provider: &dyn CryptoProvider,
1269 plaintext: &[u8],
1270 ) -> Result<Vec<u8>, ProviderError> {
1271 rustcrypto::transport_pkcs1v15(provider, &self.key, plaintext)
1272 }
1273 fn rsa_modulus(&self) -> Cow<'_, [u8]> {
1274 Cow::Borrowed(&self.modulus)
1275 }
1276
1277 fn rsa_exponent(&self) -> Cow<'_, [u8]> {
1278 Cow::Borrowed(&self.exponent)
1279 }
1280
1281 fn transport_with_provider(
1282 &self,
1283 provider: &dyn CryptoProvider,
1284 parameters: &RsaOaepParameters,
1285 plaintext: &[u8],
1286 ) -> Result<Vec<u8>, ProviderError> {
1287 rustcrypto::transport_key(provider, &self.key, parameters, plaintext)
1288 }
1289}
1290
1291#[cfg(feature = "xmlenc")]
1292impl KeyTransportKey for rsa::RsaPublicKey {
1293 #[cfg(feature = "legacy-algorithms")]
1294 fn transport_pkcs1v15(
1295 &self,
1296 provider: &dyn CryptoProvider,
1297 plaintext: &[u8],
1298 ) -> Result<Vec<u8>, ProviderError> {
1299 rustcrypto::transport_pkcs1v15(provider, self, plaintext)
1300 }
1301 fn rsa_modulus(&self) -> Cow<'_, [u8]> {
1302 use rsa::traits::PublicKeyParts as _;
1303 Cow::Owned(self.n().to_be_bytes_trimmed_vartime().into_vec())
1304 }
1305
1306 fn rsa_exponent(&self) -> Cow<'_, [u8]> {
1307 use rsa::traits::PublicKeyParts as _;
1308 Cow::Owned(self.e().to_be_bytes_trimmed_vartime().into_vec())
1309 }
1310
1311 fn transport_with_provider(
1312 &self,
1313 provider: &dyn CryptoProvider,
1314 parameters: &RsaOaepParameters,
1315 plaintext: &[u8],
1316 ) -> Result<Vec<u8>, ProviderError> {
1317 rustcrypto::transport_key(provider, self, parameters, plaintext)
1318 }
1319}
1320
1321#[cfg(feature = "xmlenc")]
1323#[derive(Clone)]
1324pub struct RustCryptoRsaPrivateKey {
1325 key: rsa::RsaPrivateKey,
1326 ciphertext_len: usize,
1327}
1328
1329#[cfg(feature = "xmlenc")]
1330impl RustCryptoRsaPrivateKey {
1331 #[must_use]
1333 pub fn new(key: rsa::RsaPrivateKey) -> Self {
1334 use rsa::traits::PublicKeyParts as _;
1335 let ciphertext_len = key.size();
1336 Self {
1337 key,
1338 ciphertext_len,
1339 }
1340 }
1341}
1342
1343#[cfg(feature = "xmlenc")]
1344impl From<rsa::RsaPrivateKey> for RustCryptoRsaPrivateKey {
1345 fn from(key: rsa::RsaPrivateKey) -> Self {
1346 Self::new(key)
1347 }
1348}
1349
1350#[cfg(feature = "xmlenc")]
1351impl KeyRecoveryKey for RustCryptoRsaPrivateKey {
1352 #[cfg(feature = "legacy-algorithms")]
1353 fn recover_pkcs1v15(
1354 &self,
1355 provider: &dyn CryptoProvider,
1356 ciphertext: &[u8],
1357 key_len: usize,
1358 ) -> Result<RecoveredContentKey, ProviderError> {
1359 rsa_pkcs1v15::recover(provider, &self.key, ciphertext, key_len)
1360 }
1361 fn rsa_modulus_bits(&self) -> usize {
1362 KeyRecoveryKey::rsa_modulus_bits(&self.key)
1363 }
1364 fn rsa_public_exponent(&self) -> Option<u64> {
1365 KeyRecoveryKey::rsa_public_exponent(&self.key)
1366 }
1367 fn ciphertext_len(&self) -> usize {
1368 self.ciphertext_len
1369 }
1370
1371 fn recover_with_provider(
1372 &self,
1373 provider: &dyn CryptoProvider,
1374 parameters: &RsaOaepParameters,
1375 ciphertext: &[u8],
1376 ) -> Result<Vec<u8>, ProviderError> {
1377 rustcrypto::recover_key(provider, &self.key, parameters, ciphertext)
1378 }
1379}
1380
1381#[cfg(feature = "xmlenc")]
1382impl KeyRecoveryKey for rsa::RsaPrivateKey {
1383 #[cfg(feature = "legacy-algorithms")]
1384 fn recover_pkcs1v15(
1385 &self,
1386 provider: &dyn CryptoProvider,
1387 ciphertext: &[u8],
1388 key_len: usize,
1389 ) -> Result<RecoveredContentKey, ProviderError> {
1390 rsa_pkcs1v15::recover(provider, self, ciphertext, key_len)
1391 }
1392 fn rsa_modulus_bits(&self) -> usize {
1393 use rsa::traits::PublicKeyParts as _;
1394 self.n().bits_vartime() as usize
1395 }
1396 fn rsa_public_exponent(&self) -> Option<u64> {
1397 use rsa::traits::PublicKeyParts as _;
1398 if self.e().bits_vartime() > 64 {
1399 return None;
1400 }
1401 let mut exponent = 0_u64;
1402 let word_bits = crypto_bigint::Word::BITS as usize;
1403 for (index, word) in self.e().as_words().iter().take(64 / word_bits).enumerate() {
1404 #[cfg(target_pointer_width = "64")]
1405 let word = *word;
1406 #[cfg(target_pointer_width = "32")]
1407 let word = u64::from(*word);
1408 exponent |= word << (index * word_bits);
1409 }
1410 Some(exponent)
1411 }
1412 fn ciphertext_len(&self) -> usize {
1413 use rsa::traits::PublicKeyParts as _;
1414 self.size()
1415 }
1416
1417 fn recover_with_provider(
1418 &self,
1419 provider: &dyn CryptoProvider,
1420 parameters: &RsaOaepParameters,
1421 ciphertext: &[u8],
1422 ) -> Result<Vec<u8>, ProviderError> {
1423 rustcrypto::recover_key(provider, self, parameters, ciphertext)
1424 }
1425}
1426
1427pub static RUST_CRYPTO_PROVIDER: RustCryptoProvider = RustCryptoProvider;
1429
1430#[must_use]
1432pub fn default_provider() -> &'static dyn CryptoProvider {
1433 &RUST_CRYPTO_PROVIDER
1434}
1435
1436#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
1438pub(crate) struct ProviderRng<'a>(pub(crate) &'a dyn CryptoProvider);
1439
1440#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
1441impl TryRng for ProviderRng<'_> {
1442 type Error = ProviderError;
1443
1444 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
1445 let mut bytes = [0_u8; 4];
1446 self.try_fill_bytes(&mut bytes)?;
1447 Ok(u32::from_le_bytes(bytes))
1448 }
1449
1450 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
1451 let mut bytes = [0_u8; 8];
1452 self.try_fill_bytes(&mut bytes)?;
1453 Ok(u64::from_le_bytes(bytes))
1454 }
1455
1456 fn try_fill_bytes(&mut self, output: &mut [u8]) -> Result<(), Self::Error> {
1457 self.0.fill_random(output)
1458 }
1459}
1460
1461#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
1462impl TryCryptoRng for ProviderRng<'_> {}
1463
1464impl CryptoProvider for RustCryptoProvider {
1465 #[cfg(feature = "xmldsig")]
1466 fn encapsulate_key(
1467 &self,
1468 key: &dyn KeyEncapsulationKey,
1469 ) -> Result<EncapsulatedKey, ProviderError> {
1470 self.require_capability(ProviderCapability::Encapsulate(key.algorithm()))?;
1471 if key.provider_binding().is_some() {
1472 return Err(ProviderError::External(ExternalProviderError::Binding));
1473 }
1474 key.encapsulate_with_provider(self)
1475 }
1476
1477 #[cfg(feature = "xmldsig")]
1478 fn decapsulate_key(
1479 &self,
1480 key: &dyn KeyDecapsulationKey,
1481 ciphertext: &[u8],
1482 ) -> Result<zeroize::Zeroizing<[u8; 32]>, ProviderError> {
1483 self.require_capability(ProviderCapability::Decapsulate(key.algorithm()))?;
1484 if key.provider_binding().is_some() {
1485 return Err(ProviderError::External(ExternalProviderError::Binding));
1486 }
1487 if ciphertext.len() != key.algorithm().ciphertext_len() {
1488 return Err(ProviderError::InvalidInput(
1489 ProviderInputError::MlKemCiphertext,
1490 ));
1491 }
1492 key.decapsulate(ciphertext)
1493 }
1494 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
1495 fn transport_pkcs1v15(
1496 &self,
1497 key: &dyn KeyTransportKey,
1498 plaintext: &[u8],
1499 ) -> Result<Vec<u8>, ProviderError> {
1500 self.require_capability(ProviderCapability::Pkcs1v15Transport)?;
1501 key.transport_pkcs1v15(self, plaintext)
1502 }
1503
1504 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
1505 fn recover_pkcs1v15(
1506 &self,
1507 key: &dyn KeyRecoveryKey,
1508 ciphertext: &[u8],
1509 key_len: usize,
1510 ) -> Result<RecoveredContentKey, ProviderError> {
1511 self.require_capability(ProviderCapability::Pkcs1v15Recovery)?;
1512 key.recover_pkcs1v15(self, ciphertext, key_len)
1513 }
1514 fn name(&self) -> &'static str {
1515 "rustcrypto"
1516 }
1517
1518 #[cfg(feature = "experimental-pq")]
1519 fn import_encapsulation_key(
1520 &self,
1521 algorithm: KeyEncapsulationAlgorithm,
1522 spki: &[u8],
1523 ) -> Result<std::sync::Arc<dyn KeyEncapsulationKey>, ProviderError> {
1524 self.require_capability(ProviderCapability::Encapsulate(algorithm))?;
1525 let key = RustCryptoMlKemPublicKey::from_spki_der_with_algorithm(spki, Some(algorithm))?;
1526 Ok(std::sync::Arc::new(key))
1527 }
1528
1529 #[cfg(feature = "experimental-pq")]
1530 fn import_decapsulation_key(
1531 &self,
1532 algorithm: KeyEncapsulationAlgorithm,
1533 pkcs8: &[u8],
1534 ) -> Result<std::sync::Arc<dyn KeyDecapsulationKey>, ProviderError> {
1535 self.require_capability(ProviderCapability::Decapsulate(algorithm))?;
1536 let key = RustCryptoMlKemPrivateKey::from_pkcs8_der_with_algorithm(pkcs8, Some(algorithm))?;
1537 Ok(std::sync::Arc::new(key))
1538 }
1539
1540 #[cfg(feature = "xmlenc")]
1541 fn import_recovery_key(
1542 &self,
1543 pkcs8: &[u8],
1544 ) -> Result<std::sync::Arc<dyn KeyRecoveryKey>, ProviderError> {
1545 use crate::rsa_encoding::RsaPrivateKeyEncoding as _;
1546 let key = rsa::RsaPrivateKey::from_pkcs8_der(pkcs8).map_err(|_| {
1547 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization(
1548 "RSA recovery key",
1549 ))
1550 })?;
1551 Ok(std::sync::Arc::new(RustCryptoRsaPrivateKey::new(key)))
1552 }
1553
1554 #[cfg(feature = "xmldsig")]
1555 fn import_signing_key(
1556 &self,
1557 algorithm: crate::xmldsig::SignatureAlgorithm,
1558 der: &[u8],
1559 ) -> Result<Box<dyn crate::xmldsig::SigningKey>, crate::xmldsig::SigningKeyError> {
1560 use crate::xmldsig::{SignatureAlgorithm as A, *};
1561 Ok(match algorithm {
1562 #[cfg(feature = "experimental-pq")]
1563 A::PostQuantum(parameter) => {
1564 Box::new(PostQuantumSigningKey::from_pkcs8_der(parameter, der)?)
1565 }
1566 A::Ed25519 | A::Ed25519Ctx | A::Ed25519Ph | A::Ed448 | A::Ed448Ph => {
1567 Box::new(EdDsaSigningKey::from_pkcs8_der(algorithm, der)?)
1568 }
1569 method if method.is_rsa() => Box::new(RsaSigningKey::from_pkcs8_der(der)?),
1570 A::DsaSha1 | A::DsaSha256 => Box::new(DsaSigningKey::from_pkcs8_der(der)?),
1571 method if method.ecdsa_digest().is_some() => {
1572 if let Ok(key) = EcdsaP256SigningKey::from_pkcs8_der(der) {
1573 Box::new(key)
1574 } else if let Ok(key) = EcdsaP384SigningKey::from_pkcs8_der(der) {
1575 Box::new(key)
1576 } else {
1577 Box::new(EcdsaP521SigningKey::from_pkcs8_der(der)?)
1578 }
1579 }
1580 _ => {
1581 return Err(SigningKeyError::UnsupportedAlgorithm {
1582 uri: algorithm.uri().into(),
1583 });
1584 }
1585 })
1586 }
1587
1588 fn supports(&self, capability: ProviderCapability<'_>) -> bool {
1589 match capability {
1590 #[cfg(feature = "xmldsig")]
1591 ProviderCapability::Encapsulate(_) | ProviderCapability::Decapsulate(_) => {
1592 cfg!(feature = "experimental-pq")
1593 }
1594 #[cfg(feature = "xmldsig")]
1595 ProviderCapability::Digest(_) => true,
1596 #[cfg(feature = "xmldsig")]
1597 ProviderCapability::Sign(algorithm) | ProviderCapability::Verify(algorithm) => {
1600 if let Some(parameters) = algorithm.rsa_pss_parameters()
1601 && parameters.salt_len > i32::MAX as usize
1602 {
1603 return false;
1604 }
1605 !matches!(
1606 algorithm,
1607 crate::xmldsig::SignatureAlgorithm::PostQuantum(_)
1608 ) || cfg!(feature = "experimental-pq")
1609 }
1610 #[cfg(feature = "xmldsig")]
1611 ProviderCapability::VerifyCertificate(algorithm) => {
1612 is_supported_x509_signature(algorithm)
1613 }
1614 #[cfg(feature = "xmlenc")]
1615 ProviderCapability::Encrypt(_) | ProviderCapability::Decrypt(_) => true,
1616 #[cfg(feature = "xmlenc")]
1617 ProviderCapability::KeyWrap(algorithm) | ProviderCapability::KeyUnwrap(algorithm) => {
1618 algorithm.wrapped_len(16).is_some()
1619 }
1620 #[cfg(feature = "xmlenc")]
1621 ProviderCapability::KeyTransport(parameters)
1622 | ProviderCapability::KeyRecovery(parameters) => {
1623 !parameters.algorithm.requires_explicit_permission()
1624 && parameters.mgf_digest.mgf_uri().is_some()
1625 }
1626 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
1627 ProviderCapability::Pkcs1v15Transport | ProviderCapability::Pkcs1v15Recovery => true,
1628 ProviderCapability::Random => true,
1629 ProviderCapability::KeyAgreement(parameters) => {
1630 #[cfg(feature = "xmlenc")]
1631 {
1632 matches!(
1633 parameters.algorithm,
1634 key_establishment::X25519_URI
1635 | key_establishment::X448_URI
1636 | key_establishment::ECDH_URI
1637 | key_establishment::DH_ES_URI
1638 | key_establishment::DH_URI
1639 )
1640 }
1641 #[cfg(not(feature = "xmlenc"))]
1642 {
1643 let _ = parameters;
1644 false
1645 }
1646 }
1647 ProviderCapability::Kdf(parameters) => {
1648 #[cfg(feature = "xmlenc")]
1649 {
1650 key_establishment::supports_kdf(parameters)
1651 }
1652 #[cfg(not(feature = "xmlenc"))]
1653 {
1654 let _ = parameters;
1655 false
1656 }
1657 }
1658 }
1659 }
1660
1661 fn fill_random(&self, output: &mut [u8]) -> Result<(), ProviderError> {
1662 SysRng
1663 .try_fill_bytes(output)
1664 .map_err(|error| ProviderError::Random(error.to_string()))
1665 }
1666
1667 fn derive_key(
1668 &self,
1669 parameters: &KdfParameters<'_>,
1670 secret: &[u8],
1671 ) -> Result<Vec<u8>, ProviderError> {
1672 self.require_capability(ProviderCapability::Kdf(parameters))?;
1673 #[cfg(feature = "xmlenc")]
1674 {
1675 key_establishment::derive_key(parameters, secret)
1676 }
1677 #[cfg(not(feature = "xmlenc"))]
1678 {
1679 let _ = secret;
1680 Err(ProviderError::Unsupported {
1681 operation: ProviderOperation::Kdf,
1682 algorithm: Some(parameters.algorithm.to_owned()),
1683 })
1684 }
1685 }
1686
1687 #[cfg(feature = "xmldsig")]
1688 fn digest(&self, algorithm: DigestAlgorithm, data: &[u8]) -> Result<Vec<u8>, ProviderError> {
1689 use sha1::Sha1;
1690 use sha2::{Digest, Sha224, Sha256, Sha384, Sha512};
1691 use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512};
1692 Ok(match algorithm {
1693 #[cfg(feature = "legacy-algorithms")]
1694 DigestAlgorithm::Md5 => md5::Md5::digest(data).to_vec(),
1695 #[cfg(feature = "legacy-algorithms")]
1696 DigestAlgorithm::Ripemd160 => ripemd::Ripemd160::digest(data).to_vec(),
1697 DigestAlgorithm::Sha1 => Sha1::digest(data).to_vec(),
1698 DigestAlgorithm::Sha224 => Sha224::digest(data).to_vec(),
1699 DigestAlgorithm::Sha256 => Sha256::digest(data).to_vec(),
1700 DigestAlgorithm::Sha384 => Sha384::digest(data).to_vec(),
1701 DigestAlgorithm::Sha512 => Sha512::digest(data).to_vec(),
1702 DigestAlgorithm::Sha3_224 => Sha3_224::digest(data).to_vec(),
1703 DigestAlgorithm::Sha3_256 => Sha3_256::digest(data).to_vec(),
1704 DigestAlgorithm::Sha3_384 => Sha3_384::digest(data).to_vec(),
1705 DigestAlgorithm::Sha3_512 => Sha3_512::digest(data).to_vec(),
1706 })
1707 }
1708
1709 #[cfg(feature = "xmldsig")]
1710 fn sign(
1711 &self,
1712 key: &dyn crate::xmldsig::SigningKey,
1713 algorithm: crate::xmldsig::SignatureAlgorithm,
1714 data: &[u8],
1715 ) -> Result<Vec<u8>, crate::xmldsig::SigningKeyError> {
1716 self.require_capability(ProviderCapability::Sign(algorithm))?;
1717 key.sign_with_provider(self, algorithm, data)
1718 }
1719
1720 #[cfg(feature = "xmldsig")]
1721 fn sign_with_context(
1722 &self,
1723 key: &dyn crate::xmldsig::SigningKey,
1724 algorithm: crate::xmldsig::SignatureAlgorithm,
1725 context: &crate::xmldsig::SignatureContext,
1726 data: &[u8],
1727 ) -> Result<Vec<u8>, crate::xmldsig::SigningKeyError> {
1728 self.require_capability(ProviderCapability::Sign(algorithm))?;
1729 key.sign_with_provider_context(self, algorithm, context, data)
1730 }
1731
1732 #[cfg(feature = "xmldsig")]
1733 fn verify_with_context(
1734 &self,
1735 key: &dyn crate::xmldsig::VerifyingKey,
1736 algorithm: crate::xmldsig::SignatureAlgorithm,
1737 context: &crate::xmldsig::SignatureContext,
1738 data: &[u8],
1739 signature: &[u8],
1740 ) -> Result<bool, crate::xmldsig::DsigError> {
1741 self.require_capability(ProviderCapability::Verify(algorithm))?;
1742 if key.provider_binding().is_some() {
1743 return Err(ProviderError::External(ExternalProviderError::Binding).into());
1744 }
1745 key.verify_with_context(algorithm, context, data, signature)
1746 }
1747
1748 #[cfg(feature = "xmldsig")]
1749 fn verify(
1750 &self,
1751 key: &dyn crate::xmldsig::VerifyingKey,
1752 algorithm: crate::xmldsig::SignatureAlgorithm,
1753 data: &[u8],
1754 signature: &[u8],
1755 ) -> Result<bool, crate::xmldsig::DsigError> {
1756 self.require_capability(ProviderCapability::Verify(algorithm))?;
1757 if key.provider_binding().is_some() {
1758 return Err(ProviderError::External(ExternalProviderError::Binding).into());
1759 }
1760 key.verify(algorithm, data, signature)
1761 }
1762
1763 #[cfg(feature = "xmldsig")]
1764 fn verify_x509_signature(
1765 &self,
1766 algorithm: X509SignatureAlgorithm,
1767 signed_data: &[u8],
1768 signature: &[u8],
1769 issuer_spki_der: &[u8],
1770 ) -> Result<bool, ProviderError> {
1771 rustcrypto_x509::verify_signature(algorithm, signed_data, signature, issuer_spki_der)
1772 }
1773
1774 #[cfg(feature = "xmlenc")]
1775 fn encrypt_data(
1776 &self,
1777 algorithm: DataEncryptionAlgorithm,
1778 key: &[u8],
1779 plaintext: &[u8],
1780 ) -> Result<Vec<u8>, ProviderError> {
1781 rustcrypto::encrypt_data(self, algorithm, key, plaintext)
1782 }
1783
1784 #[cfg(feature = "xmlenc")]
1785 fn decrypt_data(
1786 &self,
1787 algorithm: DataEncryptionAlgorithm,
1788 key: &[u8],
1789 ciphertext: &[u8],
1790 ) -> Result<Vec<u8>, ProviderError> {
1791 rustcrypto::decrypt_data(algorithm, key, ciphertext)
1792 }
1793
1794 #[cfg(feature = "xmlenc")]
1795 fn wrap_key(
1796 &self,
1797 algorithm: KeyWrapAlgorithm,
1798 kek: &[u8],
1799 key: &[u8],
1800 ) -> Result<Vec<u8>, ProviderError> {
1801 rustcrypto::wrap_key(self, algorithm, kek, key)
1802 }
1803
1804 #[cfg(feature = "xmlenc")]
1805 fn encrypt_data_with_parameters(
1806 &self,
1807 algorithm: DataEncryptionAlgorithm,
1808 key: &[u8],
1809 plaintext: &[u8],
1810 parameters: Option<crate::xmlenc::ChaChaParametersRef<'_>>,
1811 ) -> Result<Vec<u8>, ProviderError> {
1812 match parameters {
1813 Some(parameters) => chacha::encrypt(algorithm, key, plaintext, parameters),
1814 None => self.encrypt_data(algorithm, key, plaintext),
1815 }
1816 }
1817
1818 #[cfg(feature = "xmlenc")]
1819 fn decrypt_data_with_parameters(
1820 &self,
1821 algorithm: DataEncryptionAlgorithm,
1822 key: &[u8],
1823 ciphertext: &[u8],
1824 parameters: Option<crate::xmlenc::ChaChaParametersRef<'_>>,
1825 ) -> Result<Vec<u8>, ProviderError> {
1826 match parameters {
1827 Some(parameters) => chacha::decrypt(algorithm, key, ciphertext, parameters),
1828 None => self.decrypt_data(algorithm, key, ciphertext),
1829 }
1830 }
1831
1832 #[cfg(feature = "xmlenc")]
1833 fn unwrap_key(
1834 &self,
1835 algorithm: KeyWrapAlgorithm,
1836 kek: &[u8],
1837 wrapped: &[u8],
1838 ) -> Result<Vec<u8>, ProviderError> {
1839 rustcrypto::unwrap_key(algorithm, kek, wrapped)
1840 }
1841
1842 #[cfg(feature = "xmlenc")]
1843 fn transport_key(
1844 &self,
1845 key: &dyn KeyTransportKey,
1846 parameters: &RsaOaepParameters,
1847 plaintext: &[u8],
1848 ) -> Result<Vec<u8>, ProviderError> {
1849 self.require_capability(ProviderCapability::KeyTransport(parameters))?;
1850 key.transport_with_provider(self, parameters, plaintext)
1851 }
1852
1853 #[cfg(feature = "xmlenc")]
1854 fn recover_key(
1855 &self,
1856 key: &dyn KeyRecoveryKey,
1857 parameters: &RsaOaepParameters,
1858 ciphertext: &[u8],
1859 ) -> Result<Vec<u8>, ProviderError> {
1860 self.require_capability(ProviderCapability::KeyRecovery(parameters))?;
1861 key.recover_with_provider(self, parameters, ciphertext)
1862 }
1863}
1864
1865#[cfg(feature = "xmldsig")]
1866fn is_supported_x509_signature(algorithm: X509SignatureAlgorithm) -> bool {
1867 match algorithm {
1868 X509SignatureAlgorithm::Dsa(DigestAlgorithm::Sha1)
1869 | X509SignatureAlgorithm::Ed25519
1870 | X509SignatureAlgorithm::Ed448 => true,
1871 X509SignatureAlgorithm::Ecdsa(digest) => rustcrypto_x509::ecdsa_algorithm(digest).is_some(),
1872 X509SignatureAlgorithm::PostQuantum(_) => cfg!(feature = "experimental-pq"),
1873 X509SignatureAlgorithm::RsaPkcs1v15(digest) => matches!(
1874 digest,
1875 DigestAlgorithm::Sha1
1876 | DigestAlgorithm::Sha224
1877 | DigestAlgorithm::Sha256
1878 | DigestAlgorithm::Sha384
1879 | DigestAlgorithm::Sha512
1880 ),
1881 X509SignatureAlgorithm::RsaPss {
1882 digest, mgf_digest, ..
1883 } => {
1884 matches!(
1885 digest,
1886 DigestAlgorithm::Sha256 | DigestAlgorithm::Sha384 | DigestAlgorithm::Sha512
1887 ) && digest == mgf_digest
1888 }
1889 X509SignatureAlgorithm::Dsa(_) => false,
1890 }
1891}
1892
1893#[cfg(feature = "xmldsig")]
1894pub(crate) mod rustcrypto_x509 {
1895 use crate::rsa_encoding::RsaPublicKeyEncoding as _;
1896 use der::Decode as _;
1897 use dsa::pkcs8::DecodePublicKey as _;
1898 use rsa::{
1899 RsaPublicKey,
1900 pss::{Signature as RsaPssSignature, VerifyingKey as RsaPssVerifyingKey},
1901 traits::PublicKeyParts as _,
1902 };
1903 use sha1::Digest as _;
1904 use sha2::{Sha256, Sha384, Sha512};
1905 use signature::{Verifier as _, hazmat::PrehashVerifier as _};
1906 use x509_parser::prelude::FromDer as _;
1907
1908 use super::{ProviderError, X509SignatureAlgorithm};
1909 use crate::xmldsig::signature::verify_ecdsa_signature_spki_asn1_der;
1910 use crate::xmldsig::{
1911 DigestAlgorithm, DsigError, SignatureAlgorithm, VerificationKey, VerifyingKey as _,
1912 };
1913
1914 pub(super) fn verify_signature(
1915 algorithm: X509SignatureAlgorithm,
1916 signed_data: &[u8],
1917 signature: &[u8],
1918 issuer_spki_der: &[u8],
1919 ) -> Result<bool, ProviderError> {
1920 match algorithm {
1921 X509SignatureAlgorithm::Dsa(DigestAlgorithm::Sha1) => {
1922 let Ok(key) = crate::xmldsig::signature::decode_dsa_verifying_key(issuer_spki_der)
1926 else {
1927 return Ok(false);
1928 };
1929 let Ok(signature) = dsa::Signature::from_der(signature) else {
1930 return Ok(false);
1931 };
1932 let digest = sha1::Sha1::digest(signed_data);
1933 Ok(key.verify_prehash(&digest, &signature).is_ok())
1934 }
1935 X509SignatureAlgorithm::RsaPkcs1v15(digest) => {
1936 let Some(algorithm) = rsa_pkcs1_algorithm(digest) else {
1937 return unsupported(X509SignatureAlgorithm::RsaPkcs1v15(digest));
1938 };
1939 verify_xml_signature(algorithm, signed_data, signature, issuer_spki_der)
1940 }
1941 X509SignatureAlgorithm::Ecdsa(digest) => {
1942 let Some(algorithm) = ecdsa_algorithm(digest) else {
1943 return unsupported(X509SignatureAlgorithm::Ecdsa(digest));
1944 };
1945 match verify_ecdsa_signature_spki_asn1_der(
1948 algorithm,
1949 issuer_spki_der,
1950 signed_data,
1951 signature,
1952 ) {
1953 Ok(verified) => Ok(verified),
1954 Err(_) => Ok(false),
1955 }
1956 }
1957 X509SignatureAlgorithm::RsaPss {
1958 digest,
1959 mgf_digest,
1960 salt_len,
1961 } => {
1962 let Some(key) = compatible_rsa_pss_public_key_from_spki(issuer_spki_der, algorithm)
1966 else {
1967 return Ok(false);
1968 };
1969 if digest != mgf_digest {
1970 return unsupported(algorithm);
1971 }
1972 verify_rsa_pss(digest, salt_len, signed_data, signature, key)
1973 }
1974 X509SignatureAlgorithm::Ed25519 => {
1975 let Ok(key) = ed25519_dalek::VerifyingKey::from_public_key_der(issuer_spki_der)
1976 else {
1977 return Ok(false);
1978 };
1979 let Ok(signature) = ed25519_dalek::Signature::try_from(signature) else {
1980 return Ok(false);
1981 };
1982 Ok(key.verify_strict(signed_data, &signature).is_ok())
1983 }
1984 X509SignatureAlgorithm::Ed448 => {
1985 let Ok(key) = ed448_goldilocks::VerifyingKey::from_public_key_der(issuer_spki_der)
1988 else {
1989 return Ok(false);
1990 };
1991 let Ok(signature) = ed448_goldilocks::Signature::try_from(signature) else {
1992 return Ok(false);
1993 };
1994 Ok(key.verify_raw(&signature, signed_data).is_ok())
1995 }
1996 #[cfg(feature = "experimental-pq")]
1997 X509SignatureAlgorithm::PostQuantum(algorithm) => {
1998 Ok(crate::xmldsig::post_quantum::verify(
2003 algorithm,
2004 issuer_spki_der,
2005 &crate::xmldsig::SignatureContext::default(),
2006 signed_data,
2007 signature,
2008 )
2009 .unwrap_or(false))
2010 }
2011 _ => unsupported(algorithm),
2012 }
2013 }
2014
2015 fn verify_xml_signature(
2016 algorithm: SignatureAlgorithm,
2017 signed_data: &[u8],
2018 signature: &[u8],
2019 issuer_spki_der: &[u8],
2020 ) -> Result<bool, ProviderError> {
2021 let key = VerificationKey {
2022 algorithm,
2023 public_key_bytes: issuer_spki_der.to_vec(),
2024 certificate_der: None,
2025 name: None,
2026 };
2027 match key.verify(algorithm, signed_data, signature) {
2028 Ok(verified) => Ok(verified),
2029 Err(DsigError::Provider(error)) => Err(error),
2030 Err(_) => Ok(false),
2031 }
2032 }
2033
2034 fn verify_rsa_pss(
2035 digest: DigestAlgorithm,
2036 salt_len: usize,
2037 signed_data: &[u8],
2038 signature: &[u8],
2039 key: RsaPublicKey,
2040 ) -> Result<bool, ProviderError> {
2041 if !rsa_pss_salt_fits_key(&key, digest, salt_len) {
2042 return Ok(false);
2043 }
2044 let Ok(signature) = RsaPssSignature::try_from(signature) else {
2045 return Ok(false);
2046 };
2047 let verified = match digest {
2048 DigestAlgorithm::Sha256 => {
2049 RsaPssVerifyingKey::<Sha256>::new_with_salt_len(key, salt_len)
2050 .verify(signed_data, &signature)
2051 }
2052 DigestAlgorithm::Sha384 => {
2053 RsaPssVerifyingKey::<Sha384>::new_with_salt_len(key, salt_len)
2054 .verify(signed_data, &signature)
2055 }
2056 DigestAlgorithm::Sha512 => {
2057 RsaPssVerifyingKey::<Sha512>::new_with_salt_len(key, salt_len)
2058 .verify(signed_data, &signature)
2059 }
2060 _ => {
2061 return unsupported(X509SignatureAlgorithm::RsaPss {
2062 digest,
2063 mgf_digest: digest,
2064 salt_len,
2065 });
2066 }
2067 };
2068 Ok(verified.is_ok())
2069 }
2070
2071 pub(super) fn rsa_pss_salt_fits_key(
2072 key: &RsaPublicKey,
2073 digest: DigestAlgorithm,
2074 salt_len: usize,
2075 ) -> bool {
2076 let Some(em_bits) = key.n().bits().checked_sub(1) else {
2077 return false;
2078 };
2079 let Ok(em_len) = usize::try_from(em_bits.div_ceil(8)) else {
2080 return false;
2081 };
2082 digest
2083 .output_len()
2084 .checked_add(salt_len)
2085 .and_then(|length| length.checked_add(2))
2086 .is_some_and(|required| required <= em_len)
2087 }
2088
2089 pub(crate) fn compatible_rsa_pss_public_key_from_spki(
2090 spki_der: &[u8],
2091 signature_algorithm: X509SignatureAlgorithm,
2092 ) -> Option<RsaPublicKey> {
2093 let (rest, spki) = x509_parser::x509::SubjectPublicKeyInfo::from_der(spki_der).ok()?;
2094 if !rest.is_empty() {
2095 return None;
2096 }
2097 match spki.algorithm.algorithm.to_id_string().as_str() {
2098 "1.2.840.113549.1.1.1" => RsaPublicKey::from_public_key_der(spki_der).ok(),
2099 "1.2.840.113549.1.1.10" => {
2100 if spki
2103 .algorithm
2104 .parameters
2105 .as_ref()
2106 .is_some_and(|parameters| {
2107 !rsa_pss_key_parameters_allow(parameters, signature_algorithm)
2108 })
2109 {
2110 return None;
2111 }
2112 RsaPublicKey::from_pkcs1_der(&spki.subject_public_key.data).ok()
2113 }
2114 _ => None,
2115 }
2116 }
2117
2118 pub(crate) fn rsa_pss_key_parameters_allow(
2119 parameters: &x509_parser::asn1_rs::Any<'_>,
2120 signature_algorithm: X509SignatureAlgorithm,
2121 ) -> bool {
2122 let X509SignatureAlgorithm::RsaPss {
2123 digest,
2124 mgf_digest,
2125 salt_len,
2126 } = signature_algorithm
2127 else {
2128 return false;
2129 };
2130 let Ok(parameters) =
2131 x509_parser::signature_algorithm::RsaSsaPssParams::try_from(parameters)
2132 else {
2133 return false;
2134 };
2135 let Ok(mask) = parameters.mask_gen_algorithm() else {
2136 return false;
2137 };
2138 parameters.trailer_field() == 1
2139 && x509_digest_from_oid(¶meters.hash_algorithm_oid().to_id_string()) == Some(digest)
2140 && mask.mgf.to_id_string() == "1.2.840.113549.1.1.8"
2141 && x509_digest_from_oid(&mask.hash.to_id_string()) == Some(mgf_digest)
2142 && usize::try_from(parameters.salt_length()).is_ok_and(|minimum| salt_len >= minimum)
2143 }
2144
2145 fn x509_digest_from_oid(oid: &str) -> Option<DigestAlgorithm> {
2146 match oid {
2147 "1.3.14.3.2.26" => Some(DigestAlgorithm::Sha1),
2148 "2.16.840.1.101.3.4.2.4" => Some(DigestAlgorithm::Sha224),
2149 "2.16.840.1.101.3.4.2.1" => Some(DigestAlgorithm::Sha256),
2150 "2.16.840.1.101.3.4.2.2" => Some(DigestAlgorithm::Sha384),
2151 "2.16.840.1.101.3.4.2.3" => Some(DigestAlgorithm::Sha512),
2152 "2.16.840.1.101.3.4.2.7" => Some(DigestAlgorithm::Sha3_224),
2153 "2.16.840.1.101.3.4.2.8" => Some(DigestAlgorithm::Sha3_256),
2154 "2.16.840.1.101.3.4.2.9" => Some(DigestAlgorithm::Sha3_384),
2155 "2.16.840.1.101.3.4.2.10" => Some(DigestAlgorithm::Sha3_512),
2156 _ => None,
2157 }
2158 }
2159
2160 const fn rsa_pkcs1_algorithm(digest: DigestAlgorithm) -> Option<SignatureAlgorithm> {
2161 match digest {
2162 DigestAlgorithm::Sha1 => Some(SignatureAlgorithm::RsaSha1),
2163 DigestAlgorithm::Sha224 => Some(SignatureAlgorithm::RsaSha224),
2164 DigestAlgorithm::Sha256 => Some(SignatureAlgorithm::RsaSha256),
2165 DigestAlgorithm::Sha384 => Some(SignatureAlgorithm::RsaSha384),
2166 DigestAlgorithm::Sha512 => Some(SignatureAlgorithm::RsaSha512),
2167 _ => None,
2168 }
2169 }
2170
2171 pub(super) const fn ecdsa_algorithm(digest: DigestAlgorithm) -> Option<SignatureAlgorithm> {
2172 match digest {
2173 #[cfg(feature = "legacy-algorithms")]
2174 DigestAlgorithm::Md5 | DigestAlgorithm::Ripemd160 => None,
2175 DigestAlgorithm::Sha1 => Some(SignatureAlgorithm::EcdsaSha1),
2176 DigestAlgorithm::Sha224 => Some(SignatureAlgorithm::EcdsaSha224),
2177 DigestAlgorithm::Sha256 => Some(SignatureAlgorithm::EcdsaSha256),
2178 DigestAlgorithm::Sha384 => Some(SignatureAlgorithm::EcdsaSha384),
2179 DigestAlgorithm::Sha512 => Some(SignatureAlgorithm::EcdsaSha512),
2180 DigestAlgorithm::Sha3_224 => Some(SignatureAlgorithm::EcdsaSha3_224),
2181 DigestAlgorithm::Sha3_256 => Some(SignatureAlgorithm::EcdsaSha3_256),
2182 DigestAlgorithm::Sha3_384 => Some(SignatureAlgorithm::EcdsaSha3_384),
2183 DigestAlgorithm::Sha3_512 => Some(SignatureAlgorithm::EcdsaSha3_512),
2184 }
2185 }
2186
2187 fn unsupported<T>(algorithm: X509SignatureAlgorithm) -> Result<T, ProviderError> {
2188 Err(ProviderError::Unsupported {
2189 operation: super::ProviderOperation::VerifyCertificate,
2190 algorithm: algorithm.oid().map(str::to_owned),
2191 })
2192 }
2193}
2194
2195#[cfg(feature = "xmlenc")]
2196mod rustcrypto {
2197 use crate::rustcrypto_sha3 as sha3;
2198 #[cfg(feature = "legacy-algorithms")]
2199 use aes::Aes192;
2200 use aes::{
2201 Aes128, Aes256,
2202 cipher::{BlockModeDecrypt, BlockModeEncrypt, KeyIvInit, block_padding::NoPadding},
2203 };
2204 use aes_gcm::{
2205 Aes128Gcm, Aes256Gcm, Nonce,
2206 aead::{AeadInOut, KeyInit},
2207 };
2208 use aes_kw::{KwAes128, KwAes256};
2209 use camellia::{Camellia128, Camellia192, Camellia256};
2210 use cbc::{Decryptor, Encryptor};
2211 #[cfg(feature = "legacy-algorithms")]
2212 use des::TdesEde3;
2213 use rsa::{Oaep, traits::PaddingScheme};
2214 use sha1::Sha1;
2215 use sha2::{Sha224, Sha256, Sha384, Sha512};
2216
2217 use super::{CryptoProvider, ProviderError, ProviderInputError};
2218 use crate::xmlenc::{
2219 DataEncryptionAlgorithm, KeyWrapAlgorithm, OaepDigestAlgorithm, RsaOaepParameters,
2220 };
2221
2222 pub(super) fn encrypt_data(
2223 provider: &dyn CryptoProvider,
2224 algorithm: DataEncryptionAlgorithm,
2225 key: &[u8],
2226 plaintext: &[u8],
2227 ) -> Result<Vec<u8>, ProviderError> {
2228 check_key(algorithm.key_len(), key)?;
2229 match algorithm {
2230 #[cfg(feature = "legacy-algorithms")]
2231 DataEncryptionAlgorithm::TripleDesCbc => {
2232 encrypt_cbc::<TdesEde3>(provider, key, plaintext)
2233 }
2234 #[cfg(feature = "legacy-algorithms")]
2235 DataEncryptionAlgorithm::Aes192Cbc => encrypt_cbc::<Aes192>(provider, key, plaintext),
2236 #[cfg(feature = "legacy-algorithms")]
2237 DataEncryptionAlgorithm::Aes192Gcm => encrypt_gcm::<
2238 aes_gcm::AesGcm<Aes192, aes_gcm::aead::consts::U12>,
2239 >(provider, key, plaintext),
2240 DataEncryptionAlgorithm::Aes128Cbc => encrypt_cbc::<Aes128>(provider, key, plaintext),
2241 DataEncryptionAlgorithm::Aes256Cbc => encrypt_cbc::<Aes256>(provider, key, plaintext),
2242 DataEncryptionAlgorithm::Camellia128Cbc => {
2246 encrypt_cbc::<Camellia128>(provider, key, plaintext)
2247 }
2248 DataEncryptionAlgorithm::Camellia192Cbc => {
2249 encrypt_cbc::<Camellia192>(provider, key, plaintext)
2250 }
2251 DataEncryptionAlgorithm::Camellia256Cbc => {
2252 encrypt_cbc::<Camellia256>(provider, key, plaintext)
2253 }
2254 DataEncryptionAlgorithm::Aes128Gcm => {
2255 encrypt_gcm::<Aes128Gcm>(provider, key, plaintext)
2256 }
2257 DataEncryptionAlgorithm::Aes256Gcm => {
2258 encrypt_gcm::<Aes256Gcm>(provider, key, plaintext)
2259 }
2260 DataEncryptionAlgorithm::ChaCha20 | DataEncryptionAlgorithm::ChaCha20Poly1305 => {
2261 Err(ProviderError::InvalidInput(
2262 ProviderInputError::PrimitiveInitialization("missing ChaCha parameters"),
2263 ))
2264 }
2265 }
2266 }
2267
2268 pub(super) fn decrypt_data(
2269 algorithm: DataEncryptionAlgorithm,
2270 key: &[u8],
2271 ciphertext: &[u8],
2272 ) -> Result<Vec<u8>, ProviderError> {
2273 check_key(algorithm.key_len(), key)?;
2274 match algorithm {
2275 #[cfg(feature = "legacy-algorithms")]
2276 DataEncryptionAlgorithm::TripleDesCbc => decrypt_cbc::<TdesEde3>(key, ciphertext),
2277 #[cfg(feature = "legacy-algorithms")]
2278 DataEncryptionAlgorithm::Aes192Cbc => decrypt_cbc::<Aes192>(key, ciphertext),
2279 #[cfg(feature = "legacy-algorithms")]
2280 DataEncryptionAlgorithm::Aes192Gcm => {
2281 decrypt_gcm::<aes_gcm::AesGcm<Aes192, aes_gcm::aead::consts::U12>>(key, ciphertext)
2282 }
2283 DataEncryptionAlgorithm::Aes128Cbc => decrypt_cbc::<Aes128>(key, ciphertext),
2284 DataEncryptionAlgorithm::Aes256Cbc => decrypt_cbc::<Aes256>(key, ciphertext),
2285 DataEncryptionAlgorithm::Camellia128Cbc => decrypt_cbc::<Camellia128>(key, ciphertext),
2286 DataEncryptionAlgorithm::Camellia192Cbc => decrypt_cbc::<Camellia192>(key, ciphertext),
2287 DataEncryptionAlgorithm::Camellia256Cbc => decrypt_cbc::<Camellia256>(key, ciphertext),
2288 DataEncryptionAlgorithm::Aes128Gcm => decrypt_gcm::<Aes128Gcm>(key, ciphertext),
2289 DataEncryptionAlgorithm::Aes256Gcm => decrypt_gcm::<Aes256Gcm>(key, ciphertext),
2290 DataEncryptionAlgorithm::ChaCha20 | DataEncryptionAlgorithm::ChaCha20Poly1305 => {
2291 Err(ProviderError::InvalidInput(
2292 ProviderInputError::PrimitiveInitialization("missing ChaCha parameters"),
2293 ))
2294 }
2295 }
2296 }
2297
2298 fn check_key(expected: usize, key: &[u8]) -> Result<(), ProviderError> {
2299 if key.len() == expected {
2300 Ok(())
2301 } else {
2302 Err(ProviderError::InvalidKeySize {
2303 expected,
2304 actual: key.len(),
2305 })
2306 }
2307 }
2308
2309 fn encrypt_cbc<C>(
2310 provider: &dyn CryptoProvider,
2311 key: &[u8],
2312 plaintext: &[u8],
2313 ) -> Result<Vec<u8>, ProviderError>
2314 where
2315 C: aes::cipher::BlockCipherEncrypt + aes::cipher::KeyInit,
2316 {
2317 let block = C::block_size();
2318 let pad_len = block - (plaintext.len() % block);
2319 let length = plaintext
2320 .len()
2321 .checked_add(pad_len)
2322 .and_then(|len| len.checked_add(block))
2323 .ok_or(ProviderError::InvalidInput(
2324 ProviderInputError::AesCbcFraming,
2325 ))?;
2326 let mut output = zeroize::Zeroizing::new(vec![0_u8; length]);
2327 let (iv, padded) = output.split_at_mut(block);
2328 provider.fill_random(iv)?;
2329 padded[..plaintext.len()].copy_from_slice(plaintext);
2330 if pad_len > 1 {
2331 let last = padded.len() - 1;
2332 provider.fill_random(&mut padded[plaintext.len()..last])?;
2333 }
2334 *padded.last_mut().expect("padding is non-empty") = pad_len as u8;
2335 Encryptor::<C>::new_from_slices(key, iv)
2336 .map_err(|_| {
2337 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization("AES-CBC"))
2338 })?
2339 .encrypt_padded::<NoPadding>(padded, plaintext.len() + pad_len)
2340 .map_err(|_| {
2341 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization(
2342 "AES-CBC padding",
2343 ))
2344 })?;
2345 Ok(core::mem::take(&mut *output))
2346 }
2347
2348 fn decrypt_cbc<C>(key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, ProviderError>
2349 where
2350 C: aes::cipher::BlockCipherDecrypt + aes::cipher::KeyInit,
2351 {
2352 let block = C::block_size();
2353 if ciphertext.len() < 2 * block || !(ciphertext.len() - block).is_multiple_of(block) {
2354 return Err(ProviderError::InvalidInput(
2355 ProviderInputError::AesCbcFraming,
2356 ));
2357 }
2358 let (iv, body) = ciphertext.split_at(block);
2359 let mut plaintext = zeroize::Zeroizing::new(body.to_vec());
2360 Decryptor::<C>::new_from_slices(key, iv)
2361 .map_err(|_| {
2362 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization("AES-CBC"))
2363 })?
2364 .decrypt_padded::<NoPadding>(&mut plaintext)
2365 .map_err(|_| ProviderError::InvalidInput(ProviderInputError::AesCbcCiphertext))?;
2366 let pad_len = *plaintext.last().ok_or(ProviderError::InvalidInput(
2367 ProviderInputError::AesCbcCiphertext,
2368 ))?;
2369 let padding_bytes = usize::from(pad_len);
2370 if !(1..=block).contains(&padding_bytes) || padding_bytes > plaintext.len() {
2371 return Err(ProviderError::InvalidInput(
2372 ProviderInputError::AesCbcCiphertext,
2373 ));
2374 }
2375 let length = plaintext.len() - padding_bytes;
2376 plaintext.truncate(length);
2377 Ok(core::mem::take(&mut *plaintext))
2378 }
2379
2380 fn encrypt_gcm<C>(
2381 provider: &dyn CryptoProvider,
2382 key: &[u8],
2383 plaintext: &[u8],
2384 ) -> Result<Vec<u8>, ProviderError>
2385 where
2386 C: AeadInOut + KeyInit,
2387 {
2388 let mut nonce = [0_u8; 12];
2389 provider.fill_random(&mut nonce)?;
2390 let cipher = C::new_from_slice(key).map_err(|_| {
2391 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization("AES-GCM"))
2392 })?;
2393 let length = plaintext
2394 .len()
2395 .checked_add(28)
2396 .ok_or(ProviderError::InvalidInput(
2397 ProviderInputError::PrimitiveInitialization("AES-GCM length"),
2398 ))?;
2399 let mut output = zeroize::Zeroizing::new(Vec::with_capacity(length));
2402 output.extend_from_slice(&nonce);
2403 output.extend_from_slice(plaintext);
2404 let nonce = Nonce::try_from(nonce.as_slice()).map_err(|_| {
2405 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization(
2406 "AES-GCM nonce",
2407 ))
2408 })?;
2409 let tag = cipher
2410 .encrypt_inout_detached(&nonce, &[], output[12..].as_mut().into())
2411 .map_err(|_| ProviderError::AuthenticationFailed)?;
2412 output.extend_from_slice(&tag);
2413 Ok(core::mem::take(&mut *output))
2414 }
2415
2416 fn decrypt_gcm<C>(key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, ProviderError>
2417 where
2418 C: AeadInOut + KeyInit,
2419 {
2420 if ciphertext.len() < 28 {
2421 return Err(ProviderError::InvalidInput(
2422 ProviderInputError::AesGcmFraming,
2423 ));
2424 }
2425 let (nonce, body) = ciphertext.split_at(12);
2426 let cipher = C::new_from_slice(key).map_err(|_| {
2427 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization("AES-GCM"))
2428 })?;
2429 let mut plaintext = zeroize::Zeroizing::new(body.to_vec());
2430 let nonce = Nonce::try_from(nonce).map_err(|_| {
2431 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization(
2432 "AES-GCM nonce",
2433 ))
2434 })?;
2435 cipher
2436 .decrypt_in_place(&nonce, &[], &mut *plaintext)
2437 .map_err(|_| ProviderError::AuthenticationFailed)?;
2438 Ok(core::mem::take(&mut *plaintext))
2439 }
2440
2441 pub(super) fn wrap_key(
2442 provider: &dyn CryptoProvider,
2443 algorithm: KeyWrapAlgorithm,
2444 kek: &[u8],
2445 key: &[u8],
2446 ) -> Result<Vec<u8>, ProviderError> {
2447 check_key(algorithm.key_len(), kek)?;
2448 if let KeyWrapAlgorithm::Cbc(cipher) = algorithm {
2449 if cipher.cbc_block_len().is_none() {
2450 return Err(ProviderError::InvalidInput(
2451 ProviderInputError::AesKeyWrapFraming,
2452 ));
2453 }
2454 return encrypt_data(provider, cipher, kek, key);
2458 }
2459 #[cfg(feature = "legacy-algorithms")]
2460 if algorithm == KeyWrapAlgorithm::TripleDes {
2461 return wrap_des3(provider, kek, key);
2462 }
2463 #[cfg(not(feature = "legacy-algorithms"))]
2464 let _ = provider;
2465 if key.len() < 16 || !key.len().is_multiple_of(8) {
2470 return Err(ProviderError::InvalidInput(
2471 ProviderInputError::AesKeyWrapFraming,
2472 ));
2473 }
2474 let length = algorithm
2475 .wrapped_len(key.len())
2476 .ok_or(ProviderError::InvalidInput(
2477 ProviderInputError::AesKeyWrapFraming,
2478 ))?;
2479 let mut output = vec![0_u8; length];
2480 macro_rules! camellia_wrap {
2484 ($cipher:ty) => {
2485 aes_kw::AesKw::<$cipher>::new_from_slice(kek)
2486 .map_err(|_| ProviderError::InvalidKeySize {
2487 expected: algorithm.key_len(),
2488 actual: kek.len(),
2489 })?
2490 .wrap_key(key, &mut output)
2491 };
2492 }
2493 match algorithm {
2494 KeyWrapAlgorithm::Cbc(_) => unreachable!("CBC wrapping already dispatched"),
2495 KeyWrapAlgorithm::CamelliaKw128 => camellia_wrap!(Camellia128),
2496 KeyWrapAlgorithm::CamelliaKw192 => camellia_wrap!(Camellia192),
2497 KeyWrapAlgorithm::CamelliaKw256 => camellia_wrap!(Camellia256),
2498 #[cfg(feature = "legacy-algorithms")]
2499 KeyWrapAlgorithm::AesKw192 => aes_kw::KwAes192::new_from_slice(kek)
2500 .map_err(|_| ProviderError::InvalidKeySize {
2501 expected: 24,
2502 actual: kek.len(),
2503 })?
2504 .wrap_key(key, &mut output),
2505 #[cfg(feature = "legacy-algorithms")]
2506 KeyWrapAlgorithm::TripleDes => unreachable!("CMS wrapping dispatched before AES"),
2507 KeyWrapAlgorithm::AesKw128 => KwAes128::new_from_slice(kek)
2508 .map_err(|_| ProviderError::InvalidKeySize {
2509 expected: 16,
2510 actual: kek.len(),
2511 })?
2512 .wrap_key(key, &mut output),
2513 KeyWrapAlgorithm::AesKw256 => KwAes256::new_from_slice(kek)
2514 .map_err(|_| ProviderError::InvalidKeySize {
2515 expected: 32,
2516 actual: kek.len(),
2517 })?
2518 .wrap_key(key, &mut output),
2519 }
2520 .map_err(|_| ProviderError::InvalidInput(ProviderInputError::AesKeyWrapFraming))?;
2521 Ok(output)
2522 }
2523
2524 pub(super) fn unwrap_key(
2525 algorithm: KeyWrapAlgorithm,
2526 kek: &[u8],
2527 wrapped: &[u8],
2528 ) -> Result<Vec<u8>, ProviderError> {
2529 check_key(algorithm.key_len(), kek)?;
2530 if let KeyWrapAlgorithm::Cbc(cipher) = algorithm {
2531 if cipher.cbc_block_len().is_none() {
2532 return Err(ProviderError::InvalidInput(
2533 ProviderInputError::AesKeyWrapFraming,
2534 ));
2535 }
2536 return decrypt_data(cipher, kek, wrapped);
2537 }
2538 #[cfg(feature = "legacy-algorithms")]
2539 if algorithm == KeyWrapAlgorithm::TripleDes {
2540 return unwrap_des3(kek, wrapped);
2541 }
2542 if wrapped.len() < 24 || !wrapped.len().is_multiple_of(8) {
2543 return Err(ProviderError::InvalidInput(
2544 ProviderInputError::AesKeyWrapFraming,
2545 ));
2546 }
2547 let mut output = zeroize::Zeroizing::new(vec![0_u8; wrapped.len() - 8]);
2548 macro_rules! camellia_unwrap {
2549 ($cipher:ty) => {
2550 aes_kw::AesKw::<$cipher>::new_from_slice(kek)
2551 .map_err(|_| ProviderError::InvalidKeySize {
2552 expected: algorithm.key_len(),
2553 actual: kek.len(),
2554 })?
2555 .unwrap_key(wrapped, &mut output)
2556 };
2557 }
2558 match algorithm {
2559 KeyWrapAlgorithm::Cbc(_) => unreachable!("CBC unwrapping already dispatched"),
2560 KeyWrapAlgorithm::CamelliaKw128 => camellia_unwrap!(Camellia128),
2561 KeyWrapAlgorithm::CamelliaKw192 => camellia_unwrap!(Camellia192),
2562 KeyWrapAlgorithm::CamelliaKw256 => camellia_unwrap!(Camellia256),
2563 #[cfg(feature = "legacy-algorithms")]
2564 KeyWrapAlgorithm::AesKw192 => aes_kw::KwAes192::new_from_slice(kek)
2565 .map_err(|_| ProviderError::InvalidKeySize {
2566 expected: 24,
2567 actual: kek.len(),
2568 })?
2569 .unwrap_key(wrapped, &mut output),
2570 #[cfg(feature = "legacy-algorithms")]
2571 KeyWrapAlgorithm::TripleDes => unreachable!("CMS unwrapping dispatched before AES"),
2572 KeyWrapAlgorithm::AesKw128 => KwAes128::new_from_slice(kek)
2573 .map_err(|_| ProviderError::InvalidKeySize {
2574 expected: 16,
2575 actual: kek.len(),
2576 })?
2577 .unwrap_key(wrapped, &mut output),
2578 KeyWrapAlgorithm::AesKw256 => KwAes256::new_from_slice(kek)
2579 .map_err(|_| ProviderError::InvalidKeySize {
2580 expected: 32,
2581 actual: kek.len(),
2582 })?
2583 .unwrap_key(wrapped, &mut output),
2584 }
2585 .map_err(|_| ProviderError::AuthenticationFailed)?;
2586 Ok(core::mem::take(&mut *output))
2587 }
2588
2589 #[cfg(feature = "legacy-algorithms")]
2590 const CMS_IV: [u8; 8] = [0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05];
2591
2592 #[cfg(feature = "legacy-algorithms")]
2593 fn wrap_des3(
2594 provider: &dyn CryptoProvider,
2595 kek: &[u8],
2596 key: &[u8],
2597 ) -> Result<Vec<u8>, ProviderError> {
2598 use sha1::Digest as _;
2599 if key.len() < 16 || !key.len().is_multiple_of(8) {
2604 return Err(ProviderError::InvalidInput(
2605 ProviderInputError::AesKeyWrapFraming,
2606 ));
2607 }
2608 let length = key
2609 .len()
2610 .checked_add(16)
2611 .ok_or(ProviderError::InvalidInput(
2612 ProviderInputError::AesKeyWrapFraming,
2613 ))?;
2614 let mut output = zeroize::Zeroizing::new(vec![0; length]);
2615 provider.fill_random(&mut output[..8])?;
2616 output[8..8 + key.len()].copy_from_slice(key);
2617 output[8 + key.len()..].copy_from_slice(&Sha1::digest(key)[..8]);
2618 let (iv, body) = output.split_at_mut(8);
2619 let body_len = body.len();
2620 Encryptor::<TdesEde3>::new_from_slices(kek, iv)
2621 .map_err(|_| ProviderError::AuthenticationFailed)?
2622 .encrypt_padded::<NoPadding>(body, body_len)
2623 .map_err(|_| ProviderError::AuthenticationFailed)?;
2624 output.reverse();
2625 Encryptor::<TdesEde3>::new_from_slices(kek, &CMS_IV)
2626 .map_err(|_| ProviderError::AuthenticationFailed)?
2627 .encrypt_padded::<NoPadding>(&mut output, length)
2628 .map_err(|_| ProviderError::AuthenticationFailed)?;
2629 Ok(core::mem::take(&mut *output))
2630 }
2631
2632 #[cfg(feature = "legacy-algorithms")]
2633 fn unwrap_des3(kek: &[u8], wrapped: &[u8]) -> Result<Vec<u8>, ProviderError> {
2634 use sha1::Digest as _;
2635 use subtle::ConstantTimeEq as _;
2636 if wrapped.len() < 32 || !wrapped.len().is_multiple_of(8) {
2640 return Err(ProviderError::InvalidInput(
2641 ProviderInputError::AesKeyWrapFraming,
2642 ));
2643 }
2644 let mut output = zeroize::Zeroizing::new(wrapped.to_vec());
2645 Decryptor::<TdesEde3>::new_from_slices(kek, &CMS_IV)
2646 .map_err(|_| ProviderError::AuthenticationFailed)?
2647 .decrypt_padded::<NoPadding>(&mut output)
2648 .map_err(|_| ProviderError::AuthenticationFailed)?;
2649 output.reverse();
2650 let (iv, body) = output.split_at_mut(8);
2651 Decryptor::<TdesEde3>::new_from_slices(kek, iv)
2652 .map_err(|_| ProviderError::AuthenticationFailed)?
2653 .decrypt_padded::<NoPadding>(body)
2654 .map_err(|_| ProviderError::AuthenticationFailed)?;
2655 let key_len = body.len() - 8;
2656 if !bool::from(Sha1::digest(&body[..key_len])[..8].ct_eq(&body[key_len..])) {
2657 return Err(ProviderError::AuthenticationFailed);
2658 }
2659 output.copy_within(8..8 + key_len, 0);
2660 zeroize::Zeroize::zeroize(&mut output[key_len..]);
2661 output.truncate(key_len);
2662 Ok(core::mem::take(&mut *output))
2663 }
2664
2665 #[cfg(feature = "legacy-algorithms")]
2666 pub(super) fn transport_pkcs1v15(
2667 provider: &dyn CryptoProvider,
2668 key: &rsa::RsaPublicKey,
2669 plaintext: &[u8],
2670 ) -> Result<Vec<u8>, ProviderError> {
2671 rsa::Pkcs1v15Encrypt
2672 .encrypt(&mut super::ProviderRng(provider), key, plaintext)
2673 .map_err(map_rsa_error)
2674 }
2675
2676 pub(super) fn transport_key(
2677 provider: &dyn CryptoProvider,
2678 key: &rsa::RsaPublicKey,
2679 parameters: &RsaOaepParameters,
2680 plaintext: &[u8],
2681 ) -> Result<Vec<u8>, ProviderError> {
2682 if parameters.algorithm.requires_explicit_permission() {
2683 return Err(ProviderError::InvalidInput(
2684 ProviderInputError::PrimitiveInitialization("RSA-OAEP algorithm"),
2685 ));
2686 }
2687 run_oaep(provider, parameters, OaepOperation::Encrypt(key), plaintext)
2688 }
2689
2690 pub(super) fn recover_key(
2691 provider: &dyn CryptoProvider,
2692 key: &rsa::RsaPrivateKey,
2693 parameters: &RsaOaepParameters,
2694 ciphertext: &[u8],
2695 ) -> Result<Vec<u8>, ProviderError> {
2696 if parameters.algorithm.requires_explicit_permission() {
2697 return Err(ProviderError::InvalidInput(
2698 ProviderInputError::PrimitiveInitialization("RSA-OAEP algorithm"),
2699 ));
2700 }
2701 run_oaep(
2702 provider,
2703 parameters,
2704 OaepOperation::Decrypt(key),
2705 ciphertext,
2706 )
2707 }
2708
2709 enum OaepOperation<'a> {
2710 Encrypt(&'a rsa::RsaPublicKey),
2711 Decrypt(&'a rsa::RsaPrivateKey),
2712 }
2713
2714 fn run_oaep(
2715 provider: &dyn CryptoProvider,
2716 parameters: &RsaOaepParameters,
2717 operation: OaepOperation<'_>,
2718 input: &[u8],
2719 ) -> Result<Vec<u8>, ProviderError> {
2720 match parameters.digest {
2724 #[cfg(feature = "legacy-algorithms")]
2725 OaepDigestAlgorithm::Md5 => {
2726 run_oaep_mgf::<md5::Md5>(provider, parameters, operation, input)
2727 }
2728 #[cfg(feature = "legacy-algorithms")]
2729 OaepDigestAlgorithm::Ripemd160 => {
2730 run_oaep_mgf::<ripemd::Ripemd160>(provider, parameters, operation, input)
2731 }
2732 OaepDigestAlgorithm::Sha3_224 => {
2733 run_oaep_mgf::<sha3::Sha3_224>(provider, parameters, operation, input)
2734 }
2735 OaepDigestAlgorithm::Sha3_256 => {
2736 run_oaep_mgf::<sha3::Sha3_256>(provider, parameters, operation, input)
2737 }
2738 OaepDigestAlgorithm::Sha3_384 => {
2739 run_oaep_mgf::<sha3::Sha3_384>(provider, parameters, operation, input)
2740 }
2741 OaepDigestAlgorithm::Sha3_512 => {
2742 run_oaep_mgf::<sha3::Sha3_512>(provider, parameters, operation, input)
2743 }
2744 OaepDigestAlgorithm::Sha1 => {
2745 run_oaep_mgf::<Sha1>(provider, parameters, operation, input)
2746 }
2747 OaepDigestAlgorithm::Sha224 => {
2748 run_oaep_mgf::<Sha224>(provider, parameters, operation, input)
2749 }
2750 OaepDigestAlgorithm::Sha256 => {
2751 run_oaep_mgf::<Sha256>(provider, parameters, operation, input)
2752 }
2753 OaepDigestAlgorithm::Sha384 => {
2754 run_oaep_mgf::<Sha384>(provider, parameters, operation, input)
2755 }
2756 OaepDigestAlgorithm::Sha512 => {
2757 run_oaep_mgf::<Sha512>(provider, parameters, operation, input)
2758 }
2759 }
2760 }
2761
2762 fn run_oaep_mgf<D: sha2::digest::Digest + sha2::digest::FixedOutputReset>(
2763 provider: &dyn CryptoProvider,
2764 parameters: &RsaOaepParameters,
2765 operation: OaepOperation<'_>,
2766 input: &[u8],
2767 ) -> Result<Vec<u8>, ProviderError> {
2768 match parameters.mgf_digest {
2769 OaepDigestAlgorithm::Sha1 => {
2770 run_oaep_primitive::<D, Sha1>(provider, parameters, operation, input)
2771 }
2772 OaepDigestAlgorithm::Sha224 => {
2773 run_oaep_primitive::<D, Sha224>(provider, parameters, operation, input)
2774 }
2775 OaepDigestAlgorithm::Sha256 => {
2776 run_oaep_primitive::<D, Sha256>(provider, parameters, operation, input)
2777 }
2778 OaepDigestAlgorithm::Sha384 => {
2779 run_oaep_primitive::<D, Sha384>(provider, parameters, operation, input)
2780 }
2781 OaepDigestAlgorithm::Sha512 => {
2782 run_oaep_primitive::<D, Sha512>(provider, parameters, operation, input)
2783 }
2784 _ => Err(ProviderError::InvalidInput(
2785 ProviderInputError::PrimitiveInitialization("unregistered XML OAEP mask digest"),
2786 )),
2787 }
2788 }
2789
2790 fn run_oaep_primitive<D, M>(
2791 provider: &dyn CryptoProvider,
2792 parameters: &RsaOaepParameters,
2793 operation: OaepOperation<'_>,
2794 input: &[u8],
2795 ) -> Result<Vec<u8>, ProviderError>
2796 where
2797 D: sha2::digest::Digest + sha2::digest::FixedOutputReset,
2798 M: sha2::digest::Digest + sha2::digest::FixedOutputReset,
2799 {
2800 let mut rng = super::ProviderRng(provider);
2801 let padding = Oaep::<D, M>::new_with_mgf_hash_and_label(parameters.label.clone());
2802 match operation {
2803 OaepOperation::Encrypt(key) => padding.encrypt(&mut rng, key, input),
2804 OaepOperation::Decrypt(key) => padding.decrypt(Some(&mut rng), key, input),
2805 }
2806 .map_err(map_rsa_error)
2807 }
2808
2809 pub(super) fn map_rsa_error(error: rsa::Error) -> ProviderError {
2810 match error {
2811 rsa::Error::Rng => ProviderError::Random("RSA randomness failed".into()),
2812 _ => ProviderError::AuthenticationFailed,
2813 }
2814 }
2815}
2816
2817#[cfg(test)]
2818mod tests {
2819 #[cfg(feature = "xmldsig")]
2820 use std::sync::atomic::AtomicUsize;
2821 use std::sync::atomic::{AtomicBool, Ordering};
2822
2823 use super::*;
2824
2825 #[cfg(all(feature = "legacy-algorithms", feature = "xmlenc"))]
2826 #[test]
2827 fn legacy_ciphers_cover_empty_and_block_boundary_plaintexts() {
2828 for algorithm in [
2831 DataEncryptionAlgorithm::TripleDesCbc,
2832 DataEncryptionAlgorithm::Aes192Cbc,
2833 DataEncryptionAlgorithm::Aes192Gcm,
2834 ] {
2835 let key = [0x31; 24];
2836 for length in [0, 1, 7, 8, 15, 16, 17, 31, 32, 33] {
2837 let plaintext = vec![0x41; length];
2838 let ciphertext = RUST_CRYPTO_PROVIDER
2839 .encrypt_data(algorithm, &key, &plaintext)
2840 .expect("valid legacy encryption must succeed");
2841 assert_eq!(
2842 Some(ciphertext.len()),
2843 algorithm.ciphertext_len_for_plaintext(length)
2844 );
2845 assert_eq!(
2846 RUST_CRYPTO_PROVIDER
2847 .decrypt_data(algorithm, &key, &ciphertext)
2848 .expect("matching legacy key must recover plaintext"),
2849 plaintext
2850 );
2851 assert!(
2852 RUST_CRYPTO_PROVIDER
2853 .encrypt_data(algorithm, &key[..23], &plaintext)
2854 .is_err()
2855 );
2856 assert!(
2857 RUST_CRYPTO_PROVIDER
2858 .decrypt_data(algorithm, &key[..23], &ciphertext)
2859 .is_err()
2860 );
2861 assert!(
2862 RUST_CRYPTO_PROVIDER
2863 .decrypt_data(algorithm, &key, &ciphertext[..ciphertext.len() - 1])
2864 .is_err()
2865 );
2866 if algorithm == DataEncryptionAlgorithm::Aes192Gcm {
2867 let mut corrupted = ciphertext;
2868 corrupted[12] ^= 1;
2869 assert!(matches!(
2870 RUST_CRYPTO_PROVIDER.decrypt_data(algorithm, &key, &corrupted),
2871 Err(ProviderError::AuthenticationFailed)
2872 ));
2873 }
2874 }
2875 }
2876 }
2877
2878 #[cfg(all(feature = "legacy-algorithms", feature = "xmlenc"))]
2879 #[test]
2880 fn cms_triple_des_unwrap_matches_rfc3217_vector() {
2881 let kek = hex_literal::hex!("255e0d1c07b646dfb3134cc843ba8aa71f025b7c0838251f");
2885 let key = hex_literal::hex!("2923bf85e06dd6ae529149f1f1bae9eab3a7da3d860d3e98");
2886 let wrapped = hex_literal::hex!(
2887 "690107618ef092b3b48ca1796b234ae9fa33ebb4159604037db5d6a84eb3aac2768c632775a467d4"
2888 );
2889 assert_eq!(
2890 RUST_CRYPTO_PROVIDER
2891 .unwrap_key(KeyWrapAlgorithm::TripleDes, &kek, &wrapped)
2892 .expect("RFC 3217 vector must authenticate"),
2893 key
2894 );
2895 for offset in 0..wrapped.len() {
2896 let mut corrupted = wrapped;
2897 corrupted[offset] ^= 1;
2898 assert!(matches!(
2899 RUST_CRYPTO_PROVIDER.unwrap_key(KeyWrapAlgorithm::TripleDes, &kek, &corrupted),
2900 Err(ProviderError::AuthenticationFailed)
2901 ));
2902 }
2903 }
2904
2905 #[cfg(all(feature = "legacy-algorithms", feature = "xmlenc"))]
2906 #[test]
2907 fn legacy_wrap_preserves_opaque_key_bytes_and_checks_integrity() {
2908 for algorithm in [KeyWrapAlgorithm::AesKw192, KeyWrapAlgorithm::TripleDes] {
2911 let kek = [0x37; 24];
2912 for length in [16, 24, 32] {
2913 let key: Vec<_> = (0..length).map(|byte| byte as u8).collect();
2914 let mut wrapped = RUST_CRYPTO_PROVIDER
2915 .wrap_key(algorithm, &kek, &key)
2916 .expect("valid content key must wrap");
2917 assert_eq!(Some(wrapped.len()), algorithm.wrapped_len(key.len()));
2918 assert_eq!(
2919 RUST_CRYPTO_PROVIDER
2920 .unwrap_key(algorithm, &kek, &wrapped)
2921 .expect("matching KEK must recover exact key octets"),
2922 key
2923 );
2924 assert!(
2925 RUST_CRYPTO_PROVIDER
2926 .unwrap_key(algorithm, &[0x38; 24], &wrapped)
2927 .is_err()
2928 );
2929 wrapped[0] ^= 1;
2930 assert!(
2931 RUST_CRYPTO_PROVIDER
2932 .unwrap_key(algorithm, &kek, &wrapped)
2933 .is_err()
2934 );
2935 }
2936 for length in [0, 1, 8, 15, 17] {
2937 assert!(
2938 RUST_CRYPTO_PROVIDER
2939 .wrap_key(algorithm, &kek, &vec![0; length])
2940 .is_err()
2941 );
2942 }
2943 }
2944 }
2945
2946 #[cfg(all(feature = "legacy-algorithms", feature = "xmldsig"))]
2947 #[test]
2948 fn legacy_digests_match_known_answers() {
2949 for (algorithm, expected) in [
2952 (
2953 DigestAlgorithm::Md5,
2954 &hex_literal::hex!("900150983cd24fb0d6963f7d28e17f72")[..],
2955 ),
2956 (
2957 DigestAlgorithm::Ripemd160,
2958 &hex_literal::hex!("8eb208f7e05d987a9b044a8e98c6b087f15a0bfc")[..],
2959 ),
2960 ] {
2961 assert_eq!(
2962 RUST_CRYPTO_PROVIDER
2963 .digest(algorithm, b"abc")
2964 .expect("compiled digest must be supported"),
2965 expected
2966 );
2967 assert_eq!(DigestAlgorithm::from_uri(algorithm.uri()), Some(algorithm));
2968 assert!(algorithm.requires_explicit_permission());
2969 assert!(!algorithm.signing_allowed());
2970 }
2971 }
2972
2973 #[cfg(feature = "xmldsig")]
2974 struct CountingRandomProvider {
2975 random_calls: AtomicUsize,
2976 reject_digest: Option<DigestAlgorithm>,
2977 extra_digest_byte: bool,
2978 accept_signatures: bool,
2979 }
2980
2981 #[cfg(feature = "xmldsig")]
2982 impl CryptoProvider for CountingRandomProvider {
2983 fn name(&self) -> &'static str {
2984 "counting-random"
2985 }
2986
2987 fn supports(&self, capability: ProviderCapability<'_>) -> bool {
2988 RUST_CRYPTO_PROVIDER.supports(capability)
2989 }
2990
2991 fn fill_random(&self, output: &mut [u8]) -> Result<(), ProviderError> {
2992 self.random_calls.fetch_add(1, Ordering::Relaxed);
2993 RUST_CRYPTO_PROVIDER.fill_random(output)
2994 }
2995
2996 fn derive_key(
2997 &self,
2998 parameters: &KdfParameters<'_>,
2999 secret: &[u8],
3000 ) -> Result<Vec<u8>, ProviderError> {
3001 RUST_CRYPTO_PROVIDER.derive_key(parameters, secret)
3002 }
3003
3004 fn digest(
3005 &self,
3006 algorithm: DigestAlgorithm,
3007 data: &[u8],
3008 ) -> Result<Vec<u8>, ProviderError> {
3009 if self.reject_digest == Some(algorithm) {
3010 return Err(ProviderError::Unsupported {
3011 operation: ProviderOperation::Digest,
3012 algorithm: Some(algorithm.uri().to_owned()),
3013 });
3014 }
3015 let mut digest = RUST_CRYPTO_PROVIDER.digest(algorithm, data)?;
3016 if self.extra_digest_byte {
3017 digest.push(0);
3018 }
3019 Ok(digest)
3020 }
3021
3022 fn sign(
3023 &self,
3024 key: &dyn crate::xmldsig::SigningKey,
3025 algorithm: crate::xmldsig::SignatureAlgorithm,
3026 data: &[u8],
3027 ) -> Result<Vec<u8>, crate::xmldsig::SigningKeyError> {
3028 key.sign_with_provider(self, algorithm, data)
3029 }
3030
3031 fn verify(
3032 &self,
3033 key: &dyn crate::xmldsig::VerifyingKey,
3034 algorithm: crate::xmldsig::SignatureAlgorithm,
3035 data: &[u8],
3036 signature: &[u8],
3037 ) -> Result<bool, crate::xmldsig::DsigError> {
3038 if self.accept_signatures {
3039 return Ok(true);
3040 }
3041 RUST_CRYPTO_PROVIDER.verify(key, algorithm, data, signature)
3042 }
3043
3044 #[cfg(feature = "xmlenc")]
3045 fn encrypt_data(
3046 &self,
3047 algorithm: DataEncryptionAlgorithm,
3048 key: &[u8],
3049 plaintext: &[u8],
3050 ) -> Result<Vec<u8>, ProviderError> {
3051 RUST_CRYPTO_PROVIDER.encrypt_data(algorithm, key, plaintext)
3052 }
3053
3054 #[cfg(feature = "xmlenc")]
3055 fn decrypt_data(
3056 &self,
3057 algorithm: DataEncryptionAlgorithm,
3058 key: &[u8],
3059 ciphertext: &[u8],
3060 ) -> Result<Vec<u8>, ProviderError> {
3061 RUST_CRYPTO_PROVIDER.decrypt_data(algorithm, key, ciphertext)
3062 }
3063
3064 #[cfg(feature = "xmlenc")]
3065 fn wrap_key(
3066 &self,
3067 algorithm: KeyWrapAlgorithm,
3068 kek: &[u8],
3069 key: &[u8],
3070 ) -> Result<Vec<u8>, ProviderError> {
3071 RUST_CRYPTO_PROVIDER.wrap_key(algorithm, kek, key)
3072 }
3073
3074 #[cfg(feature = "xmlenc")]
3075 fn unwrap_key(
3076 &self,
3077 algorithm: KeyWrapAlgorithm,
3078 kek: &[u8],
3079 wrapped: &[u8],
3080 ) -> Result<Vec<u8>, ProviderError> {
3081 RUST_CRYPTO_PROVIDER.unwrap_key(algorithm, kek, wrapped)
3082 }
3083
3084 #[cfg(feature = "xmlenc")]
3085 fn transport_key(
3086 &self,
3087 key: &dyn KeyTransportKey,
3088 parameters: &RsaOaepParameters,
3089 plaintext: &[u8],
3090 ) -> Result<Vec<u8>, ProviderError> {
3091 RUST_CRYPTO_PROVIDER.transport_key(key, parameters, plaintext)
3092 }
3093
3094 #[cfg(feature = "xmlenc")]
3095 fn recover_key(
3096 &self,
3097 key: &dyn KeyRecoveryKey,
3098 parameters: &RsaOaepParameters,
3099 ciphertext: &[u8],
3100 ) -> Result<Vec<u8>, ProviderError> {
3101 RUST_CRYPTO_PROVIDER.recover_key(key, parameters, ciphertext)
3102 }
3103 }
3104
3105 #[cfg(feature = "xmldsig")]
3106 #[test]
3107 fn capability_query_is_explicit_about_unimplemented_operations() {
3108 assert!(RUST_CRYPTO_PROVIDER.supports(ProviderCapability::Digest(DigestAlgorithm::Sha256)));
3109 let agreement = KeyAgreementParameters {
3110 algorithm: "urn:unsupported:agreement",
3111 peer_public_key: &[],
3112 };
3113 assert!(!RUST_CRYPTO_PROVIDER.supports(ProviderCapability::KeyAgreement(&agreement)));
3114 assert!(RUST_CRYPTO_PROVIDER.supports(ProviderCapability::Sign(
3115 crate::xmldsig::SignatureAlgorithm::RsaSha1
3116 )));
3117 assert!(RUST_CRYPTO_PROVIDER.supports(ProviderCapability::Verify(
3118 crate::xmldsig::SignatureAlgorithm::RsaSha1
3119 )));
3120 for digest in [DigestAlgorithm::Sha1, DigestAlgorithm::Sha512] {
3121 assert!(
3122 RUST_CRYPTO_PROVIDER.supports(ProviderCapability::VerifyCertificate(
3123 X509SignatureAlgorithm::Ecdsa(digest)
3124 ))
3125 );
3126 }
3127 #[cfg(feature = "legacy-algorithms")]
3130 for digest in [DigestAlgorithm::Md5, DigestAlgorithm::Ripemd160] {
3131 assert!(
3132 !RUST_CRYPTO_PROVIDER.supports(ProviderCapability::VerifyCertificate(
3133 X509SignatureAlgorithm::Ecdsa(digest)
3134 ))
3135 );
3136 }
3137 }
3138
3139 #[cfg(feature = "xmldsig")]
3140 #[test]
3141 fn x509_digest_key_info_uses_the_selected_provider() {
3142 use crate::xmldsig::{
3143 DigestAlgorithm, KeyInfoWriteError, KeyInfoWriter, RsaSigningKey,
3144 X509DigestKeyInfoWriter,
3145 };
3146
3147 let key = RsaSigningKey::from_pkcs8_pem(include_str!(
3150 "../tests/fixtures/keys/rsa/rsa-2048-key.pem"
3151 ))
3152 .expect("RSA fixture must parse");
3153 let writer = X509DigestKeyInfoWriter::from_pem(
3154 include_str!("../tests/fixtures/keys/rsa/rsa-2048-cert.pem"),
3155 DigestAlgorithm::Sha224,
3156 )
3157 .expect("certificate fixture must parse");
3158 let provider = CountingRandomProvider {
3159 random_calls: AtomicUsize::new(0),
3160 reject_digest: Some(DigestAlgorithm::Sha224),
3161 extra_digest_byte: false,
3162 accept_signatures: false,
3163 };
3164
3165 let error = writer
3166 .write_key_info_with_provider(&key, &provider)
3167 .expect_err("the selected provider must control X509Digest");
3168 assert!(matches!(
3169 error,
3170 KeyInfoWriteError::Provider(ProviderError::Unsupported {
3171 operation: ProviderOperation::Digest,
3172 ..
3173 })
3174 ));
3175 }
3176
3177 #[cfg(feature = "xmldsig")]
3178 #[test]
3179 fn x509_digest_writer_rejects_trailing_certificate_der() {
3180 use crate::xmldsig::{DigestAlgorithm, KeyInfoWriteError, X509DigestKeyInfoWriter};
3181
3182 let (_, certificate) = x509_parser::pem::parse_x509_pem(include_bytes!(
3185 "../tests/fixtures/keys/rsa/rsa-2048-cert.pem"
3186 ))
3187 .expect("certificate fixture must parse");
3188 let mut certificate_der = certificate.contents;
3189 certificate_der.push(0);
3190
3191 assert!(matches!(
3192 X509DigestKeyInfoWriter::from_der(&certificate_der, DigestAlgorithm::Sha256),
3193 Err(KeyInfoWriteError::InvalidCertificateDer)
3194 ));
3195 }
3196
3197 #[cfg(all(feature = "xmldsig", feature = "xmlenc"))]
3198 #[test]
3199 fn capability_queries_include_oaep_and_pss_parameters() {
3200 use crate::xmlenc::{KeyTransportAlgorithm, OaepDigestAlgorithm};
3201
3202 let explicit_legacy = RsaOaepParameters {
3203 algorithm: KeyTransportAlgorithm::RsaOaepMgf1p,
3204 digest: OaepDigestAlgorithm::Sha256,
3205 mgf_digest: OaepDigestAlgorithm::Sha256,
3206 label: Vec::new(),
3207 };
3208 assert!(RUST_CRYPTO_PROVIDER.supports(ProviderCapability::KeyTransport(&explicit_legacy)));
3209 let modern =
3210 RsaOaepParameters::xmlenc11(OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha512)
3211 .label(b"label".to_vec());
3212 assert!(RUST_CRYPTO_PROVIDER.supports(ProviderCapability::KeyTransport(&modern)));
3213
3214 let supported_pss = X509SignatureAlgorithm::RsaPss {
3215 digest: DigestAlgorithm::Sha256,
3216 mgf_digest: DigestAlgorithm::Sha256,
3217 salt_len: 32,
3218 };
3219 assert!(
3220 RUST_CRYPTO_PROVIDER.supports(ProviderCapability::VerifyCertificate(supported_pss))
3221 );
3222 let unsupported_pss = X509SignatureAlgorithm::RsaPss {
3223 digest: DigestAlgorithm::Sha256,
3224 mgf_digest: DigestAlgorithm::Sha384,
3225 salt_len: 32,
3226 };
3227 assert!(
3228 !RUST_CRYPTO_PROVIDER.supports(ProviderCapability::VerifyCertificate(unsupported_pss))
3229 );
3230 }
3231
3232 struct RecordingAgreementKey(AtomicBool);
3233
3234 impl KeyAgreementKey for RecordingAgreementKey {
3235 fn agree(
3236 &self,
3237 _parameters: &KeyAgreementParameters<'_>,
3238 ) -> Result<Vec<u8>, ProviderError> {
3239 self.0.store(true, Ordering::Relaxed);
3240 Ok(vec![0x42])
3241 }
3242 }
3243
3244 #[test]
3245 fn unsupported_agreement_and_kdf_fail_without_dispatch_or_fallback() {
3246 let agreement = KeyAgreementParameters {
3247 algorithm: "urn:example:agreement",
3248 peer_public_key: b"peer",
3249 };
3250 let key = RecordingAgreementKey(AtomicBool::new(false));
3251 let error = RUST_CRYPTO_PROVIDER
3252 .agree_key(&key, &agreement)
3253 .expect_err("unsupported agreement must fail closed");
3254 assert!(matches!(
3255 error,
3256 ProviderError::Unsupported {
3257 operation: ProviderOperation::KeyAgreement,
3258 algorithm: Some(ref algorithm),
3259 } if algorithm == agreement.algorithm
3260 ));
3261 assert!(!key.0.load(Ordering::Relaxed));
3262
3263 let kdf = KdfParameters {
3264 algorithm: "urn:example:kdf",
3265 digest: Some("urn:example:digest"),
3266 salt: b"salt",
3267 info: KdfContext::Octets(b"info"),
3268 iterations: 1,
3269 output_len: 32,
3270 };
3271 assert!(matches!(
3272 RUST_CRYPTO_PROVIDER.derive_key(&kdf, b"secret"),
3273 Err(ProviderError::Unsupported {
3274 operation: ProviderOperation::Kdf,
3275 algorithm: Some(ref algorithm),
3276 }) if algorithm == kdf.algorithm
3277 ));
3278 }
3279
3280 #[cfg(feature = "xmldsig")]
3281 #[test]
3282 fn rsa_signing_uses_the_selected_providers_randomness() {
3283 use crate::xmldsig::{RsaSigningKey, SignatureAlgorithm};
3284
3285 let key = RsaSigningKey::from_pkcs8_pem(include_str!(
3288 "../tests/fixtures/keys/rsa/rsa-2048-key.pem"
3289 ))
3290 .expect("RSA fixture must parse");
3291 let provider = CountingRandomProvider {
3292 random_calls: AtomicUsize::new(0),
3293 reject_digest: None,
3294 extra_digest_byte: false,
3295 accept_signatures: false,
3296 };
3297
3298 let signature = provider
3299 .sign(&key, SignatureAlgorithm::RsaSha256, b"signed info")
3300 .expect("RSA signing must succeed");
3301
3302 assert!(!signature.is_empty());
3303 assert!(provider.random_calls.load(Ordering::Relaxed) > 0);
3304 }
3305
3306 #[cfg(feature = "xmldsig")]
3307 #[test]
3308 fn ecdsa_signing_uses_the_selected_providers_digest() {
3309 use crate::xmldsig::{
3310 EcdsaP256SigningKey, EcdsaP384SigningKey, SignatureAlgorithm, SigningKeyError,
3311 };
3312
3313 let cases: [(
3317 Box<dyn crate::xmldsig::SigningKey>,
3318 SignatureAlgorithm,
3319 DigestAlgorithm,
3320 ); 2] = [
3321 (
3322 Box::new(
3323 EcdsaP256SigningKey::from_pkcs8_pem(include_str!(
3324 "../tests/fixtures/keys/ec/ec-prime256v1-key.pem"
3325 ))
3326 .expect("P-256 fixture must parse"),
3327 ),
3328 SignatureAlgorithm::EcdsaSha384,
3329 DigestAlgorithm::Sha384,
3330 ),
3331 (
3332 Box::new(
3333 EcdsaP384SigningKey::from_pkcs8_pem(include_str!(
3334 "../tests/fixtures/keys/ec/ec-prime384v1-key.pem"
3335 ))
3336 .expect("P-384 fixture must parse"),
3337 ),
3338 SignatureAlgorithm::EcdsaSha256,
3339 DigestAlgorithm::Sha256,
3340 ),
3341 ];
3342
3343 for (key, signature_algorithm, digest_algorithm) in cases {
3344 let provider = CountingRandomProvider {
3345 random_calls: AtomicUsize::new(0),
3346 reject_digest: Some(digest_algorithm),
3347 extra_digest_byte: false,
3348 accept_signatures: false,
3349 };
3350 let error = provider
3351 .sign(key.as_ref(), signature_algorithm, b"signed info")
3352 .expect_err("provider digest rejection must stop ECDSA signing");
3353
3354 assert!(matches!(
3355 error,
3356 SigningKeyError::Provider(ProviderError::Unsupported {
3357 operation: ProviderOperation::Digest,
3358 algorithm: Some(ref uri),
3359 }) if uri == digest_algorithm.uri()
3360 ));
3361 }
3362 }
3363
3364 #[cfg(feature = "xmldsig")]
3365 #[test]
3366 fn ecdsa_signing_rejects_provider_digests_with_the_wrong_length() {
3367 use crate::xmldsig::{
3368 EcdsaP256SigningKey, EcdsaP384SigningKey, SignatureAlgorithm, SigningKeyError,
3369 };
3370
3371 let cases: [(
3374 Box<dyn crate::xmldsig::SigningKey>,
3375 SignatureAlgorithm,
3376 usize,
3377 ); 2] = [
3378 (
3379 Box::new(
3380 EcdsaP256SigningKey::from_pkcs8_pem(include_str!(
3381 "../tests/fixtures/keys/ec/ec-prime256v1-key.pem"
3382 ))
3383 .expect("P-256 fixture must parse"),
3384 ),
3385 SignatureAlgorithm::EcdsaSha256,
3386 32,
3387 ),
3388 (
3389 Box::new(
3390 EcdsaP384SigningKey::from_pkcs8_pem(include_str!(
3391 "../tests/fixtures/keys/ec/ec-prime384v1-key.pem"
3392 ))
3393 .expect("P-384 fixture must parse"),
3394 ),
3395 SignatureAlgorithm::EcdsaSha384,
3396 48,
3397 ),
3398 ];
3399
3400 for (key, algorithm, expected) in cases {
3401 let provider = CountingRandomProvider {
3402 random_calls: AtomicUsize::new(0),
3403 reject_digest: None,
3404 extra_digest_byte: true,
3405 accept_signatures: false,
3406 };
3407 let error = provider
3408 .sign(key.as_ref(), algorithm, b"signed info")
3409 .expect_err("an oversized provider digest must not reach ECDSA prehash signing");
3410
3411 assert!(matches!(
3412 error,
3413 SigningKeyError::Provider(ProviderError::InvalidOutputSize {
3414 operation: ProviderOperation::Digest,
3415 expected: actual_expected,
3416 actual,
3417 }) if actual_expected == expected && actual == expected + 1
3418 ));
3419 }
3420 }
3421
3422 #[cfg(feature = "xmldsig")]
3423 #[test]
3424 fn verification_facade_rejects_malformed_dsa_before_provider_dispatch() {
3425 use crate::xmldsig::{
3426 DefaultKeyResolver, DsigStatus, FailureReason, SignatureAlgorithm, VerifyContext,
3427 };
3428
3429 let original = include_str!(
3430 "../tests/fixtures/xmldsig/merlin-xmldsig-twenty-three/signature-enveloping-dsa.xml"
3431 );
3432 let value_start = original
3433 .find("<SignatureValue>")
3434 .expect("Merlin fixture must contain SignatureValue")
3435 + "<SignatureValue>".len();
3436 let value_end = original[value_start..]
3437 .find("</SignatureValue>")
3438 .map(|offset| value_start + offset)
3439 .expect("Merlin fixture must close SignatureValue");
3440 let mut malformed = original.to_owned();
3441 malformed.replace_range(value_start..value_end, "AQ==");
3442 let provider = CountingRandomProvider {
3443 random_calls: AtomicUsize::new(0),
3444 reject_digest: None,
3445 extra_digest_byte: false,
3446 accept_signatures: true,
3447 };
3448
3449 let mut policy = crate::policy::VerificationPolicy::default();
3450 policy
3451 .key_trust
3452 .allowed_legacy_signature_algorithms
3453 .insert(SignatureAlgorithm::DsaSha1);
3454 policy.key_trust.dsa_keys.minimum_modulus_bits = 1024;
3455 policy.key_trust.mode = crate::policy::VerificationTrustMode::CryptographicOnly;
3456 let result = VerifyContext::new()
3457 .policy(policy)
3458 .provider(&provider)
3459 .key_resolver(&DefaultKeyResolver::default())
3460 .verify(&malformed)
3461 .expect("malformed framing must be a verification miss");
3462
3463 assert_eq!(
3464 result.status,
3465 DsigStatus::Invalid(FailureReason::SignatureMismatch)
3466 );
3467 }
3468
3469 #[cfg(feature = "xmldsig")]
3470 #[test]
3471 fn rustcrypto_provider_verifies_parameterized_rsa_pss_certificates() {
3472 use crate::rsa_encoding::RsaPublicKeyEncoding as _;
3473 use der::{Decode as _, Encode as _};
3474 use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng};
3475 use rsa::{RsaPrivateKey, pss::SigningKey as RsaPssSigningKey};
3476 use sha2::Sha256;
3477 use signature::{RandomizedSigner, SignatureEncoding};
3478 use x509_cert::spki::{AlgorithmIdentifierOwned, ObjectIdentifier};
3479
3480 let mut rng = ChaCha20Rng::from_seed([0x5a; 32]);
3483 let private_key =
3484 RsaPrivateKey::new(&mut rng, 2048).expect("deterministic RSA key generation");
3485 let public_key = private_key
3486 .to_public_key()
3487 .to_public_key_der()
3488 .expect("RSA public key must encode as SPKI");
3489 let signing_key = RsaPssSigningKey::<Sha256>::new_with_salt_len(private_key, 32);
3490 let signed_data = b"certificate tbs bytes";
3491 let signature = signing_key
3492 .try_sign_with_rng(&mut rng, signed_data)
3493 .expect("RSA-PSS signing must succeed")
3494 .to_vec();
3495
3496 assert!(
3497 RUST_CRYPTO_PROVIDER
3498 .verify_x509_signature(
3499 X509SignatureAlgorithm::RsaPss {
3500 digest: DigestAlgorithm::Sha256,
3501 mgf_digest: DigestAlgorithm::Sha256,
3502 salt_len: 32,
3503 },
3504 signed_data,
3505 &signature,
3506 public_key.as_bytes(),
3507 )
3508 .expect("standard RSA-PSS parameters must be supported")
3509 );
3510
3511 let mut parameterless_pss_spki =
3512 x509_cert::SubjectPublicKeyInfo::from_der(public_key.as_bytes())
3513 .expect("RSA SPKI must decode");
3514 parameterless_pss_spki.algorithm = AlgorithmIdentifierOwned {
3515 oid: ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10"),
3516 parameters: None,
3517 };
3518 let parameterless_pss_spki = parameterless_pss_spki
3519 .to_der()
3520 .expect("parameterless PSS SPKI must encode");
3521 assert!(
3522 RUST_CRYPTO_PROVIDER
3523 .verify_x509_signature(
3524 X509SignatureAlgorithm::RsaPss {
3525 digest: DigestAlgorithm::Sha256,
3526 mgf_digest: DigestAlgorithm::Sha256,
3527 salt_len: 32,
3528 },
3529 signed_data,
3530 &signature,
3531 ¶meterless_pss_spki,
3532 )
3533 .expect("parameterless PSS keys impose no signature restrictions")
3534 );
3535
3536 let mut pss_spki = x509_cert::SubjectPublicKeyInfo::from_der(public_key.as_bytes())
3537 .expect("RSA SPKI must decode");
3538 let pss_parameters = der::asn1::Any::from_der(&[
3539 0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
3540 0x04, 0x02, 0x01, 0x05, 0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48,
3541 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
3542 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x20,
3543 ])
3544 .expect("standard SHA-256 PSS parameters must decode");
3545 pss_spki.algorithm = AlgorithmIdentifierOwned {
3546 oid: ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10"),
3547 parameters: Some(pss_parameters),
3548 };
3549 let pss_spki = pss_spki.to_der().expect("PSS SPKI must encode");
3550
3551 assert!(
3552 RUST_CRYPTO_PROVIDER
3553 .verify_x509_signature(
3554 X509SignatureAlgorithm::RsaPss {
3555 digest: DigestAlgorithm::Sha256,
3556 mgf_digest: DigestAlgorithm::Sha256,
3557 salt_len: 32,
3558 },
3559 signed_data,
3560 &signature,
3561 &pss_spki,
3562 )
3563 .expect("RFC 4055 PSS SubjectPublicKeyInfo must be supported")
3564 );
3565
3566 for incompatible in [
3567 X509SignatureAlgorithm::RsaPss {
3568 digest: DigestAlgorithm::Sha384,
3569 mgf_digest: DigestAlgorithm::Sha256,
3570 salt_len: 32,
3571 },
3572 X509SignatureAlgorithm::RsaPss {
3573 digest: DigestAlgorithm::Sha256,
3574 mgf_digest: DigestAlgorithm::Sha384,
3575 salt_len: 32,
3576 },
3577 X509SignatureAlgorithm::RsaPss {
3578 digest: DigestAlgorithm::Sha256,
3579 mgf_digest: DigestAlgorithm::Sha256,
3580 salt_len: 16,
3581 },
3582 ] {
3583 assert!(
3584 !RUST_CRYPTO_PROVIDER
3585 .verify_x509_signature(incompatible, signed_data, &signature, &pss_spki,)
3586 .expect("incompatible PSS key restrictions are invalid, not unsupported")
3587 );
3588 }
3589 }
3590
3591 #[cfg(feature = "xmldsig")]
3592 #[test]
3593 fn rustcrypto_provider_verifies_dsa_certificate_signature_at_q_width() {
3594 use base64::Engine as _;
3595
3596 let spki = base64::engine::general_purpose::STANDARD
3599 .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=")
3600 .expect("DSA SPKI fixture must decode");
3601 let signature = base64::engine::general_purpose::STANDARD
3602 .decode("MD0CHQChtB1c+f5BmTJCtT7Gi4cyQiR2igj0znRQYCJ3Ahw4NGg4pL5jgA8Ri07ESV9Yr90WfUmRrbRcnjsY")
3603 .expect("DSA signature fixture must decode");
3604 let message = b"certificate tbs bytes for dsa q-width regression";
3605
3606 assert!(
3607 rustcrypto_x509::verify_signature(
3608 X509SignatureAlgorithm::Dsa(DigestAlgorithm::Sha1),
3609 message,
3610 &signature,
3611 &spki,
3612 )
3613 .expect("supported DSA-SHA1 certificate signature")
3614 );
3615
3616 let mut tampered = signature;
3617 *tampered.last_mut().expect("DER signature is non-empty") ^= 1;
3618 assert!(
3619 !rustcrypto_x509::verify_signature(
3620 X509SignatureAlgorithm::Dsa(DigestAlgorithm::Sha1),
3621 message,
3622 &tampered,
3623 &spki,
3624 )
3625 .expect("tampered DSA-SHA1 certificate signature is a verification miss")
3626 );
3627 }
3628
3629 #[cfg(feature = "xmldsig")]
3630 #[test]
3631 fn primitive_provider_does_not_embed_rsa_strength_policy() {
3632 use crate::rsa_encoding::RsaPublicKeyEncoding as _;
3633 use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng};
3634 use rsa::{RsaPrivateKey, pss::SigningKey as RsaPssSigningKey};
3635 use sha2::Sha256;
3636 use signature::{RandomizedSigner, SignatureEncoding};
3637
3638 let mut rng = ChaCha20Rng::from_seed([0x3c; 32]);
3639 let private_key =
3640 RsaPrivateKey::new(&mut rng, 1024).expect("deterministic weak RSA key generation");
3641 let public_key = private_key
3642 .to_public_key()
3643 .to_public_key_der()
3644 .expect("weak RSA public key must encode as SPKI");
3645 let signed_data = b"certificate tbs bytes";
3646 let signature = RsaPssSigningKey::<Sha256>::new_with_salt_len(private_key, 32)
3647 .try_sign_with_rng(&mut rng, signed_data)
3648 .expect("weak RSA-PSS key can still produce a cryptographic signature")
3649 .to_vec();
3650
3651 assert!(
3652 RUST_CRYPTO_PROVIDER
3653 .verify_x509_signature(
3654 X509SignatureAlgorithm::RsaPss {
3655 digest: DigestAlgorithm::Sha256,
3656 mgf_digest: DigestAlgorithm::Sha256,
3657 salt_len: 32,
3658 },
3659 signed_data,
3660 &signature,
3661 public_key.as_bytes(),
3662 )
3663 .expect(
3664 "provider must evaluate structurally valid RSA-PSS independently of policy"
3665 )
3666 );
3667 }
3668
3669 #[cfg(feature = "xmldsig")]
3670 #[test]
3671 fn oversized_rsa_pss_salt_is_a_verification_miss() {
3672 use crate::rsa_encoding::RsaPublicKeyEncoding as _;
3673 use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng};
3674 use rsa::{RsaPrivateKey, traits::PublicKeyParts as _};
3675
3676 let mut rng = ChaCha20Rng::from_seed([0x55; 32]);
3679 let public_key = RsaPrivateKey::new(&mut rng, 1024)
3680 .expect("deterministic RSA key generation")
3681 .to_public_key();
3682 let spki = public_key
3683 .to_public_key_der()
3684 .expect("RSA public key must encode as SPKI");
3685
3686 assert!(rustcrypto_x509::rsa_pss_salt_fits_key(
3687 &public_key,
3688 DigestAlgorithm::Sha256,
3689 0,
3690 ));
3691 assert!(rustcrypto_x509::rsa_pss_salt_fits_key(
3692 &public_key,
3693 DigestAlgorithm::Sha256,
3694 94,
3695 ));
3696 assert!(!rustcrypto_x509::rsa_pss_salt_fits_key(
3697 &public_key,
3698 DigestAlgorithm::Sha256,
3699 95,
3700 ));
3701
3702 assert!(
3703 !RUST_CRYPTO_PROVIDER
3704 .verify_x509_signature(
3705 X509SignatureAlgorithm::RsaPss {
3706 digest: DigestAlgorithm::Sha256,
3707 mgf_digest: DigestAlgorithm::Sha256,
3708 salt_len: usize::MAX,
3709 },
3710 b"certificate tbs bytes",
3711 &vec![0_u8; public_key.size()],
3712 spki.as_bytes(),
3713 )
3714 .expect("oversized PSS salt must fail without panicking")
3715 );
3716 }
3717}