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(
87 input: &SignatureVerificationInput<'_>,
88 supported_schemes: &WebPkiSupportedAlgorithms,
89) -> Result<HandshakeSignatureValid, Error> {
90 if input
91 .signature
92 .scheme
93 .algorithm()
94 .is_none()
95 {
96 return Err(PeerMisbehaved::SignedHandshakeWithUnadvertisedSigScheme.into());
97 }
98
99 let possible_algs = supported_schemes.convert_scheme(input.signature.scheme)?;
100 let cert = match input.signer {
101 SignerPublicKey::X509(cert_der) => {
102 webpki::EndEntityCert::try_from(*cert_der).map_err(pki_error)?
103 }
104 SignerPublicKey::RawPublicKey(_) => {
105 return Err(ApiMisuse::InvalidSignerForProtocolVersion.into());
106 }
107 };
108
109 let mut error = None;
110 for alg in possible_algs {
111 match cert.verify_signature(*alg, input.message, input.signature.signature()) {
112 Err(err @ webpki::Error::UnsupportedSignatureAlgorithmForPublicKey(_)) => {
113 error = Some(err);
114 continue;
115 }
116 Err(e) => return Err(pki_error(e)),
117 Ok(()) => return Ok(HandshakeSignatureValid::assertion()),
118 }
119 }
120
121 Err(match error {
122 Some(e) => pki_error(e),
123 None => Error::ApiMisuse(ApiMisuse::NoSignatureVerificationAlgorithms),
124 })
125}
126
127pub fn verify_tls13_signature(
137 input: &SignatureVerificationInput<'_>,
138 supported_schemes: &WebPkiSupportedAlgorithms,
139) -> Result<HandshakeSignatureValid, Error> {
140 if !input
141 .signature
142 .scheme
143 .supported_in_tls13()
144 {
145 return Err(PeerMisbehaved::SignedHandshakeWithUnadvertisedSigScheme.into());
146 }
147
148 let &alg = supported_schemes
149 .convert_scheme(input.signature.scheme)?
150 .first()
151 .ok_or(Error::ApiMisuse(
152 ApiMisuse::NoSignatureVerificationAlgorithms,
153 ))?;
154
155 match input.signer {
156 SignerPublicKey::X509(cert_der) => {
157 webpki::EndEntityCert::try_from(*cert_der).and_then(|cert| {
158 cert.verify_signature(alg, input.message, input.signature.signature())
159 })
160 }
161 SignerPublicKey::RawPublicKey(spki) => webpki::RawPublicKeyEntity::try_from(*spki)
162 .and_then(|rpk| rpk.verify_signature(alg, input.message, input.signature.signature())),
163 }
164 .map_err(pki_error)
165 .map(|_| HandshakeSignatureValid::assertion())
166}
167
168pub(crate) fn verify_identity_signed_by_trust_anchor_impl(
182 cert: &ParsedCertificate<'_>,
183 roots: &RootCertStore,
184 intermediates: &[CertificateDer<'_>],
185 revocation: Option<webpki::RevocationOptions<'_>>,
186 now: UnixTime,
187 supported_algs: &[&dyn SignatureVerificationAlgorithm],
188) -> Result<(), Error> {
189 let result = cert.0.verify_for_usage(
190 supported_algs,
191 &roots.roots,
192 intermediates,
193 now,
194 &ExtendedKeyUsage::server_auth(),
195 revocation,
196 None,
197 );
198 match result {
199 Ok(_) => Ok(()),
200 Err(e) => Err(pki_error(e)),
201 }
202}
203
204#[cfg(test)]
205mod tests {
206 use alloc::vec;
207 use std::format;
208
209 use super::*;
210 use crate::crypto::{SignatureScheme, TEST_PROVIDER};
211 use crate::verify::DigitallySignedStruct;
212
213 #[test]
214 fn tls13_empty_signature_mapping_panics() {
215 let supported = WebPkiSupportedAlgorithms {
216 all: TEST_PROVIDER
217 .signature_verification_algorithms
218 .all,
219 mapping: &[(SignatureScheme::ED25519, &[])],
220 };
221
222 let cert = CertificateDer::from(vec![0u8]); let dss = DigitallySignedStruct::new(SignatureScheme::ED25519, vec![]);
224 let signer = SignerPublicKey::X509(&cert);
225 let input = SignatureVerificationInput {
226 message: b"hello",
227 signer: &signer,
228 signature: &dss,
229 };
230
231 assert_eq!(
232 verify_tls13_signature(&input, &supported).unwrap_err(),
233 Error::ApiMisuse(ApiMisuse::NoSignatureVerificationAlgorithms)
234 );
235 }
236
237 #[test]
238 fn certificate_debug() {
239 assert_eq!(
240 "CertificateDer(0x6162)",
241 format!("{:?}", CertificateDer::from(b"ab".to_vec()))
242 );
243 }
244
245 #[test]
246 fn webpki_supported_algorithms_is_debug() {
247 assert_eq!(
248 "WebPkiSupportedAlgorithms { all: [ .. ], mapping: [] }",
249 format!(
250 "{:?}",
251 WebPkiSupportedAlgorithms {
252 all: &[],
253 mapping: &[]
254 }
255 )
256 );
257 }
258}