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