clia_rustls_mod/webpki/
verify.rs1use 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};
10use crate::verify::{DigitallySignedStruct, HandshakeSignatureValid};
11
12#[allow(dead_code)]
24pub fn verify_server_cert_signed_by_trust_anchor(
25 cert: &ParsedCertificate,
26 roots: &RootCertStore,
27 intermediates: &[CertificateDer<'_>],
28 now: UnixTime,
29 supported_algs: &[&dyn SignatureVerificationAlgorithm],
30) -> Result<(), Error> {
31 verify_server_cert_signed_by_trust_anchor_impl(
32 cert,
33 roots,
34 intermediates,
35 None, now,
37 supported_algs,
38 )
39}
40
41pub 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
53#[derive(Clone, Copy)]
56#[allow(unreachable_pub)]
57pub struct WebPkiSupportedAlgorithms {
58 pub all: &'static [&'static dyn SignatureVerificationAlgorithm],
64
65 pub mapping: &'static [(
77 SignatureScheme,
78 &'static [&'static dyn SignatureVerificationAlgorithm],
79 )],
80}
81
82impl WebPkiSupportedAlgorithms {
83 pub fn supported_schemes(&self) -> Vec<SignatureScheme> {
85 self.mapping
86 .iter()
87 .map(|item| item.0)
88 .collect()
89 }
90
91 fn convert_scheme(
93 &self,
94 scheme: SignatureScheme,
95 ) -> Result<&[&'static dyn SignatureVerificationAlgorithm], Error> {
96 self.mapping
97 .iter()
98 .filter_map(|item| if item.0 == scheme { Some(item.1) } else { None })
99 .next()
100 .ok_or_else(|| PeerMisbehaved::SignedHandshakeWithUnadvertisedSigScheme.into())
101 }
102
103 pub fn fips(&self) -> bool {
105 self.all.iter().all(|alg| alg.fips())
106 && self
107 .mapping
108 .iter()
109 .all(|item| item.1.iter().all(|alg| alg.fips()))
110 }
111}
112
113impl fmt::Debug for WebPkiSupportedAlgorithms {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 write!(f, "WebPkiSupportedAlgorithms {{ all: [ .. ], mapping: ")?;
116 f.debug_list()
117 .entries(self.mapping.iter().map(|item| item.0))
118 .finish()?;
119 write!(f, " }}")
120 }
121}
122
123pub struct ParsedCertificate<'a>(pub(crate) webpki::EndEntityCert<'a>);
127
128impl<'a> TryFrom<&'a CertificateDer<'a>> for ParsedCertificate<'a> {
129 type Error = Error;
130 fn try_from(value: &'a CertificateDer<'a>) -> Result<Self, Self::Error> {
131 webpki::EndEntityCert::try_from(value)
132 .map_err(pki_error)
133 .map(ParsedCertificate)
134 }
135}
136
137pub fn verify_tls12_signature(
146 message: &[u8],
147 cert: &CertificateDer<'_>,
148 dss: &DigitallySignedStruct,
149 supported_schemes: &WebPkiSupportedAlgorithms,
150) -> Result<HandshakeSignatureValid, Error> {
151 let possible_algs = supported_schemes.convert_scheme(dss.scheme)?;
152 let cert = webpki::EndEntityCert::try_from(cert).map_err(pki_error)?;
153
154 for alg in possible_algs {
155 match cert.verify_signature(*alg, message, dss.signature()) {
156 Err(webpki::Error::UnsupportedSignatureAlgorithmForPublicKey) => continue,
157 Err(e) => return Err(pki_error(e)),
158 Ok(()) => return Ok(HandshakeSignatureValid::assertion()),
159 }
160 }
161
162 Err(pki_error(
163 webpki::Error::UnsupportedSignatureAlgorithmForPublicKey,
164 ))
165}
166
167pub fn verify_tls13_signature(
174 msg: &[u8],
175 cert: &CertificateDer<'_>,
176 dss: &DigitallySignedStruct,
177 supported_schemes: &WebPkiSupportedAlgorithms,
178) -> Result<HandshakeSignatureValid, Error> {
179 if !dss.scheme.supported_in_tls13() {
180 return Err(PeerMisbehaved::SignedHandshakeWithUnadvertisedSigScheme.into());
181 }
182
183 let alg = supported_schemes.convert_scheme(dss.scheme)?[0];
184
185 let cert = webpki::EndEntityCert::try_from(cert).map_err(pki_error)?;
186
187 cert.verify_signature(alg, msg, dss.signature())
188 .map_err(pki_error)
189 .map(|_| HandshakeSignatureValid::assertion())
190}
191
192pub(crate) fn verify_server_cert_signed_by_trust_anchor_impl(
206 cert: &ParsedCertificate,
207 roots: &RootCertStore,
208 intermediates: &[CertificateDer<'_>],
209 revocation: Option<webpki::RevocationOptions>,
210 now: UnixTime,
211 supported_algs: &[&dyn SignatureVerificationAlgorithm],
212) -> Result<(), Error> {
213 let result = cert.0.verify_for_usage(
214 supported_algs,
215 &roots.roots,
216 intermediates,
217 now,
218 webpki::KeyUsage::server_auth(),
219 revocation,
220 None,
221 );
222 match result {
223 Ok(_) => Ok(()),
224 Err(e) => Err(pki_error(e)),
225 }
226}
227
228#[cfg(test)]
229mod tests {
230 use std::format;
231
232 use super::*;
233
234 #[test]
235 fn certificate_debug() {
236 assert_eq!(
237 "CertificateDer(0x6162)",
238 format!("{:?}", CertificateDer::from(b"ab".to_vec()))
239 );
240 }
241
242 #[cfg(feature = "ring")]
243 #[test]
244 fn webpki_supported_algorithms_is_debug() {
245 assert_eq!(
246 "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] }",
247 format!("{:?}", crate::crypto::ring::default_provider().signature_verification_algorithms)
248 );
249 }
250}