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