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.convert_scheme(input.signature.scheme)?[0];
133 match input.signer {
134 SignerPublicKey::X509(cert_der) => {
135 webpki::EndEntityCert::try_from(*cert_der).and_then(|cert| {
136 cert.verify_signature(alg, input.message, input.signature.signature())
137 })
138 }
139 SignerPublicKey::RawPublicKey(spki) => webpki::RawPublicKeyEntity::try_from(*spki)
140 .and_then(|rpk| rpk.verify_signature(alg, input.message, input.signature.signature())),
141 }
142 .map_err(pki_error)
143 .map(|_| HandshakeSignatureValid::assertion())
144}
145
146pub(crate) fn verify_identity_signed_by_trust_anchor_impl(
160 cert: &ParsedCertificate<'_>,
161 roots: &RootCertStore,
162 intermediates: &[CertificateDer<'_>],
163 revocation: Option<webpki::RevocationOptions<'_>>,
164 now: UnixTime,
165 supported_algs: &[&dyn SignatureVerificationAlgorithm],
166) -> Result<(), Error> {
167 let result = cert.0.verify_for_usage(
168 supported_algs,
169 &roots.roots,
170 intermediates,
171 now,
172 &ExtendedKeyUsage::server_auth(),
173 revocation,
174 None,
175 );
176 match result {
177 Ok(_) => Ok(()),
178 Err(e) => Err(pki_error(e)),
179 }
180}
181
182#[cfg(test)]
183mod tests {
184 use std::format;
185
186 use super::*;
187
188 #[test]
189 fn certificate_debug() {
190 assert_eq!(
191 "CertificateDer(0x6162)",
192 format!("{:?}", CertificateDer::from(b"ab".to_vec()))
193 );
194 }
195
196 #[test]
197 fn webpki_supported_algorithms_is_debug() {
198 assert_eq!(
199 "WebPkiSupportedAlgorithms { all: [ .. ], mapping: [] }",
200 format!(
201 "{:?}",
202 WebPkiSupportedAlgorithms {
203 all: &[],
204 mapping: &[]
205 }
206 )
207 );
208 }
209}