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