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