@@ -11,6 +11,7 @@ use core::{convert::TryInto, ptr::NonNull};
1111use s2n_tls_sys:: * ;
1212use std:: {
1313 ffi:: { c_void, CString } ,
14+ path:: Path ,
1415 sync:: atomic:: { AtomicUsize , Ordering } ,
1516} ;
1617
@@ -73,7 +74,7 @@ impl Config {
7374 }
7475
7576 /// Retrieve a mutable reference to the [`Context`] stored on the config.
76- fn context_mut ( & mut self ) -> & mut Context {
77+ pub ( crate ) fn context_mut ( & mut self ) -> & mut Context {
7778 let mut ctx = core:: ptr:: null_mut ( ) ;
7879 unsafe {
7980 s2n_config_get_ctx ( self . as_mut_ptr ( ) , & mut ctx)
@@ -230,6 +231,12 @@ impl Builder {
230231 Ok ( self )
231232 }
232233
234+ pub fn add_dhparams ( & mut self , pem : & [ u8 ] ) -> Result < & mut Self , Error > {
235+ let cstring = CString :: new ( pem) . map_err ( |_| Error :: InvalidInput ) ?;
236+ unsafe { s2n_config_add_dhparams ( self . as_mut_ptr ( ) , cstring. as_ptr ( ) ) . into_result ( ) } ?;
237+ Ok ( self )
238+ }
239+
233240 pub fn load_pem ( & mut self , certificate : & [ u8 ] , private_key : & [ u8 ] ) -> Result < & mut Self , Error > {
234241 let certificate = CString :: new ( certificate) . map_err ( |_| Error :: InvalidInput ) ?;
235242 let private_key = CString :: new ( private_key) . map_err ( |_| Error :: InvalidInput ) ?;
@@ -252,6 +259,41 @@ impl Builder {
252259 Ok ( self )
253260 }
254261
262+ pub fn trust_location (
263+ & mut self ,
264+ file : Option < & Path > ,
265+ dir : Option < & Path > ,
266+ ) -> Result < & mut Self , Error > {
267+ fn to_cstr ( input : Option < & Path > ) -> Result < Option < CString > , Error > {
268+ Ok ( match input {
269+ Some ( input) => {
270+ let string = input. to_str ( ) . ok_or ( Error :: InvalidInput ) ?;
271+ let cstring = CString :: new ( string) . map_err ( |_| Error :: InvalidInput ) ?;
272+ Some ( cstring)
273+ }
274+ None => None ,
275+ } )
276+ }
277+
278+ let file_cstr = to_cstr ( file) ?;
279+ let file_ptr = file_cstr
280+ . as_ref ( )
281+ . map ( |f| f. as_ptr ( ) )
282+ . unwrap_or ( core:: ptr:: null ( ) ) ;
283+
284+ let dir_cstr = to_cstr ( dir) ?;
285+ let dir_ptr = dir_cstr
286+ . as_ref ( )
287+ . map ( |f| f. as_ptr ( ) )
288+ . unwrap_or ( core:: ptr:: null ( ) ) ;
289+
290+ unsafe {
291+ s2n_config_set_verification_ca_location ( self . as_mut_ptr ( ) , file_ptr, dir_ptr)
292+ . into_result ( )
293+ } ?;
294+ Ok ( self )
295+ }
296+
255297 pub fn wipe_trust_store ( & mut self ) -> Result < & mut Self , Error > {
256298 unsafe { s2n_config_wipe_trust_store ( self . as_mut_ptr ( ) ) . into_result ( ) ? } ;
257299 Ok ( self )
@@ -267,6 +309,39 @@ impl Builder {
267309 Ok ( self )
268310 }
269311
312+ /// Clients will request OCSP stapling from the server.
313+ pub fn enable_ocsp ( & mut self ) -> Result < & mut Self , Error > {
314+ unsafe {
315+ s2n_config_set_status_request_type ( self . as_mut_ptr ( ) , s2n_status_request_type:: OCSP )
316+ . into_result ( )
317+ } ?;
318+ Ok ( self )
319+ }
320+
321+ /// Sets the OCSP data for the default certificate chain associated with the Config.
322+ ///
323+ /// Servers will send the data in response to OCSP stapling requests from clients.
324+ //
325+ // NOTE: this modifies a certificate chain, NOT the Config itself. This is currently safe
326+ // because the certificate chain is set with s2n_config_add_cert_chain_and_key, which
327+ // creates a new certificate chain only accessible by the given config. It will
328+ // NOT be safe when we add support for the newer s2n_config_add_cert_chain_and_key_to_store API,
329+ // which allows certificate chains to be shared across configs.
330+ // In that case, we'll need additional guard rails either in these bindings or in the underlying C.
331+ pub fn set_ocsp_data ( & mut self , data : & [ u8 ] ) -> Result < & mut Self , Error > {
332+ let size: u32 = data. len ( ) . try_into ( ) . map_err ( |_| Error :: InvalidInput ) ?;
333+ unsafe {
334+ s2n_config_set_extension_data (
335+ self . as_mut_ptr ( ) ,
336+ s2n_tls_extension_type:: OCSP_STAPLING ,
337+ data. as_ptr ( ) ,
338+ size,
339+ )
340+ . into_result ( )
341+ } ?;
342+ self . enable_ocsp ( )
343+ }
344+
270345 /// Set a custom callback function which is run during client certificate validation during
271346 /// a mutual TLS handshake.
272347 ///
@@ -358,6 +433,80 @@ impl Builder {
358433 Ok ( self )
359434 }
360435
436+ /// Set a callback function that will be used to get the system time.
437+ ///
438+ /// The wall clock time is the best-guess at the real time, measured since the epoch.
439+ /// Unlike monotonic time, it CAN move backwards.
440+ /// It is used by s2n-tls for timestamps.
441+ pub fn set_wall_clock < T : ' static + WallClock > (
442+ & mut self ,
443+ handler : T ,
444+ ) -> Result < & mut Self , Error > {
445+ unsafe extern "C" fn clock_cb (
446+ context : * mut :: libc:: c_void ,
447+ time_in_nanos : * mut u64 ,
448+ ) -> libc:: c_int {
449+ let context = & mut * ( context as * mut Context ) ;
450+ if let Some ( handler) = context. wall_clock . as_mut ( ) {
451+ if let Ok ( nanos) = handler. get_time_since_epoch ( ) . as_nanos ( ) . try_into ( ) {
452+ * time_in_nanos = nanos;
453+ return CallbackResult :: Success . into ( ) ;
454+ }
455+ }
456+ CallbackResult :: Failure . into ( )
457+ }
458+
459+ let handler = Box :: new ( handler) ;
460+ let context = self . 0 . context_mut ( ) ;
461+ context. wall_clock = Some ( handler) ;
462+ unsafe {
463+ s2n_config_set_wall_clock (
464+ self . as_mut_ptr ( ) ,
465+ Some ( clock_cb) ,
466+ self . 0 . context_mut ( ) as * mut _ as * mut c_void ,
467+ )
468+ . into_result ( ) ?;
469+ }
470+ Ok ( self )
471+ }
472+
473+ /// Set a callback function that will be used to get the monotonic time.
474+ ///
475+ /// The monotonic time is the time since an arbitrary, unspecified point.
476+ /// Unlike wall clock time, it MUST never move backwards.
477+ /// It is used by s2n-tls for timers.
478+ pub fn set_monotonic_clock < T : ' static + MonotonicClock > (
479+ & mut self ,
480+ handler : T ,
481+ ) -> Result < & mut Self , Error > {
482+ unsafe extern "C" fn clock_cb (
483+ context : * mut :: libc:: c_void ,
484+ time_in_nanos : * mut u64 ,
485+ ) -> libc:: c_int {
486+ let context = & mut * ( context as * mut Context ) ;
487+ if let Some ( handler) = context. monotonic_clock . as_mut ( ) {
488+ if let Ok ( nanos) = handler. get_time ( ) . as_nanos ( ) . try_into ( ) {
489+ * time_in_nanos = nanos;
490+ return CallbackResult :: Success . into ( ) ;
491+ }
492+ }
493+ CallbackResult :: Failure . into ( )
494+ }
495+
496+ let handler = Box :: new ( handler) ;
497+ let context = self . 0 . context_mut ( ) ;
498+ context. monotonic_clock = Some ( handler) ;
499+ unsafe {
500+ s2n_config_set_monotonic_clock (
501+ self . as_mut_ptr ( ) ,
502+ Some ( clock_cb) ,
503+ self . 0 . context_mut ( ) as * mut _ as * mut c_void ,
504+ )
505+ . into_result ( ) ?;
506+ }
507+ Ok ( self )
508+ }
509+
361510 pub fn build ( self ) -> Result < Config , Error > {
362511 Ok ( self . 0 )
363512 }
@@ -379,6 +528,8 @@ pub(crate) struct Context {
379528 refcount : AtomicUsize ,
380529 pub ( crate ) client_hello_callback : Option < Box < dyn ClientHelloCallback > > ,
381530 pub ( crate ) verify_host_callback : Option < Box < dyn VerifyHostNameCallback > > ,
531+ pub ( crate ) wall_clock : Option < Box < dyn WallClock > > ,
532+ pub ( crate ) monotonic_clock : Option < Box < dyn MonotonicClock > > ,
382533}
383534
384535impl Default for Context {
@@ -391,6 +542,8 @@ impl Default for Context {
391542 refcount,
392543 client_hello_callback : None ,
393544 verify_host_callback : None ,
545+ wall_clock : None ,
546+ monotonic_clock : None ,
394547 }
395548 }
396549}
0 commit comments