1use alloc::vec::Vec;
2use core::fmt;
3
4use pki_types::{CertificateDer, ServerName, SignatureVerificationAlgorithm, UnixTime};
5
6use super::anchors::RootCertStore;
7use super::pki_error;
8use crate::enums::SignatureScheme;
9use crate::error::{Error, PeerMisbehaved};
10
11use crate::verify::{DigitallySignedStruct, HandshakeSignatureValid};
12
13#[allow(dead_code)]
25pub fn verify_server_cert_signed_by_trust_anchor(
26 cert: &ParsedCertificate,
27 roots: &RootCertStore,
28 intermediates: &[CertificateDer<'_>],
29 now: UnixTime,
30 supported_algs: &[&dyn SignatureVerificationAlgorithm],
31) -> Result<(), Error> {
32 verify_server_cert_signed_by_trust_anchor_impl(
33 cert,
34 roots,
35 intermediates,
36 None, now,
38 supported_algs,
39 )
40}
41
42pub fn verify_server_name(
46 cert: &ParsedCertificate,
47 server_name: &ServerName<'_>,
48) -> Result<(), Error> {
49 cert.0
50 .verify_is_valid_for_subject_name(server_name)
51 .map_err(pki_error)
52}
53
54#[derive(Clone, Copy)]
57#[allow(unreachable_pub)]
58pub struct WebPkiSupportedAlgorithms {
59 pub all: &'static [&'static dyn SignatureVerificationAlgorithm],
65
66 pub mapping: &'static [(
78 SignatureScheme,
79 &'static [&'static dyn SignatureVerificationAlgorithm],
80 )],
81}
82
83impl WebPkiSupportedAlgorithms {
84 pub fn supported_schemes(&self) -> Vec<SignatureScheme> {
86 self.mapping
87 .iter()
88 .map(|item| item.0)
89 .collect()
90 }
91
92 fn convert_scheme(
94 &self,
95 scheme: SignatureScheme,
96 ) -> Result<&[&'static dyn SignatureVerificationAlgorithm], Error> {
97 self.mapping
98 .iter()
99 .filter_map(|item| if item.0 == scheme { Some(item.1) } else { None })
100 .next()
101 .ok_or_else(|| PeerMisbehaved::SignedHandshakeWithUnadvertisedSigScheme.into())
102 }
103}
104
105impl fmt::Debug for WebPkiSupportedAlgorithms {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 write!(f, "WebPkiSupportedAlgorithms {{ all: [ .. ], mapping: ")?;
108 f.debug_list()
109 .entries(self.mapping.iter().map(|item| item.0))
110 .finish()?;
111 write!(f, " }}")
112 }
113}
114
115pub struct ParsedCertificate<'a>(pub(crate) webpki::EndEntityCert<'a>);
119
120impl<'a> TryFrom<&'a CertificateDer<'a>> for ParsedCertificate<'a> {
121 type Error = Error;
122 fn try_from(value: &'a CertificateDer<'a>) -> Result<Self, Self::Error> {
123 webpki::EndEntityCert::try_from(value)
124 .map_err(pki_error)
125 .map(ParsedCertificate)
126 }
127}
128
129pub fn verify_tls12_signature(
138 message: &[u8],
139 cert: &CertificateDer<'_>,
140 dss: &DigitallySignedStruct,
141 supported_schemes: &WebPkiSupportedAlgorithms,
142) -> Result<HandshakeSignatureValid, Error> {
143 let possible_algs = supported_schemes.convert_scheme(dss.scheme)?;
144 let cert = webpki::EndEntityCert::try_from(cert).map_err(pki_error)?;
145
146 for alg in possible_algs {
147 match cert.verify_signature(*alg, message, dss.signature()) {
148 Err(webpki::Error::UnsupportedSignatureAlgorithmForPublicKey) => continue,
149 Err(e) => return Err(pki_error(e)),
150 Ok(()) => return Ok(HandshakeSignatureValid::assertion()),
151 }
152 }
153
154 Err(pki_error(
155 webpki::Error::UnsupportedSignatureAlgorithmForPublicKey,
156 ))
157}
158
159pub fn verify_tls13_signature(
166 msg: &[u8],
167 cert: &CertificateDer<'_>,
168 dss: &DigitallySignedStruct,
169 supported_schemes: &WebPkiSupportedAlgorithms,
170) -> Result<HandshakeSignatureValid, Error> {
171 if !dss.scheme.supported_in_tls13() {
172 return Err(PeerMisbehaved::SignedHandshakeWithUnadvertisedSigScheme.into());
173 }
174
175 let alg = supported_schemes.convert_scheme(dss.scheme)?[0];
176
177 let cert = webpki::EndEntityCert::try_from(cert).map_err(pki_error)?;
178
179 cert.verify_signature(alg, msg, dss.signature())
180 .map_err(pki_error)
181 .map(|_| HandshakeSignatureValid::assertion())
182}
183
184pub(crate) fn verify_server_cert_signed_by_trust_anchor_impl(
198 cert: &ParsedCertificate,
199 roots: &RootCertStore,
200 intermediates: &[CertificateDer<'_>],
201 revocation: Option<webpki::RevocationOptions>,
202 now: UnixTime,
203 supported_algs: &[&dyn SignatureVerificationAlgorithm],
204) -> Result<(), Error> {
205 let result = cert.0.verify_for_usage(
206 supported_algs,
207 &roots.roots,
208 intermediates,
209 now,
210 webpki::KeyUsage::server_auth(),
211 revocation,
212 None,
213 );
214 match result {
215 Ok(_) => Ok(()),
216 Err(e) => Err(pki_error(e)),
217 }
218}
219
220#[cfg(test)]
221mod tests {
222 use super::*;
223 use std::format;
224
225 #[test]
226 fn certificate_debug() {
227 assert_eq!(
228 "CertificateDer(0x6162)",
229 format!("{:?}", CertificateDer::from(b"ab".to_vec()))
230 );
231 }
232
233 #[cfg(feature = "ring")]
234 #[test]
235 fn webpki_supported_algorithms_is_debug() {
236 assert_eq!(
237 "WebPkiSupportedAlgorithms { all: [ .. ], mapping: [ECDSA_NISTP384_SHA384, ECDSA_NISTP256_SHA256, ED25519, RSA_PSS_SHA512, RSA_PSS_SHA384, RSA_PSS_SHA256, RSA_PKCS1_SHA512, RSA_PKCS1_SHA384, RSA_PKCS1_SHA256] }",
238 format!("{:?}", crate::crypto::ring::default_provider().signature_verification_algorithms)
239 );
240 }
241}