1#[cfg(feature = "aws-lc-fips")]
9mod aws_lc;
10#[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
11mod rsa_pkcs1v15;
12
13#[cfg(feature = "xmlenc")]
16pub struct RecoveredContentKey {
17 bytes: zeroize::Zeroizing<Vec<u8>>,
18 valid: subtle::Choice,
19}
20
21#[cfg(feature = "xmlenc")]
22impl std::fmt::Debug for RecoveredContentKey {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 f.debug_struct("RecoveredContentKey")
25 .finish_non_exhaustive()
26 }
27}
28
29#[cfg(feature = "xmlenc")]
30impl RecoveredContentKey {
31 pub fn confirmed(bytes: Vec<u8>) -> Self {
34 Self {
35 bytes: zeroize::Zeroizing::new(bytes),
36 valid: subtle::Choice::from(1),
37 }
38 }
39
40 #[cfg(feature = "legacy-algorithms")]
41 pub fn recovery(bytes: zeroize::Zeroizing<Vec<u8>>, valid: subtle::Choice) -> Self {
46 Self { bytes, valid }
47 }
48
49 pub(crate) fn bytes(&self) -> &[u8] {
50 &self.bytes
51 }
52 pub(crate) fn valid(&self) -> bool {
53 bool::from(self.valid)
54 }
55 pub fn into_key(mut self) -> Result<Vec<u8>, ProviderError> {
58 if !self.valid() {
59 return Err(ProviderError::AuthenticationFailed);
60 }
61 Ok(core::mem::take(&mut *self.bytes))
62 }
63}
64#[cfg(all(feature = "aws-lc-fips", feature = "xmlenc"))]
65pub use aws_lc::AwsLcRsaPrivateKey;
66#[cfg(feature = "aws-lc-fips")]
67pub use aws_lc::{AwsLcFipsProvider, AwsLcSigningKey};
68
69#[cfg(feature = "xmlenc")]
70use std::borrow::Cow;
71
72#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
73use getrandom::rand_core::TryCryptoRng;
74use getrandom::{SysRng, rand_core::TryRng};
75
76#[cfg(feature = "xmldsig")]
77use crate::xmldsig::DigestAlgorithm;
78#[cfg(feature = "xmlenc")]
79use crate::xmlenc::{DataEncryptionAlgorithm, KeyWrapAlgorithm, RsaOaepParameters};
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
83#[non_exhaustive]
84pub enum ProviderOperation {
85 Digest,
87 Sign,
89 Verify,
91 VerifyCertificate,
93 Encrypt,
95 Decrypt,
97 KeyWrap,
99 KeyUnwrap,
101 KeyTransport,
103 KeyRecovery,
105 KeyAgreement,
107 Kdf,
109 Random,
111}
112
113#[derive(Debug, Clone, Copy)]
118#[non_exhaustive]
119pub enum ProviderCapability<'a> {
120 #[cfg(feature = "xmldsig")]
122 Digest(DigestAlgorithm),
123 #[cfg(feature = "xmldsig")]
128 Sign(crate::xmldsig::SignatureAlgorithm),
129 #[cfg(feature = "xmldsig")]
134 Verify(crate::xmldsig::SignatureAlgorithm),
135 #[cfg(feature = "xmldsig")]
137 VerifyCertificate(X509SignatureAlgorithm),
138 #[cfg(feature = "xmlenc")]
140 Encrypt(DataEncryptionAlgorithm),
141 #[cfg(feature = "xmlenc")]
143 Decrypt(DataEncryptionAlgorithm),
144 #[cfg(feature = "xmlenc")]
146 KeyWrap(KeyWrapAlgorithm),
147 #[cfg(feature = "xmlenc")]
149 KeyUnwrap(KeyWrapAlgorithm),
150 #[cfg(feature = "xmlenc")]
152 KeyTransport(&'a RsaOaepParameters),
153 #[cfg(feature = "xmlenc")]
155 KeyRecovery(&'a RsaOaepParameters),
156 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
158 Pkcs1v15Transport,
159 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
161 Pkcs1v15Recovery,
162 KeyAgreement(&'a KeyAgreementParameters<'a>),
164 Kdf(&'a KdfParameters<'a>),
166 Random,
168}
169
170impl ProviderCapability<'_> {
171 #[must_use]
173 pub const fn operation(&self) -> ProviderOperation {
174 match self {
175 #[cfg(feature = "xmldsig")]
176 Self::Digest(_) => ProviderOperation::Digest,
177 #[cfg(feature = "xmldsig")]
178 Self::Sign(_) => ProviderOperation::Sign,
179 #[cfg(feature = "xmldsig")]
180 Self::Verify(_) => ProviderOperation::Verify,
181 #[cfg(feature = "xmldsig")]
182 Self::VerifyCertificate(_) => ProviderOperation::VerifyCertificate,
183 #[cfg(feature = "xmlenc")]
184 Self::Encrypt(_) => ProviderOperation::Encrypt,
185 #[cfg(feature = "xmlenc")]
186 Self::Decrypt(_) => ProviderOperation::Decrypt,
187 #[cfg(feature = "xmlenc")]
188 Self::KeyWrap(_) => ProviderOperation::KeyWrap,
189 #[cfg(feature = "xmlenc")]
190 Self::KeyUnwrap(_) => ProviderOperation::KeyUnwrap,
191 #[cfg(feature = "xmlenc")]
192 Self::KeyTransport(_) => ProviderOperation::KeyTransport,
193 #[cfg(feature = "xmlenc")]
194 Self::KeyRecovery(_) => ProviderOperation::KeyRecovery,
195 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
196 Self::Pkcs1v15Transport => ProviderOperation::KeyTransport,
197 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
198 Self::Pkcs1v15Recovery => ProviderOperation::KeyRecovery,
199 Self::KeyAgreement(_) => ProviderOperation::KeyAgreement,
200 Self::Kdf(_) => ProviderOperation::Kdf,
201 Self::Random => ProviderOperation::Random,
202 }
203 }
204
205 #[must_use]
207 pub fn algorithm(&self) -> Option<&str> {
208 match self {
209 #[cfg(feature = "xmldsig")]
210 Self::Digest(algorithm) => Some(algorithm.uri()),
211 #[cfg(feature = "xmldsig")]
212 Self::Sign(algorithm) | Self::Verify(algorithm) => Some(algorithm.uri()),
213 #[cfg(feature = "xmldsig")]
214 Self::VerifyCertificate(algorithm) => algorithm.oid(),
215 #[cfg(feature = "xmlenc")]
216 Self::Encrypt(algorithm) | Self::Decrypt(algorithm) => Some(algorithm.uri()),
217 #[cfg(feature = "xmlenc")]
218 Self::KeyWrap(algorithm) | Self::KeyUnwrap(algorithm) => Some(algorithm.uri()),
219 #[cfg(feature = "xmlenc")]
220 Self::KeyTransport(parameters) | Self::KeyRecovery(parameters) => {
221 Some(parameters.algorithm.uri())
222 }
223 Self::KeyAgreement(parameters) => Some(parameters.algorithm),
224 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
225 Self::Pkcs1v15Transport | Self::Pkcs1v15Recovery => {
226 Some(crate::xmlenc::KeyTransportAlgorithm::RsaPkcs1v15.uri())
227 }
228 Self::Kdf(parameters) => Some(parameters.algorithm),
229 Self::Random => None,
230 }
231 }
232}
233
234#[derive(Debug, Clone, Copy, PartialEq, Eq)]
236pub struct KeyAgreementParameters<'a> {
237 pub algorithm: &'a str,
239 pub peer_public_key: &'a [u8],
241}
242
243#[derive(Debug, Clone, Copy, PartialEq, Eq)]
245pub struct KdfParameters<'a> {
246 pub algorithm: &'a str,
248 pub digest: Option<&'a str>,
250 pub salt: &'a [u8],
252 pub info: &'a [u8],
254 pub iterations: u64,
256 pub output_len: usize,
258}
259
260#[cfg(feature = "xmldsig")]
262#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
263#[non_exhaustive]
264pub enum X509SignatureAlgorithm {
265 Dsa(DigestAlgorithm),
267 RsaPkcs1v15(DigestAlgorithm),
269 RsaPss {
271 digest: DigestAlgorithm,
273 mgf_digest: DigestAlgorithm,
275 salt_len: usize,
277 },
278 Ecdsa(DigestAlgorithm),
280 Ed25519,
282 Ed448,
284 PostQuantum(crate::xmldsig::PqAlgorithm),
286}
287
288#[cfg(feature = "xmldsig")]
289impl X509SignatureAlgorithm {
290 #[must_use]
292 pub const fn oid(self) -> Option<&'static str> {
293 Some(match self {
294 #[cfg(feature = "legacy-algorithms")]
295 Self::Dsa(DigestAlgorithm::Md5 | DigestAlgorithm::Ripemd160)
296 | Self::RsaPkcs1v15(DigestAlgorithm::Md5 | DigestAlgorithm::Ripemd160)
297 | Self::Ecdsa(DigestAlgorithm::Md5 | DigestAlgorithm::Ripemd160) => return None,
298 Self::Dsa(DigestAlgorithm::Sha1) => "1.2.840.10040.4.3",
299 Self::Dsa(DigestAlgorithm::Sha224) => "2.16.840.1.101.3.4.3.1",
300 Self::Dsa(DigestAlgorithm::Sha256) => "2.16.840.1.101.3.4.3.2",
301 Self::Dsa(DigestAlgorithm::Sha384) => "2.16.840.1.101.3.4.3.3",
302 Self::Dsa(DigestAlgorithm::Sha512) => "2.16.840.1.101.3.4.3.4",
303 Self::Dsa(DigestAlgorithm::Sha3_224) => "2.16.840.1.101.3.4.3.5",
304 Self::Dsa(DigestAlgorithm::Sha3_256) => "2.16.840.1.101.3.4.3.6",
305 Self::Dsa(DigestAlgorithm::Sha3_384) => "2.16.840.1.101.3.4.3.7",
306 Self::Dsa(DigestAlgorithm::Sha3_512) => "2.16.840.1.101.3.4.3.8",
307 Self::RsaPkcs1v15(DigestAlgorithm::Sha1) => "1.2.840.113549.1.1.5",
308 Self::RsaPkcs1v15(DigestAlgorithm::Sha224) => "1.2.840.113549.1.1.14",
309 Self::RsaPkcs1v15(DigestAlgorithm::Sha256) => "1.2.840.113549.1.1.11",
310 Self::RsaPkcs1v15(DigestAlgorithm::Sha384) => "1.2.840.113549.1.1.12",
311 Self::RsaPkcs1v15(DigestAlgorithm::Sha512) => "1.2.840.113549.1.1.13",
312 Self::RsaPkcs1v15(DigestAlgorithm::Sha3_224) => "2.16.840.1.101.3.4.3.13",
313 Self::RsaPkcs1v15(DigestAlgorithm::Sha3_256) => "2.16.840.1.101.3.4.3.14",
314 Self::RsaPkcs1v15(DigestAlgorithm::Sha3_384) => "2.16.840.1.101.3.4.3.15",
315 Self::RsaPkcs1v15(DigestAlgorithm::Sha3_512) => "2.16.840.1.101.3.4.3.16",
316 Self::RsaPss { .. } => "1.2.840.113549.1.1.10",
317 Self::Ecdsa(DigestAlgorithm::Sha1) => "1.2.840.10045.4.1",
318 Self::Ecdsa(DigestAlgorithm::Sha224) => "1.2.840.10045.4.3.1",
319 Self::Ecdsa(DigestAlgorithm::Sha256) => "1.2.840.10045.4.3.2",
320 Self::Ecdsa(DigestAlgorithm::Sha384) => "1.2.840.10045.4.3.3",
321 Self::Ecdsa(DigestAlgorithm::Sha512) => "1.2.840.10045.4.3.4",
322 Self::Ecdsa(DigestAlgorithm::Sha3_224) => "2.16.840.1.101.3.4.3.9",
323 Self::Ecdsa(DigestAlgorithm::Sha3_256) => "2.16.840.1.101.3.4.3.10",
324 Self::Ecdsa(DigestAlgorithm::Sha3_384) => "2.16.840.1.101.3.4.3.11",
325 Self::Ecdsa(DigestAlgorithm::Sha3_512) => "2.16.840.1.101.3.4.3.12",
326 Self::Ed25519 => "1.3.101.112",
327 Self::Ed448 => "1.3.101.113",
328 Self::PostQuantum(algorithm) => algorithm.oid(),
329 })
330 }
331}
332
333#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
335#[non_exhaustive]
336pub enum ProviderInputError {
337 #[error("failed to initialize {0}")]
339 PrimitiveInitialization(&'static str),
340 #[error("invalid AES-CBC framing")]
342 AesCbcFraming,
343 #[error("invalid AES-CBC ciphertext")]
345 AesCbcCiphertext,
346 #[error("invalid AES-GCM framing")]
348 AesGcmFraming,
349 #[error("invalid AES key-wrap framing")]
351 AesKeyWrapFraming,
352 #[deprecated(note = "explicit MGF parameters are supported for both RSA-OAEP URIs")]
357 #[error("legacy RSA-OAEP requires MGF1-SHA1")]
358 LegacyRsaOaepMgf,
359}
360
361#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
363#[non_exhaustive]
364pub enum ProviderError {
365 #[error("provider does not support {operation:?} with algorithm {algorithm:?}")]
367 Unsupported {
368 operation: ProviderOperation,
370 algorithm: Option<String>,
372 },
373 #[error("invalid key size: expected {expected} bytes, got {actual}")]
375 InvalidKeySize {
376 expected: usize,
378 actual: usize,
380 },
381 #[error(
384 "invalid provider output size for {operation:?}: expected {expected} bytes, got {actual}"
385 )]
386 InvalidOutputSize {
387 operation: ProviderOperation,
389 expected: usize,
391 actual: usize,
393 },
394 #[error(
397 "invalid provider output size for {operation:?}: expected {minimum}..={maximum} bytes, got {actual}"
398 )]
399 InvalidOutputSizeRange {
400 operation: ProviderOperation,
402 minimum: usize,
404 maximum: usize,
406 actual: usize,
408 },
409 #[error("invalid cryptographic input: {0}")]
411 InvalidInput(ProviderInputError),
412 #[error("cryptographic authentication failed")]
414 AuthenticationFailed,
415 #[error("operating-system random number generation failed: {0}")]
417 Random(String),
418}
419
420#[cfg(feature = "xmlenc")]
426pub trait KeyTransportKey: Send + Sync {
427 #[cfg(feature = "legacy-algorithms")]
429 fn transport_pkcs1v15(
430 &self,
431 _provider: &dyn CryptoProvider,
432 _plaintext: &[u8],
433 ) -> Result<Vec<u8>, ProviderError> {
434 Err(ProviderError::Unsupported {
435 operation: ProviderOperation::KeyTransport,
436 algorithm: Some(
437 crate::xmlenc::KeyTransportAlgorithm::RsaPkcs1v15
438 .uri()
439 .into(),
440 ),
441 })
442 }
443 fn rsa_modulus(&self) -> Cow<'_, [u8]>;
449
450 fn rsa_exponent(&self) -> Cow<'_, [u8]>;
452
453 fn transport_with_provider(
455 &self,
456 provider: &dyn CryptoProvider,
457 parameters: &RsaOaepParameters,
458 plaintext: &[u8],
459 ) -> Result<Vec<u8>, ProviderError>;
460}
461
462#[cfg(feature = "xmlenc")]
467pub trait KeyRecoveryKey: Send + Sync {
468 #[cfg(feature = "legacy-algorithms")]
470 fn recover_pkcs1v15(
471 &self,
472 _provider: &dyn CryptoProvider,
473 _ciphertext: &[u8],
474 _key_len: usize,
475 ) -> Result<RecoveredContentKey, ProviderError> {
476 Err(ProviderError::Unsupported {
477 operation: ProviderOperation::KeyRecovery,
478 algorithm: Some(
479 crate::xmlenc::KeyTransportAlgorithm::RsaPkcs1v15
480 .uri()
481 .into(),
482 ),
483 })
484 }
485 fn provider_name(&self) -> Option<&'static str> {
487 None
488 }
489 fn public_spki(&self) -> Option<&[u8]> {
491 None
492 }
493 fn rsa_modulus_bits(&self) -> usize;
496
497 fn rsa_public_exponent(&self) -> Option<u64>;
500
501 fn ciphertext_len(&self) -> usize;
504
505 fn recover_with_provider(
507 &self,
508 provider: &dyn CryptoProvider,
509 parameters: &RsaOaepParameters,
510 ciphertext: &[u8],
511 ) -> Result<Vec<u8>, ProviderError>;
512}
513
514pub trait KeyAgreementKey: Send + Sync {
516 fn agree(&self, parameters: &KeyAgreementParameters<'_>) -> Result<Vec<u8>, ProviderError>;
518}
519
520pub trait CryptoProvider: Send + Sync {
522 fn name(&self) -> &'static str;
524
525 #[cfg(feature = "xmldsig")]
528 fn import_signing_key(
529 &self,
530 algorithm: crate::xmldsig::SignatureAlgorithm,
531 _pkcs8: &[u8],
532 ) -> Result<Box<dyn crate::xmldsig::SigningKey>, crate::xmldsig::SigningKeyError> {
533 Err(ProviderError::Unsupported {
534 operation: ProviderOperation::Sign,
535 algorithm: Some(algorithm.uri().into()),
536 }
537 .into())
538 }
539
540 #[cfg(feature = "xmlenc")]
542 fn import_recovery_key(
543 &self,
544 _pkcs8: &[u8],
545 ) -> Result<std::sync::Arc<dyn KeyRecoveryKey>, ProviderError> {
546 Err(ProviderError::Unsupported {
547 operation: ProviderOperation::KeyRecovery,
548 algorithm: None,
549 })
550 }
551
552 fn supports(&self, capability: ProviderCapability<'_>) -> bool;
558
559 fn fill_random(&self, output: &mut [u8]) -> Result<(), ProviderError>;
561
562 #[cfg(feature = "xmldsig")]
564 fn digest(&self, algorithm: DigestAlgorithm, data: &[u8]) -> Result<Vec<u8>, ProviderError>;
565
566 #[cfg(feature = "xmldsig")]
572 fn sign(
573 &self,
574 key: &dyn crate::xmldsig::SigningKey,
575 algorithm: crate::xmldsig::SignatureAlgorithm,
576 data: &[u8],
577 ) -> Result<Vec<u8>, crate::xmldsig::SigningKeyError>;
578
579 #[cfg(feature = "xmldsig")]
584 fn verify(
585 &self,
586 key: &dyn crate::xmldsig::VerifyingKey,
587 algorithm: crate::xmldsig::SignatureAlgorithm,
588 data: &[u8],
589 signature: &[u8],
590 ) -> Result<bool, crate::xmldsig::DsigError>;
591
592 #[cfg(feature = "xmldsig")]
594 fn sign_with_context(
595 &self,
596 key: &dyn crate::xmldsig::SigningKey,
597 algorithm: crate::xmldsig::SignatureAlgorithm,
598 context: &crate::xmldsig::SignatureContext,
599 data: &[u8],
600 ) -> Result<Vec<u8>, crate::xmldsig::SigningKeyError> {
601 if !context.as_bytes().is_empty() {
602 return Err(crate::xmldsig::SigningKeyError::UnsupportedAlgorithm {
603 uri: algorithm.uri().to_owned(),
604 });
605 }
606 self.sign(key, algorithm, data)
607 }
608
609 #[cfg(feature = "xmldsig")]
611 fn verify_with_context(
612 &self,
613 key: &dyn crate::xmldsig::VerifyingKey,
614 algorithm: crate::xmldsig::SignatureAlgorithm,
615 context: &crate::xmldsig::SignatureContext,
616 data: &[u8],
617 signature: &[u8],
618 ) -> Result<bool, crate::xmldsig::DsigError> {
619 if !context.as_bytes().is_empty() {
620 return Err(
621 crate::xmldsig::SignatureVerificationError::UnsupportedAlgorithm {
622 uri: algorithm.uri().to_owned(),
623 }
624 .into(),
625 );
626 }
627 self.verify(key, algorithm, data, signature)
628 }
629
630 #[cfg(feature = "xmldsig")]
632 fn verify_x509_signature(
633 &self,
634 algorithm: X509SignatureAlgorithm,
635 signed_data: &[u8],
636 signature: &[u8],
637 issuer_spki_der: &[u8],
638 ) -> Result<bool, ProviderError> {
639 let _ = (signed_data, signature, issuer_spki_der);
640 Err(ProviderError::Unsupported {
641 operation: ProviderOperation::VerifyCertificate,
642 algorithm: algorithm.oid().map(str::to_owned),
643 })
644 }
645
646 #[cfg(feature = "xmlenc")]
648 fn encrypt_data(
649 &self,
650 algorithm: DataEncryptionAlgorithm,
651 key: &[u8],
652 plaintext: &[u8],
653 ) -> Result<Vec<u8>, ProviderError>;
654
655 #[cfg(feature = "xmlenc")]
657 fn decrypt_data(
658 &self,
659 algorithm: DataEncryptionAlgorithm,
660 key: &[u8],
661 ciphertext: &[u8],
662 ) -> Result<Vec<u8>, ProviderError>;
663
664 #[cfg(feature = "xmlenc")]
670 fn wrap_key(
671 &self,
672 algorithm: KeyWrapAlgorithm,
673 kek: &[u8],
674 key: &[u8],
675 ) -> Result<Vec<u8>, ProviderError>;
676
677 #[cfg(feature = "xmlenc")]
679 fn unwrap_key(
680 &self,
681 algorithm: KeyWrapAlgorithm,
682 kek: &[u8],
683 wrapped: &[u8],
684 ) -> Result<Vec<u8>, ProviderError>;
685
686 #[cfg(feature = "xmlenc")]
688 fn transport_key(
689 &self,
690 key: &dyn KeyTransportKey,
691 parameters: &RsaOaepParameters,
692 plaintext: &[u8],
693 ) -> Result<Vec<u8>, ProviderError>;
694
695 #[cfg(feature = "xmlenc")]
697 fn recover_key(
698 &self,
699 key: &dyn KeyRecoveryKey,
700 parameters: &RsaOaepParameters,
701 ciphertext: &[u8],
702 ) -> Result<Vec<u8>, ProviderError>;
703
704 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
706 fn transport_pkcs1v15(
707 &self,
708 _key: &dyn KeyTransportKey,
709 _plaintext: &[u8],
710 ) -> Result<Vec<u8>, ProviderError> {
711 Err(ProviderError::Unsupported {
712 operation: ProviderOperation::KeyTransport,
713 algorithm: Some(
714 crate::xmlenc::KeyTransportAlgorithm::RsaPkcs1v15
715 .uri()
716 .into(),
717 ),
718 })
719 }
720
721 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
723 fn recover_pkcs1v15(
724 &self,
725 _key: &dyn KeyRecoveryKey,
726 _ciphertext: &[u8],
727 _key_len: usize,
728 ) -> Result<RecoveredContentKey, ProviderError> {
729 Err(ProviderError::Unsupported {
730 operation: ProviderOperation::KeyRecovery,
731 algorithm: Some(
732 crate::xmlenc::KeyTransportAlgorithm::RsaPkcs1v15
733 .uri()
734 .into(),
735 ),
736 })
737 }
738
739 fn agree_key(
741 &self,
742 key: &dyn KeyAgreementKey,
743 parameters: &KeyAgreementParameters<'_>,
744 ) -> Result<Vec<u8>, ProviderError> {
745 self.require_capability(ProviderCapability::KeyAgreement(parameters))?;
746 key.agree(parameters)
747 }
748
749 fn derive_key(
755 &self,
756 parameters: &KdfParameters<'_>,
757 secret: &[u8],
758 ) -> Result<Vec<u8>, ProviderError>;
759
760 fn require_capability(&self, capability: ProviderCapability<'_>) -> Result<(), ProviderError> {
762 if self.supports(capability) {
763 Ok(())
764 } else {
765 Err(ProviderError::Unsupported {
766 operation: capability.operation(),
767 algorithm: capability.algorithm().map(str::to_owned),
768 })
769 }
770 }
771}
772
773#[derive(Debug, Clone, Copy, Default)]
775pub struct RustCryptoProvider;
776
777#[cfg(feature = "xmlenc")]
779#[derive(Clone)]
780pub struct RustCryptoRsaPublicKey {
781 key: rsa::RsaPublicKey,
782 modulus: Vec<u8>,
783 exponent: Vec<u8>,
784}
785
786#[cfg(feature = "xmlenc")]
787impl RustCryptoRsaPublicKey {
788 #[must_use]
790 pub fn new(key: rsa::RsaPublicKey) -> Self {
791 use rsa::traits::PublicKeyParts as _;
792 let modulus = key.n().to_be_bytes_trimmed_vartime().into_vec();
793 let exponent = key.e().to_be_bytes_trimmed_vartime().into_vec();
794 Self {
795 key,
796 modulus,
797 exponent,
798 }
799 }
800}
801
802#[cfg(feature = "xmlenc")]
803impl From<rsa::RsaPublicKey> for RustCryptoRsaPublicKey {
804 fn from(key: rsa::RsaPublicKey) -> Self {
805 Self::new(key)
806 }
807}
808
809#[cfg(feature = "xmlenc")]
810impl KeyTransportKey for RustCryptoRsaPublicKey {
811 #[cfg(feature = "legacy-algorithms")]
812 fn transport_pkcs1v15(
813 &self,
814 provider: &dyn CryptoProvider,
815 plaintext: &[u8],
816 ) -> Result<Vec<u8>, ProviderError> {
817 rustcrypto::transport_pkcs1v15(provider, &self.key, plaintext)
818 }
819 fn rsa_modulus(&self) -> Cow<'_, [u8]> {
820 Cow::Borrowed(&self.modulus)
821 }
822
823 fn rsa_exponent(&self) -> Cow<'_, [u8]> {
824 Cow::Borrowed(&self.exponent)
825 }
826
827 fn transport_with_provider(
828 &self,
829 provider: &dyn CryptoProvider,
830 parameters: &RsaOaepParameters,
831 plaintext: &[u8],
832 ) -> Result<Vec<u8>, ProviderError> {
833 rustcrypto::transport_key(provider, &self.key, parameters, plaintext)
834 }
835}
836
837#[cfg(feature = "xmlenc")]
838impl KeyTransportKey for rsa::RsaPublicKey {
839 #[cfg(feature = "legacy-algorithms")]
840 fn transport_pkcs1v15(
841 &self,
842 provider: &dyn CryptoProvider,
843 plaintext: &[u8],
844 ) -> Result<Vec<u8>, ProviderError> {
845 rustcrypto::transport_pkcs1v15(provider, self, plaintext)
846 }
847 fn rsa_modulus(&self) -> Cow<'_, [u8]> {
848 use rsa::traits::PublicKeyParts as _;
849 Cow::Owned(self.n().to_be_bytes_trimmed_vartime().into_vec())
850 }
851
852 fn rsa_exponent(&self) -> Cow<'_, [u8]> {
853 use rsa::traits::PublicKeyParts as _;
854 Cow::Owned(self.e().to_be_bytes_trimmed_vartime().into_vec())
855 }
856
857 fn transport_with_provider(
858 &self,
859 provider: &dyn CryptoProvider,
860 parameters: &RsaOaepParameters,
861 plaintext: &[u8],
862 ) -> Result<Vec<u8>, ProviderError> {
863 rustcrypto::transport_key(provider, self, parameters, plaintext)
864 }
865}
866
867#[cfg(feature = "xmlenc")]
869#[derive(Clone)]
870pub struct RustCryptoRsaPrivateKey {
871 key: rsa::RsaPrivateKey,
872 ciphertext_len: usize,
873}
874
875#[cfg(feature = "xmlenc")]
876impl RustCryptoRsaPrivateKey {
877 #[must_use]
879 pub fn new(key: rsa::RsaPrivateKey) -> Self {
880 use rsa::traits::PublicKeyParts as _;
881 let ciphertext_len = key.size();
882 Self {
883 key,
884 ciphertext_len,
885 }
886 }
887}
888
889#[cfg(feature = "xmlenc")]
890impl From<rsa::RsaPrivateKey> for RustCryptoRsaPrivateKey {
891 fn from(key: rsa::RsaPrivateKey) -> Self {
892 Self::new(key)
893 }
894}
895
896#[cfg(feature = "xmlenc")]
897impl KeyRecoveryKey for RustCryptoRsaPrivateKey {
898 #[cfg(feature = "legacy-algorithms")]
899 fn recover_pkcs1v15(
900 &self,
901 provider: &dyn CryptoProvider,
902 ciphertext: &[u8],
903 key_len: usize,
904 ) -> Result<RecoveredContentKey, ProviderError> {
905 rsa_pkcs1v15::recover(provider, &self.key, ciphertext, key_len)
906 }
907 fn rsa_modulus_bits(&self) -> usize {
908 KeyRecoveryKey::rsa_modulus_bits(&self.key)
909 }
910 fn rsa_public_exponent(&self) -> Option<u64> {
911 KeyRecoveryKey::rsa_public_exponent(&self.key)
912 }
913 fn ciphertext_len(&self) -> usize {
914 self.ciphertext_len
915 }
916
917 fn recover_with_provider(
918 &self,
919 provider: &dyn CryptoProvider,
920 parameters: &RsaOaepParameters,
921 ciphertext: &[u8],
922 ) -> Result<Vec<u8>, ProviderError> {
923 rustcrypto::recover_key(provider, &self.key, parameters, ciphertext)
924 }
925}
926
927#[cfg(feature = "xmlenc")]
928impl KeyRecoveryKey for rsa::RsaPrivateKey {
929 #[cfg(feature = "legacy-algorithms")]
930 fn recover_pkcs1v15(
931 &self,
932 provider: &dyn CryptoProvider,
933 ciphertext: &[u8],
934 key_len: usize,
935 ) -> Result<RecoveredContentKey, ProviderError> {
936 rsa_pkcs1v15::recover(provider, self, ciphertext, key_len)
937 }
938 fn rsa_modulus_bits(&self) -> usize {
939 use rsa::traits::PublicKeyParts as _;
940 self.n().bits_vartime() as usize
941 }
942 fn rsa_public_exponent(&self) -> Option<u64> {
943 use rsa::traits::PublicKeyParts as _;
944 if self.e().bits_vartime() > 64 {
945 return None;
946 }
947 let mut exponent = 0_u64;
948 let word_bits = crypto_bigint::Word::BITS as usize;
949 for (index, word) in self.e().as_words().iter().take(64 / word_bits).enumerate() {
950 #[cfg(target_pointer_width = "64")]
951 let word = *word;
952 #[cfg(target_pointer_width = "32")]
953 let word = u64::from(*word);
954 exponent |= word << (index * word_bits);
955 }
956 Some(exponent)
957 }
958 fn ciphertext_len(&self) -> usize {
959 use rsa::traits::PublicKeyParts as _;
960 self.size()
961 }
962
963 fn recover_with_provider(
964 &self,
965 provider: &dyn CryptoProvider,
966 parameters: &RsaOaepParameters,
967 ciphertext: &[u8],
968 ) -> Result<Vec<u8>, ProviderError> {
969 rustcrypto::recover_key(provider, self, parameters, ciphertext)
970 }
971}
972
973pub static RUST_CRYPTO_PROVIDER: RustCryptoProvider = RustCryptoProvider;
975
976#[must_use]
978pub fn default_provider() -> &'static dyn CryptoProvider {
979 &RUST_CRYPTO_PROVIDER
980}
981
982#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
984pub(crate) struct ProviderRng<'a>(pub(crate) &'a dyn CryptoProvider);
985
986#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
987impl TryRng for ProviderRng<'_> {
988 type Error = ProviderError;
989
990 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
991 let mut bytes = [0_u8; 4];
992 self.try_fill_bytes(&mut bytes)?;
993 Ok(u32::from_le_bytes(bytes))
994 }
995
996 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
997 let mut bytes = [0_u8; 8];
998 self.try_fill_bytes(&mut bytes)?;
999 Ok(u64::from_le_bytes(bytes))
1000 }
1001
1002 fn try_fill_bytes(&mut self, output: &mut [u8]) -> Result<(), Self::Error> {
1003 self.0.fill_random(output)
1004 }
1005}
1006
1007#[cfg(any(feature = "xmldsig", feature = "xmlenc"))]
1008impl TryCryptoRng for ProviderRng<'_> {}
1009
1010impl CryptoProvider for RustCryptoProvider {
1011 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
1012 fn transport_pkcs1v15(
1013 &self,
1014 key: &dyn KeyTransportKey,
1015 plaintext: &[u8],
1016 ) -> Result<Vec<u8>, ProviderError> {
1017 self.require_capability(ProviderCapability::Pkcs1v15Transport)?;
1018 key.transport_pkcs1v15(self, plaintext)
1019 }
1020
1021 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
1022 fn recover_pkcs1v15(
1023 &self,
1024 key: &dyn KeyRecoveryKey,
1025 ciphertext: &[u8],
1026 key_len: usize,
1027 ) -> Result<RecoveredContentKey, ProviderError> {
1028 self.require_capability(ProviderCapability::Pkcs1v15Recovery)?;
1029 key.recover_pkcs1v15(self, ciphertext, key_len)
1030 }
1031 fn name(&self) -> &'static str {
1032 "rustcrypto"
1033 }
1034
1035 #[cfg(feature = "xmlenc")]
1036 fn import_recovery_key(
1037 &self,
1038 pkcs8: &[u8],
1039 ) -> Result<std::sync::Arc<dyn KeyRecoveryKey>, ProviderError> {
1040 use rsa::pkcs8::DecodePrivateKey as _;
1041 let key = rsa::RsaPrivateKey::from_pkcs8_der(pkcs8).map_err(|_| {
1042 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization(
1043 "RSA recovery key",
1044 ))
1045 })?;
1046 Ok(std::sync::Arc::new(RustCryptoRsaPrivateKey::new(key)))
1047 }
1048
1049 #[cfg(feature = "xmldsig")]
1050 fn import_signing_key(
1051 &self,
1052 algorithm: crate::xmldsig::SignatureAlgorithm,
1053 der: &[u8],
1054 ) -> Result<Box<dyn crate::xmldsig::SigningKey>, crate::xmldsig::SigningKeyError> {
1055 use crate::xmldsig::{SignatureAlgorithm as A, *};
1056 Ok(match algorithm {
1057 #[cfg(feature = "experimental-pq")]
1058 A::PostQuantum(parameter) => {
1059 Box::new(PostQuantumSigningKey::from_pkcs8_der(parameter, der)?)
1060 }
1061 A::Ed25519 | A::Ed25519Ctx | A::Ed25519Ph | A::Ed448 | A::Ed448Ph => {
1062 Box::new(EdDsaSigningKey::from_pkcs8_der(algorithm, der)?)
1063 }
1064 method if method.is_rsa() => Box::new(RsaSigningKey::from_pkcs8_der(der)?),
1065 A::DsaSha1 | A::DsaSha256 => Box::new(DsaSigningKey::from_pkcs8_der(der)?),
1066 method if method.ecdsa_digest().is_some() => {
1067 if let Ok(key) = EcdsaP256SigningKey::from_pkcs8_der(der) {
1068 Box::new(key)
1069 } else if let Ok(key) = EcdsaP384SigningKey::from_pkcs8_der(der) {
1070 Box::new(key)
1071 } else {
1072 Box::new(EcdsaP521SigningKey::from_pkcs8_der(der)?)
1073 }
1074 }
1075 _ => {
1076 return Err(SigningKeyError::UnsupportedAlgorithm {
1077 uri: algorithm.uri().into(),
1078 });
1079 }
1080 })
1081 }
1082
1083 fn supports(&self, capability: ProviderCapability<'_>) -> bool {
1084 match capability {
1085 #[cfg(feature = "xmldsig")]
1086 ProviderCapability::Digest(_) => true,
1087 #[cfg(feature = "xmldsig")]
1088 ProviderCapability::Sign(algorithm) | ProviderCapability::Verify(algorithm) => {
1091 !matches!(
1092 algorithm,
1093 crate::xmldsig::SignatureAlgorithm::PostQuantum(_)
1094 ) || cfg!(feature = "experimental-pq")
1095 }
1096 #[cfg(feature = "xmldsig")]
1097 ProviderCapability::VerifyCertificate(algorithm) => {
1098 is_supported_x509_signature(algorithm)
1099 }
1100 #[cfg(feature = "xmlenc")]
1101 ProviderCapability::Encrypt(_) | ProviderCapability::Decrypt(_) => true,
1102 #[cfg(feature = "xmlenc")]
1103 ProviderCapability::KeyWrap(_) | ProviderCapability::KeyUnwrap(_) => true,
1104 #[cfg(feature = "xmlenc")]
1105 ProviderCapability::KeyTransport(_) | ProviderCapability::KeyRecovery(_) => true,
1106 #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))]
1107 ProviderCapability::Pkcs1v15Transport | ProviderCapability::Pkcs1v15Recovery => true,
1108 ProviderCapability::Random => true,
1109 ProviderCapability::KeyAgreement(_) | ProviderCapability::Kdf(_) => false,
1110 }
1111 }
1112
1113 fn fill_random(&self, output: &mut [u8]) -> Result<(), ProviderError> {
1114 SysRng
1115 .try_fill_bytes(output)
1116 .map_err(|error| ProviderError::Random(error.to_string()))
1117 }
1118
1119 fn derive_key(
1120 &self,
1121 parameters: &KdfParameters<'_>,
1122 _secret: &[u8],
1123 ) -> Result<Vec<u8>, ProviderError> {
1124 self.require_capability(ProviderCapability::Kdf(parameters))?;
1125 Err(ProviderError::Unsupported {
1126 operation: ProviderOperation::Kdf,
1127 algorithm: Some(parameters.algorithm.to_owned()),
1128 })
1129 }
1130
1131 #[cfg(feature = "xmldsig")]
1132 fn digest(&self, algorithm: DigestAlgorithm, data: &[u8]) -> Result<Vec<u8>, ProviderError> {
1133 use sha1::Sha1;
1134 use sha2::{Digest, Sha224, Sha256, Sha384, Sha512};
1135 use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512};
1136 Ok(match algorithm {
1137 #[cfg(feature = "legacy-algorithms")]
1138 DigestAlgorithm::Md5 => md5::Md5::digest(data).to_vec(),
1139 #[cfg(feature = "legacy-algorithms")]
1140 DigestAlgorithm::Ripemd160 => ripemd::Ripemd160::digest(data).to_vec(),
1141 DigestAlgorithm::Sha1 => Sha1::digest(data).to_vec(),
1142 DigestAlgorithm::Sha224 => Sha224::digest(data).to_vec(),
1143 DigestAlgorithm::Sha256 => Sha256::digest(data).to_vec(),
1144 DigestAlgorithm::Sha384 => Sha384::digest(data).to_vec(),
1145 DigestAlgorithm::Sha512 => Sha512::digest(data).to_vec(),
1146 DigestAlgorithm::Sha3_224 => Sha3_224::digest(data).to_vec(),
1147 DigestAlgorithm::Sha3_256 => Sha3_256::digest(data).to_vec(),
1148 DigestAlgorithm::Sha3_384 => Sha3_384::digest(data).to_vec(),
1149 DigestAlgorithm::Sha3_512 => Sha3_512::digest(data).to_vec(),
1150 })
1151 }
1152
1153 #[cfg(feature = "xmldsig")]
1154 fn sign(
1155 &self,
1156 key: &dyn crate::xmldsig::SigningKey,
1157 algorithm: crate::xmldsig::SignatureAlgorithm,
1158 data: &[u8],
1159 ) -> Result<Vec<u8>, crate::xmldsig::SigningKeyError> {
1160 self.require_capability(ProviderCapability::Sign(algorithm))?;
1161 key.sign_with_provider(self, algorithm, data)
1162 }
1163
1164 #[cfg(feature = "xmldsig")]
1165 fn sign_with_context(
1166 &self,
1167 key: &dyn crate::xmldsig::SigningKey,
1168 algorithm: crate::xmldsig::SignatureAlgorithm,
1169 context: &crate::xmldsig::SignatureContext,
1170 data: &[u8],
1171 ) -> Result<Vec<u8>, crate::xmldsig::SigningKeyError> {
1172 self.require_capability(ProviderCapability::Sign(algorithm))?;
1173 key.sign_with_provider_context(self, algorithm, context, data)
1174 }
1175
1176 #[cfg(feature = "xmldsig")]
1177 fn verify_with_context(
1178 &self,
1179 key: &dyn crate::xmldsig::VerifyingKey,
1180 algorithm: crate::xmldsig::SignatureAlgorithm,
1181 context: &crate::xmldsig::SignatureContext,
1182 data: &[u8],
1183 signature: &[u8],
1184 ) -> Result<bool, crate::xmldsig::DsigError> {
1185 self.require_capability(ProviderCapability::Verify(algorithm))?;
1186 key.verify_with_context(algorithm, context, data, signature)
1187 }
1188
1189 #[cfg(feature = "xmldsig")]
1190 fn verify(
1191 &self,
1192 key: &dyn crate::xmldsig::VerifyingKey,
1193 algorithm: crate::xmldsig::SignatureAlgorithm,
1194 data: &[u8],
1195 signature: &[u8],
1196 ) -> Result<bool, crate::xmldsig::DsigError> {
1197 self.require_capability(ProviderCapability::Verify(algorithm))?;
1198 key.verify(algorithm, data, signature)
1199 }
1200
1201 #[cfg(feature = "xmldsig")]
1202 fn verify_x509_signature(
1203 &self,
1204 algorithm: X509SignatureAlgorithm,
1205 signed_data: &[u8],
1206 signature: &[u8],
1207 issuer_spki_der: &[u8],
1208 ) -> Result<bool, ProviderError> {
1209 rustcrypto_x509::verify_signature(algorithm, signed_data, signature, issuer_spki_der)
1210 }
1211
1212 #[cfg(feature = "xmlenc")]
1213 fn encrypt_data(
1214 &self,
1215 algorithm: DataEncryptionAlgorithm,
1216 key: &[u8],
1217 plaintext: &[u8],
1218 ) -> Result<Vec<u8>, ProviderError> {
1219 rustcrypto::encrypt_data(self, algorithm, key, plaintext)
1220 }
1221
1222 #[cfg(feature = "xmlenc")]
1223 fn decrypt_data(
1224 &self,
1225 algorithm: DataEncryptionAlgorithm,
1226 key: &[u8],
1227 ciphertext: &[u8],
1228 ) -> Result<Vec<u8>, ProviderError> {
1229 rustcrypto::decrypt_data(algorithm, key, ciphertext)
1230 }
1231
1232 #[cfg(feature = "xmlenc")]
1233 fn wrap_key(
1234 &self,
1235 algorithm: KeyWrapAlgorithm,
1236 kek: &[u8],
1237 key: &[u8],
1238 ) -> Result<Vec<u8>, ProviderError> {
1239 rustcrypto::wrap_key(self, algorithm, kek, key)
1240 }
1241
1242 #[cfg(feature = "xmlenc")]
1243 fn unwrap_key(
1244 &self,
1245 algorithm: KeyWrapAlgorithm,
1246 kek: &[u8],
1247 wrapped: &[u8],
1248 ) -> Result<Vec<u8>, ProviderError> {
1249 rustcrypto::unwrap_key(algorithm, kek, wrapped)
1250 }
1251
1252 #[cfg(feature = "xmlenc")]
1253 fn transport_key(
1254 &self,
1255 key: &dyn KeyTransportKey,
1256 parameters: &RsaOaepParameters,
1257 plaintext: &[u8],
1258 ) -> Result<Vec<u8>, ProviderError> {
1259 self.require_capability(ProviderCapability::KeyTransport(parameters))?;
1260 key.transport_with_provider(self, parameters, plaintext)
1261 }
1262
1263 #[cfg(feature = "xmlenc")]
1264 fn recover_key(
1265 &self,
1266 key: &dyn KeyRecoveryKey,
1267 parameters: &RsaOaepParameters,
1268 ciphertext: &[u8],
1269 ) -> Result<Vec<u8>, ProviderError> {
1270 self.require_capability(ProviderCapability::KeyRecovery(parameters))?;
1271 key.recover_with_provider(self, parameters, ciphertext)
1272 }
1273}
1274
1275#[cfg(feature = "xmldsig")]
1276fn is_supported_x509_signature(algorithm: X509SignatureAlgorithm) -> bool {
1277 match algorithm {
1278 X509SignatureAlgorithm::Dsa(DigestAlgorithm::Sha1)
1279 | X509SignatureAlgorithm::Ed25519
1280 | X509SignatureAlgorithm::Ed448 => true,
1281 X509SignatureAlgorithm::Ecdsa(digest) => rustcrypto_x509::ecdsa_algorithm(digest).is_some(),
1282 X509SignatureAlgorithm::PostQuantum(_) => cfg!(feature = "experimental-pq"),
1283 X509SignatureAlgorithm::RsaPkcs1v15(digest) => matches!(
1284 digest,
1285 DigestAlgorithm::Sha1
1286 | DigestAlgorithm::Sha224
1287 | DigestAlgorithm::Sha256
1288 | DigestAlgorithm::Sha384
1289 | DigestAlgorithm::Sha512
1290 ),
1291 X509SignatureAlgorithm::RsaPss {
1292 digest, mgf_digest, ..
1293 } => {
1294 matches!(
1295 digest,
1296 DigestAlgorithm::Sha256 | DigestAlgorithm::Sha384 | DigestAlgorithm::Sha512
1297 ) && digest == mgf_digest
1298 }
1299 X509SignatureAlgorithm::Dsa(_) => false,
1300 }
1301}
1302
1303#[cfg(feature = "xmldsig")]
1304mod rustcrypto_x509 {
1305 use der::Decode as _;
1306 use dsa::pkcs8::DecodePublicKey as _;
1307 use rsa::{
1308 RsaPublicKey,
1309 pkcs1::DecodeRsaPublicKey as _,
1310 pss::{Signature as RsaPssSignature, VerifyingKey as RsaPssVerifyingKey},
1311 traits::PublicKeyParts as _,
1312 };
1313 use sha1::Digest as _;
1314 use sha2::{Sha256, Sha384, Sha512};
1315 use signature::{Verifier as _, hazmat::PrehashVerifier as _};
1316 use x509_parser::prelude::FromDer as _;
1317
1318 use super::{ProviderError, X509SignatureAlgorithm};
1319 use crate::xmldsig::signature::verify_ecdsa_signature_spki_asn1_der;
1320 use crate::xmldsig::{
1321 DigestAlgorithm, DsigError, SignatureAlgorithm, VerificationKey, VerifyingKey as _,
1322 };
1323
1324 pub(super) fn verify_signature(
1325 algorithm: X509SignatureAlgorithm,
1326 signed_data: &[u8],
1327 signature: &[u8],
1328 issuer_spki_der: &[u8],
1329 ) -> Result<bool, ProviderError> {
1330 match algorithm {
1331 X509SignatureAlgorithm::Dsa(DigestAlgorithm::Sha1) => {
1332 let Ok(key) = crate::xmldsig::signature::decode_dsa_verifying_key(issuer_spki_der)
1336 else {
1337 return Ok(false);
1338 };
1339 let Ok(signature) = dsa::Signature::from_der(signature) else {
1340 return Ok(false);
1341 };
1342 let digest = sha1::Sha1::digest(signed_data);
1343 Ok(key.verify_prehash(&digest, &signature).is_ok())
1344 }
1345 X509SignatureAlgorithm::RsaPkcs1v15(digest) => {
1346 let Some(algorithm) = rsa_pkcs1_algorithm(digest) else {
1347 return unsupported(X509SignatureAlgorithm::RsaPkcs1v15(digest));
1348 };
1349 verify_xml_signature(algorithm, signed_data, signature, issuer_spki_der)
1350 }
1351 X509SignatureAlgorithm::Ecdsa(digest) => {
1352 let Some(algorithm) = ecdsa_algorithm(digest) else {
1353 return unsupported(X509SignatureAlgorithm::Ecdsa(digest));
1354 };
1355 match verify_ecdsa_signature_spki_asn1_der(
1358 algorithm,
1359 issuer_spki_der,
1360 signed_data,
1361 signature,
1362 ) {
1363 Ok(verified) => Ok(verified),
1364 Err(_) => Ok(false),
1365 }
1366 }
1367 X509SignatureAlgorithm::RsaPss {
1368 digest,
1369 mgf_digest,
1370 salt_len,
1371 } => {
1372 let Some(key) = compatible_rsa_pss_public_key_from_spki(issuer_spki_der, algorithm)
1376 else {
1377 return Ok(false);
1378 };
1379 if digest != mgf_digest {
1380 return unsupported(algorithm);
1381 }
1382 verify_rsa_pss(digest, salt_len, signed_data, signature, key)
1383 }
1384 X509SignatureAlgorithm::Ed25519 => {
1385 let Ok(key) = ed25519_dalek::VerifyingKey::from_public_key_der(issuer_spki_der)
1386 else {
1387 return Ok(false);
1388 };
1389 let Ok(signature) = ed25519_dalek::Signature::try_from(signature) else {
1390 return Ok(false);
1391 };
1392 Ok(key.verify_strict(signed_data, &signature).is_ok())
1393 }
1394 X509SignatureAlgorithm::Ed448 => {
1395 let Ok(key) = ed448_goldilocks::VerifyingKey::from_public_key_der(issuer_spki_der)
1398 else {
1399 return Ok(false);
1400 };
1401 let Ok(signature) = ed448_goldilocks::Signature::try_from(signature) else {
1402 return Ok(false);
1403 };
1404 Ok(key.verify_raw(&signature, signed_data).is_ok())
1405 }
1406 #[cfg(feature = "experimental-pq")]
1407 X509SignatureAlgorithm::PostQuantum(algorithm) => {
1408 Ok(crate::xmldsig::post_quantum::verify(
1413 algorithm,
1414 issuer_spki_der,
1415 &crate::xmldsig::SignatureContext::default(),
1416 signed_data,
1417 signature,
1418 )
1419 .unwrap_or(false))
1420 }
1421 _ => unsupported(algorithm),
1422 }
1423 }
1424
1425 fn verify_xml_signature(
1426 algorithm: SignatureAlgorithm,
1427 signed_data: &[u8],
1428 signature: &[u8],
1429 issuer_spki_der: &[u8],
1430 ) -> Result<bool, ProviderError> {
1431 let key = VerificationKey {
1432 algorithm,
1433 public_key_bytes: issuer_spki_der.to_vec(),
1434 certificate_der: None,
1435 name: None,
1436 };
1437 match key.verify(algorithm, signed_data, signature) {
1438 Ok(verified) => Ok(verified),
1439 Err(DsigError::Provider(error)) => Err(error),
1440 Err(_) => Ok(false),
1441 }
1442 }
1443
1444 fn verify_rsa_pss(
1445 digest: DigestAlgorithm,
1446 salt_len: usize,
1447 signed_data: &[u8],
1448 signature: &[u8],
1449 key: RsaPublicKey,
1450 ) -> Result<bool, ProviderError> {
1451 if !rsa_pss_salt_fits_key(&key, digest, salt_len) {
1452 return Ok(false);
1453 }
1454 let Ok(signature) = RsaPssSignature::try_from(signature) else {
1455 return Ok(false);
1456 };
1457 let verified = match digest {
1458 DigestAlgorithm::Sha256 => {
1459 RsaPssVerifyingKey::<Sha256>::new_with_salt_len(key, salt_len)
1460 .verify(signed_data, &signature)
1461 }
1462 DigestAlgorithm::Sha384 => {
1463 RsaPssVerifyingKey::<Sha384>::new_with_salt_len(key, salt_len)
1464 .verify(signed_data, &signature)
1465 }
1466 DigestAlgorithm::Sha512 => {
1467 RsaPssVerifyingKey::<Sha512>::new_with_salt_len(key, salt_len)
1468 .verify(signed_data, &signature)
1469 }
1470 _ => {
1471 return unsupported(X509SignatureAlgorithm::RsaPss {
1472 digest,
1473 mgf_digest: digest,
1474 salt_len,
1475 });
1476 }
1477 };
1478 Ok(verified.is_ok())
1479 }
1480
1481 pub(super) fn rsa_pss_salt_fits_key(
1482 key: &RsaPublicKey,
1483 digest: DigestAlgorithm,
1484 salt_len: usize,
1485 ) -> bool {
1486 let Some(em_bits) = key.n().bits().checked_sub(1) else {
1487 return false;
1488 };
1489 let Ok(em_len) = usize::try_from(em_bits.div_ceil(8)) else {
1490 return false;
1491 };
1492 digest
1493 .output_len()
1494 .checked_add(salt_len)
1495 .and_then(|length| length.checked_add(2))
1496 .is_some_and(|required| required <= em_len)
1497 }
1498
1499 fn compatible_rsa_pss_public_key_from_spki(
1500 spki_der: &[u8],
1501 signature_algorithm: X509SignatureAlgorithm,
1502 ) -> Option<RsaPublicKey> {
1503 let (_, spki) = x509_parser::x509::SubjectPublicKeyInfo::from_der(spki_der).ok()?;
1504 match spki.algorithm.algorithm.to_id_string().as_str() {
1505 "1.2.840.113549.1.1.1" => RsaPublicKey::from_public_key_der(spki_der).ok(),
1506 "1.2.840.113549.1.1.10" => {
1507 if spki
1510 .algorithm
1511 .parameters
1512 .as_ref()
1513 .is_some_and(|parameters| {
1514 !rsa_pss_key_parameters_allow(parameters, signature_algorithm)
1515 })
1516 {
1517 return None;
1518 }
1519 RsaPublicKey::from_pkcs1_der(&spki.subject_public_key.data).ok()
1520 }
1521 _ => None,
1522 }
1523 }
1524
1525 fn rsa_pss_key_parameters_allow(
1526 parameters: &x509_parser::asn1_rs::Any<'_>,
1527 signature_algorithm: X509SignatureAlgorithm,
1528 ) -> bool {
1529 let X509SignatureAlgorithm::RsaPss {
1530 digest,
1531 mgf_digest,
1532 salt_len,
1533 } = signature_algorithm
1534 else {
1535 return false;
1536 };
1537 let Ok(parameters) =
1538 x509_parser::signature_algorithm::RsaSsaPssParams::try_from(parameters)
1539 else {
1540 return false;
1541 };
1542 let Ok(mask) = parameters.mask_gen_algorithm() else {
1543 return false;
1544 };
1545 parameters.trailer_field() == 1
1546 && x509_digest_from_oid(¶meters.hash_algorithm_oid().to_id_string()) == Some(digest)
1547 && mask.mgf.to_id_string() == "1.2.840.113549.1.1.8"
1548 && x509_digest_from_oid(&mask.hash.to_id_string()) == Some(mgf_digest)
1549 && usize::try_from(parameters.salt_length()).is_ok_and(|minimum| salt_len >= minimum)
1550 }
1551
1552 fn x509_digest_from_oid(oid: &str) -> Option<DigestAlgorithm> {
1553 match oid {
1554 "1.3.14.3.2.26" => Some(DigestAlgorithm::Sha1),
1555 "2.16.840.1.101.3.4.2.4" => Some(DigestAlgorithm::Sha224),
1556 "2.16.840.1.101.3.4.2.1" => Some(DigestAlgorithm::Sha256),
1557 "2.16.840.1.101.3.4.2.2" => Some(DigestAlgorithm::Sha384),
1558 "2.16.840.1.101.3.4.2.3" => Some(DigestAlgorithm::Sha512),
1559 _ => None,
1560 }
1561 }
1562
1563 const fn rsa_pkcs1_algorithm(digest: DigestAlgorithm) -> Option<SignatureAlgorithm> {
1564 match digest {
1565 DigestAlgorithm::Sha1 => Some(SignatureAlgorithm::RsaSha1),
1566 DigestAlgorithm::Sha224 => Some(SignatureAlgorithm::RsaSha224),
1567 DigestAlgorithm::Sha256 => Some(SignatureAlgorithm::RsaSha256),
1568 DigestAlgorithm::Sha384 => Some(SignatureAlgorithm::RsaSha384),
1569 DigestAlgorithm::Sha512 => Some(SignatureAlgorithm::RsaSha512),
1570 _ => None,
1571 }
1572 }
1573
1574 pub(super) const fn ecdsa_algorithm(digest: DigestAlgorithm) -> Option<SignatureAlgorithm> {
1575 match digest {
1576 #[cfg(feature = "legacy-algorithms")]
1577 DigestAlgorithm::Md5 | DigestAlgorithm::Ripemd160 => None,
1578 DigestAlgorithm::Sha1 => Some(SignatureAlgorithm::EcdsaSha1),
1579 DigestAlgorithm::Sha224 => Some(SignatureAlgorithm::EcdsaSha224),
1580 DigestAlgorithm::Sha256 => Some(SignatureAlgorithm::EcdsaSha256),
1581 DigestAlgorithm::Sha384 => Some(SignatureAlgorithm::EcdsaSha384),
1582 DigestAlgorithm::Sha512 => Some(SignatureAlgorithm::EcdsaSha512),
1583 DigestAlgorithm::Sha3_224 => Some(SignatureAlgorithm::EcdsaSha3_224),
1584 DigestAlgorithm::Sha3_256 => Some(SignatureAlgorithm::EcdsaSha3_256),
1585 DigestAlgorithm::Sha3_384 => Some(SignatureAlgorithm::EcdsaSha3_384),
1586 DigestAlgorithm::Sha3_512 => Some(SignatureAlgorithm::EcdsaSha3_512),
1587 }
1588 }
1589
1590 fn unsupported<T>(algorithm: X509SignatureAlgorithm) -> Result<T, ProviderError> {
1591 Err(ProviderError::Unsupported {
1592 operation: super::ProviderOperation::VerifyCertificate,
1593 algorithm: algorithm.oid().map(str::to_owned),
1594 })
1595 }
1596}
1597
1598#[cfg(feature = "xmlenc")]
1599mod rustcrypto {
1600 #[cfg(feature = "legacy-algorithms")]
1601 use aes::Aes192;
1602 use aes::{
1603 Aes128, Aes256,
1604 cipher::{BlockModeDecrypt, BlockModeEncrypt, KeyIvInit, block_padding::NoPadding},
1605 };
1606 use aes_gcm::{
1607 Aes128Gcm, Aes256Gcm, Nonce,
1608 aead::{AeadInOut, KeyInit},
1609 };
1610 use aes_kw::{KwAes128, KwAes256};
1611 use cbc::{Decryptor, Encryptor};
1612 #[cfg(feature = "legacy-algorithms")]
1613 use des::TdesEde3;
1614 use rsa::{Oaep, traits::PaddingScheme};
1615 use sha1::Sha1;
1616 use sha2::{Sha256, Sha384, Sha512};
1617
1618 use super::{CryptoProvider, ProviderError, ProviderInputError};
1619 use crate::xmlenc::{
1620 DataEncryptionAlgorithm, KeyWrapAlgorithm, OaepDigestAlgorithm, RsaOaepParameters,
1621 };
1622
1623 pub(super) fn encrypt_data(
1624 provider: &dyn CryptoProvider,
1625 algorithm: DataEncryptionAlgorithm,
1626 key: &[u8],
1627 plaintext: &[u8],
1628 ) -> Result<Vec<u8>, ProviderError> {
1629 check_key(algorithm.key_len(), key)?;
1630 match algorithm {
1631 #[cfg(feature = "legacy-algorithms")]
1632 DataEncryptionAlgorithm::TripleDesCbc => {
1633 encrypt_cbc::<TdesEde3>(provider, key, plaintext)
1634 }
1635 #[cfg(feature = "legacy-algorithms")]
1636 DataEncryptionAlgorithm::Aes192Cbc => encrypt_cbc::<Aes192>(provider, key, plaintext),
1637 #[cfg(feature = "legacy-algorithms")]
1638 DataEncryptionAlgorithm::Aes192Gcm => encrypt_gcm::<
1639 aes_gcm::AesGcm<Aes192, aes_gcm::aead::consts::U12>,
1640 >(provider, key, plaintext),
1641 DataEncryptionAlgorithm::Aes128Cbc => encrypt_cbc::<Aes128>(provider, key, plaintext),
1642 DataEncryptionAlgorithm::Aes256Cbc => encrypt_cbc::<Aes256>(provider, key, plaintext),
1643 DataEncryptionAlgorithm::Aes128Gcm => {
1644 encrypt_gcm::<Aes128Gcm>(provider, key, plaintext)
1645 }
1646 DataEncryptionAlgorithm::Aes256Gcm => {
1647 encrypt_gcm::<Aes256Gcm>(provider, key, plaintext)
1648 }
1649 }
1650 }
1651
1652 pub(super) fn decrypt_data(
1653 algorithm: DataEncryptionAlgorithm,
1654 key: &[u8],
1655 ciphertext: &[u8],
1656 ) -> Result<Vec<u8>, ProviderError> {
1657 check_key(algorithm.key_len(), key)?;
1658 match algorithm {
1659 #[cfg(feature = "legacy-algorithms")]
1660 DataEncryptionAlgorithm::TripleDesCbc => decrypt_cbc::<TdesEde3>(key, ciphertext),
1661 #[cfg(feature = "legacy-algorithms")]
1662 DataEncryptionAlgorithm::Aes192Cbc => decrypt_cbc::<Aes192>(key, ciphertext),
1663 #[cfg(feature = "legacy-algorithms")]
1664 DataEncryptionAlgorithm::Aes192Gcm => {
1665 decrypt_gcm::<aes_gcm::AesGcm<Aes192, aes_gcm::aead::consts::U12>>(key, ciphertext)
1666 }
1667 DataEncryptionAlgorithm::Aes128Cbc => decrypt_cbc::<Aes128>(key, ciphertext),
1668 DataEncryptionAlgorithm::Aes256Cbc => decrypt_cbc::<Aes256>(key, ciphertext),
1669 DataEncryptionAlgorithm::Aes128Gcm => decrypt_gcm::<Aes128Gcm>(key, ciphertext),
1670 DataEncryptionAlgorithm::Aes256Gcm => decrypt_gcm::<Aes256Gcm>(key, ciphertext),
1671 }
1672 }
1673
1674 fn check_key(expected: usize, key: &[u8]) -> Result<(), ProviderError> {
1675 if key.len() == expected {
1676 Ok(())
1677 } else {
1678 Err(ProviderError::InvalidKeySize {
1679 expected,
1680 actual: key.len(),
1681 })
1682 }
1683 }
1684
1685 fn encrypt_cbc<C>(
1686 provider: &dyn CryptoProvider,
1687 key: &[u8],
1688 plaintext: &[u8],
1689 ) -> Result<Vec<u8>, ProviderError>
1690 where
1691 C: aes::cipher::BlockCipherEncrypt + aes::cipher::KeyInit,
1692 {
1693 let block = C::block_size();
1694 let pad_len = block - (plaintext.len() % block);
1695 let length = plaintext
1696 .len()
1697 .checked_add(pad_len)
1698 .and_then(|len| len.checked_add(block))
1699 .ok_or(ProviderError::InvalidInput(
1700 ProviderInputError::AesCbcFraming,
1701 ))?;
1702 let mut output = zeroize::Zeroizing::new(vec![0_u8; length]);
1703 let (iv, padded) = output.split_at_mut(block);
1704 provider.fill_random(iv)?;
1705 padded[..plaintext.len()].copy_from_slice(plaintext);
1706 if pad_len > 1 {
1707 let last = padded.len() - 1;
1708 provider.fill_random(&mut padded[plaintext.len()..last])?;
1709 }
1710 *padded.last_mut().expect("padding is non-empty") = pad_len as u8;
1711 Encryptor::<C>::new_from_slices(key, iv)
1712 .map_err(|_| {
1713 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization("AES-CBC"))
1714 })?
1715 .encrypt_padded::<NoPadding>(padded, plaintext.len() + pad_len)
1716 .map_err(|_| {
1717 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization(
1718 "AES-CBC padding",
1719 ))
1720 })?;
1721 Ok(core::mem::take(&mut *output))
1722 }
1723
1724 fn decrypt_cbc<C>(key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, ProviderError>
1725 where
1726 C: aes::cipher::BlockCipherDecrypt + aes::cipher::KeyInit,
1727 {
1728 let block = C::block_size();
1729 if ciphertext.len() < 2 * block || !(ciphertext.len() - block).is_multiple_of(block) {
1730 return Err(ProviderError::InvalidInput(
1731 ProviderInputError::AesCbcFraming,
1732 ));
1733 }
1734 let (iv, body) = ciphertext.split_at(block);
1735 let mut plaintext = zeroize::Zeroizing::new(body.to_vec());
1736 Decryptor::<C>::new_from_slices(key, iv)
1737 .map_err(|_| {
1738 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization("AES-CBC"))
1739 })?
1740 .decrypt_padded::<NoPadding>(&mut plaintext)
1741 .map_err(|_| ProviderError::InvalidInput(ProviderInputError::AesCbcCiphertext))?;
1742 let pad_len = *plaintext.last().ok_or(ProviderError::InvalidInput(
1743 ProviderInputError::AesCbcCiphertext,
1744 ))?;
1745 let padding_bytes = usize::from(pad_len);
1746 if !(1..=block).contains(&padding_bytes) || padding_bytes > plaintext.len() {
1747 return Err(ProviderError::InvalidInput(
1748 ProviderInputError::AesCbcCiphertext,
1749 ));
1750 }
1751 let length = plaintext.len() - padding_bytes;
1752 plaintext.truncate(length);
1753 Ok(core::mem::take(&mut *plaintext))
1754 }
1755
1756 fn encrypt_gcm<C>(
1757 provider: &dyn CryptoProvider,
1758 key: &[u8],
1759 plaintext: &[u8],
1760 ) -> Result<Vec<u8>, ProviderError>
1761 where
1762 C: AeadInOut + KeyInit,
1763 {
1764 let mut nonce = [0_u8; 12];
1765 provider.fill_random(&mut nonce)?;
1766 let cipher = C::new_from_slice(key).map_err(|_| {
1767 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization("AES-GCM"))
1768 })?;
1769 let length = plaintext
1770 .len()
1771 .checked_add(28)
1772 .ok_or(ProviderError::InvalidInput(
1773 ProviderInputError::PrimitiveInitialization("AES-GCM length"),
1774 ))?;
1775 let mut output = zeroize::Zeroizing::new(Vec::with_capacity(length));
1778 output.extend_from_slice(&nonce);
1779 output.extend_from_slice(plaintext);
1780 let nonce = Nonce::try_from(nonce.as_slice()).map_err(|_| {
1781 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization(
1782 "AES-GCM nonce",
1783 ))
1784 })?;
1785 let tag = cipher
1786 .encrypt_inout_detached(&nonce, &[], output[12..].as_mut().into())
1787 .map_err(|_| ProviderError::AuthenticationFailed)?;
1788 output.extend_from_slice(&tag);
1789 Ok(core::mem::take(&mut *output))
1790 }
1791
1792 fn decrypt_gcm<C>(key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, ProviderError>
1793 where
1794 C: AeadInOut + KeyInit,
1795 {
1796 if ciphertext.len() < 28 {
1797 return Err(ProviderError::InvalidInput(
1798 ProviderInputError::AesGcmFraming,
1799 ));
1800 }
1801 let (nonce, body) = ciphertext.split_at(12);
1802 let cipher = C::new_from_slice(key).map_err(|_| {
1803 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization("AES-GCM"))
1804 })?;
1805 let mut plaintext = zeroize::Zeroizing::new(body.to_vec());
1806 let nonce = Nonce::try_from(nonce).map_err(|_| {
1807 ProviderError::InvalidInput(ProviderInputError::PrimitiveInitialization(
1808 "AES-GCM nonce",
1809 ))
1810 })?;
1811 cipher
1812 .decrypt_in_place(&nonce, &[], &mut *plaintext)
1813 .map_err(|_| ProviderError::AuthenticationFailed)?;
1814 Ok(core::mem::take(&mut *plaintext))
1815 }
1816
1817 pub(super) fn wrap_key(
1818 provider: &dyn CryptoProvider,
1819 algorithm: KeyWrapAlgorithm,
1820 kek: &[u8],
1821 key: &[u8],
1822 ) -> Result<Vec<u8>, ProviderError> {
1823 check_key(algorithm.key_len(), kek)?;
1824 #[cfg(feature = "legacy-algorithms")]
1825 if algorithm == KeyWrapAlgorithm::TripleDes {
1826 return wrap_des3(provider, kek, key);
1827 }
1828 #[cfg(not(feature = "legacy-algorithms"))]
1829 let _ = provider;
1830 if key.len() < 16 || !key.len().is_multiple_of(8) {
1835 return Err(ProviderError::InvalidInput(
1836 ProviderInputError::AesKeyWrapFraming,
1837 ));
1838 }
1839 let length =
1840 key.len()
1841 .checked_add(algorithm.overhead())
1842 .ok_or(ProviderError::InvalidInput(
1843 ProviderInputError::AesKeyWrapFraming,
1844 ))?;
1845 let mut output = vec![0_u8; length];
1846 match algorithm {
1847 #[cfg(feature = "legacy-algorithms")]
1848 KeyWrapAlgorithm::AesKw192 => aes_kw::KwAes192::new_from_slice(kek)
1849 .map_err(|_| ProviderError::InvalidKeySize {
1850 expected: 24,
1851 actual: kek.len(),
1852 })?
1853 .wrap_key(key, &mut output),
1854 #[cfg(feature = "legacy-algorithms")]
1855 KeyWrapAlgorithm::TripleDes => unreachable!("CMS wrapping dispatched before AES"),
1856 KeyWrapAlgorithm::AesKw128 => KwAes128::new_from_slice(kek)
1857 .map_err(|_| ProviderError::InvalidKeySize {
1858 expected: 16,
1859 actual: kek.len(),
1860 })?
1861 .wrap_key(key, &mut output),
1862 KeyWrapAlgorithm::AesKw256 => KwAes256::new_from_slice(kek)
1863 .map_err(|_| ProviderError::InvalidKeySize {
1864 expected: 32,
1865 actual: kek.len(),
1866 })?
1867 .wrap_key(key, &mut output),
1868 }
1869 .map_err(|_| ProviderError::InvalidInput(ProviderInputError::AesKeyWrapFraming))?;
1870 Ok(output)
1871 }
1872
1873 pub(super) fn unwrap_key(
1874 algorithm: KeyWrapAlgorithm,
1875 kek: &[u8],
1876 wrapped: &[u8],
1877 ) -> Result<Vec<u8>, ProviderError> {
1878 check_key(algorithm.key_len(), kek)?;
1879 #[cfg(feature = "legacy-algorithms")]
1880 if algorithm == KeyWrapAlgorithm::TripleDes {
1881 return unwrap_des3(kek, wrapped);
1882 }
1883 if wrapped.len() < 24 || !wrapped.len().is_multiple_of(8) {
1884 return Err(ProviderError::InvalidInput(
1885 ProviderInputError::AesKeyWrapFraming,
1886 ));
1887 }
1888 let mut output = zeroize::Zeroizing::new(vec![0_u8; wrapped.len() - 8]);
1889 match algorithm {
1890 #[cfg(feature = "legacy-algorithms")]
1891 KeyWrapAlgorithm::AesKw192 => aes_kw::KwAes192::new_from_slice(kek)
1892 .map_err(|_| ProviderError::InvalidKeySize {
1893 expected: 24,
1894 actual: kek.len(),
1895 })?
1896 .unwrap_key(wrapped, &mut output),
1897 #[cfg(feature = "legacy-algorithms")]
1898 KeyWrapAlgorithm::TripleDes => unreachable!("CMS unwrapping dispatched before AES"),
1899 KeyWrapAlgorithm::AesKw128 => KwAes128::new_from_slice(kek)
1900 .map_err(|_| ProviderError::InvalidKeySize {
1901 expected: 16,
1902 actual: kek.len(),
1903 })?
1904 .unwrap_key(wrapped, &mut output),
1905 KeyWrapAlgorithm::AesKw256 => KwAes256::new_from_slice(kek)
1906 .map_err(|_| ProviderError::InvalidKeySize {
1907 expected: 32,
1908 actual: kek.len(),
1909 })?
1910 .unwrap_key(wrapped, &mut output),
1911 }
1912 .map_err(|_| ProviderError::AuthenticationFailed)?;
1913 Ok(core::mem::take(&mut *output))
1914 }
1915
1916 #[cfg(feature = "legacy-algorithms")]
1917 const CMS_IV: [u8; 8] = [0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05];
1918
1919 #[cfg(feature = "legacy-algorithms")]
1920 fn wrap_des3(
1921 provider: &dyn CryptoProvider,
1922 kek: &[u8],
1923 key: &[u8],
1924 ) -> Result<Vec<u8>, ProviderError> {
1925 use sha1::Digest as _;
1926 if key.len() < 16 || !key.len().is_multiple_of(8) {
1931 return Err(ProviderError::InvalidInput(
1932 ProviderInputError::AesKeyWrapFraming,
1933 ));
1934 }
1935 let length = key
1936 .len()
1937 .checked_add(16)
1938 .ok_or(ProviderError::InvalidInput(
1939 ProviderInputError::AesKeyWrapFraming,
1940 ))?;
1941 let mut output = zeroize::Zeroizing::new(vec![0; length]);
1942 provider.fill_random(&mut output[..8])?;
1943 output[8..8 + key.len()].copy_from_slice(key);
1944 output[8 + key.len()..].copy_from_slice(&Sha1::digest(key)[..8]);
1945 let (iv, body) = output.split_at_mut(8);
1946 let body_len = body.len();
1947 Encryptor::<TdesEde3>::new_from_slices(kek, iv)
1948 .map_err(|_| ProviderError::AuthenticationFailed)?
1949 .encrypt_padded::<NoPadding>(body, body_len)
1950 .map_err(|_| ProviderError::AuthenticationFailed)?;
1951 output.reverse();
1952 Encryptor::<TdesEde3>::new_from_slices(kek, &CMS_IV)
1953 .map_err(|_| ProviderError::AuthenticationFailed)?
1954 .encrypt_padded::<NoPadding>(&mut output, length)
1955 .map_err(|_| ProviderError::AuthenticationFailed)?;
1956 Ok(core::mem::take(&mut *output))
1957 }
1958
1959 #[cfg(feature = "legacy-algorithms")]
1960 fn unwrap_des3(kek: &[u8], wrapped: &[u8]) -> Result<Vec<u8>, ProviderError> {
1961 use sha1::Digest as _;
1962 use subtle::ConstantTimeEq as _;
1963 if wrapped.len() < 32 || !wrapped.len().is_multiple_of(8) {
1967 return Err(ProviderError::InvalidInput(
1968 ProviderInputError::AesKeyWrapFraming,
1969 ));
1970 }
1971 let mut output = zeroize::Zeroizing::new(wrapped.to_vec());
1972 Decryptor::<TdesEde3>::new_from_slices(kek, &CMS_IV)
1973 .map_err(|_| ProviderError::AuthenticationFailed)?
1974 .decrypt_padded::<NoPadding>(&mut output)
1975 .map_err(|_| ProviderError::AuthenticationFailed)?;
1976 output.reverse();
1977 let (iv, body) = output.split_at_mut(8);
1978 Decryptor::<TdesEde3>::new_from_slices(kek, iv)
1979 .map_err(|_| ProviderError::AuthenticationFailed)?
1980 .decrypt_padded::<NoPadding>(body)
1981 .map_err(|_| ProviderError::AuthenticationFailed)?;
1982 let key_len = body.len() - 8;
1983 if !bool::from(Sha1::digest(&body[..key_len])[..8].ct_eq(&body[key_len..])) {
1984 return Err(ProviderError::AuthenticationFailed);
1985 }
1986 output.copy_within(8..8 + key_len, 0);
1987 zeroize::Zeroize::zeroize(&mut output[key_len..]);
1988 output.truncate(key_len);
1989 Ok(core::mem::take(&mut *output))
1990 }
1991
1992 #[cfg(feature = "legacy-algorithms")]
1993 pub(super) fn transport_pkcs1v15(
1994 provider: &dyn CryptoProvider,
1995 key: &rsa::RsaPublicKey,
1996 plaintext: &[u8],
1997 ) -> Result<Vec<u8>, ProviderError> {
1998 rsa::Pkcs1v15Encrypt
1999 .encrypt(&mut super::ProviderRng(provider), key, plaintext)
2000 .map_err(map_rsa_error)
2001 }
2002
2003 pub(super) fn transport_key(
2004 provider: &dyn CryptoProvider,
2005 key: &rsa::RsaPublicKey,
2006 parameters: &RsaOaepParameters,
2007 plaintext: &[u8],
2008 ) -> Result<Vec<u8>, ProviderError> {
2009 if parameters.algorithm.requires_explicit_permission() {
2010 return Err(ProviderError::InvalidInput(
2011 ProviderInputError::PrimitiveInitialization("RSA-OAEP algorithm"),
2012 ));
2013 }
2014 let mut rng = super::ProviderRng(provider);
2015 macro_rules! encrypt_with {
2016 ($digest:ty, $mgf:ty) => {
2017 Oaep::<$digest, $mgf>::new_with_mgf_hash_and_label(parameters.label.clone())
2018 .encrypt(&mut rng, key, plaintext)
2019 };
2020 }
2021 let result = match (parameters.digest, parameters.mgf_digest) {
2022 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha1) => {
2023 encrypt_with!(Sha1, Sha1)
2024 }
2025 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha256) => {
2026 encrypt_with!(Sha1, Sha256)
2027 }
2028 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha384) => {
2029 encrypt_with!(Sha1, Sha384)
2030 }
2031 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha512) => {
2032 encrypt_with!(Sha1, Sha512)
2033 }
2034 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha1) => {
2035 encrypt_with!(Sha256, Sha1)
2036 }
2037 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha256) => {
2038 encrypt_with!(Sha256, Sha256)
2039 }
2040 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha384) => {
2041 encrypt_with!(Sha256, Sha384)
2042 }
2043 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha512) => {
2044 encrypt_with!(Sha256, Sha512)
2045 }
2046 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha1) => {
2047 encrypt_with!(Sha384, Sha1)
2048 }
2049 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha256) => {
2050 encrypt_with!(Sha384, Sha256)
2051 }
2052 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha384) => {
2053 encrypt_with!(Sha384, Sha384)
2054 }
2055 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha512) => {
2056 encrypt_with!(Sha384, Sha512)
2057 }
2058 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha1) => {
2059 encrypt_with!(Sha512, Sha1)
2060 }
2061 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha256) => {
2062 encrypt_with!(Sha512, Sha256)
2063 }
2064 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha384) => {
2065 encrypt_with!(Sha512, Sha384)
2066 }
2067 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha512) => {
2068 encrypt_with!(Sha512, Sha512)
2069 }
2070 };
2071 result.map_err(map_rsa_error)
2072 }
2073
2074 pub(super) fn recover_key(
2075 provider: &dyn CryptoProvider,
2076 key: &rsa::RsaPrivateKey,
2077 parameters: &RsaOaepParameters,
2078 ciphertext: &[u8],
2079 ) -> Result<Vec<u8>, ProviderError> {
2080 if parameters.algorithm.requires_explicit_permission() {
2081 return Err(ProviderError::InvalidInput(
2082 ProviderInputError::PrimitiveInitialization("RSA-OAEP algorithm"),
2083 ));
2084 }
2085 let mut rng = super::ProviderRng(provider);
2086 macro_rules! decrypt_with {
2087 ($digest:ty, $mgf:ty) => {
2088 Oaep::<$digest, $mgf>::new_with_mgf_hash_and_label(parameters.label.clone())
2089 .decrypt(Some(&mut rng), key, ciphertext)
2090 };
2091 }
2092 let result = match (parameters.digest, parameters.mgf_digest) {
2093 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha1) => {
2094 decrypt_with!(Sha1, Sha1)
2095 }
2096 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha256) => {
2097 decrypt_with!(Sha1, Sha256)
2098 }
2099 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha384) => {
2100 decrypt_with!(Sha1, Sha384)
2101 }
2102 (OaepDigestAlgorithm::Sha1, OaepDigestAlgorithm::Sha512) => {
2103 decrypt_with!(Sha1, Sha512)
2104 }
2105 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha1) => {
2106 decrypt_with!(Sha256, Sha1)
2107 }
2108 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha256) => {
2109 decrypt_with!(Sha256, Sha256)
2110 }
2111 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha384) => {
2112 decrypt_with!(Sha256, Sha384)
2113 }
2114 (OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha512) => {
2115 decrypt_with!(Sha256, Sha512)
2116 }
2117 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha1) => {
2118 decrypt_with!(Sha384, Sha1)
2119 }
2120 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha256) => {
2121 decrypt_with!(Sha384, Sha256)
2122 }
2123 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha384) => {
2124 decrypt_with!(Sha384, Sha384)
2125 }
2126 (OaepDigestAlgorithm::Sha384, OaepDigestAlgorithm::Sha512) => {
2127 decrypt_with!(Sha384, Sha512)
2128 }
2129 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha1) => {
2130 decrypt_with!(Sha512, Sha1)
2131 }
2132 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha256) => {
2133 decrypt_with!(Sha512, Sha256)
2134 }
2135 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha384) => {
2136 decrypt_with!(Sha512, Sha384)
2137 }
2138 (OaepDigestAlgorithm::Sha512, OaepDigestAlgorithm::Sha512) => {
2139 decrypt_with!(Sha512, Sha512)
2140 }
2141 };
2142 result.map_err(map_rsa_error)
2143 }
2144
2145 pub(super) fn map_rsa_error(error: rsa::Error) -> ProviderError {
2146 match error {
2147 rsa::Error::Rng => ProviderError::Random("RSA randomness failed".into()),
2148 _ => ProviderError::AuthenticationFailed,
2149 }
2150 }
2151}
2152
2153#[cfg(test)]
2154mod tests {
2155 #[cfg(feature = "xmldsig")]
2156 use std::sync::atomic::AtomicUsize;
2157 use std::sync::atomic::{AtomicBool, Ordering};
2158
2159 use super::*;
2160
2161 #[cfg(all(feature = "legacy-algorithms", feature = "xmlenc"))]
2162 #[test]
2163 fn legacy_ciphers_cover_empty_and_block_boundary_plaintexts() {
2164 for algorithm in [
2167 DataEncryptionAlgorithm::TripleDesCbc,
2168 DataEncryptionAlgorithm::Aes192Cbc,
2169 DataEncryptionAlgorithm::Aes192Gcm,
2170 ] {
2171 let key = [0x31; 24];
2172 for length in [0, 1, 7, 8, 15, 16, 17, 31, 32, 33] {
2173 let plaintext = vec![0x41; length];
2174 let ciphertext = RUST_CRYPTO_PROVIDER
2175 .encrypt_data(algorithm, &key, &plaintext)
2176 .expect("valid legacy encryption must succeed");
2177 assert_eq!(
2178 Some(ciphertext.len()),
2179 algorithm.ciphertext_len_for_plaintext(length)
2180 );
2181 assert_eq!(
2182 RUST_CRYPTO_PROVIDER
2183 .decrypt_data(algorithm, &key, &ciphertext)
2184 .expect("matching legacy key must recover plaintext"),
2185 plaintext
2186 );
2187 assert!(
2188 RUST_CRYPTO_PROVIDER
2189 .encrypt_data(algorithm, &key[..23], &plaintext)
2190 .is_err()
2191 );
2192 assert!(
2193 RUST_CRYPTO_PROVIDER
2194 .decrypt_data(algorithm, &key[..23], &ciphertext)
2195 .is_err()
2196 );
2197 assert!(
2198 RUST_CRYPTO_PROVIDER
2199 .decrypt_data(algorithm, &key, &ciphertext[..ciphertext.len() - 1])
2200 .is_err()
2201 );
2202 if algorithm == DataEncryptionAlgorithm::Aes192Gcm {
2203 let mut corrupted = ciphertext;
2204 corrupted[12] ^= 1;
2205 assert!(matches!(
2206 RUST_CRYPTO_PROVIDER.decrypt_data(algorithm, &key, &corrupted),
2207 Err(ProviderError::AuthenticationFailed)
2208 ));
2209 }
2210 }
2211 }
2212 }
2213
2214 #[cfg(all(feature = "legacy-algorithms", feature = "xmlenc"))]
2215 #[test]
2216 fn cms_triple_des_unwrap_matches_rfc3217_vector() {
2217 let kek = hex_literal::hex!("255e0d1c07b646dfb3134cc843ba8aa71f025b7c0838251f");
2221 let key = hex_literal::hex!("2923bf85e06dd6ae529149f1f1bae9eab3a7da3d860d3e98");
2222 let wrapped = hex_literal::hex!(
2223 "690107618ef092b3b48ca1796b234ae9fa33ebb4159604037db5d6a84eb3aac2768c632775a467d4"
2224 );
2225 assert_eq!(
2226 RUST_CRYPTO_PROVIDER
2227 .unwrap_key(KeyWrapAlgorithm::TripleDes, &kek, &wrapped)
2228 .expect("RFC 3217 vector must authenticate"),
2229 key
2230 );
2231 for offset in 0..wrapped.len() {
2232 let mut corrupted = wrapped;
2233 corrupted[offset] ^= 1;
2234 assert!(matches!(
2235 RUST_CRYPTO_PROVIDER.unwrap_key(KeyWrapAlgorithm::TripleDes, &kek, &corrupted),
2236 Err(ProviderError::AuthenticationFailed)
2237 ));
2238 }
2239 }
2240
2241 #[cfg(all(feature = "legacy-algorithms", feature = "xmlenc"))]
2242 #[test]
2243 fn legacy_wrap_preserves_opaque_key_bytes_and_checks_integrity() {
2244 for algorithm in [KeyWrapAlgorithm::AesKw192, KeyWrapAlgorithm::TripleDes] {
2247 let kek = [0x37; 24];
2248 for length in [16, 24, 32] {
2249 let key: Vec<_> = (0..length).map(|byte| byte as u8).collect();
2250 let mut wrapped = RUST_CRYPTO_PROVIDER
2251 .wrap_key(algorithm, &kek, &key)
2252 .expect("valid content key must wrap");
2253 assert_eq!(wrapped.len(), key.len() + algorithm.overhead());
2254 assert_eq!(
2255 RUST_CRYPTO_PROVIDER
2256 .unwrap_key(algorithm, &kek, &wrapped)
2257 .expect("matching KEK must recover exact key octets"),
2258 key
2259 );
2260 assert!(
2261 RUST_CRYPTO_PROVIDER
2262 .unwrap_key(algorithm, &[0x38; 24], &wrapped)
2263 .is_err()
2264 );
2265 wrapped[0] ^= 1;
2266 assert!(
2267 RUST_CRYPTO_PROVIDER
2268 .unwrap_key(algorithm, &kek, &wrapped)
2269 .is_err()
2270 );
2271 }
2272 for length in [0, 1, 8, 15, 17] {
2273 assert!(
2274 RUST_CRYPTO_PROVIDER
2275 .wrap_key(algorithm, &kek, &vec![0; length])
2276 .is_err()
2277 );
2278 }
2279 }
2280 }
2281
2282 #[cfg(all(feature = "legacy-algorithms", feature = "xmldsig"))]
2283 #[test]
2284 fn legacy_digests_match_known_answers() {
2285 for (algorithm, expected) in [
2288 (
2289 DigestAlgorithm::Md5,
2290 &hex_literal::hex!("900150983cd24fb0d6963f7d28e17f72")[..],
2291 ),
2292 (
2293 DigestAlgorithm::Ripemd160,
2294 &hex_literal::hex!("8eb208f7e05d987a9b044a8e98c6b087f15a0bfc")[..],
2295 ),
2296 ] {
2297 assert_eq!(
2298 RUST_CRYPTO_PROVIDER
2299 .digest(algorithm, b"abc")
2300 .expect("compiled digest must be supported"),
2301 expected
2302 );
2303 assert_eq!(DigestAlgorithm::from_uri(algorithm.uri()), Some(algorithm));
2304 assert!(algorithm.requires_explicit_permission());
2305 assert!(!algorithm.signing_allowed());
2306 }
2307 }
2308
2309 #[cfg(feature = "xmldsig")]
2310 struct CountingRandomProvider {
2311 random_calls: AtomicUsize,
2312 reject_digest: Option<DigestAlgorithm>,
2313 extra_digest_byte: bool,
2314 accept_signatures: bool,
2315 }
2316
2317 #[cfg(feature = "xmldsig")]
2318 impl CryptoProvider for CountingRandomProvider {
2319 fn name(&self) -> &'static str {
2320 "counting-random"
2321 }
2322
2323 fn supports(&self, capability: ProviderCapability<'_>) -> bool {
2324 RUST_CRYPTO_PROVIDER.supports(capability)
2325 }
2326
2327 fn fill_random(&self, output: &mut [u8]) -> Result<(), ProviderError> {
2328 self.random_calls.fetch_add(1, Ordering::Relaxed);
2329 RUST_CRYPTO_PROVIDER.fill_random(output)
2330 }
2331
2332 fn derive_key(
2333 &self,
2334 parameters: &KdfParameters<'_>,
2335 secret: &[u8],
2336 ) -> Result<Vec<u8>, ProviderError> {
2337 RUST_CRYPTO_PROVIDER.derive_key(parameters, secret)
2338 }
2339
2340 fn digest(
2341 &self,
2342 algorithm: DigestAlgorithm,
2343 data: &[u8],
2344 ) -> Result<Vec<u8>, ProviderError> {
2345 if self.reject_digest == Some(algorithm) {
2346 return Err(ProviderError::Unsupported {
2347 operation: ProviderOperation::Digest,
2348 algorithm: Some(algorithm.uri().to_owned()),
2349 });
2350 }
2351 let mut digest = RUST_CRYPTO_PROVIDER.digest(algorithm, data)?;
2352 if self.extra_digest_byte {
2353 digest.push(0);
2354 }
2355 Ok(digest)
2356 }
2357
2358 fn sign(
2359 &self,
2360 key: &dyn crate::xmldsig::SigningKey,
2361 algorithm: crate::xmldsig::SignatureAlgorithm,
2362 data: &[u8],
2363 ) -> Result<Vec<u8>, crate::xmldsig::SigningKeyError> {
2364 key.sign_with_provider(self, algorithm, data)
2365 }
2366
2367 fn verify(
2368 &self,
2369 key: &dyn crate::xmldsig::VerifyingKey,
2370 algorithm: crate::xmldsig::SignatureAlgorithm,
2371 data: &[u8],
2372 signature: &[u8],
2373 ) -> Result<bool, crate::xmldsig::DsigError> {
2374 if self.accept_signatures {
2375 return Ok(true);
2376 }
2377 RUST_CRYPTO_PROVIDER.verify(key, algorithm, data, signature)
2378 }
2379
2380 #[cfg(feature = "xmlenc")]
2381 fn encrypt_data(
2382 &self,
2383 algorithm: DataEncryptionAlgorithm,
2384 key: &[u8],
2385 plaintext: &[u8],
2386 ) -> Result<Vec<u8>, ProviderError> {
2387 RUST_CRYPTO_PROVIDER.encrypt_data(algorithm, key, plaintext)
2388 }
2389
2390 #[cfg(feature = "xmlenc")]
2391 fn decrypt_data(
2392 &self,
2393 algorithm: DataEncryptionAlgorithm,
2394 key: &[u8],
2395 ciphertext: &[u8],
2396 ) -> Result<Vec<u8>, ProviderError> {
2397 RUST_CRYPTO_PROVIDER.decrypt_data(algorithm, key, ciphertext)
2398 }
2399
2400 #[cfg(feature = "xmlenc")]
2401 fn wrap_key(
2402 &self,
2403 algorithm: KeyWrapAlgorithm,
2404 kek: &[u8],
2405 key: &[u8],
2406 ) -> Result<Vec<u8>, ProviderError> {
2407 RUST_CRYPTO_PROVIDER.wrap_key(algorithm, kek, key)
2408 }
2409
2410 #[cfg(feature = "xmlenc")]
2411 fn unwrap_key(
2412 &self,
2413 algorithm: KeyWrapAlgorithm,
2414 kek: &[u8],
2415 wrapped: &[u8],
2416 ) -> Result<Vec<u8>, ProviderError> {
2417 RUST_CRYPTO_PROVIDER.unwrap_key(algorithm, kek, wrapped)
2418 }
2419
2420 #[cfg(feature = "xmlenc")]
2421 fn transport_key(
2422 &self,
2423 key: &dyn KeyTransportKey,
2424 parameters: &RsaOaepParameters,
2425 plaintext: &[u8],
2426 ) -> Result<Vec<u8>, ProviderError> {
2427 RUST_CRYPTO_PROVIDER.transport_key(key, parameters, plaintext)
2428 }
2429
2430 #[cfg(feature = "xmlenc")]
2431 fn recover_key(
2432 &self,
2433 key: &dyn KeyRecoveryKey,
2434 parameters: &RsaOaepParameters,
2435 ciphertext: &[u8],
2436 ) -> Result<Vec<u8>, ProviderError> {
2437 RUST_CRYPTO_PROVIDER.recover_key(key, parameters, ciphertext)
2438 }
2439 }
2440
2441 #[cfg(feature = "xmldsig")]
2442 #[test]
2443 fn capability_query_is_explicit_about_unimplemented_operations() {
2444 assert!(RUST_CRYPTO_PROVIDER.supports(ProviderCapability::Digest(DigestAlgorithm::Sha256)));
2445 let agreement = KeyAgreementParameters {
2446 algorithm: "urn:unsupported:agreement",
2447 peer_public_key: &[],
2448 };
2449 assert!(!RUST_CRYPTO_PROVIDER.supports(ProviderCapability::KeyAgreement(&agreement)));
2450 assert!(RUST_CRYPTO_PROVIDER.supports(ProviderCapability::Sign(
2451 crate::xmldsig::SignatureAlgorithm::RsaSha1
2452 )));
2453 assert!(RUST_CRYPTO_PROVIDER.supports(ProviderCapability::Verify(
2454 crate::xmldsig::SignatureAlgorithm::RsaSha1
2455 )));
2456 for digest in [DigestAlgorithm::Sha1, DigestAlgorithm::Sha512] {
2457 assert!(
2458 RUST_CRYPTO_PROVIDER.supports(ProviderCapability::VerifyCertificate(
2459 X509SignatureAlgorithm::Ecdsa(digest)
2460 ))
2461 );
2462 }
2463 #[cfg(feature = "legacy-algorithms")]
2466 for digest in [DigestAlgorithm::Md5, DigestAlgorithm::Ripemd160] {
2467 assert!(
2468 !RUST_CRYPTO_PROVIDER.supports(ProviderCapability::VerifyCertificate(
2469 X509SignatureAlgorithm::Ecdsa(digest)
2470 ))
2471 );
2472 }
2473 }
2474
2475 #[cfg(feature = "xmldsig")]
2476 #[test]
2477 fn x509_digest_key_info_uses_the_selected_provider() {
2478 use crate::xmldsig::{
2479 DigestAlgorithm, KeyInfoWriteError, KeyInfoWriter, RsaSigningKey,
2480 X509DigestKeyInfoWriter,
2481 };
2482
2483 let key = RsaSigningKey::from_pkcs8_pem(include_str!(
2486 "../tests/fixtures/keys/rsa/rsa-2048-key.pem"
2487 ))
2488 .expect("RSA fixture must parse");
2489 let writer = X509DigestKeyInfoWriter::from_pem(
2490 include_str!("../tests/fixtures/keys/rsa/rsa-2048-cert.pem"),
2491 DigestAlgorithm::Sha224,
2492 )
2493 .expect("certificate fixture must parse");
2494 let provider = CountingRandomProvider {
2495 random_calls: AtomicUsize::new(0),
2496 reject_digest: Some(DigestAlgorithm::Sha224),
2497 extra_digest_byte: false,
2498 accept_signatures: false,
2499 };
2500
2501 let error = writer
2502 .write_key_info_with_provider(&key, &provider)
2503 .expect_err("the selected provider must control X509Digest");
2504 assert!(matches!(
2505 error,
2506 KeyInfoWriteError::Provider(ProviderError::Unsupported {
2507 operation: ProviderOperation::Digest,
2508 ..
2509 })
2510 ));
2511 }
2512
2513 #[cfg(feature = "xmldsig")]
2514 #[test]
2515 fn x509_digest_writer_rejects_trailing_certificate_der() {
2516 use crate::xmldsig::{DigestAlgorithm, KeyInfoWriteError, X509DigestKeyInfoWriter};
2517
2518 let (_, certificate) = x509_parser::pem::parse_x509_pem(include_bytes!(
2521 "../tests/fixtures/keys/rsa/rsa-2048-cert.pem"
2522 ))
2523 .expect("certificate fixture must parse");
2524 let mut certificate_der = certificate.contents;
2525 certificate_der.push(0);
2526
2527 assert!(matches!(
2528 X509DigestKeyInfoWriter::from_der(&certificate_der, DigestAlgorithm::Sha256),
2529 Err(KeyInfoWriteError::InvalidCertificateDer)
2530 ));
2531 }
2532
2533 #[cfg(all(feature = "xmldsig", feature = "xmlenc"))]
2534 #[test]
2535 fn capability_queries_include_oaep_and_pss_parameters() {
2536 use crate::xmlenc::{KeyTransportAlgorithm, OaepDigestAlgorithm};
2537
2538 let explicit_legacy = RsaOaepParameters {
2539 algorithm: KeyTransportAlgorithm::RsaOaepMgf1p,
2540 digest: OaepDigestAlgorithm::Sha256,
2541 mgf_digest: OaepDigestAlgorithm::Sha256,
2542 label: Vec::new(),
2543 };
2544 assert!(RUST_CRYPTO_PROVIDER.supports(ProviderCapability::KeyTransport(&explicit_legacy)));
2545 let modern =
2546 RsaOaepParameters::xmlenc11(OaepDigestAlgorithm::Sha256, OaepDigestAlgorithm::Sha512)
2547 .label(b"label".to_vec());
2548 assert!(RUST_CRYPTO_PROVIDER.supports(ProviderCapability::KeyTransport(&modern)));
2549
2550 let supported_pss = X509SignatureAlgorithm::RsaPss {
2551 digest: DigestAlgorithm::Sha256,
2552 mgf_digest: DigestAlgorithm::Sha256,
2553 salt_len: 32,
2554 };
2555 assert!(
2556 RUST_CRYPTO_PROVIDER.supports(ProviderCapability::VerifyCertificate(supported_pss))
2557 );
2558 let unsupported_pss = X509SignatureAlgorithm::RsaPss {
2559 digest: DigestAlgorithm::Sha256,
2560 mgf_digest: DigestAlgorithm::Sha384,
2561 salt_len: 32,
2562 };
2563 assert!(
2564 !RUST_CRYPTO_PROVIDER.supports(ProviderCapability::VerifyCertificate(unsupported_pss))
2565 );
2566 }
2567
2568 struct RecordingAgreementKey(AtomicBool);
2569
2570 impl KeyAgreementKey for RecordingAgreementKey {
2571 fn agree(
2572 &self,
2573 _parameters: &KeyAgreementParameters<'_>,
2574 ) -> Result<Vec<u8>, ProviderError> {
2575 self.0.store(true, Ordering::Relaxed);
2576 Ok(vec![0x42])
2577 }
2578 }
2579
2580 #[test]
2581 fn unsupported_agreement_and_kdf_fail_without_dispatch_or_fallback() {
2582 let agreement = KeyAgreementParameters {
2583 algorithm: "urn:example:agreement",
2584 peer_public_key: b"peer",
2585 };
2586 let key = RecordingAgreementKey(AtomicBool::new(false));
2587 let error = RUST_CRYPTO_PROVIDER
2588 .agree_key(&key, &agreement)
2589 .expect_err("unsupported agreement must fail closed");
2590 assert!(matches!(
2591 error,
2592 ProviderError::Unsupported {
2593 operation: ProviderOperation::KeyAgreement,
2594 algorithm: Some(ref algorithm),
2595 } if algorithm == agreement.algorithm
2596 ));
2597 assert!(!key.0.load(Ordering::Relaxed));
2598
2599 let kdf = KdfParameters {
2600 algorithm: "urn:example:kdf",
2601 digest: Some("urn:example:digest"),
2602 salt: b"salt",
2603 info: b"info",
2604 iterations: 1,
2605 output_len: 32,
2606 };
2607 assert!(matches!(
2608 RUST_CRYPTO_PROVIDER.derive_key(&kdf, b"secret"),
2609 Err(ProviderError::Unsupported {
2610 operation: ProviderOperation::Kdf,
2611 algorithm: Some(ref algorithm),
2612 }) if algorithm == kdf.algorithm
2613 ));
2614 }
2615
2616 #[cfg(feature = "xmldsig")]
2617 #[test]
2618 fn rsa_signing_uses_the_selected_providers_randomness() {
2619 use crate::xmldsig::{RsaSigningKey, SignatureAlgorithm};
2620
2621 let key = RsaSigningKey::from_pkcs8_pem(include_str!(
2624 "../tests/fixtures/keys/rsa/rsa-2048-key.pem"
2625 ))
2626 .expect("RSA fixture must parse");
2627 let provider = CountingRandomProvider {
2628 random_calls: AtomicUsize::new(0),
2629 reject_digest: None,
2630 extra_digest_byte: false,
2631 accept_signatures: false,
2632 };
2633
2634 let signature = provider
2635 .sign(&key, SignatureAlgorithm::RsaSha256, b"signed info")
2636 .expect("RSA signing must succeed");
2637
2638 assert!(!signature.is_empty());
2639 assert!(provider.random_calls.load(Ordering::Relaxed) > 0);
2640 }
2641
2642 #[cfg(feature = "xmldsig")]
2643 #[test]
2644 fn ecdsa_signing_uses_the_selected_providers_digest() {
2645 use crate::xmldsig::{
2646 EcdsaP256SigningKey, EcdsaP384SigningKey, SignatureAlgorithm, SigningKeyError,
2647 };
2648
2649 let cases: [(
2653 Box<dyn crate::xmldsig::SigningKey>,
2654 SignatureAlgorithm,
2655 DigestAlgorithm,
2656 ); 2] = [
2657 (
2658 Box::new(
2659 EcdsaP256SigningKey::from_pkcs8_pem(include_str!(
2660 "../tests/fixtures/keys/ec/ec-prime256v1-key.pem"
2661 ))
2662 .expect("P-256 fixture must parse"),
2663 ),
2664 SignatureAlgorithm::EcdsaSha384,
2665 DigestAlgorithm::Sha384,
2666 ),
2667 (
2668 Box::new(
2669 EcdsaP384SigningKey::from_pkcs8_pem(include_str!(
2670 "../tests/fixtures/keys/ec/ec-prime384v1-key.pem"
2671 ))
2672 .expect("P-384 fixture must parse"),
2673 ),
2674 SignatureAlgorithm::EcdsaSha256,
2675 DigestAlgorithm::Sha256,
2676 ),
2677 ];
2678
2679 for (key, signature_algorithm, digest_algorithm) in cases {
2680 let provider = CountingRandomProvider {
2681 random_calls: AtomicUsize::new(0),
2682 reject_digest: Some(digest_algorithm),
2683 extra_digest_byte: false,
2684 accept_signatures: false,
2685 };
2686 let error = provider
2687 .sign(key.as_ref(), signature_algorithm, b"signed info")
2688 .expect_err("provider digest rejection must stop ECDSA signing");
2689
2690 assert!(matches!(
2691 error,
2692 SigningKeyError::Provider(ProviderError::Unsupported {
2693 operation: ProviderOperation::Digest,
2694 algorithm: Some(ref uri),
2695 }) if uri == digest_algorithm.uri()
2696 ));
2697 }
2698 }
2699
2700 #[cfg(feature = "xmldsig")]
2701 #[test]
2702 fn ecdsa_signing_rejects_provider_digests_with_the_wrong_length() {
2703 use crate::xmldsig::{
2704 EcdsaP256SigningKey, EcdsaP384SigningKey, SignatureAlgorithm, SigningKeyError,
2705 };
2706
2707 let cases: [(
2710 Box<dyn crate::xmldsig::SigningKey>,
2711 SignatureAlgorithm,
2712 usize,
2713 ); 2] = [
2714 (
2715 Box::new(
2716 EcdsaP256SigningKey::from_pkcs8_pem(include_str!(
2717 "../tests/fixtures/keys/ec/ec-prime256v1-key.pem"
2718 ))
2719 .expect("P-256 fixture must parse"),
2720 ),
2721 SignatureAlgorithm::EcdsaSha256,
2722 32,
2723 ),
2724 (
2725 Box::new(
2726 EcdsaP384SigningKey::from_pkcs8_pem(include_str!(
2727 "../tests/fixtures/keys/ec/ec-prime384v1-key.pem"
2728 ))
2729 .expect("P-384 fixture must parse"),
2730 ),
2731 SignatureAlgorithm::EcdsaSha384,
2732 48,
2733 ),
2734 ];
2735
2736 for (key, algorithm, expected) in cases {
2737 let provider = CountingRandomProvider {
2738 random_calls: AtomicUsize::new(0),
2739 reject_digest: None,
2740 extra_digest_byte: true,
2741 accept_signatures: false,
2742 };
2743 let error = provider
2744 .sign(key.as_ref(), algorithm, b"signed info")
2745 .expect_err("an oversized provider digest must not reach ECDSA prehash signing");
2746
2747 assert!(matches!(
2748 error,
2749 SigningKeyError::Provider(ProviderError::InvalidOutputSize {
2750 operation: ProviderOperation::Digest,
2751 expected: actual_expected,
2752 actual,
2753 }) if actual_expected == expected && actual == expected + 1
2754 ));
2755 }
2756 }
2757
2758 #[cfg(feature = "xmldsig")]
2759 #[test]
2760 fn verification_facade_rejects_malformed_dsa_before_provider_dispatch() {
2761 use crate::xmldsig::{
2762 DefaultKeyResolver, DsigStatus, FailureReason, SignatureAlgorithm, VerifyContext,
2763 };
2764
2765 let original = include_str!(
2766 "../tests/fixtures/xmldsig/merlin-xmldsig-twenty-three/signature-enveloping-dsa.xml"
2767 );
2768 let value_start = original
2769 .find("<SignatureValue>")
2770 .expect("Merlin fixture must contain SignatureValue")
2771 + "<SignatureValue>".len();
2772 let value_end = original[value_start..]
2773 .find("</SignatureValue>")
2774 .map(|offset| value_start + offset)
2775 .expect("Merlin fixture must close SignatureValue");
2776 let mut malformed = original.to_owned();
2777 malformed.replace_range(value_start..value_end, "AQ==");
2778 let provider = CountingRandomProvider {
2779 random_calls: AtomicUsize::new(0),
2780 reject_digest: None,
2781 extra_digest_byte: false,
2782 accept_signatures: true,
2783 };
2784
2785 let mut policy = crate::policy::VerificationPolicy::default();
2786 policy
2787 .key_trust
2788 .allowed_legacy_signature_algorithms
2789 .insert(SignatureAlgorithm::DsaSha1);
2790 policy.key_trust.dsa_keys.minimum_modulus_bits = 1024;
2791 policy.key_trust.mode = crate::policy::VerificationTrustMode::CryptographicOnly;
2792 let result = VerifyContext::new()
2793 .policy(policy)
2794 .provider(&provider)
2795 .key_resolver(&DefaultKeyResolver::default())
2796 .verify(&malformed)
2797 .expect("malformed framing must be a verification miss");
2798
2799 assert_eq!(
2800 result.status,
2801 DsigStatus::Invalid(FailureReason::SignatureMismatch)
2802 );
2803 }
2804
2805 #[cfg(feature = "xmldsig")]
2806 #[test]
2807 fn rustcrypto_provider_verifies_parameterized_rsa_pss_certificates() {
2808 use der::{Decode as _, Encode as _};
2809 use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng};
2810 use rsa::{RsaPrivateKey, pkcs8::EncodePublicKey, pss::SigningKey as RsaPssSigningKey};
2811 use sha2::Sha256;
2812 use signature::{RandomizedSigner, SignatureEncoding};
2813 use x509_cert::spki::{AlgorithmIdentifierOwned, ObjectIdentifier};
2814
2815 let mut rng = ChaCha20Rng::from_seed([0x5a; 32]);
2818 let private_key =
2819 RsaPrivateKey::new(&mut rng, 2048).expect("deterministic RSA key generation");
2820 let public_key = private_key
2821 .to_public_key()
2822 .to_public_key_der()
2823 .expect("RSA public key must encode as SPKI");
2824 let signing_key = RsaPssSigningKey::<Sha256>::new_with_salt_len(private_key, 32);
2825 let signed_data = b"certificate tbs bytes";
2826 let signature = signing_key
2827 .try_sign_with_rng(&mut rng, signed_data)
2828 .expect("RSA-PSS signing must succeed")
2829 .to_vec();
2830
2831 assert!(
2832 RUST_CRYPTO_PROVIDER
2833 .verify_x509_signature(
2834 X509SignatureAlgorithm::RsaPss {
2835 digest: DigestAlgorithm::Sha256,
2836 mgf_digest: DigestAlgorithm::Sha256,
2837 salt_len: 32,
2838 },
2839 signed_data,
2840 &signature,
2841 public_key.as_bytes(),
2842 )
2843 .expect("standard RSA-PSS parameters must be supported")
2844 );
2845
2846 let mut parameterless_pss_spki =
2847 x509_cert::SubjectPublicKeyInfo::from_der(public_key.as_bytes())
2848 .expect("RSA SPKI must decode");
2849 parameterless_pss_spki.algorithm = AlgorithmIdentifierOwned {
2850 oid: ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10"),
2851 parameters: None,
2852 };
2853 let parameterless_pss_spki = parameterless_pss_spki
2854 .to_der()
2855 .expect("parameterless PSS SPKI must encode");
2856 assert!(
2857 RUST_CRYPTO_PROVIDER
2858 .verify_x509_signature(
2859 X509SignatureAlgorithm::RsaPss {
2860 digest: DigestAlgorithm::Sha256,
2861 mgf_digest: DigestAlgorithm::Sha256,
2862 salt_len: 32,
2863 },
2864 signed_data,
2865 &signature,
2866 ¶meterless_pss_spki,
2867 )
2868 .expect("parameterless PSS keys impose no signature restrictions")
2869 );
2870
2871 let mut pss_spki = x509_cert::SubjectPublicKeyInfo::from_der(public_key.as_bytes())
2872 .expect("RSA SPKI must decode");
2873 let pss_parameters = der::asn1::Any::from_der(&[
2874 0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
2875 0x04, 0x02, 0x01, 0x05, 0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48,
2876 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
2877 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x20,
2878 ])
2879 .expect("standard SHA-256 PSS parameters must decode");
2880 pss_spki.algorithm = AlgorithmIdentifierOwned {
2881 oid: ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10"),
2882 parameters: Some(pss_parameters),
2883 };
2884 let pss_spki = pss_spki.to_der().expect("PSS SPKI must encode");
2885
2886 assert!(
2887 RUST_CRYPTO_PROVIDER
2888 .verify_x509_signature(
2889 X509SignatureAlgorithm::RsaPss {
2890 digest: DigestAlgorithm::Sha256,
2891 mgf_digest: DigestAlgorithm::Sha256,
2892 salt_len: 32,
2893 },
2894 signed_data,
2895 &signature,
2896 &pss_spki,
2897 )
2898 .expect("RFC 4055 PSS SubjectPublicKeyInfo must be supported")
2899 );
2900
2901 for incompatible in [
2902 X509SignatureAlgorithm::RsaPss {
2903 digest: DigestAlgorithm::Sha384,
2904 mgf_digest: DigestAlgorithm::Sha256,
2905 salt_len: 32,
2906 },
2907 X509SignatureAlgorithm::RsaPss {
2908 digest: DigestAlgorithm::Sha256,
2909 mgf_digest: DigestAlgorithm::Sha384,
2910 salt_len: 32,
2911 },
2912 X509SignatureAlgorithm::RsaPss {
2913 digest: DigestAlgorithm::Sha256,
2914 mgf_digest: DigestAlgorithm::Sha256,
2915 salt_len: 16,
2916 },
2917 ] {
2918 assert!(
2919 !RUST_CRYPTO_PROVIDER
2920 .verify_x509_signature(incompatible, signed_data, &signature, &pss_spki,)
2921 .expect("incompatible PSS key restrictions are invalid, not unsupported")
2922 );
2923 }
2924 }
2925
2926 #[cfg(feature = "xmldsig")]
2927 #[test]
2928 fn rustcrypto_provider_verifies_dsa_certificate_signature_at_q_width() {
2929 use base64::Engine as _;
2930
2931 let spki = base64::engine::general_purpose::STANDARD
2934 .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=")
2935 .expect("DSA SPKI fixture must decode");
2936 let signature = base64::engine::general_purpose::STANDARD
2937 .decode("MD0CHQChtB1c+f5BmTJCtT7Gi4cyQiR2igj0znRQYCJ3Ahw4NGg4pL5jgA8Ri07ESV9Yr90WfUmRrbRcnjsY")
2938 .expect("DSA signature fixture must decode");
2939 let message = b"certificate tbs bytes for dsa q-width regression";
2940
2941 assert!(
2942 rustcrypto_x509::verify_signature(
2943 X509SignatureAlgorithm::Dsa(DigestAlgorithm::Sha1),
2944 message,
2945 &signature,
2946 &spki,
2947 )
2948 .expect("supported DSA-SHA1 certificate signature")
2949 );
2950
2951 let mut tampered = signature;
2952 *tampered.last_mut().expect("DER signature is non-empty") ^= 1;
2953 assert!(
2954 !rustcrypto_x509::verify_signature(
2955 X509SignatureAlgorithm::Dsa(DigestAlgorithm::Sha1),
2956 message,
2957 &tampered,
2958 &spki,
2959 )
2960 .expect("tampered DSA-SHA1 certificate signature is a verification miss")
2961 );
2962 }
2963
2964 #[cfg(feature = "xmldsig")]
2965 #[test]
2966 fn primitive_provider_does_not_embed_rsa_strength_policy() {
2967 use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng};
2968 use rsa::{RsaPrivateKey, pkcs8::EncodePublicKey, pss::SigningKey as RsaPssSigningKey};
2969 use sha2::Sha256;
2970 use signature::{RandomizedSigner, SignatureEncoding};
2971
2972 let mut rng = ChaCha20Rng::from_seed([0x3c; 32]);
2973 let private_key =
2974 RsaPrivateKey::new(&mut rng, 1024).expect("deterministic weak RSA key generation");
2975 let public_key = private_key
2976 .to_public_key()
2977 .to_public_key_der()
2978 .expect("weak RSA public key must encode as SPKI");
2979 let signed_data = b"certificate tbs bytes";
2980 let signature = RsaPssSigningKey::<Sha256>::new_with_salt_len(private_key, 32)
2981 .try_sign_with_rng(&mut rng, signed_data)
2982 .expect("weak RSA-PSS key can still produce a cryptographic signature")
2983 .to_vec();
2984
2985 assert!(
2986 RUST_CRYPTO_PROVIDER
2987 .verify_x509_signature(
2988 X509SignatureAlgorithm::RsaPss {
2989 digest: DigestAlgorithm::Sha256,
2990 mgf_digest: DigestAlgorithm::Sha256,
2991 salt_len: 32,
2992 },
2993 signed_data,
2994 &signature,
2995 public_key.as_bytes(),
2996 )
2997 .expect(
2998 "provider must evaluate structurally valid RSA-PSS independently of policy"
2999 )
3000 );
3001 }
3002
3003 #[cfg(feature = "xmldsig")]
3004 #[test]
3005 fn oversized_rsa_pss_salt_is_a_verification_miss() {
3006 use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng};
3007 use rsa::{RsaPrivateKey, pkcs8::EncodePublicKey as _, traits::PublicKeyParts as _};
3008
3009 let mut rng = ChaCha20Rng::from_seed([0x55; 32]);
3012 let public_key = RsaPrivateKey::new(&mut rng, 1024)
3013 .expect("deterministic RSA key generation")
3014 .to_public_key();
3015 let spki = public_key
3016 .to_public_key_der()
3017 .expect("RSA public key must encode as SPKI");
3018
3019 assert!(rustcrypto_x509::rsa_pss_salt_fits_key(
3020 &public_key,
3021 DigestAlgorithm::Sha256,
3022 0,
3023 ));
3024 assert!(rustcrypto_x509::rsa_pss_salt_fits_key(
3025 &public_key,
3026 DigestAlgorithm::Sha256,
3027 94,
3028 ));
3029 assert!(!rustcrypto_x509::rsa_pss_salt_fits_key(
3030 &public_key,
3031 DigestAlgorithm::Sha256,
3032 95,
3033 ));
3034
3035 assert!(
3036 !RUST_CRYPTO_PROVIDER
3037 .verify_x509_signature(
3038 X509SignatureAlgorithm::RsaPss {
3039 digest: DigestAlgorithm::Sha256,
3040 mgf_digest: DigestAlgorithm::Sha256,
3041 salt_len: usize::MAX,
3042 },
3043 b"certificate tbs bytes",
3044 &vec![0_u8; public_key.size()],
3045 spki.as_bytes(),
3046 )
3047 .expect("oversized PSS salt must fail without panicking")
3048 );
3049 }
3050}