1use crate::rsa_encoding::RsaPublicKeyEncoding as _;
14use der::Decode as _;
15use p256::ecdsa::{Signature as P256Signature, VerifyingKey as P256VerifyingKey};
16use p384::ecdsa::{Signature as P384Signature, VerifyingKey as P384VerifyingKey};
17use p521::ecdsa::{Signature as P521Signature, VerifyingKey as P521VerifyingKey};
18use pkcs8::DecodePublicKey as _;
19use pkcs8::SubjectPublicKeyInfoRef;
20use rsa::signature::hazmat::PrehashVerifier;
21use rsa::{
22 pkcs1v15::{Signature as RsaPkcs1v15Signature, VerifyingKey as RsaVerifyingKey},
23 traits::PublicKeyParts,
24};
25use sha1::Sha1;
26use sha2::{Digest, Sha224, Sha256, Sha384, Sha512};
27use signature::Verifier;
28
29use super::parse::SignatureAlgorithm;
30use crate::policy::EcdsaSignatureValueEncoding;
31
32pub(crate) fn signature_value_matches_algorithm(
33 algorithm: SignatureAlgorithm,
34 signature_value: &[u8],
35) -> bool {
36 signature_value_matches_algorithm_with_encoding(
37 algorithm,
38 signature_value,
39 EcdsaSignatureValueEncoding::XmlDsig,
40 )
41}
42
43pub(crate) fn signature_value_matches_algorithm_with_encoding(
44 algorithm: SignatureAlgorithm,
45 signature_value: &[u8],
46 encoding: EcdsaSignatureValueEncoding,
47) -> bool {
48 if algorithm.rsa_pss_parameters().is_some() {
49 return (1..=crate::hard_limits::RSA_MODULUS_BIT_CEILING / 8)
50 .contains(&signature_value.len());
51 }
52 match algorithm {
53 #[cfg(feature = "legacy-algorithms")]
54 SignatureAlgorithm::RsaMd5 | SignatureAlgorithm::RsaRipemd160 => {
55 (1..=crate::hard_limits::RSA_MODULUS_BIT_CEILING / 8).contains(&signature_value.len())
56 }
57 #[cfg(feature = "legacy-algorithms")]
58 SignatureAlgorithm::HmacMd5 | SignatureAlgorithm::HmacRipemd160 => algorithm
59 .hmac_output_bits()
60 .is_some_and(|bits| (1..=bits / 8).contains(&signature_value.len())),
61 #[cfg(feature = "legacy-algorithms")]
62 SignatureAlgorithm::EcdsaRipemd160 => {
63 [32, 48, 66]
64 .into_iter()
65 .any(|component_len| match encoding {
66 EcdsaSignatureValueEncoding::XmlDsig => {
67 signature_value.len() == component_len * 2
68 }
69 EcdsaSignatureValueEncoding::XmlSecAsn1Der => {
70 inspect_der_encoded_ecdsa_signature(signature_value, component_len)
71 .is_ok_and(|value| value.is_some())
72 }
73 })
74 }
75 SignatureAlgorithm::PostQuantum(algorithm) => {
76 signature_value.len() == algorithm.signature_len()
77 }
78 SignatureAlgorithm::Ed25519
79 | SignatureAlgorithm::Ed25519Ctx
80 | SignatureAlgorithm::Ed25519Ph => signature_value.len() == 64,
81 SignatureAlgorithm::Ed448 | SignatureAlgorithm::Ed448Ph => signature_value.len() == 114,
82 SignatureAlgorithm::DsaSha1 | SignatureAlgorithm::DsaSha256 => algorithm
83 .dsa_component_len()
84 .is_some_and(|component_len| signature_value.len() == component_len * 2),
85 SignatureAlgorithm::HmacSha1
86 | SignatureAlgorithm::HmacSha224
87 | SignatureAlgorithm::HmacSha256
88 | SignatureAlgorithm::HmacSha384
89 | SignatureAlgorithm::HmacSha512 => algorithm
90 .hmac_output_bits()
91 .is_some_and(|bits| (1..=bits / 8).contains(&signature_value.len())),
92 SignatureAlgorithm::RsaSha1
96 | SignatureAlgorithm::RsaSha224
97 | SignatureAlgorithm::RsaSha256
98 | SignatureAlgorithm::RsaSha384
99 | SignatureAlgorithm::RsaSha512 => {
100 (1..=crate::hard_limits::RSA_MODULUS_BIT_CEILING / 8).contains(&signature_value.len())
101 }
102 SignatureAlgorithm::RsaPssSha1
103 | SignatureAlgorithm::RsaPssSha224
104 | SignatureAlgorithm::RsaPssSha256
105 | SignatureAlgorithm::RsaPssSha384
106 | SignatureAlgorithm::RsaPssSha512
107 | SignatureAlgorithm::RsaPssSha3_224
108 | SignatureAlgorithm::RsaPssSha3_256
109 | SignatureAlgorithm::RsaPssSha3_384
110 | SignatureAlgorithm::RsaPssSha3_512
111 | SignatureAlgorithm::RsaPss(_) => unreachable!("PSS handled before dispatch"),
112 SignatureAlgorithm::EcdsaSha1
113 | SignatureAlgorithm::EcdsaSha224
114 | SignatureAlgorithm::EcdsaSha256
115 | SignatureAlgorithm::EcdsaSha384
116 | SignatureAlgorithm::EcdsaSha512
117 | SignatureAlgorithm::EcdsaSha3_224
118 | SignatureAlgorithm::EcdsaSha3_256
119 | SignatureAlgorithm::EcdsaSha3_384
120 | SignatureAlgorithm::EcdsaSha3_512 => {
121 [32, 48, 66]
122 .into_iter()
123 .any(|component_len| match encoding {
124 EcdsaSignatureValueEncoding::XmlDsig => {
125 signature_value.len() == component_len * 2
126 }
127 EcdsaSignatureValueEncoding::XmlSecAsn1Der => {
128 inspect_der_encoded_ecdsa_signature(signature_value, component_len)
129 .is_ok_and(|value| value.is_some())
130 }
131 })
132 }
133 }
134}
135
136pub(crate) fn signature_value_matches_spki(
137 algorithm: SignatureAlgorithm,
138 public_key_spki_der: &[u8],
139 signature_value: &[u8],
140) -> Result<bool, SignatureVerificationError> {
141 signature_value_matches_spki_with_encoding(
142 algorithm,
143 public_key_spki_der,
144 signature_value,
145 EcdsaSignatureValueEncoding::XmlDsig,
146 )
147}
148
149pub(crate) fn signature_value_matches_spki_with_encoding(
150 algorithm: SignatureAlgorithm,
151 public_key_spki_der: &[u8],
152 signature_value: &[u8],
153 encoding: EcdsaSignatureValueEncoding,
154) -> Result<bool, SignatureVerificationError> {
155 if let Some(length) = algorithm.eddsa_signature_len() {
156 super::modern::validate_public_key(algorithm, public_key_spki_der)?;
157 return Ok(signature_value.len() == length);
158 }
159 if let SignatureAlgorithm::PostQuantum(algorithm) = algorithm {
160 #[cfg(feature = "experimental-pq")]
161 {
162 super::post_quantum::validate_public_key(algorithm, public_key_spki_der)?;
163 return Ok(signature_value.len() == algorithm.signature_len());
164 }
165 #[cfg(not(feature = "experimental-pq"))]
166 {
167 return Err(SignatureVerificationError::UnsupportedAlgorithm {
168 uri: algorithm.uri().to_owned(),
169 });
170 }
171 }
172 if let Some(parameters) = algorithm.rsa_pss_parameters() {
173 use der::Decode as _;
174 let bytes = crate::provider::rsa_pss::encoded_public_key(public_key_spki_der, parameters)
175 .ok_or(SignatureVerificationError::InvalidKeyDer)?;
176 let key = pkcs1::RsaPublicKeyRef::from_der(bytes)
177 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
178 let modulus = key.modulus.as_bytes();
179 let Some(first) = modulus.first() else {
180 return Err(SignatureVerificationError::InvalidKeyDer);
181 };
182 let bits = modulus.len() * 8 - first.leading_zeros() as usize;
183 return Ok(parameters.fits_modulus_bits(bits) && signature_value.len() == modulus.len());
184 }
185 let spki = SubjectPublicKeyInfoRef::from_der(public_key_spki_der)
186 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
187 match (algorithm, spki.algorithm.oid) {
188 (algorithm @ (SignatureAlgorithm::DsaSha1 | SignatureAlgorithm::DsaSha256), dsa::OID) => {
189 let key = decode_dsa_verifying_key(public_key_spki_der)?;
190 let component_len = usize::try_from(key.components().q().bits_vartime())
191 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?
192 .div_ceil(8);
193 Ok(algorithm.dsa_component_len() == Some(component_len)
194 && signature_value.len() == component_len * 2)
195 }
196 (method, pkcs1::ALGORITHM_OID) if method.is_rsa() => {
197 let key = rsa::RsaPublicKey::from_public_key_der(public_key_spki_der)
198 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
199 Ok(signature_value.len() == key.size())
200 }
201 (method, oid)
202 if method.ecdsa_digest().is_some() && oid == p256::elliptic_curve::ALGORITHM_OID =>
203 {
204 let (_, component_len) = ecdsa_curve_and_component_len(&spki)?;
205 match encoding {
206 EcdsaSignatureValueEncoding::XmlDsig
207 if signature_value.len() == component_len * 2 => {}
208 EcdsaSignatureValueEncoding::XmlSecAsn1Der
209 if inspect_der_encoded_ecdsa_signature(signature_value, component_len)?
210 .is_some() => {}
211 _ => return Err(SignatureVerificationError::InvalidSignatureFormat),
212 }
213 Ok(true)
214 }
215 (
216 SignatureAlgorithm::HmacSha1
217 | SignatureAlgorithm::HmacSha224
218 | SignatureAlgorithm::HmacSha256
219 | SignatureAlgorithm::HmacSha384
220 | SignatureAlgorithm::HmacSha512,
221 _,
222 ) => Err(SignatureVerificationError::KeyAlgorithmMismatch {
223 uri: algorithm.uri().to_owned(),
224 }),
225 _ => Err(SignatureVerificationError::KeyAlgorithmMismatch {
226 uri: algorithm.uri().to_owned(),
227 }),
228 }
229}
230
231#[derive(Debug, thiserror::Error)]
233#[non_exhaustive]
234pub enum SignatureVerificationError {
235 #[error("invalid PEM public key")]
237 InvalidKeyPem,
238
239 #[error("unsupported signature algorithm: {uri}")]
241 UnsupportedAlgorithm {
242 uri: String,
244 },
245
246 #[error("invalid key format: expected PUBLIC KEY PEM, got {label}")]
248 InvalidKeyFormat {
249 label: String,
251 },
252
253 #[error("invalid SubjectPublicKeyInfo DER")]
255 InvalidKeyDer,
256
257 #[error("verification key rejected by policy: {0}")]
259 KeyPolicy(#[from] crate::policy::PolicyViolation),
260
261 #[error("public key does not match signature algorithm: {uri}")]
263 KeyAlgorithmMismatch {
264 uri: String,
266 },
267
268 #[error("invalid ECDSA signature encoding")]
271 InvalidSignatureFormat,
272}
273
274#[must_use = "discarding the verification result skips signature validation"]
279pub fn verify_rsa_signature_pem(
280 algorithm: SignatureAlgorithm,
281 public_key_pem: &str,
282 signed_data: &[u8],
283 signature_value: &[u8],
284) -> Result<bool, SignatureVerificationError> {
285 let public_key_spki_der = parse_public_key_pem(public_key_pem)?;
286 verify_rsa_signature_spki(
287 algorithm,
288 &public_key_spki_der,
289 signed_data,
290 signature_value,
291 )
292}
293
294#[must_use = "discarding the verification result skips signature validation"]
303pub fn verify_ecdsa_signature_pem(
304 algorithm: SignatureAlgorithm,
305 public_key_pem: &str,
306 signed_data: &[u8],
307 signature_value: &[u8],
308) -> Result<bool, SignatureVerificationError> {
309 verify_ecdsa_signature_pem_with_encoding(
310 algorithm,
311 public_key_pem,
312 signed_data,
313 signature_value,
314 EcdsaSignatureValueEncoding::XmlDsig,
315 )
316}
317
318#[must_use = "discarding the verification result skips signature validation"]
320pub fn verify_ecdsa_signature_pem_with_encoding(
321 algorithm: SignatureAlgorithm,
322 public_key_pem: &str,
323 signed_data: &[u8],
324 signature_value: &[u8],
325 encoding: EcdsaSignatureValueEncoding,
326) -> Result<bool, SignatureVerificationError> {
327 let public_key_spki_der = parse_public_key_pem(public_key_pem)?;
328 verify_ecdsa_signature_spki_with_encoding(
329 algorithm,
330 &public_key_spki_der,
331 signed_data,
332 signature_value,
333 encoding,
334 )
335}
336
337fn parse_public_key_pem(public_key_pem: &str) -> Result<Vec<u8>, SignatureVerificationError> {
338 let (rest, pem) = x509_parser::pem::parse_x509_pem(public_key_pem.as_bytes())
339 .map_err(|_| SignatureVerificationError::InvalidKeyPem)?;
340 if !rest.iter().all(|byte| byte.is_ascii_whitespace()) {
341 return Err(SignatureVerificationError::InvalidKeyPem);
342 }
343 if pem.label != "PUBLIC KEY" {
344 return Err(SignatureVerificationError::InvalidKeyFormat { label: pem.label });
345 }
346
347 Ok(pem.contents)
348}
349
350#[must_use = "discarding the verification result skips signature validation"]
356pub fn verify_rsa_signature_spki(
357 algorithm: SignatureAlgorithm,
358 public_key_spki_der: &[u8],
359 signed_data: &[u8],
360 signature_value: &[u8],
361) -> Result<bool, SignatureVerificationError> {
362 verify_rsa_signature_spki_with_minimum(
363 algorithm,
364 public_key_spki_der,
365 signed_data,
366 signature_value,
367 2048,
368 )
369}
370
371pub(crate) fn verify_rsa_signature_spki_with_minimum(
372 algorithm: SignatureAlgorithm,
373 public_key_spki_der: &[u8],
374 signed_data: &[u8],
375 signature_value: &[u8],
376 minimum_modulus_bits: usize,
377) -> Result<bool, SignatureVerificationError> {
378 validate_rsa_signature_spki_with_minimum(algorithm, public_key_spki_der, minimum_modulus_bits)?;
379 verify_rsa_signature_spki_primitive(
380 algorithm,
381 public_key_spki_der,
382 signed_data,
383 signature_value,
384 )
385}
386
387pub(crate) fn validate_rsa_signature_spki_with_minimum(
388 algorithm: SignatureAlgorithm,
389 public_key_spki_der: &[u8],
390 minimum_modulus_bits: usize,
391) -> Result<(), SignatureVerificationError> {
392 if let Some(parameters) = algorithm.rsa_pss_parameters() {
393 use der::Decode as _;
394 let bytes = crate::provider::rsa_pss::encoded_public_key(public_key_spki_der, parameters)
395 .ok_or(SignatureVerificationError::InvalidKeyDer)?;
396 let key = pkcs1::RsaPublicKeyRef::from_der(bytes)
397 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
398 let modulus = key.modulus.as_bytes();
399 validate_rsa_key_components(
400 modulus,
401 key.public_exponent.as_bytes(),
402 minimum_modulus_bits,
403 )?;
404 let bits = modulus.len() * 8 - modulus[0].leading_zeros() as usize;
405 return if parameters.fits_modulus_bits(bits) {
406 Ok(())
407 } else {
408 Err(SignatureVerificationError::KeyAlgorithmMismatch {
409 uri: algorithm.uri().into(),
410 })
411 };
412 }
413 let spki = SubjectPublicKeyInfoRef::from_der(public_key_spki_der)
414 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
415 match spki.algorithm.oid {
416 pkcs1::ALGORITHM_OID => {
417 let octets = spki
418 .subject_public_key
419 .as_bytes()
420 .ok_or(SignatureVerificationError::InvalidKeyDer)?;
421 let key = pkcs1::RsaPublicKeyRef::from_der(octets)
422 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
423 validate_rsa_public_key(&key, algorithm, minimum_modulus_bits)
424 }
425 _ => Err(SignatureVerificationError::KeyAlgorithmMismatch {
426 uri: algorithm.uri().to_string(),
427 }),
428 }
429}
430
431pub(crate) fn verify_rsa_signature_spki_primitive(
432 algorithm: SignatureAlgorithm,
433 public_key_spki_der: &[u8],
434 signed_data: &[u8],
435 signature_value: &[u8],
436) -> Result<bool, SignatureVerificationError> {
437 ensure_rsa_signature_algorithm(algorithm)?;
438 if let Some(parameters) = algorithm.rsa_pss_parameters() {
439 let key = crate::provider::rsa_pss::public_key(public_key_spki_der, parameters)
440 .ok_or(SignatureVerificationError::InvalidKeyDer)?;
441 return Ok(crate::provider::rsa_pss::verify(
442 &key,
443 parameters,
444 signed_data,
445 signature_value,
446 ));
447 }
448 let key = rsa::RsaPublicKey::from_public_key_der(public_key_spki_der)
449 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
450 let Ok(signature) = RsaPkcs1v15Signature::try_from(signature_value) else {
451 return Ok(false);
452 };
453 let verified = match algorithm {
454 #[cfg(feature = "legacy-algorithms")]
455 SignatureAlgorithm::RsaMd5 => RsaVerifyingKey::<md5::Md5>::new(key)
456 .verify(signed_data, &signature)
457 .is_ok(),
458 #[cfg(feature = "legacy-algorithms")]
459 SignatureAlgorithm::RsaRipemd160 => RsaVerifyingKey::<ripemd::Ripemd160>::new(key)
460 .verify(signed_data, &signature)
461 .is_ok(),
462 SignatureAlgorithm::RsaSha1 => RsaVerifyingKey::<Sha1>::new(key)
463 .verify(signed_data, &signature)
464 .is_ok(),
465 SignatureAlgorithm::RsaSha224 => RsaVerifyingKey::<Sha224>::new(key)
466 .verify(signed_data, &signature)
467 .is_ok(),
468 SignatureAlgorithm::RsaSha256 => RsaVerifyingKey::<Sha256>::new(key)
469 .verify(signed_data, &signature)
470 .is_ok(),
471 SignatureAlgorithm::RsaSha384 => RsaVerifyingKey::<Sha384>::new(key)
472 .verify(signed_data, &signature)
473 .is_ok(),
474 SignatureAlgorithm::RsaSha512 => RsaVerifyingKey::<Sha512>::new(key)
475 .verify(signed_data, &signature)
476 .is_ok(),
477 _ => unreachable!("RSA algorithm checked above"),
478 };
479 Ok(verified)
480}
481
482#[must_use = "discarding the verification result skips signature validation"]
489pub fn verify_dsa_signature_spki(
490 algorithm: SignatureAlgorithm,
491 public_key_spki_der: &[u8],
492 signed_data: &[u8],
493 signature_value: &[u8],
494) -> Result<bool, SignatureVerificationError> {
495 verify_dsa_signature_spki_with_minimum(
496 algorithm,
497 public_key_spki_der,
498 signed_data,
499 signature_value,
500 crate::policy::DsaKeyPolicy::default().minimum_modulus_bits,
501 )
502}
503
504pub(crate) fn verify_dsa_signature_spki_with_minimum(
505 algorithm: SignatureAlgorithm,
506 public_key_spki_der: &[u8],
507 signed_data: &[u8],
508 signature_value: &[u8],
509 minimum_modulus_bits: usize,
510) -> Result<bool, SignatureVerificationError> {
511 validate_dsa_signature_spki_with_minimum(public_key_spki_der, minimum_modulus_bits)?;
512 verify_dsa_signature_spki_primitive(
513 algorithm,
514 public_key_spki_der,
515 signed_data,
516 signature_value,
517 )
518}
519
520pub(crate) fn validate_dsa_signature_spki_with_minimum(
521 public_key_spki_der: &[u8],
522 minimum_modulus_bits: usize,
523) -> Result<(), SignatureVerificationError> {
524 let key = decode_dsa_verifying_key(public_key_spki_der)?;
525 let modulus_bits = usize::try_from(key.components().p().bits_vartime())
526 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
527 crate::policy::DsaKeyPolicy {
528 minimum_modulus_bits,
529 }
530 .validate_modulus_bits(modulus_bits)
531 .map_err(SignatureVerificationError::KeyPolicy)
532}
533
534#[derive(der::Sequence)]
535pub(crate) struct BorrowedDsaPublicParameters<'a> {
536 pub(crate) p: der::asn1::UintRef<'a>,
537 pub(crate) q: der::asn1::UintRef<'a>,
538 pub(crate) g: der::asn1::UintRef<'a>,
539}
540
541pub(crate) fn decode_dsa_verifying_key(
542 bytes: &[u8],
543) -> Result<dsa::VerifyingKey, SignatureVerificationError> {
544 let spki = pkcs8::SubjectPublicKeyInfoRef::from_der(bytes)
548 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
549 let parameters = spki
550 .algorithm
551 .parameters
552 .as_ref()
553 .ok_or(SignatureVerificationError::InvalidKeyDer)?
554 .decode_as::<BorrowedDsaPublicParameters<'_>>()
555 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
556 let y = der::asn1::UintRef::from_der(spki.subject_public_key.raw_bytes())
557 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
558 for component in [parameters.p, parameters.q, parameters.g, y] {
559 if component.as_bytes().len() > crate::hard_limits::DSA_KEY_COMPONENT_BYTE_CEILING {
560 return Err(SignatureVerificationError::InvalidKeyDer);
561 }
562 }
563 dsa::VerifyingKey::from_public_key_der(bytes)
564 .map_err(|_| SignatureVerificationError::InvalidKeyDer)
565}
566
567pub(crate) fn verify_dsa_signature_spki_primitive(
568 algorithm: SignatureAlgorithm,
569 public_key_spki_der: &[u8],
570 signed_data: &[u8],
571 signature_value: &[u8],
572) -> Result<bool, SignatureVerificationError> {
573 if !matches!(
574 algorithm,
575 SignatureAlgorithm::DsaSha1 | SignatureAlgorithm::DsaSha256
576 ) {
577 return Err(SignatureVerificationError::UnsupportedAlgorithm {
578 uri: algorithm.uri().to_string(),
579 });
580 }
581 let key = decode_dsa_verifying_key(public_key_spki_der)?;
582 let component_len = usize::try_from(key.components().q().bits_vartime())
583 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?
584 .div_ceil(8);
585 if algorithm.dsa_component_len() != Some(component_len) {
586 return Ok(false);
587 }
588 if signature_value.len() != component_len.saturating_mul(2) {
589 return Ok(false);
590 }
591 let Some(signature) = dsa::Signature::from_components(
592 crypto_bigint::BoxedUint::from_be_slice_vartime(&signature_value[..component_len]),
593 crypto_bigint::BoxedUint::from_be_slice_vartime(&signature_value[component_len..]),
594 ) else {
595 return Ok(false);
596 };
597 let verified = match algorithm {
598 SignatureAlgorithm::DsaSha1 => key.verify_prehash(&Sha1::digest(signed_data), &signature),
599 SignatureAlgorithm::DsaSha256 => {
600 key.verify_prehash(&Sha256::digest(signed_data), &signature)
601 }
602 _ => unreachable!("DSA algorithm checked above"),
603 };
604 Ok(verified.is_ok())
605}
606
607#[must_use = "discarding the verification result skips signature validation"]
614pub fn verify_ecdsa_signature_spki(
615 algorithm: SignatureAlgorithm,
616 public_key_spki_der: &[u8],
617 signed_data: &[u8],
618 signature_value: &[u8],
619) -> Result<bool, SignatureVerificationError> {
620 verify_ecdsa_signature_spki_with_encoding(
621 algorithm,
622 public_key_spki_der,
623 signed_data,
624 signature_value,
625 EcdsaSignatureValueEncoding::XmlDsig,
626 )
627}
628
629#[must_use = "discarding the verification result skips signature validation"]
631pub fn verify_ecdsa_signature_spki_with_encoding(
632 algorithm: SignatureAlgorithm,
633 public_key_spki_der: &[u8],
634 signed_data: &[u8],
635 signature_value: &[u8],
636 encoding: EcdsaSignatureValueEncoding,
637) -> Result<bool, SignatureVerificationError> {
638 let digest_algorithm = algorithm.ecdsa_digest().ok_or_else(|| {
639 SignatureVerificationError::UnsupportedAlgorithm {
640 uri: algorithm.uri().to_string(),
641 }
642 })?;
643
644 let spki = SubjectPublicKeyInfoRef::from_der(public_key_spki_der)
645 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
646 match spki.algorithm.oid {
647 oid if oid == p256::elliptic_curve::ALGORITHM_OID => {
648 let public_key = spki
649 .subject_public_key
650 .as_bytes()
651 .ok_or(SignatureVerificationError::InvalidKeyDer)?;
652 let (curve, component_len) = ecdsa_curve_and_component_len(&spki)?;
653 let signature_encoding = match encoding {
654 EcdsaSignatureValueEncoding::XmlDsig => {
655 if signature_value.len() != component_len * 2 {
656 return Err(SignatureVerificationError::InvalidSignatureFormat);
657 }
658 EcdsaSignatureEncoding::XmlDsigFixed
659 }
660 EcdsaSignatureValueEncoding::XmlSecAsn1Der => {
661 if inspect_der_encoded_ecdsa_signature(signature_value, component_len)?
662 .is_none()
663 {
664 return Err(SignatureVerificationError::InvalidSignatureFormat);
665 }
666 EcdsaSignatureEncoding::Asn1Der
667 }
668 };
669 let prehash = super::compute_digest(digest_algorithm, signed_data);
670 match curve {
671 EcCurve::P256 => {
672 verify_ecdsa_p256(public_key, &prehash, signature_value, signature_encoding)
673 }
674 EcCurve::P384 => {
675 verify_ecdsa_p384(public_key, &prehash, signature_value, signature_encoding)
676 }
677 EcCurve::P521 => {
678 verify_ecdsa_p521(public_key, &prehash, signature_value, signature_encoding)
679 }
680 }
681 }
682 _ => Err(SignatureVerificationError::KeyAlgorithmMismatch {
683 uri: algorithm.uri().to_string(),
684 }),
685 }
686}
687
688pub(crate) fn verify_ecdsa_signature_spki_asn1_der(
694 algorithm: SignatureAlgorithm,
695 public_key_spki_der: &[u8],
696 signed_data: &[u8],
697 signature_value: &[u8],
698) -> Result<bool, SignatureVerificationError> {
699 verify_ecdsa_signature_spki_with_encoding(
700 algorithm,
701 public_key_spki_der,
702 signed_data,
703 signature_value,
704 EcdsaSignatureValueEncoding::XmlSecAsn1Der,
705 )
706}
707
708fn validate_rsa_public_key(
709 rsa: &pkcs1::RsaPublicKeyRef<'_>,
710 algorithm: SignatureAlgorithm,
711 minimum_modulus_bits: usize,
712) -> Result<(), SignatureVerificationError> {
713 ensure_rsa_signature_algorithm(algorithm)?;
714 validate_rsa_key_components(
715 rsa.modulus.as_bytes(),
716 rsa.public_exponent.as_bytes(),
717 minimum_modulus_bits,
718 )?;
719 if let Some(parameters) = algorithm.rsa_pss_parameters() {
720 let modulus = rsa
721 .modulus
722 .as_bytes()
723 .iter()
724 .position(|byte| *byte != 0)
725 .map(|start| &rsa.modulus.as_bytes()[start..])
726 .ok_or(SignatureVerificationError::InvalidKeyDer)?;
727 let bits = modulus.len() * 8 - modulus[0].leading_zeros() as usize;
728 if !parameters.fits_modulus_bits(bits) {
729 return Err(SignatureVerificationError::KeyAlgorithmMismatch {
730 uri: algorithm.uri().into(),
731 });
732 }
733 }
734 Ok(())
735}
736
737pub(crate) fn validate_rsa_key_components(
739 modulus: &[u8],
740 exponent: &[u8],
741 minimum_modulus_bits: usize,
742) -> Result<(), SignatureVerificationError> {
743 crate::policy::RsaKeyPolicy {
744 minimum_modulus_bits,
745 }
746 .validate_components("verification", modulus, exponent)
747 .map(|_| ())
748 .map_err(SignatureVerificationError::KeyPolicy)
749}
750
751fn ensure_rsa_signature_algorithm(
752 algorithm: SignatureAlgorithm,
753) -> Result<(), SignatureVerificationError> {
754 if algorithm.is_rsa() {
755 Ok(())
756 } else {
757 Err(SignatureVerificationError::UnsupportedAlgorithm {
758 uri: algorithm.uri().to_string(),
759 })
760 }
761}
762
763#[derive(Clone, Copy, Debug, Eq, PartialEq)]
764pub(crate) enum EcCurve {
765 P256,
766 P384,
767 P521,
768}
769
770impl EcCurve {
771 pub(crate) fn from_oid(oid: der::asn1::ObjectIdentifier) -> Option<Self> {
772 Self::from_oid_bytes(oid.as_bytes())
773 }
774
775 pub(crate) fn from_oid_bytes(oid: &[u8]) -> Option<Self> {
777 use pkcs8::AssociatedOid as _;
778 if oid == p256::NistP256::OID.as_bytes() {
779 Some(Self::P256)
780 } else if oid == p384::NistP384::OID.as_bytes() {
781 Some(Self::P384)
782 } else if oid == p521::NistP521::OID.as_bytes() {
783 Some(Self::P521)
784 } else {
785 None
786 }
787 }
788
789 fn component_len(self) -> usize {
790 match self {
791 Self::P256 => 32,
792 Self::P384 => 48,
793 Self::P521 => 66,
794 }
795 }
796
797 pub(crate) fn validate_point(self, point: &[u8]) -> Result<(), SignatureVerificationError> {
798 if point.len() != self.component_len() * 2 + 1 || point.first() != Some(&4) {
802 return Err(SignatureVerificationError::InvalidKeyDer);
803 }
804 Ok(())
805 }
806}
807
808pub(crate) fn ecdsa_curve_and_component_len(
809 spki: &SubjectPublicKeyInfoRef<'_>,
810) -> Result<(EcCurve, usize), SignatureVerificationError> {
811 let curve_oid = spki
812 .algorithm
813 .parameters
814 .and_then(|params| params.decode_as::<der::asn1::ObjectIdentifier>().ok())
815 .ok_or(SignatureVerificationError::InvalidKeyDer)?;
816 let curve = EcCurve::from_oid(curve_oid).ok_or(SignatureVerificationError::InvalidKeyDer)?;
817 let point = spki
818 .subject_public_key
819 .as_bytes()
820 .ok_or(SignatureVerificationError::InvalidKeyDer)?;
821 curve.validate_point(point)?;
822 Ok((curve, curve.component_len()))
823}
824
825fn verify_ecdsa_p256(
826 public_key: &[u8],
827 prehash: &[u8],
828 signature_value: &[u8],
829 signature_encoding: EcdsaSignatureEncoding,
830) -> Result<bool, SignatureVerificationError> {
831 let key = P256VerifyingKey::from_sec1_bytes(public_key)
832 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
833 verify_p256_signature(&key, signature_value, signature_encoding, prehash)
834}
835
836fn verify_ecdsa_p384(
837 public_key: &[u8],
838 prehash: &[u8],
839 signature_value: &[u8],
840 signature_encoding: EcdsaSignatureEncoding,
841) -> Result<bool, SignatureVerificationError> {
842 let key = P384VerifyingKey::from_sec1_bytes(public_key)
843 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
844 verify_p384_signature(&key, signature_value, signature_encoding, prehash)
845}
846
847fn verify_ecdsa_p521(
848 public_key: &[u8],
849 prehash: &[u8],
850 signature_value: &[u8],
851 signature_encoding: EcdsaSignatureEncoding,
852) -> Result<bool, SignatureVerificationError> {
853 let key = P521VerifyingKey::from_sec1_bytes(public_key)
854 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
855 verify_p521_signature(&key, signature_value, signature_encoding, prehash)
856}
857
858trait DecodeEcdsaSignature: Sized {
859 fn decode_fixed_width(bytes: &[u8]) -> Result<Self, SignatureVerificationError>;
860 fn decode_der(bytes: &[u8]) -> Result<Self, SignatureVerificationError>;
861}
862
863macro_rules! impl_ecdsa_signature_decoder {
864 ($signature:ty) => {
865 impl DecodeEcdsaSignature for $signature {
866 fn decode_fixed_width(bytes: &[u8]) -> Result<Self, SignatureVerificationError> {
867 Self::from_slice(bytes)
868 .map_err(|_| SignatureVerificationError::InvalidSignatureFormat)
869 }
870
871 fn decode_der(bytes: &[u8]) -> Result<Self, SignatureVerificationError> {
872 Self::from_der(bytes)
873 .map_err(|_| SignatureVerificationError::InvalidSignatureFormat)
874 }
875 }
876 };
877}
878
879impl_ecdsa_signature_decoder!(P256Signature);
880impl_ecdsa_signature_decoder!(P384Signature);
881impl_ecdsa_signature_decoder!(P521Signature);
882
883fn verify_ecdsa_signature<K, S>(
884 key: &K,
885 signature_value: &[u8],
886 signature_encoding: EcdsaSignatureEncoding,
887 prehash: &[u8],
888) -> Result<bool, SignatureVerificationError>
889where
890 K: PrehashVerifier<S>,
891 S: DecodeEcdsaSignature,
892{
893 let signature = match signature_encoding {
894 EcdsaSignatureEncoding::XmlDsigFixed => S::decode_fixed_width(signature_value)?,
895 EcdsaSignatureEncoding::Asn1Der => S::decode_der(signature_value)?,
896 };
897 Ok(key.verify_prehash(prehash, &signature).is_ok())
898}
899
900fn verify_p256_signature(
901 key: &P256VerifyingKey,
902 signature_value: &[u8],
903 signature_encoding: EcdsaSignatureEncoding,
904 prehash: &[u8],
905) -> Result<bool, SignatureVerificationError> {
906 verify_ecdsa_signature::<_, P256Signature>(key, signature_value, signature_encoding, prehash)
907}
908
909fn verify_p384_signature(
910 key: &P384VerifyingKey,
911 signature_value: &[u8],
912 signature_encoding: EcdsaSignatureEncoding,
913 prehash: &[u8],
914) -> Result<bool, SignatureVerificationError> {
915 verify_ecdsa_signature::<_, P384Signature>(key, signature_value, signature_encoding, prehash)
916}
917
918fn verify_p521_signature(
919 key: &P521VerifyingKey,
920 signature_value: &[u8],
921 signature_encoding: EcdsaSignatureEncoding,
922 prehash: &[u8],
923) -> Result<bool, SignatureVerificationError> {
924 verify_ecdsa_signature::<_, P521Signature>(key, signature_value, signature_encoding, prehash)
925}
926
927#[derive(Clone, Copy, Debug, Eq, PartialEq)]
928enum EcdsaSignatureEncoding {
929 XmlDsigFixed,
930 Asn1Der,
931}
932
933pub(crate) fn encode_ecdsa_signature_as_der(signature: &[u8]) -> Option<Vec<u8>> {
934 if signature.is_empty() || !signature.len().is_multiple_of(2) {
935 return None;
936 }
937 let component_len = signature.len() / 2;
938 let mut content = Vec::with_capacity(signature.len() + 8);
939 encode_der_integer(&signature[..component_len], &mut content);
940 encode_der_integer(&signature[component_len..], &mut content);
941
942 let mut encoded = Vec::with_capacity(content.len() + 3);
943 encoded.push(0x30);
944 encode_der_length(content.len(), &mut encoded);
945 encoded.extend_from_slice(&content);
946 Some(encoded)
947}
948
949pub(crate) fn maximum_ecdsa_der_signature_len(raw_signature_len: usize) -> Option<usize> {
950 if raw_signature_len == 0 || !raw_signature_len.is_multiple_of(2) {
951 return None;
952 }
953 let component_len = raw_signature_len / 2;
954 let integer_content_len = component_len.checked_add(1)?;
955 let integer_len = 1_usize
956 .checked_add(der_length_octets(integer_content_len)?)?
957 .checked_add(integer_content_len)?;
958 let sequence_content_len = integer_len.checked_mul(2)?;
959 1_usize
960 .checked_add(der_length_octets(sequence_content_len)?)?
961 .checked_add(sequence_content_len)
962}
963
964fn encode_der_integer(component: &[u8], output: &mut Vec<u8>) {
965 let first_nonzero = component
966 .iter()
967 .position(|byte| *byte != 0)
968 .unwrap_or(component.len() - 1);
969 let magnitude = &component[first_nonzero..];
970 let needs_sign_octet = magnitude[0] & 0x80 != 0;
971 output.push(0x02);
972 encode_der_length(magnitude.len() + usize::from(needs_sign_octet), output);
973 if needs_sign_octet {
974 output.push(0);
975 }
976 output.extend_from_slice(magnitude);
977}
978
979fn encode_der_length(len: usize, output: &mut Vec<u8>) {
980 if len < 128 {
981 output.push(len as u8);
982 return;
983 }
984
985 let bytes = len.to_be_bytes();
986 let first_nonzero = bytes
987 .iter()
988 .position(|byte| *byte != 0)
989 .expect("non-short DER lengths are nonzero");
990 let encoded = &bytes[first_nonzero..];
991 output.push(0x80 | encoded.len() as u8);
992 output.extend_from_slice(encoded);
993}
994
995fn der_length_octets(len: usize) -> Option<usize> {
996 if len < 128 {
997 return Some(1);
998 }
999 let significant_bytes = (usize::BITS - len.leading_zeros()).div_ceil(8) as usize;
1000 significant_bytes.checked_add(1)
1001}
1002
1003fn inspect_der_encoded_ecdsa_signature(
1004 signature_value: &[u8],
1005 component_len: usize,
1006) -> Result<Option<()>, SignatureVerificationError> {
1007 let Some((&tag, rest)) = signature_value.split_first() else {
1008 return Ok(None);
1009 };
1010 if tag != 0x30 {
1011 return Ok(None);
1012 }
1013
1014 let sequence = parse_der_length(rest)
1015 .ok_or(SignatureVerificationError::InvalidSignatureFormat)?
1016 .map_err(|_| SignatureVerificationError::InvalidSignatureFormat)?;
1017 let (sequence_len, sequence_rest) = sequence;
1018 let (sequence_content, trailing) = sequence_rest
1019 .split_at_checked(sequence_len)
1020 .ok_or(SignatureVerificationError::InvalidSignatureFormat)?;
1021 if !trailing.is_empty() {
1022 return Err(SignatureVerificationError::InvalidSignatureFormat);
1023 }
1024
1025 let after_r = parse_der_integer(sequence_content, component_len)?;
1026 let after_s = parse_der_integer(after_r, component_len)?;
1027 if !after_s.is_empty() {
1028 return Err(SignatureVerificationError::InvalidSignatureFormat);
1029 }
1030
1031 Ok(Some(()))
1032}
1033
1034fn parse_der_integer(
1035 input: &[u8],
1036 component_len: usize,
1037) -> Result<&[u8], SignatureVerificationError> {
1038 let Some((&tag, rest)) = input.split_first() else {
1039 return Err(SignatureVerificationError::InvalidSignatureFormat);
1040 };
1041 if tag != 0x02 {
1042 return Err(SignatureVerificationError::InvalidSignatureFormat);
1043 }
1044
1045 let (len, rest) = parse_der_length(rest)
1046 .ok_or(SignatureVerificationError::InvalidSignatureFormat)?
1047 .map_err(|_| SignatureVerificationError::InvalidSignatureFormat)?;
1048 let (integer_bytes, remainder) = rest
1049 .split_at_checked(len)
1050 .ok_or(SignatureVerificationError::InvalidSignatureFormat)?;
1051
1052 if integer_bytes.is_empty() {
1053 return Err(SignatureVerificationError::InvalidSignatureFormat);
1054 }
1055 if integer_bytes.len() > component_len + 1 {
1056 return Err(SignatureVerificationError::InvalidSignatureFormat);
1057 }
1058 if integer_bytes.len() == component_len + 1 && integer_bytes[0] != 0 {
1059 return Err(SignatureVerificationError::InvalidSignatureFormat);
1060 }
1061 if integer_bytes[0] & 0x80 != 0 {
1062 return Err(SignatureVerificationError::InvalidSignatureFormat);
1063 }
1064 if integer_bytes.len() > 1 && integer_bytes[0] == 0 && integer_bytes[1] & 0x80 == 0 {
1065 return Err(SignatureVerificationError::InvalidSignatureFormat);
1066 }
1067
1068 Ok(remainder)
1069}
1070
1071fn parse_der_length(input: &[u8]) -> Option<Result<(usize, &[u8]), ()>> {
1072 let (&len_byte, rest) = input.split_first()?;
1073
1074 if len_byte & 0x80 == 0 {
1075 return Some(Ok((usize::from(len_byte), rest)));
1076 }
1077
1078 let len_len = usize::from(len_byte & 0x7f);
1079 if len_len == 0 || len_len > std::mem::size_of::<usize>() || rest.len() < len_len {
1080 return Some(Err(()));
1081 }
1082
1083 let (len_bytes, remainder) = rest.split_at(len_len);
1084 if len_bytes[0] == 0 {
1085 return Some(Err(()));
1086 }
1087
1088 let mut declared_len = 0_usize;
1089 for &byte in len_bytes {
1090 declared_len = match declared_len.checked_mul(256) {
1091 Some(len) => len,
1092 None => return Some(Err(())),
1093 };
1094 declared_len = match declared_len.checked_add(usize::from(byte)) {
1095 Some(len) => len,
1096 None => return Some(Err(())),
1097 };
1098 }
1099
1100 if declared_len < 128 {
1101 return Some(Err(()));
1102 }
1103
1104 Some(Ok((declared_len, remainder)))
1105}
1106
1107#[cfg(test)]
1108fn ec_coordinate_len_bytes(key_bits: usize) -> Result<usize, SignatureVerificationError> {
1109 key_bits
1110 .checked_add(7)
1111 .and_then(|bits| bits.checked_div(8))
1112 .ok_or(SignatureVerificationError::InvalidKeyDer)
1113}
1114
1115#[cfg(test)]
1116#[expect(clippy::unwrap_used, reason = "unit tests use fixed fixture data")]
1117mod tests {
1118 use super::*;
1119
1120 #[test]
1121 fn ecdsa_algorithms_are_rejected_for_rsa_verification() {
1122 for algorithm in [
1123 SignatureAlgorithm::EcdsaSha256,
1124 SignatureAlgorithm::EcdsaSha384,
1125 ] {
1126 let err = ensure_rsa_signature_algorithm(algorithm).unwrap_err();
1127 assert!(matches!(
1128 err,
1129 SignatureVerificationError::UnsupportedAlgorithm { .. }
1130 ));
1131 }
1132 }
1133
1134 #[test]
1135 fn malformed_dsa_components_are_verification_misses() {
1136 let public_key = include_bytes!(
1137 "../../tests/fixtures/xmldsig/merlin-xmldsig-twenty-three/certs/lugh.der"
1138 );
1139 let signature = [0_u8; 40];
1140
1141 assert!(matches!(
1142 verify_dsa_signature_spki_with_minimum(
1143 SignatureAlgorithm::DsaSha1,
1144 public_key,
1145 b"signed",
1146 &signature,
1147 1024,
1148 ),
1149 Ok(false)
1150 ));
1151 }
1152
1153 #[test]
1154 fn spki_signature_framing_uses_the_resolved_key_width() {
1155 let rsa = parse_public_key_pem(include_str!(
1156 "../../tests/fixtures/keys/rsa/rsa-2048-pubkey.pem"
1157 ))
1158 .expect("RSA fixture must parse");
1159 assert!(
1160 signature_value_matches_spki(SignatureAlgorithm::RsaSha256, &rsa, &[0; 256]).unwrap()
1161 );
1162 assert!(
1163 !signature_value_matches_spki(SignatureAlgorithm::RsaSha256, &rsa, &[0; 255]).unwrap()
1164 );
1165
1166 let p256 = parse_public_key_pem(include_str!(
1167 "../../tests/fixtures/keys/ec/ec-prime256v1-pubkey.pem"
1168 ))
1169 .expect("P-256 fixture must parse");
1170 assert!(
1171 signature_value_matches_spki(SignatureAlgorithm::EcdsaSha256, &p256, &[0xAA; 64])
1172 .unwrap()
1173 );
1174 assert!(matches!(
1175 signature_value_matches_spki(SignatureAlgorithm::EcdsaSha256, &p256, &[0xAA; 96]),
1176 Err(SignatureVerificationError::InvalidSignatureFormat)
1177 ));
1178 }
1179
1180 #[test]
1181 fn der_like_prefix_with_fixed_width_len_is_not_valid_der() {
1182 let mut signature = vec![0xAA_u8; 96];
1183 signature[0] = 0x30;
1184 signature[1] = 0x20;
1185
1186 assert!(inspect_der_encoded_ecdsa_signature(&signature, 48).is_err());
1187 }
1188
1189 #[test]
1190 fn overlong_der_length_below_128_is_rejected() {
1191 let bad = [0x81_u8, 0x7f];
1192 let parsed = parse_der_length(&bad).expect("length bytes should be present");
1193 assert!(
1194 matches!(parsed, Err(())),
1195 "DER must reject long-form lengths below 128"
1196 );
1197 }
1198
1199 #[test]
1200 fn ec_coordinate_length_rounds_up_for_non_byte_aligned_curves() {
1201 assert_eq!(
1202 ec_coordinate_len_bytes(521).expect("521-bit curves require rounded byte length"),
1203 66
1204 );
1205 }
1206
1207 #[test]
1208 fn same_width_valid_der_is_recognized_in_explicit_mode() {
1209 let mut signature = Vec::with_capacity(64);
1210 signature.extend_from_slice(&[0x30, 0x3e, 0x02, 0x1d]);
1211 signature.extend(std::iter::repeat_n(0x11_u8, 29));
1212 signature.extend_from_slice(&[0x02, 0x1d]);
1213 signature.extend(std::iter::repeat_n(0x22_u8, 29));
1214
1215 assert_eq!(
1216 inspect_der_encoded_ecdsa_signature(&signature, 32).unwrap(),
1217 Some(())
1218 );
1219 }
1220
1221 #[test]
1222 fn der_integer_longer_than_component_requires_sign_byte() {
1223 let mut signature = Vec::with_capacity(72);
1224 signature.extend_from_slice(&[0x30, 0x46, 0x02, 0x21, 0x01]);
1225 signature.extend(std::iter::repeat_n(0x11_u8, 32));
1226 signature.extend_from_slice(&[0x02, 0x21, 0x01]);
1227 signature.extend(std::iter::repeat_n(0x22_u8, 32));
1228
1229 let encoding = inspect_der_encoded_ecdsa_signature(&signature, 32);
1230 assert!(matches!(
1231 encoding,
1232 Err(SignatureVerificationError::InvalidSignatureFormat)
1233 ));
1234 }
1235
1236 #[test]
1237 fn fixed_width_ecdsa_is_encoded_as_canonical_der() {
1238 let mut raw = vec![0_u8; 64];
1241 raw[31] = 1;
1242 raw[32] = 0x80;
1243
1244 let encoded = encode_ecdsa_signature_as_der(&raw).unwrap();
1245 assert_eq!(
1246 encoded,
1247 [
1248 &[0x30, 0x26, 0x02, 0x01, 0x01, 0x02, 0x21, 0x00][..],
1249 &[0x80],
1250 &[0; 31],
1251 ]
1252 .concat()
1253 );
1254 assert_eq!(
1255 inspect_der_encoded_ecdsa_signature(&encoded, 32).unwrap(),
1256 Some(())
1257 );
1258 }
1259
1260 #[test]
1261 fn maximum_der_length_covers_supported_curve_widths() {
1262 assert_eq!(maximum_ecdsa_der_signature_len(64), Some(72));
1265 assert_eq!(maximum_ecdsa_der_signature_len(96), Some(104));
1266 assert_eq!(maximum_ecdsa_der_signature_len(132), Some(141));
1267 assert_eq!(maximum_ecdsa_der_signature_len(0), None);
1268 assert_eq!(maximum_ecdsa_der_signature_len(65), None);
1269 }
1270}