1#[cfg(feature = "unstable-cert_authorities")]
5use crate::cert_authorities::CertificateRequestCallback;
6#[cfg(feature = "unstable-events")]
7use crate::events::{EventSubscriber, HandshakeEvent};
8#[cfg(feature = "unstable-renegotiate")]
9use crate::renegotiate::RenegotiateCallback;
10use crate::{
11 callbacks::*,
12 cert_chain::CertificateChain,
13 enums::*,
14 error::{Error, ErrorType, Fallible},
15 security,
16};
17use core::{convert::TryInto, ptr::NonNull};
18use s2n_tls_sys::*;
19use std::{
20 ffi::{c_void, CString},
21 path::Path,
22 pin::Pin,
23 sync::atomic::{AtomicUsize, Ordering},
24 task::Poll,
25 time::{Duration, SystemTime},
26};
27
28#[derive(Debug, PartialEq)]
30pub struct Config(NonNull<s2n_config>);
31
32unsafe impl Send for Config {}
36
37unsafe impl Sync for Config {}
42
43impl Config {
44 pub fn new() -> Self {
56 Self::default()
57 }
58
59 pub fn builder() -> Builder {
61 Builder::default()
62 }
63
64 pub(crate) unsafe fn from_raw(config: NonNull<s2n_config>) -> Self {
71 let config = Self(config);
72
73 config.context();
76
77 config
78 }
79
80 pub(crate) fn as_mut_ptr(&mut self) -> *mut s2n_config {
81 self.0.as_ptr()
82 }
83
84 pub(crate) fn context(&self) -> &Context {
88 let mut ctx = core::ptr::null_mut();
89 unsafe {
90 s2n_config_get_ctx(self.0.as_ptr(), &mut ctx)
91 .into_result()
92 .unwrap();
93 &*(ctx as *const Context)
94 }
95 }
96
97 pub(crate) unsafe fn context_mut(&mut self) -> &mut Context {
105 let mut ctx = core::ptr::null_mut();
106 s2n_config_get_ctx(self.as_mut_ptr(), &mut ctx)
107 .into_result()
108 .unwrap();
109 &mut *(ctx as *mut Context)
110 }
111
112 #[cfg(test)]
113 pub fn test_get_refcount(&self) -> Result<usize, Error> {
115 let context = self.context();
116 Ok(context.refcount.load(Ordering::SeqCst))
117 }
118}
119
120impl Default for Config {
121 fn default() -> Self {
122 Builder::new().build().unwrap()
123 }
124}
125
126impl Clone for Config {
127 fn clone(&self) -> Self {
128 let context = self.context();
129
130 let _count = context.refcount.fetch_add(1, Ordering::Relaxed);
137 Self(self.0)
138 }
139}
140
141impl Drop for Config {
142 fn drop(&mut self) {
144 let context = self.context();
145 let count = context.refcount.fetch_sub(1, Ordering::Release);
146 debug_assert!(count > 0, "refcount should not drop below 1 instance");
147
148 if count != 1 {
150 return;
151 }
152
153 std::sync::atomic::fence(Ordering::Acquire);
166
167 let context = unsafe {
169 Box::from_raw(self.context_mut())
172 };
173 drop(context);
174
175 let _ = unsafe { s2n_config_free(self.0.as_ptr()).into_result() };
176 }
177}
178
179pub struct Builder {
180 pub(crate) config: Config,
181 load_system_certs: bool,
182 enable_ocsp: bool,
183}
184
185impl Builder {
186 pub fn new() -> Self {
198 crate::init::init();
199 let config = unsafe { s2n_config_new_minimal().into_result() }.unwrap();
200
201 let context = Box::<Context>::default();
202 let context = Box::into_raw(context) as *mut c_void;
203
204 unsafe {
205 s2n_config_set_ctx(config.as_ptr(), context)
206 .into_result()
207 .unwrap();
208
209 s2n_config_set_client_hello_cb_mode(
213 config.as_ptr(),
214 s2n_client_hello_cb_mode::NONBLOCKING,
215 )
216 .into_result()
217 .unwrap();
218 }
219
220 Self {
221 config: Config(config),
222 load_system_certs: true,
223 enable_ocsp: false,
224 }
225 }
226
227 pub fn set_alert_behavior(&mut self, value: AlertBehavior) -> Result<&mut Self, Error> {
229 unsafe { s2n_config_set_alert_behavior(self.as_mut_ptr(), value.into()).into_result() }?;
230 Ok(self)
231 }
232
233 pub fn set_security_policy(&mut self, policy: &security::Policy) -> Result<&mut Self, Error> {
235 unsafe {
236 s2n_config_set_cipher_preferences(self.as_mut_ptr(), policy.as_cstr().as_ptr())
237 .into_result()
238 }?;
239 Ok(self)
240 }
241
242 pub fn set_application_protocol_preference<P: IntoIterator<Item = I>, I: AsRef<[u8]>>(
253 &mut self,
254 protocols: P,
255 ) -> Result<&mut Self, Error> {
256 unsafe {
258 s2n_config_set_protocol_preferences(self.as_mut_ptr(), core::ptr::null(), 0)
259 .into_result()
260 }?;
261
262 for protocol in protocols {
263 self.append_application_protocol_preference(protocol.as_ref())?;
264 }
265
266 Ok(self)
267 }
268
269 pub fn append_application_protocol_preference(
271 &mut self,
272 protocol: &[u8],
273 ) -> Result<&mut Self, Error> {
274 unsafe {
275 s2n_config_append_protocol_preference(
276 self.as_mut_ptr(),
277 protocol.as_ptr(),
278 protocol
279 .len()
280 .try_into()
281 .map_err(|_| Error::INVALID_INPUT)?,
282 )
283 .into_result()
284 }?;
285 Ok(self)
286 }
287
288 pub unsafe fn disable_x509_verification(&mut self) -> Result<&mut Self, Error> {
296 s2n_config_disable_x509_verification(self.as_mut_ptr()).into_result()?;
297 Ok(self)
298 }
299
300 pub fn disable_x509_intent_verification(&mut self) -> Result<&mut Self, Error> {
308 unsafe { s2n_config_disable_x509_intent_verification(self.as_mut_ptr()).into_result() }?;
309 Ok(self)
310 }
311
312 pub fn add_dhparams(&mut self, pem: &[u8]) -> Result<&mut Self, Error> {
314 let cstring = CString::new(pem).map_err(|_| Error::INVALID_INPUT)?;
315 unsafe { s2n_config_add_dhparams(self.as_mut_ptr(), cstring.as_ptr()).into_result() }?;
316 Ok(self)
317 }
318
319 pub fn load_pem(&mut self, certificate: &[u8], private_key: &[u8]) -> Result<&mut Self, Error> {
328 let certificate = CString::new(certificate).map_err(|_| Error::INVALID_INPUT)?;
329 let private_key = CString::new(private_key).map_err(|_| Error::INVALID_INPUT)?;
330 unsafe {
331 s2n_config_add_cert_chain_and_key(
332 self.as_mut_ptr(),
333 certificate.as_ptr(),
334 private_key.as_ptr(),
335 )
336 .into_result()
337 }?;
338 Ok(self)
339 }
340
341 pub fn load_chain(&mut self, chain: CertificateChain<'static>) -> Result<&mut Self, Error> {
343 let result = unsafe {
349 s2n_config_add_cert_chain_and_key_to_store(
350 self.as_mut_ptr(),
351 chain.as_ptr() as *mut _,
354 )
355 .into_result()
356 };
357 let context = unsafe {
358 self.config.context_mut()
361 };
362 context.application_owned_certs.push(chain);
363 result?;
364
365 Ok(self)
366 }
367
368 pub fn set_default_chains<T: IntoIterator<Item = CertificateChain<'static>>>(
370 &mut self,
371 chains: T,
372 ) -> Result<&mut Self, Error> {
373 const CHAINS_MAX_COUNT: usize = 4;
375
376 let mut chain_arrays: [Option<CertificateChain<'static>>; CHAINS_MAX_COUNT] =
377 [None, None, None, None];
378 let mut pointer_array = [std::ptr::null_mut(); CHAINS_MAX_COUNT];
379 let mut cert_chain_count = 0;
380
381 for chain in chains.into_iter() {
382 if cert_chain_count >= CHAINS_MAX_COUNT {
383 return Err(Error::bindings(
384 ErrorType::UsageError,
385 "InvalidInput",
386 "A single default can be specified for each supported
387 cert type, but more than 4 certs were supplied",
388 ));
389 }
390
391 pointer_array[cert_chain_count] = chain.as_ptr() as *mut _;
394 chain_arrays[cert_chain_count] = Some(chain);
395
396 cert_chain_count += 1;
397 }
398
399 let collected_chains = chain_arrays.into_iter().take(cert_chain_count).flatten();
400
401 let context = unsafe {
402 self.config.context_mut()
405 };
406 context.application_owned_certs.extend(collected_chains);
407
408 unsafe {
409 s2n_config_set_cert_chain_and_key_defaults(
410 self.as_mut_ptr(),
411 pointer_array.as_mut_ptr(),
412 cert_chain_count as u32,
413 )
414 .into_result()
415 }?;
416
417 Ok(self)
418 }
419
420 pub fn load_public_pem(&mut self, certificate: &[u8]) -> Result<&mut Self, Error> {
422 let size: u32 = certificate
423 .len()
424 .try_into()
425 .map_err(|_| Error::INVALID_INPUT)?;
426 let certificate = certificate.as_ptr() as *mut u8;
427 unsafe { s2n_config_add_cert_chain(self.as_mut_ptr(), certificate, size) }.into_result()?;
428 Ok(self)
429 }
430
431 pub fn trust_pem(&mut self, certificate: &[u8]) -> Result<&mut Self, Error> {
433 let certificate = CString::new(certificate).map_err(|_| Error::INVALID_INPUT)?;
434 unsafe {
435 s2n_config_add_pem_to_trust_store(self.as_mut_ptr(), certificate.as_ptr()).into_result()
436 }?;
437 Ok(self)
438 }
439
440 pub fn trust_location(
446 &mut self,
447 file: Option<&Path>,
448 dir: Option<&Path>,
449 ) -> Result<&mut Self, Error> {
450 fn to_cstr(input: Option<&Path>) -> Result<Option<CString>, Error> {
451 Ok(match input {
452 Some(input) => {
453 let string = input.to_str().ok_or(Error::INVALID_INPUT)?;
454 let cstring = CString::new(string).map_err(|_| Error::INVALID_INPUT)?;
455 Some(cstring)
456 }
457 None => None,
458 })
459 }
460
461 let file_cstr = to_cstr(file)?;
462 let file_ptr = file_cstr
463 .as_ref()
464 .map(|f| f.as_ptr())
465 .unwrap_or(core::ptr::null());
466
467 let dir_cstr = to_cstr(dir)?;
468 let dir_ptr = dir_cstr
469 .as_ref()
470 .map(|f| f.as_ptr())
471 .unwrap_or(core::ptr::null());
472
473 unsafe {
474 s2n_config_set_verification_ca_location(self.as_mut_ptr(), file_ptr, dir_ptr)
475 .into_result()
476 }?;
477
478 if !self.enable_ocsp {
481 unsafe {
482 s2n_config_set_status_request_type(self.as_mut_ptr(), s2n_status_request_type::NONE)
483 .into_result()?
484 };
485 }
486
487 Ok(self)
488 }
489
490 pub fn with_system_certs(&mut self, load_system_certs: bool) -> Result<&mut Self, Error> {
497 self.load_system_certs = load_system_certs;
498 Ok(self)
499 }
500
501 pub fn wipe_trust_store(&mut self) -> Result<&mut Self, Error> {
503 unsafe { s2n_config_wipe_trust_store(self.as_mut_ptr()).into_result()? };
504 Ok(self)
505 }
506
507 pub fn set_client_auth_type(&mut self, auth_type: ClientAuthType) -> Result<&mut Self, Error> {
513 unsafe {
514 s2n_config_set_client_auth_type(self.as_mut_ptr(), auth_type.into()).into_result()
515 }?;
516 Ok(self)
517 }
518
519 pub fn enable_ocsp(&mut self) -> Result<&mut Self, Error> {
523 unsafe {
524 s2n_config_set_status_request_type(self.as_mut_ptr(), s2n_status_request_type::OCSP)
525 .into_result()
526 }?;
527 self.enable_ocsp = true;
528 Ok(self)
529 }
530
531 pub fn set_ocsp_data(&mut self, data: &[u8]) -> Result<&mut Self, Error> {
544 let size: u32 = data.len().try_into().map_err(|_| Error::INVALID_INPUT)?;
545 unsafe {
546 s2n_config_set_extension_data(
547 self.as_mut_ptr(),
548 s2n_tls_extension_type::OCSP_STAPLING,
549 data.as_ptr(),
550 size,
551 )
552 .into_result()
553 }?;
554 self.enable_ocsp()
555 }
556
557 pub fn set_verify_host_callback<T: 'static + VerifyHostNameCallback>(
565 &mut self,
566 handler: T,
567 ) -> Result<&mut Self, Error> {
568 unsafe extern "C" fn verify_host_cb_fn(
569 host_name: *const ::libc::c_char,
570 host_name_len: usize,
571 context: *mut ::libc::c_void,
572 ) -> u8 {
573 let context = &mut *(context as *mut Context);
574 let handler = context.verify_host_callback.as_mut().unwrap();
575 verify_host(host_name, host_name_len, handler)
576 }
577
578 let context = unsafe {
579 self.config.context_mut()
582 };
583 context.verify_host_callback = Some(Box::new(handler));
584 unsafe {
585 s2n_config_set_verify_host_callback(
586 self.as_mut_ptr(),
587 Some(verify_host_cb_fn),
588 self.config.context() as *const Context as *mut c_void,
589 )
590 .into_result()?;
591 }
592 Ok(self)
593 }
594
595 pub unsafe fn set_key_log_callback(
601 &mut self,
602 callback: s2n_key_log_fn,
603 context: *mut core::ffi::c_void,
604 ) -> Result<&mut Self, Error> {
605 s2n_config_set_key_log_cb(self.as_mut_ptr(), callback, context).into_result()?;
606 Ok(self)
607 }
608
609 pub fn set_max_cert_chain_depth(&mut self, depth: u16) -> Result<&mut Self, Error> {
611 unsafe { s2n_config_set_max_cert_chain_depth(self.as_mut_ptr(), depth).into_result() }?;
612 Ok(self)
613 }
614
615 pub fn set_send_buffer_size(&mut self, size: u32) -> Result<&mut Self, Error> {
617 unsafe { s2n_config_set_send_buffer_size(self.as_mut_ptr(), size).into_result() }?;
618 Ok(self)
619 }
620
621 #[cfg(feature = "unstable-custom_x509_extensions")]
623 pub fn add_custom_x509_extension(&mut self, extension_oid: &str) -> Result<&mut Self, Error> {
624 let extension_oid_len: u32 = extension_oid
625 .len()
626 .try_into()
627 .map_err(|_| Error::INVALID_INPUT)?;
628 let extension_oid = extension_oid.as_ptr() as *mut u8;
629 unsafe {
630 s2n_config_add_custom_x509_extension(
631 self.as_mut_ptr(),
632 extension_oid,
633 extension_oid_len,
634 )
635 .into_result()
636 }?;
637 Ok(self)
638 }
639
640 #[cfg(feature = "unstable-crl")]
645 pub fn set_cert_validation_callback_sync<T: 'static + CertValidationCallbackSync>(
646 &mut self,
647 handler: T,
648 ) -> Result<&mut Self, Error> {
649 unsafe extern "C" fn cert_validation_cb(
650 conn_ptr: *mut s2n_connection,
651 validation_info: *mut s2n_cert_validation_info,
652 _context: *mut core::ffi::c_void,
653 ) -> libc::c_int {
654 let mut info = CertValidationInfo::from_ptr(validation_info);
655 with_context(conn_ptr, |conn, context| {
656 let callback = context.cert_validation_callback_sync.as_ref();
657 callback.map(|callback| {
658 let accepted = callback.handle_validation(conn, &mut info).unwrap();
659 match accepted {
660 true => info.accept().unwrap(),
661 false => info.reject().unwrap(),
662 }
663 })
664 });
665 CallbackResult::Success.into()
666 }
667
668 let handler = Box::new(handler);
669 let context = unsafe {
670 self.config.context_mut()
673 };
674 context.cert_validation_callback_sync = Some(handler);
675
676 unsafe {
677 s2n_config_set_cert_validation_cb(
678 self.as_mut_ptr(),
679 Some(cert_validation_cb),
680 core::ptr::null_mut(),
681 )
682 .into_result()?;
683 }
684
685 Ok(self)
686 }
687
688 pub fn set_client_hello_callback<T: 'static + ClientHelloCallback>(
692 &mut self,
693 handler: T,
694 ) -> Result<&mut Self, Error> {
695 unsafe extern "C" fn client_hello_cb(
696 connection_ptr: *mut s2n_connection,
697 _context: *mut core::ffi::c_void,
698 ) -> libc::c_int {
699 with_context(connection_ptr, |conn, context| {
700 let callback = context.client_hello_callback.as_ref();
701 let future = callback
702 .map(|c| c.on_client_hello(conn))
703 .unwrap_or(Ok(None));
704 AsyncCallback::trigger_client_hello_cb(future, conn)
705 })
706 .into()
707 }
708
709 let handler = Box::new(handler);
710 let context = unsafe {
711 self.config.context_mut()
714 };
715 context.client_hello_callback = Some(handler);
716
717 unsafe {
718 s2n_config_set_client_hello_cb(
719 self.as_mut_ptr(),
720 Some(client_hello_cb),
721 core::ptr::null_mut(),
722 )
723 .into_result()?;
724 }
725
726 Ok(self)
727 }
728
729 #[cfg(feature = "unstable-events")]
731 pub fn set_event_subscriber<T: 'static + EventSubscriber>(
732 &mut self,
733 subscriber: T,
734 ) -> Result<&mut Self, Error> {
735 unsafe extern "C" fn on_handshake_event(
736 conn_ptr: *mut s2n_tls_sys::s2n_connection,
737 _subscriber: *mut c_void,
738 event: *mut s2n_tls_sys::s2n_event_handshake,
739 ) {
740 with_context(conn_ptr, |conn, context| {
741 let callback = context.event_subscriber.as_ref();
742 if let Some(callback) = callback {
743 callback.on_handshake_event(conn, &HandshakeEvent::new(&*event));
744 }
745 });
746 }
747
748 let handler = Box::new(subscriber);
749 let context = unsafe {
750 self.config.context_mut()
753 };
754 context.event_subscriber = Some(handler);
755
756 unsafe {
757 s2n_config_set_subscriber(
758 self.as_mut_ptr(),
759 self.config.context_mut() as *mut Context as *mut c_void,
760 )
761 };
762
763 unsafe {
764 s2n_config_set_handshake_event(self.as_mut_ptr(), Some(on_handshake_event))
765 .into_result()
766 }?;
767 Ok(self)
768 }
769
770 pub fn set_connection_initializer<T: 'static + ConnectionInitializer>(
771 &mut self,
772 handler: T,
773 ) -> Result<&mut Self, Error> {
774 let handler = Box::new(handler);
776 let context = unsafe {
777 self.config.context_mut()
780 };
781 context.connection_initializer = Some(handler);
782 Ok(self)
783 }
784
785 pub fn set_session_ticket_callback<T: 'static + SessionTicketCallback>(
789 &mut self,
790 handler: T,
791 ) -> Result<&mut Self, Error> {
792 self.enable_session_tickets(true)?;
794
795 unsafe extern "C" fn session_ticket_cb(
797 conn_ptr: *mut s2n_connection,
798 _context: *mut ::libc::c_void,
799 session_ticket: *mut s2n_session_ticket,
800 ) -> libc::c_int {
801 let session_ticket = SessionTicket::from_ptr(&*session_ticket);
802 with_context(conn_ptr, |conn, context| {
803 let callback = context.session_ticket_callback.as_ref();
804 callback.map(|c| c.on_session_ticket(conn, session_ticket))
805 });
806 CallbackResult::Success.into()
807 }
808
809 let handler = Box::new(handler);
811 let context = unsafe {
812 self.config.context_mut()
815 };
816 context.session_ticket_callback = Some(handler);
817
818 unsafe {
819 s2n_config_set_session_ticket_cb(
820 self.as_mut_ptr(),
821 Some(session_ticket_cb),
822 self.config.context() as *const Context as *mut c_void,
823 )
824 .into_result()
825 }?;
826 Ok(self)
827 }
828
829 pub fn set_private_key_callback<T: 'static + PrivateKeyCallback>(
835 &mut self,
836 handler: T,
837 ) -> Result<&mut Self, Error> {
838 unsafe extern "C" fn private_key_cb(
839 conn_ptr: *mut s2n_connection,
840 op_ptr: *mut s2n_async_pkey_op,
841 ) -> libc::c_int {
842 with_context(conn_ptr, |conn, context| {
843 let state = PrivateKeyOperation::try_from_cb(conn, op_ptr);
844 let callback = context.private_key_callback.as_ref();
845 let future_result = state.and_then(|state| {
846 callback.map_or(Ok(None), |callback| callback.handle_operation(conn, state))
847 });
848 AsyncCallback::trigger(future_result, conn)
849 })
850 .into()
851 }
852
853 let handler = Box::new(handler);
854 let context = unsafe {
855 self.config.context_mut()
858 };
859 context.private_key_callback = Some(handler);
860
861 unsafe {
862 s2n_config_set_async_pkey_callback(self.as_mut_ptr(), Some(private_key_cb))
863 .into_result()?;
864 }
865 Ok(self)
866 }
867
868 pub fn set_wall_clock<T: 'static + WallClock>(
876 &mut self,
877 handler: T,
878 ) -> Result<&mut Self, Error> {
879 unsafe extern "C" fn clock_cb(
880 context: *mut ::libc::c_void,
881 time_in_nanos: *mut u64,
882 ) -> libc::c_int {
883 let context = &mut *(context as *mut Context);
884 if let Some(handler) = context.wall_clock.as_mut() {
885 if let Ok(nanos) = handler.get_time_since_epoch().as_nanos().try_into() {
886 *time_in_nanos = nanos;
887 return CallbackResult::Success.into();
888 }
889 }
890 CallbackResult::Failure.into()
891 }
892
893 let handler = Box::new(handler);
894 let context = unsafe {
895 self.config.context_mut()
898 };
899 context.wall_clock = Some(handler);
900 unsafe {
901 s2n_config_set_wall_clock(
902 self.as_mut_ptr(),
903 Some(clock_cb),
904 self.config.context() as *const _ as *mut c_void,
905 )
906 .into_result()?;
907 }
908 Ok(self)
909 }
910
911 pub fn set_monotonic_clock<T: 'static + MonotonicClock>(
919 &mut self,
920 handler: T,
921 ) -> Result<&mut Self, Error> {
922 unsafe extern "C" fn clock_cb(
923 context: *mut ::libc::c_void,
924 time_in_nanos: *mut u64,
925 ) -> libc::c_int {
926 let context = &mut *(context as *mut Context);
927 if let Some(handler) = context.monotonic_clock.as_mut() {
928 if let Ok(nanos) = handler.get_time().as_nanos().try_into() {
929 *time_in_nanos = nanos;
930 return CallbackResult::Success.into();
931 }
932 }
933 CallbackResult::Failure.into()
934 }
935
936 let handler = Box::new(handler);
937 let context = unsafe {
938 self.config.context_mut()
941 };
942 context.monotonic_clock = Some(handler);
943 unsafe {
944 s2n_config_set_monotonic_clock(
945 self.as_mut_ptr(),
946 Some(clock_cb),
947 self.config.context() as *const _ as *mut c_void,
948 )
949 .into_result()?;
950 }
951 Ok(self)
952 }
953
954 pub fn enable_session_tickets(&mut self, enable: bool) -> Result<&mut Self, Error> {
958 unsafe {
959 s2n_config_set_session_tickets_onoff(self.as_mut_ptr(), enable.into()).into_result()
960 }?;
961 Ok(self)
962 }
963
964 pub fn add_session_ticket_key(
970 &mut self,
971 key_name: &[u8],
972 key: &[u8],
973 intro_time: SystemTime,
974 ) -> Result<&mut Self, Error> {
975 let key_name_len: u32 = key_name
976 .len()
977 .try_into()
978 .map_err(|_| Error::INVALID_INPUT)?;
979 let key_len: u32 = key.len().try_into().map_err(|_| Error::INVALID_INPUT)?;
980 let intro_time = intro_time
981 .duration_since(std::time::UNIX_EPOCH)
982 .map_err(|_| Error::INVALID_INPUT)?;
983 if key_len < 16 {
986 return Err(Error::INVALID_INPUT);
987 }
988 self.enable_session_tickets(true)?;
989 unsafe {
990 s2n_config_add_ticket_crypto_key(
991 self.as_mut_ptr(),
992 key_name.as_ptr(),
993 key_name_len,
994 key.as_ptr() as *mut u8,
996 key_len,
997 intro_time.as_secs(),
998 )
999 .into_result()
1000 }?;
1001 Ok(self)
1002 }
1003
1004 pub fn set_ticket_key_encrypt_decrypt_lifetime(
1009 &mut self,
1010 lifetime: Duration,
1011 ) -> Result<&mut Self, Error> {
1012 unsafe {
1013 s2n_config_set_ticket_encrypt_decrypt_key_lifetime(
1014 self.as_mut_ptr(),
1015 lifetime.as_secs(),
1016 )
1017 .into_result()
1018 }?;
1019 Ok(self)
1020 }
1021
1022 pub fn set_ticket_key_decrypt_lifetime(
1026 &mut self,
1027 lifetime: Duration,
1028 ) -> Result<&mut Self, Error> {
1029 unsafe {
1030 s2n_config_set_ticket_decrypt_key_lifetime(self.as_mut_ptr(), lifetime.as_secs())
1031 .into_result()
1032 }?;
1033 Ok(self)
1034 }
1035
1036 pub fn set_serialization_version(
1041 &mut self,
1042 version: SerializationVersion,
1043 ) -> Result<&mut Self, Error> {
1044 unsafe {
1045 s2n_config_set_serialization_version(self.as_mut_ptr(), version.into()).into_result()
1046 }?;
1047 Ok(self)
1048 }
1049
1050 pub fn set_max_blinding_delay(&mut self, seconds: u32) -> Result<&mut Self, Error> {
1054 unsafe { s2n_config_set_max_blinding_delay(self.as_mut_ptr(), seconds).into_result() }?;
1055 Ok(self)
1056 }
1057
1058 pub fn require_ticket_forward_secrecy(&mut self, enable: bool) -> Result<&mut Self, Error> {
1062 unsafe {
1063 s2n_config_require_ticket_forward_secrecy(self.as_mut_ptr(), enable).into_result()
1064 }?;
1065 Ok(self)
1066 }
1067
1068 pub fn build(mut self) -> Result<Config, Error> {
1069 if self.load_system_certs {
1070 unsafe {
1071 s2n_config_load_system_certs(self.as_mut_ptr()).into_result()?;
1072 }
1073 }
1074
1075 Ok(self.config)
1076 }
1077
1078 pub(crate) fn as_mut_ptr(&mut self) -> *mut s2n_config {
1079 self.config.as_mut_ptr()
1080 }
1081
1082 #[cfg(s2n_tls_external_build)]
1090 pub fn unstable_as_ptr(&mut self) -> *mut s2n_config {
1091 self.as_mut_ptr()
1092 }
1093
1094 pub fn set_certificate_authorities_from_trust_store(&mut self) -> Result<(), Error> {
1098 unsafe {
1100 s2n_config_set_cert_authorities_from_trust_store(self.as_mut_ptr()).into_result()?;
1101 }
1102
1103 Ok(())
1104 }
1105}
1106
1107#[cfg(feature = "quic")]
1108impl Builder {
1109 pub fn enable_quic(&mut self) -> Result<&mut Self, Error> {
1111 unsafe { s2n_tls_sys::s2n_config_enable_quic(self.as_mut_ptr()).into_result() }?;
1112 Ok(self)
1113 }
1114}
1115
1116impl Default for Builder {
1124 fn default() -> Self {
1125 Self::new()
1126 }
1127}
1128
1129pub(crate) struct Context {
1130 refcount: AtomicUsize,
1131 application_owned_certs: Vec<CertificateChain<'static>>,
1141 pub(crate) client_hello_callback: Option<Box<dyn ClientHelloCallback>>,
1142 pub(crate) private_key_callback: Option<Box<dyn PrivateKeyCallback>>,
1143 pub(crate) verify_host_callback: Option<Box<dyn VerifyHostNameCallback>>,
1144 pub(crate) session_ticket_callback: Option<Box<dyn SessionTicketCallback>>,
1145 pub(crate) connection_initializer: Option<Box<dyn ConnectionInitializer>>,
1146 pub(crate) wall_clock: Option<Box<dyn WallClock>>,
1147 pub(crate) monotonic_clock: Option<Box<dyn MonotonicClock>>,
1148 #[cfg(feature = "unstable-renegotiate")]
1149 pub(crate) renegotiate: Option<Box<dyn RenegotiateCallback>>,
1150 #[cfg(feature = "unstable-cert_authorities")]
1151 pub(crate) cert_authorities: Option<Box<dyn CertificateRequestCallback>>,
1152 #[cfg(feature = "unstable-crl")]
1153 pub(crate) cert_validation_callback_sync: Option<Box<dyn CertValidationCallbackSync>>,
1154 #[cfg(feature = "unstable-events")]
1155 pub(crate) event_subscriber: Option<Box<dyn crate::events::EventSubscriber>>,
1156}
1157
1158impl Default for Context {
1159 fn default() -> Self {
1160 let refcount = AtomicUsize::new(1);
1163
1164 Self {
1165 refcount,
1166 application_owned_certs: Vec::new(),
1167 client_hello_callback: None,
1168 private_key_callback: None,
1169 verify_host_callback: None,
1170 session_ticket_callback: None,
1171 connection_initializer: None,
1172 wall_clock: None,
1173 monotonic_clock: None,
1174 #[cfg(feature = "unstable-renegotiate")]
1175 renegotiate: None,
1176 #[cfg(feature = "unstable-cert_authorities")]
1177 cert_authorities: None,
1178 #[cfg(feature = "unstable-crl")]
1179 cert_validation_callback_sync: None,
1180 #[cfg(feature = "unstable-events")]
1181 event_subscriber: None,
1182 }
1183 }
1184}
1185
1186pub trait ConnectionInitializer: 'static + Send + Sync {
1194 fn initialize_connection(
1198 &self,
1199 connection: &mut crate::connection::Connection,
1200 ) -> ConnectionFutureResult;
1201}
1202
1203impl<A: ConnectionInitializer, B: ConnectionInitializer> ConnectionInitializer for (A, B) {
1204 fn initialize_connection(
1205 &self,
1206 connection: &mut crate::connection::Connection,
1207 ) -> ConnectionFutureResult {
1208 let a = self.0.initialize_connection(connection)?;
1209 let b = self.1.initialize_connection(connection)?;
1210 match (a, b) {
1211 (None, None) => Ok(None),
1212 (None, Some(fut)) => Ok(Some(fut)),
1213 (Some(fut), None) => Ok(Some(fut)),
1214 (Some(fut_a), Some(fut_b)) => Ok(Some(Box::pin(ConcurrentConnectionFuture::new([
1215 fut_a, fut_b,
1216 ])))),
1217 }
1218 }
1219}
1220
1221struct ConcurrentConnectionFuture<const N: usize> {
1222 futures: [Option<Pin<Box<dyn ConnectionFuture>>>; N],
1223}
1224
1225impl<const N: usize> ConcurrentConnectionFuture<N> {
1226 fn new(futures: [Pin<Box<dyn ConnectionFuture>>; N]) -> Self {
1227 let futures = futures.map(Some);
1228 Self { futures }
1229 }
1230}
1231
1232impl<const N: usize> ConnectionFuture for ConcurrentConnectionFuture<N> {
1233 fn poll(
1234 mut self: std::pin::Pin<&mut Self>,
1235 connection: &mut crate::connection::Connection,
1236 ctx: &mut core::task::Context,
1237 ) -> std::task::Poll<Result<(), Error>> {
1238 let mut is_pending = false;
1239 for container in self.futures.iter_mut() {
1240 if let Some(future) = container.as_mut() {
1241 match future.as_mut().poll(connection, ctx) {
1242 Poll::Ready(result) => {
1243 result?;
1244 *container = None;
1245 }
1246 Poll::Pending => is_pending = true,
1247 }
1248 }
1249 }
1250 if is_pending {
1251 Poll::Pending
1252 } else {
1253 Poll::Ready(Ok(()))
1254 }
1255 }
1256}
1257
1258#[cfg(test)]
1259mod tests {
1260 use super::*;
1261 use crate::testing::*;
1262
1263 #[test]
1265 fn context_send_sync_test() {
1266 fn assert_send_sync<T: 'static + Send + Sync>() {}
1267 assert_send_sync::<Context>();
1268 }
1269
1270 #[cfg(s2n_tls_external_build)]
1272 #[test]
1273 fn test_config_unstable_as_ptr() -> Result<(), Error> {
1274 let mut builder = Config::builder();
1275
1276 let auth_types = [
1277 ClientAuthType::None,
1278 ClientAuthType::Optional,
1279 ClientAuthType::Required,
1280 ];
1281 for auth_type in auth_types {
1282 builder.set_client_auth_type(auth_type)?;
1283
1284 let mut retrieved_auth_type = s2n_cert_auth_type::NONE;
1285 unsafe {
1286 s2n_config_get_client_auth_type(
1287 builder.unstable_as_ptr(),
1288 &mut retrieved_auth_type,
1289 );
1290 }
1291
1292 assert_eq!(retrieved_auth_type, auth_type.into());
1293 }
1294
1295 Ok(())
1296 }
1297
1298 #[test]
1299 fn disable_intent_verification() -> Result<(), Error> {
1300 let invalid_certs = CertKeyPair::from_path(
1301 "intent/cert_chains/ku_key_cert_sign_leaf/",
1302 "cert-chain",
1303 "leaf-key",
1304 "root-cert",
1305 );
1306
1307 for disable_intent in [true, false] {
1308 let config = {
1309 let mut config = Builder::new();
1310 config.set_security_policy(&security::DEFAULT_TLS13)?;
1311 config.set_verify_host_callback(InsecureAcceptAllCertificatesHandler {})?;
1312
1313 if disable_intent {
1314 config.disable_x509_intent_verification()?;
1315 }
1316
1317 config.load_pem(invalid_certs.cert(), invalid_certs.key())?;
1318 config.trust_pem(invalid_certs.ca_cert())?;
1319 config.build()?
1320 };
1321 let mut pair = TestPair::from_config(&config);
1322
1323 if disable_intent {
1324 pair.handshake()?;
1325 } else {
1326 let s2n_err = pair.handshake().unwrap_err();
1327 assert_eq!(s2n_err.name(), "S2N_ERR_CERT_INTENT_INVALID");
1328 }
1329 }
1330
1331 Ok(())
1332 }
1333
1334 #[cfg(all(
1335 feature = "unstable-custom_x509_extensions",
1337 not(s2n_tls_external_build),
1340 not(feature = "fips")
1342 ))]
1343 #[test]
1344 fn custom_critical_extensions() -> Result<(), Error> {
1345 let certs = CertKeyPair::from_path(
1346 "custom_oids/",
1347 "single_oid_cert_chain",
1348 "single_oid_key",
1349 "ca-cert",
1350 );
1351 let single_oid = "1.3.187.25240.2";
1352
1353 for add_oid in [true, false] {
1354 let config = {
1355 let mut config = Builder::new();
1356 config.set_security_policy(&security::DEFAULT_TLS13)?;
1357 config.set_verify_host_callback(InsecureAcceptAllCertificatesHandler {})?;
1358
1359 if add_oid {
1360 config.add_custom_x509_extension(single_oid)?;
1361 }
1362
1363 config.load_pem(certs.cert(), certs.key())?;
1364 config.trust_pem(certs.cert())?;
1365 config.build()?
1366 };
1367 let mut pair = TestPair::from_config(&config);
1368
1369 if add_oid {
1370 pair.handshake()?;
1371 } else {
1372 let s2n_err = pair.handshake().unwrap_err();
1373 assert_eq!(s2n_err.name(), "S2N_ERR_CERT_UNHANDLED_CRITICAL_EXTENSION");
1374 }
1375 }
1376
1377 Ok(())
1378 }
1379}