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