webtrans_quinn/tls/
mod.rs1pub mod cert;
4pub mod key;
5
6use webtrans_proto::{Error, Result};
7
8use cert::SkipServerVerification;
9use rustls::client::{ClientConfig, WebPkiServerVerifier};
10use rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer};
11use rustls::server::ServerConfig;
12use std::path::Path;
13use std::sync::Arc;
14
15pub type TlsServerConfig = rustls::server::ServerConfig;
17
18pub type TlsClientConfig = rustls::client::ClientConfig;
20
21pub fn generate_self_signed_pair_der(
23 subject_alt_names: Vec<String>,
24) -> Result<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)> {
25 let cert = rcgen::generate_simple_self_signed(subject_alt_names)
26 .map_err(|e| Error::Tls(e.to_string()))?;
27
28 let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(cert.signing_key.serialize_der()));
29 let cert_chain = vec![CertificateDer::from(cert.cert)];
30 Ok((cert_chain, key))
31}
32
33pub fn generate_self_signed_pair_pem(
35 subject_alt_names: Vec<String>,
36) -> Result<(Vec<String>, String)> {
37 let cert = rcgen::generate_simple_self_signed(subject_alt_names)
38 .map_err(|e| Error::Tls(e.to_string()))?;
39
40 let key = cert.signing_key.serialize_pem();
41 let cert_chain = vec![cert.cert.pem()];
42 Ok((cert_chain, key))
43}
44
45pub fn load_cert(
47 cert_path: &Path,
48 key_path: &Path,
49) -> Result<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)> {
50 let cert_chain = cert::load_certs(cert_path)?;
51 let key = key::load_key(key_path)?;
52 Ok((cert_chain, key))
53}
54
55#[derive(Debug, Clone)]
57pub struct TlsConfig {
58 pub client_config: ClientConfig,
60 pub server_config: ServerConfig,
62}
63
64impl TlsConfig {
65 pub fn with_cert(cert_path: &Path, key_path: &Path) -> Result<Self> {
67 let client_config = TlsClientConfigBuilder::new_with_native_certs()?
68 .with_alpn_protocols(vec![b"h3".to_vec()])
69 .build();
70
71 let server_config = TlsServerConfigBuilder::new_with_cert(cert_path, key_path)?
72 .with_alpn_protocols(vec![b"h3".to_vec()])
73 .build();
74
75 Ok(Self {
76 client_config,
77 server_config,
78 })
79 }
80
81 pub fn with_self_signed_certs() -> Result<Self> {
83 let client_config = TlsClientConfigBuilder::new_with_native_certs()?
84 .with_alpn_protocols(vec![b"h3".to_vec()])
85 .build();
86
87 let server_config =
88 TlsServerConfigBuilder::new_with_self_signed_certs(vec!["localhost".into()])?
89 .with_alpn_protocols(vec![b"h3".to_vec()])
90 .build();
91
92 Ok(Self {
93 client_config,
94 server_config,
95 })
96 }
97
98 pub fn new_native_config() -> Result<Self> {
100 let client_config = TlsClientConfigBuilder::new_with_native_certs()?
101 .with_alpn_protocols(vec![b"h3".to_vec()])
102 .build();
103
104 let server_config =
105 TlsServerConfigBuilder::new_with_self_signed_certs(vec!["localhost".into()])?
106 .with_alpn_protocols(vec![b"h3".to_vec()])
107 .build();
108
109 Ok(Self {
110 client_config,
111 server_config,
112 })
113 }
114
115 pub fn new_insecure_config() -> Result<Self> {
117 let client_config = TlsClientConfigBuilder::new_insecure()?
118 .with_alpn_protocols(vec![b"h3".to_vec()])
119 .build();
120
121 let server_config =
122 TlsServerConfigBuilder::new_with_self_signed_certs(vec!["localhost".into()])?
123 .with_alpn_protocols(vec![b"h3".to_vec()])
124 .build();
125
126 Ok(Self {
127 client_config,
128 server_config,
129 })
130 }
131}
132
133#[derive(Debug, Clone)]
135pub struct TlsServerConfigBuilder {
136 inner: TlsServerConfig,
137}
138
139impl TlsServerConfigBuilder {
140 pub fn new_insecure(subject_alt_names: Vec<String>) -> Result<Self> {
142 let (certs, key) = generate_self_signed_pair_der(subject_alt_names)?;
143 let inner = ServerConfig::builder()
144 .with_no_client_auth()
145 .with_single_cert(certs, key)
146 .map_err(|e| Error::Tls(e.to_string()))?;
147 Ok(Self { inner })
148 }
149
150 pub fn new_with_cert(cert_path: &Path, key_path: &Path) -> Result<Self> {
152 let (certs, key) = load_cert(cert_path, key_path)?;
153 let inner = ServerConfig::builder()
154 .with_no_client_auth()
155 .with_single_cert(certs, key)
156 .map_err(|e| Error::Tls(e.to_string()))?;
157 Ok(Self { inner })
158 }
159
160 pub fn new_with_self_signed_certs(subject_alt_names: Vec<String>) -> Result<Self> {
162 Self::new_insecure(subject_alt_names)
163 }
164
165 pub fn with_alpn_protocols(mut self, protocols: Vec<Vec<u8>>) -> Self {
167 self.inner.alpn_protocols = protocols;
168 self
169 }
170
171 pub fn build(self) -> TlsServerConfig {
173 self.inner
174 }
175}
176
177#[derive(Debug, Clone)]
179pub struct TlsClientConfigBuilder {
180 inner: TlsClientConfig,
181}
182
183impl TlsClientConfigBuilder {
184 pub fn new_insecure() -> Result<Self> {
186 let inner = ClientConfig::builder()
187 .dangerous()
188 .with_custom_certificate_verifier(SkipServerVerification::new())
189 .with_no_client_auth();
190 Ok(Self { inner })
191 }
192
193 pub fn new_with_native_certs() -> Result<Self> {
195 let native_certs = cert::get_native_certs()?;
196 let inner = ClientConfig::builder()
197 .with_root_certificates(native_certs)
198 .with_no_client_auth();
199 Ok(Self { inner })
200 }
201
202 pub fn new_with_webpki_verifier(verifier: Arc<WebPkiServerVerifier>) -> Result<Self> {
204 let inner = ClientConfig::builder()
205 .with_webpki_verifier(verifier)
206 .with_no_client_auth();
207 Ok(Self { inner })
208 }
209
210 pub fn with_alpn_protocols(mut self, protocols: Vec<Vec<u8>>) -> Self {
212 self.inner.alpn_protocols = protocols;
213 self
214 }
215
216 pub fn build(self) -> TlsClientConfig {
218 self.inner
219 }
220}
221
222#[cfg(test)]
223mod tests {
224 use super::*;
225
226 #[test]
227 fn test_generate_self_signed_pair_der() {
228 let (cert_chain, key) = generate_self_signed_pair_der(vec!["localhost".into()]).unwrap();
229 let rustls_server_config = ServerConfig::builder()
230 .with_no_client_auth()
231 .with_single_cert(cert_chain, key);
232
233 if let Err(e) = rustls_server_config {
234 panic!("Failed to create ServerConfig: {e}");
235 }
236 }
237
238 #[test]
239 fn test_generate_self_signed_pair_pem() {
240 let (cert_chain, key) = generate_self_signed_pair_pem(vec!["localhost".into()]).unwrap();
241
242 let cert_path = Path::new("cert.pem");
243 let key_path = Path::new("key.pem");
244 std::fs::write(cert_path, cert_chain.join("\n")).unwrap();
245 std::fs::write(key_path, key).unwrap();
246
247 let (cert_chain, key) = load_cert(cert_path, key_path).unwrap();
248 let rustls_server_config = ServerConfig::builder()
249 .with_no_client_auth()
250 .with_single_cert(cert_chain, key);
251
252 if let Err(e) = rustls_server_config {
253 panic!("Failed to create ServerConfig: {e}");
254 }
255
256 std::fs::remove_file(cert_path).unwrap();
257 std::fs::remove_file(key_path).unwrap();
258 }
259}