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, 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;
30
31pub(crate) fn signature_value_matches_algorithm(
32 algorithm: SignatureAlgorithm,
33 signature_value: &[u8],
34) -> bool {
35 match algorithm {
36 SignatureAlgorithm::DsaSha1 => signature_value.len() == 40,
37 SignatureAlgorithm::HmacSha1 => (10..=20).contains(&signature_value.len()),
38 SignatureAlgorithm::RsaSha1
42 | SignatureAlgorithm::RsaSha256
43 | SignatureAlgorithm::RsaSha384
44 | SignatureAlgorithm::RsaSha512 => {
45 (1..=crate::hard_limits::RSA_MODULUS_BIT_CEILING / 8).contains(&signature_value.len())
46 }
47 SignatureAlgorithm::EcdsaSha256 | SignatureAlgorithm::EcdsaSha384 => {
48 [32, 48, 66].into_iter().any(|component_len| {
49 classify_ecdsa_signature_encoding(signature_value, component_len).is_ok()
50 })
51 }
52 }
53}
54
55pub(crate) fn signature_value_matches_spki(
56 algorithm: SignatureAlgorithm,
57 public_key_spki_der: &[u8],
58 signature_value: &[u8],
59) -> Result<bool, SignatureVerificationError> {
60 let (rest, spki) = SubjectPublicKeyInfo::from_der(public_key_spki_der)
61 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
62 if !rest.is_empty() {
63 return Err(SignatureVerificationError::InvalidKeyDer);
64 }
65 let public_key = spki
66 .parsed()
67 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
68
69 match (algorithm, public_key) {
70 (SignatureAlgorithm::DsaSha1, PublicKey::DSA(_)) => Ok(signature_value.len() == 40),
71 (
72 SignatureAlgorithm::RsaSha1
73 | SignatureAlgorithm::RsaSha256
74 | SignatureAlgorithm::RsaSha384
75 | SignatureAlgorithm::RsaSha512,
76 PublicKey::RSA(_),
77 ) => {
78 let key = rsa::RsaPublicKey::from_public_key_der(public_key_spki_der)
79 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
80 Ok(signature_value.len() == key.size())
81 }
82 (SignatureAlgorithm::EcdsaSha256 | SignatureAlgorithm::EcdsaSha384, PublicKey::EC(ec)) => {
83 validate_ec_public_key_encoding(&ec, &spki.subject_public_key.data)?;
84 let (_, component_len) = ecdsa_curve_and_component_len(&spki, &ec)?;
85 classify_ecdsa_signature_encoding(signature_value, component_len)?;
86 Ok(true)
87 }
88 (SignatureAlgorithm::HmacSha1, _) => {
89 Err(SignatureVerificationError::KeyAlgorithmMismatch {
90 uri: algorithm.uri().to_owned(),
91 })
92 }
93 _ => Err(SignatureVerificationError::KeyAlgorithmMismatch {
94 uri: algorithm.uri().to_owned(),
95 }),
96 }
97}
98
99#[derive(Debug, thiserror::Error)]
101#[non_exhaustive]
102pub enum SignatureVerificationError {
103 #[error("invalid PEM public key")]
105 InvalidKeyPem,
106
107 #[error("unsupported signature algorithm: {uri}")]
109 UnsupportedAlgorithm {
110 uri: String,
112 },
113
114 #[error("invalid key format: expected PUBLIC KEY PEM, got {label}")]
116 InvalidKeyFormat {
117 label: String,
119 },
120
121 #[error("invalid SubjectPublicKeyInfo DER")]
123 InvalidKeyDer,
124
125 #[error("verification key rejected by policy: {0}")]
127 KeyPolicy(#[from] crate::policy::PolicyViolation),
128
129 #[error("public key does not match signature algorithm: {uri}")]
131 KeyAlgorithmMismatch {
132 uri: String,
134 },
135
136 #[error("invalid ECDSA signature encoding")]
139 InvalidSignatureFormat,
140}
141
142#[must_use = "discarding the verification result skips signature validation"]
147pub fn verify_rsa_signature_pem(
148 algorithm: SignatureAlgorithm,
149 public_key_pem: &str,
150 signed_data: &[u8],
151 signature_value: &[u8],
152) -> Result<bool, SignatureVerificationError> {
153 let public_key_spki_der = parse_public_key_pem(public_key_pem)?;
154 verify_rsa_signature_spki(
155 algorithm,
156 &public_key_spki_der,
157 signed_data,
158 signature_value,
159 )
160}
161
162#[must_use = "discarding the verification result skips signature validation"]
172pub fn verify_ecdsa_signature_pem(
173 algorithm: SignatureAlgorithm,
174 public_key_pem: &str,
175 signed_data: &[u8],
176 signature_value: &[u8],
177) -> Result<bool, SignatureVerificationError> {
178 let public_key_spki_der = parse_public_key_pem(public_key_pem)?;
179 verify_ecdsa_signature_spki(
180 algorithm,
181 &public_key_spki_der,
182 signed_data,
183 signature_value,
184 )
185}
186
187fn parse_public_key_pem(public_key_pem: &str) -> Result<Vec<u8>, SignatureVerificationError> {
188 let (rest, pem) = x509_parser::pem::parse_x509_pem(public_key_pem.as_bytes())
189 .map_err(|_| SignatureVerificationError::InvalidKeyPem)?;
190 if !rest.iter().all(|byte| byte.is_ascii_whitespace()) {
191 return Err(SignatureVerificationError::InvalidKeyPem);
192 }
193 if pem.label != "PUBLIC KEY" {
194 return Err(SignatureVerificationError::InvalidKeyFormat { label: pem.label });
195 }
196
197 Ok(pem.contents)
198}
199
200#[must_use = "discarding the verification result skips signature validation"]
206pub fn verify_rsa_signature_spki(
207 algorithm: SignatureAlgorithm,
208 public_key_spki_der: &[u8],
209 signed_data: &[u8],
210 signature_value: &[u8],
211) -> Result<bool, SignatureVerificationError> {
212 verify_rsa_signature_spki_with_minimum(
213 algorithm,
214 public_key_spki_der,
215 signed_data,
216 signature_value,
217 2048,
218 )
219}
220
221pub(crate) fn verify_rsa_signature_spki_with_minimum(
222 algorithm: SignatureAlgorithm,
223 public_key_spki_der: &[u8],
224 signed_data: &[u8],
225 signature_value: &[u8],
226 minimum_modulus_bits: usize,
227) -> Result<bool, SignatureVerificationError> {
228 validate_rsa_signature_spki_with_minimum(algorithm, public_key_spki_der, minimum_modulus_bits)?;
229 verify_rsa_signature_spki_primitive(
230 algorithm,
231 public_key_spki_der,
232 signed_data,
233 signature_value,
234 )
235}
236
237pub(crate) fn validate_rsa_signature_spki_with_minimum(
238 algorithm: SignatureAlgorithm,
239 public_key_spki_der: &[u8],
240 minimum_modulus_bits: usize,
241) -> Result<(), SignatureVerificationError> {
242 let (rest, spki) = SubjectPublicKeyInfo::from_der(public_key_spki_der)
243 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
244 if !rest.is_empty() {
245 return Err(SignatureVerificationError::InvalidKeyDer);
246 }
247 match spki
248 .parsed()
249 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?
250 {
251 PublicKey::RSA(rsa) => validate_rsa_public_key(&rsa, algorithm, minimum_modulus_bits),
252 _ => Err(SignatureVerificationError::KeyAlgorithmMismatch {
253 uri: algorithm.uri().to_string(),
254 }),
255 }
256}
257
258pub(crate) fn verify_rsa_signature_spki_primitive(
259 algorithm: SignatureAlgorithm,
260 public_key_spki_der: &[u8],
261 signed_data: &[u8],
262 signature_value: &[u8],
263) -> Result<bool, SignatureVerificationError> {
264 ensure_rsa_signature_algorithm(algorithm)?;
265 let key = rsa::RsaPublicKey::from_public_key_der(public_key_spki_der)
266 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
267 let Ok(signature) = RsaPkcs1v15Signature::try_from(signature_value) else {
268 return Ok(false);
269 };
270 let verified = match algorithm {
271 SignatureAlgorithm::RsaSha1 => RsaVerifyingKey::<Sha1>::new(key)
272 .verify(signed_data, &signature)
273 .is_ok(),
274 SignatureAlgorithm::RsaSha256 => RsaVerifyingKey::<Sha256>::new(key)
275 .verify(signed_data, &signature)
276 .is_ok(),
277 SignatureAlgorithm::RsaSha384 => RsaVerifyingKey::<Sha384>::new(key)
278 .verify(signed_data, &signature)
279 .is_ok(),
280 SignatureAlgorithm::RsaSha512 => RsaVerifyingKey::<Sha512>::new(key)
281 .verify(signed_data, &signature)
282 .is_ok(),
283 _ => unreachable!("RSA algorithm checked above"),
284 };
285 Ok(verified)
286}
287
288#[must_use = "discarding the verification result skips signature validation"]
293pub fn verify_dsa_signature_spki(
294 algorithm: SignatureAlgorithm,
295 public_key_spki_der: &[u8],
296 signed_data: &[u8],
297 signature_value: &[u8],
298) -> Result<bool, SignatureVerificationError> {
299 verify_dsa_signature_spki_with_minimum(
300 algorithm,
301 public_key_spki_der,
302 signed_data,
303 signature_value,
304 crate::policy::DsaKeyPolicy::default().minimum_modulus_bits,
305 )
306}
307
308pub(crate) fn verify_dsa_signature_spki_with_minimum(
309 algorithm: SignatureAlgorithm,
310 public_key_spki_der: &[u8],
311 signed_data: &[u8],
312 signature_value: &[u8],
313 minimum_modulus_bits: usize,
314) -> Result<bool, SignatureVerificationError> {
315 validate_dsa_signature_spki_with_minimum(public_key_spki_der, minimum_modulus_bits)?;
316 verify_dsa_signature_spki_primitive(
317 algorithm,
318 public_key_spki_der,
319 signed_data,
320 signature_value,
321 )
322}
323
324pub(crate) fn validate_dsa_signature_spki_with_minimum(
325 public_key_spki_der: &[u8],
326 minimum_modulus_bits: usize,
327) -> Result<(), SignatureVerificationError> {
328 let key = dsa::VerifyingKey::from_public_key_der(public_key_spki_der)
329 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
330 let modulus_bits = usize::try_from(key.components().p().bits_vartime())
331 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
332 crate::policy::DsaKeyPolicy {
333 minimum_modulus_bits,
334 }
335 .validate_modulus_bits(modulus_bits)
336 .map_err(SignatureVerificationError::KeyPolicy)
337}
338
339pub(crate) fn verify_dsa_signature_spki_primitive(
340 algorithm: SignatureAlgorithm,
341 public_key_spki_der: &[u8],
342 signed_data: &[u8],
343 signature_value: &[u8],
344) -> Result<bool, SignatureVerificationError> {
345 if algorithm != SignatureAlgorithm::DsaSha1 {
346 return Err(SignatureVerificationError::UnsupportedAlgorithm {
347 uri: algorithm.uri().to_string(),
348 });
349 }
350 if signature_value.len() != 40 {
351 return Ok(false);
352 }
353 let key = dsa::VerifyingKey::from_public_key_der(public_key_spki_der)
354 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
355 let Some(signature) = dsa::Signature::from_components(
356 crypto_bigint::BoxedUint::from_be_slice_vartime(&signature_value[..20]),
357 crypto_bigint::BoxedUint::from_be_slice_vartime(&signature_value[20..]),
358 ) else {
359 return Ok(false);
360 };
361 let digest = Sha1::digest(signed_data);
362 Ok(key.verify_prehash(&digest, &signature).is_ok())
363}
364
365#[must_use = "discarding the verification result skips signature validation"]
373pub fn verify_ecdsa_signature_spki(
374 algorithm: SignatureAlgorithm,
375 public_key_spki_der: &[u8],
376 signed_data: &[u8],
377 signature_value: &[u8],
378) -> Result<bool, SignatureVerificationError> {
379 if !matches!(
380 algorithm,
381 SignatureAlgorithm::EcdsaSha256 | SignatureAlgorithm::EcdsaSha384
382 ) {
383 return Err(SignatureVerificationError::UnsupportedAlgorithm {
384 uri: algorithm.uri().to_string(),
385 });
386 }
387
388 let (rest, spki) = SubjectPublicKeyInfo::from_der(public_key_spki_der)
389 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
390 if !rest.is_empty() {
391 return Err(SignatureVerificationError::InvalidKeyDer);
392 }
393 let public_key = spki
394 .parsed()
395 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
396
397 match public_key {
398 PublicKey::EC(ec) => {
399 validate_ec_public_key_encoding(&ec, &spki.subject_public_key.data)?;
400 let (curve, component_len) = ecdsa_curve_and_component_len(&spki, &ec)?;
401 let signature_encoding =
402 classify_ecdsa_signature_encoding(signature_value, component_len)?;
403 let prehash = match algorithm {
404 SignatureAlgorithm::EcdsaSha256 => Sha256::digest(signed_data).to_vec(),
405 SignatureAlgorithm::EcdsaSha384 => Sha384::digest(signed_data).to_vec(),
406 _ => unreachable!("ECDSA algorithm was validated above"),
407 };
408 match curve {
409 EcCurve::P256 => verify_ecdsa_p256(
410 &spki.subject_public_key.data,
411 &prehash,
412 signature_value,
413 signature_encoding,
414 ),
415 EcCurve::P384 => verify_ecdsa_p384(
416 &spki.subject_public_key.data,
417 &prehash,
418 signature_value,
419 signature_encoding,
420 ),
421 EcCurve::P521 => verify_ecdsa_p521(
422 &spki.subject_public_key.data,
423 &prehash,
424 signature_value,
425 signature_encoding,
426 ),
427 }
428 }
429 _ => Err(SignatureVerificationError::KeyAlgorithmMismatch {
430 uri: algorithm.uri().to_string(),
431 }),
432 }
433}
434
435fn validate_rsa_public_key(
436 rsa: &x509_parser::public_key::RSAPublicKey<'_>,
437 algorithm: SignatureAlgorithm,
438 minimum_modulus_bits: usize,
439) -> Result<(), SignatureVerificationError> {
440 ensure_rsa_signature_algorithm(algorithm)?;
441 validate_rsa_key_components(rsa.modulus, rsa.exponent, minimum_modulus_bits)
442}
443
444pub(crate) fn validate_rsa_key_components(
446 modulus: &[u8],
447 exponent: &[u8],
448 minimum_modulus_bits: usize,
449) -> Result<(), SignatureVerificationError> {
450 crate::policy::RsaKeyPolicy {
451 minimum_modulus_bits,
452 }
453 .validate_components("verification", modulus, exponent)
454 .map(|_| ())
455 .map_err(SignatureVerificationError::KeyPolicy)
456}
457
458fn ensure_rsa_signature_algorithm(
459 algorithm: SignatureAlgorithm,
460) -> Result<(), SignatureVerificationError> {
461 match algorithm {
462 SignatureAlgorithm::RsaSha1
463 | SignatureAlgorithm::RsaSha256
464 | SignatureAlgorithm::RsaSha384
465 | SignatureAlgorithm::RsaSha512 => Ok(()),
466 _ => Err(SignatureVerificationError::UnsupportedAlgorithm {
467 uri: algorithm.uri().to_string(),
468 }),
469 }
470}
471
472#[derive(Clone, Copy, Debug, Eq, PartialEq)]
473enum EcCurve {
474 P256,
475 P384,
476 P521,
477}
478
479fn ecdsa_curve_and_component_len(
480 spki: &SubjectPublicKeyInfo<'_>,
481 ec: &ECPoint<'_>,
482) -> Result<(EcCurve, usize), SignatureVerificationError> {
483 let curve_oid = spki
484 .algorithm
485 .parameters
486 .as_ref()
487 .and_then(|params| params.as_oid().ok())
488 .ok_or(SignatureVerificationError::InvalidKeyDer)?;
489 let point_len = ec.key_size();
490
491 let curve_oid = curve_oid.to_id_string();
492 match (curve_oid.as_str(), point_len) {
493 ("1.2.840.10045.3.1.7", 256) => Ok((EcCurve::P256, 32)),
494 ("1.3.132.0.34", 384) => Ok((EcCurve::P384, 48)),
495 ("1.3.132.0.35", 528) => Ok((EcCurve::P521, 66)),
497 _ => Err(SignatureVerificationError::InvalidKeyDer),
498 }
499}
500
501fn verify_ecdsa_p256(
502 public_key: &[u8],
503 prehash: &[u8],
504 signature_value: &[u8],
505 signature_encoding: EcdsaSignatureEncoding,
506) -> Result<bool, SignatureVerificationError> {
507 let key = P256VerifyingKey::from_sec1_bytes(public_key)
508 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
509 verify_p256_signature(&key, signature_value, signature_encoding, prehash)
510}
511
512fn verify_ecdsa_p384(
513 public_key: &[u8],
514 prehash: &[u8],
515 signature_value: &[u8],
516 signature_encoding: EcdsaSignatureEncoding,
517) -> Result<bool, SignatureVerificationError> {
518 let key = P384VerifyingKey::from_sec1_bytes(public_key)
519 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
520 verify_p384_signature(&key, signature_value, signature_encoding, prehash)
521}
522
523fn verify_ecdsa_p521(
524 public_key: &[u8],
525 prehash: &[u8],
526 signature_value: &[u8],
527 signature_encoding: EcdsaSignatureEncoding,
528) -> Result<bool, SignatureVerificationError> {
529 let key = P521VerifyingKey::from_sec1_bytes(public_key)
530 .map_err(|_| SignatureVerificationError::InvalidKeyDer)?;
531 verify_p521_signature(&key, signature_value, signature_encoding, prehash)
532}
533
534fn verify_p256_signature(
535 key: &P256VerifyingKey,
536 signature_value: &[u8],
537 signature_encoding: EcdsaSignatureEncoding,
538 prehash: &[u8],
539) -> Result<bool, SignatureVerificationError> {
540 match signature_encoding {
541 EcdsaSignatureEncoding::XmlDsigFixed => {
542 let signature = P256Signature::from_slice(signature_value)
543 .map_err(|_| SignatureVerificationError::InvalidSignatureFormat)?;
544 Ok(key.verify_prehash(prehash, &signature).is_ok())
545 }
546 EcdsaSignatureEncoding::Asn1Der => {
547 let signature = P256Signature::from_der(signature_value)
548 .map_err(|_| SignatureVerificationError::InvalidSignatureFormat)?;
549 Ok(key.verify_prehash(prehash, &signature).is_ok())
550 }
551 EcdsaSignatureEncoding::Ambiguous => {
552 if let Ok(signature) = P256Signature::from_der(signature_value)
553 && key.verify_prehash(prehash, &signature).is_ok()
554 {
555 return Ok(true);
556 }
557
558 let signature = P256Signature::from_slice(signature_value)
559 .map_err(|_| SignatureVerificationError::InvalidSignatureFormat)?;
560 Ok(key.verify_prehash(prehash, &signature).is_ok())
561 }
562 }
563}
564
565fn verify_p384_signature(
566 key: &P384VerifyingKey,
567 signature_value: &[u8],
568 signature_encoding: EcdsaSignatureEncoding,
569 prehash: &[u8],
570) -> Result<bool, SignatureVerificationError> {
571 match signature_encoding {
572 EcdsaSignatureEncoding::XmlDsigFixed => {
573 let signature = P384Signature::from_slice(signature_value)
574 .map_err(|_| SignatureVerificationError::InvalidSignatureFormat)?;
575 Ok(key.verify_prehash(prehash, &signature).is_ok())
576 }
577 EcdsaSignatureEncoding::Asn1Der => {
578 let signature = P384Signature::from_der(signature_value)
579 .map_err(|_| SignatureVerificationError::InvalidSignatureFormat)?;
580 Ok(key.verify_prehash(prehash, &signature).is_ok())
581 }
582 EcdsaSignatureEncoding::Ambiguous => {
583 if let Ok(signature) = P384Signature::from_der(signature_value)
584 && key.verify_prehash(prehash, &signature).is_ok()
585 {
586 return Ok(true);
587 }
588
589 let signature = P384Signature::from_slice(signature_value)
590 .map_err(|_| SignatureVerificationError::InvalidSignatureFormat)?;
591 Ok(key.verify_prehash(prehash, &signature).is_ok())
592 }
593 }
594}
595
596fn verify_p521_signature(
597 key: &P521VerifyingKey,
598 signature_value: &[u8],
599 signature_encoding: EcdsaSignatureEncoding,
600 prehash: &[u8],
601) -> Result<bool, SignatureVerificationError> {
602 match signature_encoding {
603 EcdsaSignatureEncoding::XmlDsigFixed => {
604 let signature = P521Signature::from_slice(signature_value)
605 .map_err(|_| SignatureVerificationError::InvalidSignatureFormat)?;
606 Ok(key.verify_prehash(prehash, &signature).is_ok())
607 }
608 EcdsaSignatureEncoding::Asn1Der => {
609 let signature = P521Signature::from_der(signature_value)
610 .map_err(|_| SignatureVerificationError::InvalidSignatureFormat)?;
611 Ok(key.verify_prehash(prehash, &signature).is_ok())
612 }
613 EcdsaSignatureEncoding::Ambiguous => {
614 if let Ok(signature) = P521Signature::from_der(signature_value)
615 && key.verify_prehash(prehash, &signature).is_ok()
616 {
617 return Ok(true);
618 }
619
620 let signature = P521Signature::from_slice(signature_value)
621 .map_err(|_| SignatureVerificationError::InvalidSignatureFormat)?;
622 Ok(key.verify_prehash(prehash, &signature).is_ok())
623 }
624 }
625}
626
627#[derive(Clone, Copy, Debug, Eq, PartialEq)]
628enum EcdsaSignatureEncoding {
629 XmlDsigFixed,
630 Asn1Der,
631 Ambiguous,
632}
633
634fn classify_ecdsa_signature_encoding(
635 signature_value: &[u8],
636 component_len: usize,
637) -> Result<EcdsaSignatureEncoding, SignatureVerificationError> {
638 let expected_len = component_len
639 .checked_mul(2)
640 .ok_or(SignatureVerificationError::InvalidSignatureFormat)?;
641
642 match inspect_der_encoded_ecdsa_signature(signature_value, component_len) {
643 Ok(Some(())) if signature_value.len() == expected_len => {
644 Ok(EcdsaSignatureEncoding::Ambiguous)
645 }
646 Ok(Some(())) => Ok(EcdsaSignatureEncoding::Asn1Der),
647 Ok(None) | Err(_) if signature_value.len() == expected_len => {
648 Ok(EcdsaSignatureEncoding::XmlDsigFixed)
649 }
650 Ok(None) | Err(_) => Err(SignatureVerificationError::InvalidSignatureFormat),
651 }
652}
653
654fn inspect_der_encoded_ecdsa_signature(
655 signature_value: &[u8],
656 component_len: usize,
657) -> Result<Option<()>, SignatureVerificationError> {
658 let Some((&tag, rest)) = signature_value.split_first() else {
659 return Ok(None);
660 };
661 if tag != 0x30 {
662 return Ok(None);
663 }
664
665 let sequence = parse_der_length(rest)
666 .ok_or(SignatureVerificationError::InvalidSignatureFormat)?
667 .map_err(|_| SignatureVerificationError::InvalidSignatureFormat)?;
668 let (sequence_len, sequence_rest) = sequence;
669 let (sequence_content, trailing) = sequence_rest
670 .split_at_checked(sequence_len)
671 .ok_or(SignatureVerificationError::InvalidSignatureFormat)?;
672 if !trailing.is_empty() {
673 return Err(SignatureVerificationError::InvalidSignatureFormat);
674 }
675
676 let after_r = parse_der_integer(sequence_content, component_len)?;
677 let after_s = parse_der_integer(after_r, component_len)?;
678 if !after_s.is_empty() {
679 return Err(SignatureVerificationError::InvalidSignatureFormat);
680 }
681
682 Ok(Some(()))
683}
684
685fn parse_der_integer(
686 input: &[u8],
687 component_len: usize,
688) -> Result<&[u8], SignatureVerificationError> {
689 let Some((&tag, rest)) = input.split_first() else {
690 return Err(SignatureVerificationError::InvalidSignatureFormat);
691 };
692 if tag != 0x02 {
693 return Err(SignatureVerificationError::InvalidSignatureFormat);
694 }
695
696 let (len, rest) = parse_der_length(rest)
697 .ok_or(SignatureVerificationError::InvalidSignatureFormat)?
698 .map_err(|_| SignatureVerificationError::InvalidSignatureFormat)?;
699 let (integer_bytes, remainder) = rest
700 .split_at_checked(len)
701 .ok_or(SignatureVerificationError::InvalidSignatureFormat)?;
702
703 if integer_bytes.is_empty() {
704 return Err(SignatureVerificationError::InvalidSignatureFormat);
705 }
706 if integer_bytes.len() > component_len + 1 {
707 return Err(SignatureVerificationError::InvalidSignatureFormat);
708 }
709 if integer_bytes.len() == component_len + 1 && integer_bytes[0] != 0 {
710 return Err(SignatureVerificationError::InvalidSignatureFormat);
711 }
712 if integer_bytes[0] & 0x80 != 0 {
713 return Err(SignatureVerificationError::InvalidSignatureFormat);
714 }
715 if integer_bytes.len() > 1 && integer_bytes[0] == 0 && integer_bytes[1] & 0x80 == 0 {
716 return Err(SignatureVerificationError::InvalidSignatureFormat);
717 }
718
719 Ok(remainder)
720}
721
722fn parse_der_length(input: &[u8]) -> Option<Result<(usize, &[u8]), ()>> {
723 let (&len_byte, rest) = input.split_first()?;
724
725 if len_byte & 0x80 == 0 {
726 return Some(Ok((usize::from(len_byte), rest)));
727 }
728
729 let len_len = usize::from(len_byte & 0x7f);
730 if len_len == 0 || len_len > std::mem::size_of::<usize>() || rest.len() < len_len {
731 return Some(Err(()));
732 }
733
734 let (len_bytes, remainder) = rest.split_at(len_len);
735 if len_bytes[0] == 0 {
736 return Some(Err(()));
737 }
738
739 let mut declared_len = 0_usize;
740 for &byte in len_bytes {
741 declared_len = match declared_len.checked_mul(256) {
742 Some(len) => len,
743 None => return Some(Err(())),
744 };
745 declared_len = match declared_len.checked_add(usize::from(byte)) {
746 Some(len) => len,
747 None => return Some(Err(())),
748 };
749 }
750
751 if declared_len < 128 {
752 return Some(Err(()));
753 }
754
755 Some(Ok((declared_len, remainder)))
756}
757
758fn validate_ec_public_key_encoding(
759 ec: &ECPoint<'_>,
760 public_key_bytes: &[u8],
761) -> Result<(), SignatureVerificationError> {
762 let coordinate_len = ec_coordinate_len_bytes(ec.key_size())?;
763 let expected_len = coordinate_len
764 .checked_mul(2)
765 .and_then(|len| len.checked_add(1))
766 .ok_or(SignatureVerificationError::InvalidKeyDer)?;
767
768 let is_uncompressed_sec1 =
769 public_key_bytes.len() == expected_len && public_key_bytes.first() == Some(&0x04);
770 if !is_uncompressed_sec1 {
771 return Err(SignatureVerificationError::InvalidKeyDer);
772 }
773
774 Ok(())
775}
776
777fn ec_coordinate_len_bytes(key_bits: usize) -> Result<usize, SignatureVerificationError> {
778 key_bits
779 .checked_add(7)
780 .and_then(|bits| bits.checked_div(8))
781 .ok_or(SignatureVerificationError::InvalidKeyDer)
782}
783
784#[cfg(test)]
785#[expect(clippy::unwrap_used, reason = "unit tests use fixed fixture data")]
786mod tests {
787 use super::*;
788
789 #[test]
790 fn ecdsa_algorithms_are_rejected_for_rsa_verification() {
791 for algorithm in [
792 SignatureAlgorithm::EcdsaSha256,
793 SignatureAlgorithm::EcdsaSha384,
794 ] {
795 let err = ensure_rsa_signature_algorithm(algorithm).unwrap_err();
796 assert!(matches!(
797 err,
798 SignatureVerificationError::UnsupportedAlgorithm { .. }
799 ));
800 }
801 }
802
803 #[test]
804 fn malformed_dsa_components_are_verification_misses() {
805 let public_key = include_bytes!(
806 "../../tests/fixtures/xmldsig/merlin-xmldsig-twenty-three/certs/lugh.der"
807 );
808 let signature = [0_u8; 40];
809
810 assert!(matches!(
811 verify_dsa_signature_spki_with_minimum(
812 SignatureAlgorithm::DsaSha1,
813 public_key,
814 b"signed",
815 &signature,
816 1024,
817 ),
818 Ok(false)
819 ));
820 }
821
822 #[test]
823 fn spki_signature_framing_uses_the_resolved_key_width() {
824 let rsa = parse_public_key_pem(include_str!(
825 "../../tests/fixtures/keys/rsa/rsa-2048-pubkey.pem"
826 ))
827 .expect("RSA fixture must parse");
828 assert!(
829 signature_value_matches_spki(SignatureAlgorithm::RsaSha256, &rsa, &[0; 256]).unwrap()
830 );
831 assert!(
832 !signature_value_matches_spki(SignatureAlgorithm::RsaSha256, &rsa, &[0; 255]).unwrap()
833 );
834
835 let p256 = parse_public_key_pem(include_str!(
836 "../../tests/fixtures/keys/ec/ec-prime256v1-pubkey.pem"
837 ))
838 .expect("P-256 fixture must parse");
839 assert!(
840 signature_value_matches_spki(SignatureAlgorithm::EcdsaSha256, &p256, &[0xAA; 64])
841 .unwrap()
842 );
843 assert!(matches!(
844 signature_value_matches_spki(SignatureAlgorithm::EcdsaSha256, &p256, &[0xAA; 96]),
845 Err(SignatureVerificationError::InvalidSignatureFormat)
846 ));
847 }
848
849 #[test]
850 fn der_like_prefix_with_fixed_width_len_is_classified_as_raw() {
851 let mut signature = vec![0xAA_u8; 96];
852 signature[0] = 0x30;
853 signature[1] = 0x20;
854
855 let encoding = classify_ecdsa_signature_encoding(&signature, 48)
856 .expect("same-width signature with invalid DER must fall back to raw");
857 assert_eq!(encoding, EcdsaSignatureEncoding::XmlDsigFixed);
858 }
859
860 #[test]
861 fn overlong_der_length_below_128_is_rejected() {
862 let bad = [0x81_u8, 0x7f];
863 let parsed = parse_der_length(&bad).expect("length bytes should be present");
864 assert!(
865 matches!(parsed, Err(())),
866 "DER must reject long-form lengths below 128"
867 );
868 }
869
870 #[test]
871 fn ec_coordinate_length_rounds_up_for_non_byte_aligned_curves() {
872 assert_eq!(
873 ec_coordinate_len_bytes(521).expect("521-bit curves require rounded byte length"),
874 66
875 );
876 }
877
878 #[test]
879 fn same_width_valid_der_is_marked_ambiguous() {
880 let mut signature = Vec::with_capacity(64);
881 signature.extend_from_slice(&[0x30, 0x3e, 0x02, 0x1d]);
882 signature.extend(std::iter::repeat_n(0x11_u8, 29));
883 signature.extend_from_slice(&[0x02, 0x1d]);
884 signature.extend(std::iter::repeat_n(0x22_u8, 29));
885
886 let encoding = classify_ecdsa_signature_encoding(&signature, 32)
887 .expect("same-width structurally valid DER should classify as ambiguous");
888 assert_eq!(encoding, EcdsaSignatureEncoding::Ambiguous);
889 }
890
891 #[test]
892 fn der_integer_longer_than_component_requires_sign_byte() {
893 let mut signature = Vec::with_capacity(72);
894 signature.extend_from_slice(&[0x30, 0x46, 0x02, 0x21, 0x01]);
895 signature.extend(std::iter::repeat_n(0x11_u8, 32));
896 signature.extend_from_slice(&[0x02, 0x21, 0x01]);
897 signature.extend(std::iter::repeat_n(0x22_u8, 32));
898
899 let encoding = classify_ecdsa_signature_encoding(&signature, 32);
900 assert!(matches!(
901 encoding,
902 Err(SignatureVerificationError::InvalidSignatureFormat)
903 ));
904 }
905}