1use pki_types::{
2 CertificateDer, ServerName, SignatureVerificationAlgorithm, SubjectPublicKeyInfoDer, UnixTime,
3};
4use webpki::ExtendedKeyUsage;
5
6use super::anchors::RootCertStore;
7use super::pki_error;
8use crate::crypto::WebPkiSupportedAlgorithms;
9use crate::error::{ApiMisuse, Error, PeerMisbehaved};
10use crate::verify::{HandshakeSignatureValid, SignatureVerificationInput, SignerPublicKey};
11
12pub fn verify_identity_signed_by_trust_anchor(
24 cert: &ParsedCertificate<'_>,
25 roots: &RootCertStore,
26 intermediates: &[CertificateDer<'_>],
27 now: UnixTime,
28 supported_algs: &[&dyn SignatureVerificationAlgorithm],
29) -> Result<(), Error> {
30 verify_identity_signed_by_trust_anchor_impl(
31 cert,
32 roots,
33 intermediates,
34 None, now,
36 supported_algs,
37 )
38}
39
40pub fn verify_server_name(
45 cert: &ParsedCertificate<'_>,
46 server_name: &ServerName<'_>,
47) -> Result<(), Error> {
48 cert.0
49 .verify_is_valid_for_subject_name(server_name)
50 .map_err(pki_error)
51}
52
53pub struct ParsedCertificate<'a>(pub(crate) webpki::EndEntityCert<'a>);
57
58impl ParsedCertificate<'_> {
59 pub fn subject_public_key_info(&self) -> SubjectPublicKeyInfoDer<'static> {
61 self.0.subject_public_key_info()
62 }
63}
64
65impl<'a> TryFrom<&'a CertificateDer<'a>> for ParsedCertificate<'a> {
66 type Error = Error;
67 fn try_from(value: &'a CertificateDer<'a>) -> Result<Self, Self::Error> {
68 webpki::EndEntityCert::try_from(value)
69 .map_err(pki_error)
70 .map(ParsedCertificate)
71 }
72}
73
74pub fn verify_tls12_signature(
83 input: &SignatureVerificationInput<'_>,
84 supported_schemes: &WebPkiSupportedAlgorithms,
85) -> Result<HandshakeSignatureValid, Error> {
86 let possible_algs = supported_schemes.convert_scheme(input.signature.scheme)?;
87 let cert = match input.signer {
88 SignerPublicKey::X509(cert_der) => {
89 webpki::EndEntityCert::try_from(*cert_der).map_err(pki_error)?
90 }
91 SignerPublicKey::RawPublicKey(_) => {
92 return Err(ApiMisuse::InvalidSignerForProtocolVersion.into());
93 }
94 };
95
96 let mut error = None;
97 for alg in possible_algs {
98 match cert.verify_signature(*alg, input.message, input.signature.signature()) {
99 Err(err @ webpki::Error::UnsupportedSignatureAlgorithmForPublicKey(_)) => {
100 error = Some(err);
101 continue;
102 }
103 Err(e) => return Err(pki_error(e)),
104 Ok(()) => return Ok(HandshakeSignatureValid::assertion()),
105 }
106 }
107
108 Err(match error {
109 Some(e) => pki_error(e),
110 None => Error::ApiMisuse(ApiMisuse::NoSignatureVerificationAlgorithms),
111 })
112}
113
114pub fn verify_tls13_signature(
121 input: &SignatureVerificationInput<'_>,
122 supported_schemes: &WebPkiSupportedAlgorithms,
123) -> Result<HandshakeSignatureValid, Error> {
124 if !input
125 .signature
126 .scheme
127 .supported_in_tls13()
128 {
129 return Err(PeerMisbehaved::SignedHandshakeWithUnadvertisedSigScheme.into());
130 }
131
132 let &alg = supported_schemes
133 .convert_scheme(input.signature.scheme)?
134 .first()
135 .ok_or(Error::ApiMisuse(
136 ApiMisuse::NoSignatureVerificationAlgorithms,
137 ))?;
138
139 match input.signer {
140 SignerPublicKey::X509(cert_der) => {
141 webpki::EndEntityCert::try_from(*cert_der).and_then(|cert| {
142 cert.verify_signature(alg, input.message, input.signature.signature())
143 })
144 }
145 SignerPublicKey::RawPublicKey(spki) => webpki::RawPublicKeyEntity::try_from(*spki)
146 .and_then(|rpk| rpk.verify_signature(alg, input.message, input.signature.signature())),
147 }
148 .map_err(pki_error)
149 .map(|_| HandshakeSignatureValid::assertion())
150}
151
152pub(crate) fn verify_identity_signed_by_trust_anchor_impl(
166 cert: &ParsedCertificate<'_>,
167 roots: &RootCertStore,
168 intermediates: &[CertificateDer<'_>],
169 revocation: Option<webpki::RevocationOptions<'_>>,
170 now: UnixTime,
171 supported_algs: &[&dyn SignatureVerificationAlgorithm],
172) -> Result<(), Error> {
173 let result = cert.0.verify_for_usage(
174 supported_algs,
175 &roots.roots,
176 intermediates,
177 now,
178 &ExtendedKeyUsage::server_auth(),
179 revocation,
180 None,
181 );
182 match result {
183 Ok(_) => Ok(()),
184 Err(e) => Err(pki_error(e)),
185 }
186}
187
188#[cfg(test)]
189mod tests {
190 use alloc::vec;
191 use std::format;
192
193 use super::*;
194 use crate::crypto::{SignatureScheme, TEST_PROVIDER};
195 use crate::verify::DigitallySignedStruct;
196
197 #[test]
198 fn tls13_empty_signature_mapping_panics() {
199 let supported = WebPkiSupportedAlgorithms {
200 all: TEST_PROVIDER
201 .signature_verification_algorithms
202 .all,
203 mapping: &[(SignatureScheme::ED25519, &[])],
204 };
205
206 let cert = CertificateDer::from(vec![0u8]); let dss = DigitallySignedStruct::new(SignatureScheme::ED25519, vec![]);
208 let signer = SignerPublicKey::X509(&cert);
209 let input = SignatureVerificationInput {
210 message: b"hello",
211 signer: &signer,
212 signature: &dss,
213 };
214
215 assert_eq!(
216 verify_tls13_signature(&input, &supported).unwrap_err(),
217 Error::ApiMisuse(ApiMisuse::NoSignatureVerificationAlgorithms)
218 );
219 }
220
221 #[test]
222 fn certificate_debug() {
223 assert_eq!(
224 "CertificateDer(0x6162)",
225 format!("{:?}", CertificateDer::from(b"ab".to_vec()))
226 );
227 }
228
229 #[test]
230 fn webpki_supported_algorithms_is_debug() {
231 assert_eq!(
232 "WebPkiSupportedAlgorithms { all: [ .. ], mapping: [] }",
233 format!(
234 "{:?}",
235 WebPkiSupportedAlgorithms {
236 all: &[],
237 mapping: &[]
238 }
239 )
240 );
241 }
242}