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