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