uselesskey_rustls/
config.rs1use std::sync::Arc;
4
5use rustls::crypto::CryptoProvider;
6
7#[cfg(feature = "x509")]
8use crate::RustlsCertExt;
9#[cfg(feature = "x509")]
10use crate::RustlsChainExt;
11#[cfg(feature = "server-config")]
12use crate::RustlsPrivateKeyExt;
13
14#[cfg(feature = "server-config")]
20pub trait RustlsServerConfigExt {
21 fn server_config_rustls(&self) -> rustls::ServerConfig;
23
24 fn server_config_rustls_with_provider(
26 &self,
27 provider: Arc<CryptoProvider>,
28 ) -> rustls::ServerConfig;
29}
30
31#[cfg(all(feature = "x509", feature = "server-config"))]
32impl RustlsServerConfigExt for uselesskey_x509::X509Chain {
33 fn server_config_rustls(&self) -> rustls::ServerConfig {
34 let private_key = self.private_key_der_rustls();
35 let cert_chain = self.chain_der_rustls();
36 rustls::ServerConfig::builder()
37 .with_no_client_auth()
38 .with_single_cert(cert_chain, private_key)
39 .expect("valid server config")
40 }
41
42 fn server_config_rustls_with_provider(
43 &self,
44 provider: Arc<CryptoProvider>,
45 ) -> rustls::ServerConfig {
46 let private_key = self.private_key_der_rustls();
47 let cert_chain = self.chain_der_rustls();
48 rustls::ServerConfig::builder_with_provider(provider)
49 .with_safe_default_protocol_versions()
50 .expect("valid protocol versions")
51 .with_no_client_auth()
52 .with_single_cert(cert_chain, private_key)
53 .expect("valid server config")
54 }
55}
56
57#[cfg(all(feature = "x509", feature = "server-config"))]
58impl RustlsServerConfigExt for uselesskey_x509::X509Cert {
59 fn server_config_rustls(&self) -> rustls::ServerConfig {
60 let private_key = self.private_key_der_rustls();
61 let cert_chain = vec![self.certificate_der_rustls()];
62 rustls::ServerConfig::builder()
63 .with_no_client_auth()
64 .with_single_cert(cert_chain, private_key)
65 .expect("valid server config")
66 }
67
68 fn server_config_rustls_with_provider(
69 &self,
70 provider: Arc<CryptoProvider>,
71 ) -> rustls::ServerConfig {
72 let private_key = self.private_key_der_rustls();
73 let cert_chain = vec![self.certificate_der_rustls()];
74 rustls::ServerConfig::builder_with_provider(provider)
75 .with_safe_default_protocol_versions()
76 .expect("valid protocol versions")
77 .with_no_client_auth()
78 .with_single_cert(cert_chain, private_key)
79 .expect("valid server config")
80 }
81}
82
83#[cfg(feature = "client-config")]
89pub trait RustlsClientConfigExt {
90 fn client_config_rustls(&self) -> rustls::ClientConfig;
92
93 fn client_config_rustls_with_provider(
95 &self,
96 provider: Arc<CryptoProvider>,
97 ) -> rustls::ClientConfig;
98}
99
100#[cfg(all(feature = "x509", feature = "client-config"))]
101impl RustlsClientConfigExt for uselesskey_x509::X509Chain {
102 fn client_config_rustls(&self) -> rustls::ClientConfig {
103 let mut root_store = rustls::RootCertStore::empty();
104 root_store
105 .add(self.root_certificate_der_rustls())
106 .expect("valid root cert");
107 rustls::ClientConfig::builder()
108 .with_root_certificates(root_store)
109 .with_no_client_auth()
110 }
111
112 fn client_config_rustls_with_provider(
113 &self,
114 provider: Arc<CryptoProvider>,
115 ) -> rustls::ClientConfig {
116 let mut root_store = rustls::RootCertStore::empty();
117 root_store
118 .add(self.root_certificate_der_rustls())
119 .expect("valid root cert");
120 rustls::ClientConfig::builder_with_provider(provider)
121 .with_safe_default_protocol_versions()
122 .expect("valid protocol versions")
123 .with_root_certificates(root_store)
124 .with_no_client_auth()
125 }
126}
127
128#[cfg(all(feature = "x509", feature = "client-config"))]
129impl RustlsClientConfigExt for uselesskey_x509::X509Cert {
130 fn client_config_rustls(&self) -> rustls::ClientConfig {
131 let mut root_store = rustls::RootCertStore::empty();
132 root_store
133 .add(self.certificate_der_rustls())
134 .expect("valid root cert");
135 rustls::ClientConfig::builder()
136 .with_root_certificates(root_store)
137 .with_no_client_auth()
138 }
139
140 fn client_config_rustls_with_provider(
141 &self,
142 provider: Arc<CryptoProvider>,
143 ) -> rustls::ClientConfig {
144 let mut root_store = rustls::RootCertStore::empty();
145 root_store
146 .add(self.certificate_der_rustls())
147 .expect("valid root cert");
148 rustls::ClientConfig::builder_with_provider(provider)
149 .with_safe_default_protocol_versions()
150 .expect("valid protocol versions")
151 .with_root_certificates(root_store)
152 .with_no_client_auth()
153 }
154}
155
156#[cfg(all(feature = "server-config", feature = "client-config"))]
162pub trait RustlsMtlsExt {
163 fn server_config_mtls_rustls(&self) -> rustls::ServerConfig;
166
167 fn server_config_mtls_rustls_with_provider(
169 &self,
170 provider: Arc<CryptoProvider>,
171 ) -> rustls::ServerConfig;
172
173 fn client_config_mtls_rustls(&self) -> rustls::ClientConfig;
176
177 fn client_config_mtls_rustls_with_provider(
179 &self,
180 provider: Arc<CryptoProvider>,
181 ) -> rustls::ClientConfig;
182}
183
184#[cfg(all(feature = "x509", feature = "server-config", feature = "client-config"))]
185impl RustlsMtlsExt for uselesskey_x509::X509Chain {
186 fn server_config_mtls_rustls(&self) -> rustls::ServerConfig {
187 let mut root_store = rustls::RootCertStore::empty();
188 root_store
189 .add(self.root_certificate_der_rustls())
190 .expect("valid root cert");
191
192 let client_verifier = rustls::server::WebPkiClientVerifier::builder(root_store.into())
193 .build()
194 .expect("valid client verifier");
195
196 let private_key = self.private_key_der_rustls();
197 let cert_chain = self.chain_der_rustls();
198
199 rustls::ServerConfig::builder()
200 .with_client_cert_verifier(client_verifier)
201 .with_single_cert(cert_chain, private_key)
202 .expect("valid mTLS server config")
203 }
204
205 fn server_config_mtls_rustls_with_provider(
206 &self,
207 provider: Arc<CryptoProvider>,
208 ) -> rustls::ServerConfig {
209 let mut root_store = rustls::RootCertStore::empty();
210 root_store
211 .add(self.root_certificate_der_rustls())
212 .expect("valid root cert");
213
214 let client_verifier = rustls::server::WebPkiClientVerifier::builder(root_store.into())
215 .build()
216 .expect("valid client verifier");
217
218 let private_key = self.private_key_der_rustls();
219 let cert_chain = self.chain_der_rustls();
220
221 rustls::ServerConfig::builder_with_provider(provider)
222 .with_safe_default_protocol_versions()
223 .expect("valid protocol versions")
224 .with_client_cert_verifier(client_verifier)
225 .with_single_cert(cert_chain, private_key)
226 .expect("valid mTLS server config")
227 }
228
229 fn client_config_mtls_rustls(&self) -> rustls::ClientConfig {
230 let mut root_store = rustls::RootCertStore::empty();
231 root_store
232 .add(self.root_certificate_der_rustls())
233 .expect("valid root cert");
234
235 let private_key = self.private_key_der_rustls();
236 let cert_chain = self.chain_der_rustls();
237
238 rustls::ClientConfig::builder()
239 .with_root_certificates(root_store)
240 .with_client_auth_cert(cert_chain, private_key)
241 .expect("valid mTLS client config")
242 }
243
244 fn client_config_mtls_rustls_with_provider(
245 &self,
246 provider: Arc<CryptoProvider>,
247 ) -> rustls::ClientConfig {
248 let mut root_store = rustls::RootCertStore::empty();
249 root_store
250 .add(self.root_certificate_der_rustls())
251 .expect("valid root cert");
252
253 let private_key = self.private_key_der_rustls();
254 let cert_chain = self.chain_der_rustls();
255
256 rustls::ClientConfig::builder_with_provider(provider)
257 .with_safe_default_protocol_versions()
258 .expect("valid protocol versions")
259 .with_root_certificates(root_store)
260 .with_client_auth_cert(cert_chain, private_key)
261 .expect("valid mTLS client config")
262 }
263}
264
265#[cfg(test)]
270#[cfg(all(feature = "server-config", feature = "client-config"))]
271mod tests {
272 use super::*;
273 use uselesskey_x509::{ChainSpec, X509FactoryExt, X509Spec};
274
275 use std::sync::Once;
276 static INIT: Once = Once::new();
277
278 fn install_provider() {
279 INIT.call_once(|| {
280 let _ = rustls::crypto::ring::default_provider().install_default();
285 });
286 }
287
288 fn ring_provider() -> Arc<CryptoProvider> {
289 Arc::new(rustls::crypto::ring::default_provider())
290 }
291
292 const MAX_HANDSHAKE_ITERATIONS: usize = 10;
295
296 #[test]
297 fn server_config_from_chain() {
298 install_provider();
299 let fx = super::super::testutil::fx();
300 let chain = fx.x509_chain("test", ChainSpec::new("test.example.com"));
301 let _cfg = chain.server_config_rustls();
303 }
304
305 #[test]
306 fn server_config_from_chain_with_provider() {
307 install_provider();
308 let fx = super::super::testutil::fx();
309 let chain = fx.x509_chain("test-provider", ChainSpec::new("test.example.com"));
310 let _cfg = chain.server_config_rustls_with_provider(ring_provider());
311 }
312
313 #[test]
314 fn client_config_from_chain() {
315 install_provider();
316 let fx = super::super::testutil::fx();
317 let chain = fx.x509_chain("test", ChainSpec::new("test.example.com"));
318 let _cfg = chain.client_config_rustls();
319 }
320
321 #[test]
322 fn client_config_from_chain_with_provider() {
323 install_provider();
324 let fx = super::super::testutil::fx();
325 let chain = fx.x509_chain("test-provider", ChainSpec::new("test.example.com"));
326 let _cfg = chain.client_config_rustls_with_provider(ring_provider());
327 }
328
329 #[test]
330 fn server_config_from_self_signed() {
331 install_provider();
332 let fx = super::super::testutil::fx();
333 let cert = fx.x509_self_signed("test", X509Spec::self_signed("test.example.com"));
334 let _cfg = cert.server_config_rustls();
335 }
336
337 #[test]
338 fn server_config_from_self_signed_with_provider() {
339 install_provider();
340 let fx = super::super::testutil::fx();
341 let cert = fx.x509_self_signed("test-provider", X509Spec::self_signed("test.example.com"));
342 let _cfg = cert.server_config_rustls_with_provider(ring_provider());
343 }
344
345 #[test]
346 fn client_config_from_self_signed() {
347 install_provider();
348 let fx = super::super::testutil::fx();
349 let cert = fx.x509_self_signed("test", X509Spec::self_signed("test.example.com"));
350 let _cfg = cert.client_config_rustls();
351 }
352
353 #[test]
354 fn client_config_from_self_signed_with_provider() {
355 install_provider();
356 let fx = super::super::testutil::fx();
357 let cert = fx.x509_self_signed("test-provider", X509Spec::self_signed("test.example.com"));
358 let _cfg = cert.client_config_rustls_with_provider(ring_provider());
359 }
360
361 #[test]
362 fn tls_handshake_roundtrip() {
363 let fx = super::super::testutil::fx();
364 let chain = fx.x509_chain("tls-test", ChainSpec::new("test.example.com"));
365
366 let provider = ring_provider();
367 let server_config = Arc::new(chain.server_config_rustls_with_provider(provider.clone()));
368 let client_config = Arc::new(chain.client_config_rustls_with_provider(provider));
369
370 let server_name: rustls::pki_types::ServerName<'_> = "test.example.com".try_into().unwrap();
371 let mut server = rustls::ServerConnection::new(server_config).unwrap();
372 let mut client =
373 rustls::ClientConnection::new(client_config, server_name.to_owned()).unwrap();
374
375 let mut buf = Vec::new();
378 for iteration in 0..MAX_HANDSHAKE_ITERATIONS {
379 let mut progress = false;
380
381 buf.clear();
383 if client.wants_write() {
384 client.write_tls(&mut buf).unwrap();
385 if !buf.is_empty() {
386 server.read_tls(&mut &buf[..]).unwrap();
387 server.process_new_packets().unwrap();
388 progress = true;
389 }
390 }
391
392 buf.clear();
394 if server.wants_write() {
395 server.write_tls(&mut buf).unwrap();
396 if !buf.is_empty() {
397 client.read_tls(&mut &buf[..]).unwrap();
398 client.process_new_packets().unwrap();
399 progress = true;
400 }
401 }
402
403 if !progress {
404 break;
405 }
406
407 assert!(
410 iteration < MAX_HANDSHAKE_ITERATIONS - 1,
411 "TLS handshake did not complete within {} iterations",
412 MAX_HANDSHAKE_ITERATIONS
413 );
414 }
415
416 assert!(!client.is_handshaking());
417 assert!(!server.is_handshaking());
418 }
419
420 #[test]
421 fn mtls_with_provider_roundtrip() {
422 let fx = super::super::testutil::fx();
423 let chain = fx.x509_chain("mtls-provider-test", ChainSpec::new("test.example.com"));
424
425 let provider = ring_provider();
426 let server_config =
427 Arc::new(chain.server_config_mtls_rustls_with_provider(provider.clone()));
428 let client_config = Arc::new(chain.client_config_mtls_rustls_with_provider(provider));
429
430 let server_name: rustls::pki_types::ServerName<'_> = "test.example.com".try_into().unwrap();
431 let mut server = rustls::ServerConnection::new(server_config).unwrap();
432 let mut client =
433 rustls::ClientConnection::new(client_config, server_name.to_owned()).unwrap();
434
435 let mut buf = Vec::new();
436 for iteration in 0..MAX_HANDSHAKE_ITERATIONS {
437 let mut progress = false;
438
439 buf.clear();
440 if client.wants_write() {
441 client.write_tls(&mut buf).unwrap();
442 if !buf.is_empty() {
443 server.read_tls(&mut &buf[..]).unwrap();
444 server.process_new_packets().unwrap();
445 progress = true;
446 }
447 }
448
449 buf.clear();
450 if server.wants_write() {
451 server.write_tls(&mut buf).unwrap();
452 if !buf.is_empty() {
453 client.read_tls(&mut &buf[..]).unwrap();
454 client.process_new_packets().unwrap();
455 progress = true;
456 }
457 }
458
459 if !progress {
460 break;
461 }
462
463 assert!(
466 iteration < MAX_HANDSHAKE_ITERATIONS - 1,
467 "mTLS handshake did not complete within {} iterations",
468 MAX_HANDSHAKE_ITERATIONS
469 );
470 }
471
472 assert!(!client.is_handshaking());
473 assert!(!server.is_handshaking());
474 }
475
476 use uselesskey_test_support::{TestResult, ensure, require_ok};
489
490 #[test]
491 fn server_config_mtls_from_chain_default_provider() -> TestResult<()> {
492 install_provider();
493 let fx = super::super::testutil::fx();
494 let chain = fx.x509_chain("mtls-default-server", ChainSpec::new("test.example.com"));
495
496 let cfg = chain.server_config_mtls_rustls();
500
501 ensure!(
505 cfg.alpn_protocols.is_empty(),
506 "default ServerConfig must have no ALPN protocols configured",
507 );
508 Ok(())
509 }
510
511 #[test]
512 fn client_config_mtls_from_chain_default_provider() -> TestResult<()> {
513 install_provider();
514 let fx = super::super::testutil::fx();
515 let chain = fx.x509_chain("mtls-default-client", ChainSpec::new("test.example.com"));
516
517 let cfg = chain.client_config_mtls_rustls();
518
519 ensure!(
520 cfg.alpn_protocols.is_empty(),
521 "default ClientConfig must have no ALPN protocols configured",
522 );
523 Ok(())
524 }
525
526 #[test]
527 fn mtls_default_provider_pair_completes_handshake() -> TestResult<()> {
528 install_provider();
529 let fx = super::super::testutil::fx();
530 let chain = fx.x509_chain("mtls-default-handshake", ChainSpec::new("test.example.com"));
531
532 let server_config = Arc::new(chain.server_config_mtls_rustls());
533 let client_config = Arc::new(chain.client_config_mtls_rustls());
534
535 let server_name: rustls::pki_types::ServerName<'_> = require_ok(
536 "test.example.com".try_into(),
537 "test.example.com must parse as ServerName",
538 )?;
539 let mut server = require_ok(
540 rustls::ServerConnection::new(server_config),
541 "ServerConnection::new",
542 )?;
543 let mut client = require_ok(
544 rustls::ClientConnection::new(client_config, server_name.to_owned()),
545 "ClientConnection::new",
546 )?;
547
548 let mut buf = Vec::new();
549 for iteration in 0..MAX_HANDSHAKE_ITERATIONS {
550 let mut progress = false;
551
552 buf.clear();
553 if client.wants_write() {
554 require_ok(client.write_tls(&mut buf), "client.write_tls")?;
555 if !buf.is_empty() {
556 require_ok(server.read_tls(&mut &buf[..]), "server.read_tls")?;
557 require_ok(server.process_new_packets(), "server.process_new_packets")?;
558 progress = true;
559 }
560 }
561
562 buf.clear();
563 if server.wants_write() {
564 require_ok(server.write_tls(&mut buf), "server.write_tls")?;
565 if !buf.is_empty() {
566 require_ok(client.read_tls(&mut &buf[..]), "client.read_tls")?;
567 require_ok(client.process_new_packets(), "client.process_new_packets")?;
568 progress = true;
569 }
570 }
571
572 if !progress {
573 break;
574 }
575
576 ensure!(
577 iteration < MAX_HANDSHAKE_ITERATIONS - 1,
578 "default-provider mTLS handshake did not complete within {} iterations",
579 MAX_HANDSHAKE_ITERATIONS,
580 );
581 }
582
583 ensure!(!client.is_handshaking(), "client must finish handshaking");
584 ensure!(!server.is_handshaking(), "server must finish handshaking");
585 Ok(())
586 }
587
588 #[test]
589 fn mtls_roundtrip() {
590 let fx = super::super::testutil::fx();
591 let chain = fx.x509_chain("mtls-test", ChainSpec::new("test.example.com"));
592
593 let provider = ring_provider();
594 let server_config =
595 Arc::new(chain.server_config_mtls_rustls_with_provider(provider.clone()));
596 let client_config = Arc::new(chain.client_config_mtls_rustls_with_provider(provider));
597
598 let server_name: rustls::pki_types::ServerName<'_> = "test.example.com".try_into().unwrap();
599 let mut server = rustls::ServerConnection::new(server_config).unwrap();
600 let mut client =
601 rustls::ClientConnection::new(client_config, server_name.to_owned()).unwrap();
602
603 let mut buf = Vec::new();
604 for iteration in 0..MAX_HANDSHAKE_ITERATIONS {
605 let mut progress = false;
606
607 buf.clear();
608 if client.wants_write() {
609 client.write_tls(&mut buf).unwrap();
610 if !buf.is_empty() {
611 server.read_tls(&mut &buf[..]).unwrap();
612 server.process_new_packets().unwrap();
613 progress = true;
614 }
615 }
616
617 buf.clear();
618 if server.wants_write() {
619 server.write_tls(&mut buf).unwrap();
620 if !buf.is_empty() {
621 client.read_tls(&mut &buf[..]).unwrap();
622 client.process_new_packets().unwrap();
623 progress = true;
624 }
625 }
626
627 if !progress {
628 break;
629 }
630
631 assert!(
634 iteration < MAX_HANDSHAKE_ITERATIONS - 1,
635 "mTLS handshake did not complete within {} iterations",
636 MAX_HANDSHAKE_ITERATIONS
637 );
638 }
639
640 assert!(!client.is_handshaking());
641 assert!(!server.is_handshaking());
642 }
643}