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