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