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