1 // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 use crate::raw::{ 5 error::{Error, Fallible}, 6 security, 7 }; 8 use alloc::sync::Arc; 9 use core::{convert::TryInto, ptr::NonNull}; 10 use s2n_tls_sys::*; 11 use std::ffi::CString; 12 13 struct Owned(NonNull<s2n_config>); 14 15 impl Default for Owned { default() -> Self16 fn default() -> Self { 17 Self::new() 18 } 19 } 20 21 impl Owned { new() -> Self22 fn new() -> Self { 23 crate::raw::init::init(); 24 let config = unsafe { s2n_config_new().into_result() }.unwrap(); 25 Self(config) 26 } 27 as_mut_ptr(&mut self) -> *mut s2n_config28 pub(crate) fn as_mut_ptr(&mut self) -> *mut s2n_config { 29 self.0.as_ptr() 30 } 31 } 32 33 impl Drop for Owned { drop(&mut self)34 fn drop(&mut self) { 35 let _ = unsafe { s2n_config_free(self.0.as_ptr()).into_result() }; 36 } 37 } 38 39 /// Safety: s2n_config objects can be sent across threads 40 unsafe impl Send for Owned {} 41 42 #[derive(Clone, Default)] 43 pub struct Config(Arc<Owned>); 44 45 impl Config { new() -> Self46 pub fn new() -> Self { 47 Self::default() 48 } 49 builder() -> Builder50 pub fn builder() -> Builder { 51 Builder::default() 52 } 53 as_mut_ptr(&mut self) -> *mut s2n_config54 pub(crate) fn as_mut_ptr(&mut self) -> *mut s2n_config { 55 (self.0).0.as_ptr() 56 } 57 } 58 59 #[derive(Default)] 60 pub struct Builder(Owned); 61 62 impl Builder { new() -> Self63 pub fn new() -> Self { 64 Default::default() 65 } 66 set_alert_behavior( &mut self, value: s2n_alert_behavior::Type, ) -> Result<&mut Self, Error>67 pub fn set_alert_behavior( 68 &mut self, 69 value: s2n_alert_behavior::Type, 70 ) -> Result<&mut Self, Error> { 71 unsafe { s2n_config_set_alert_behavior(self.as_mut_ptr(), value).into_result() }?; 72 Ok(self) 73 } 74 set_security_policy(&mut self, policy: &security::Policy) -> Result<&mut Self, Error>75 pub fn set_security_policy(&mut self, policy: &security::Policy) -> Result<&mut Self, Error> { 76 unsafe { 77 s2n_config_set_cipher_preferences(self.as_mut_ptr(), policy.as_cstr().as_ptr()) 78 .into_result() 79 }?; 80 Ok(self) 81 } 82 83 /// sets the application protocol preferences on an s2n_config object. 84 /// 85 /// protocols is a list in order of preference, with most preferred protocol first, 86 /// and of length protocol_count. When acting as an S2N_CLIENT the protocol list is 87 /// included in the Client Hello message as the ALPN extension. As an S2N_SERVER, the 88 /// list is used to negotiate a mutual application protocol with the client. After 89 /// the negotiation for the connection has completed, the agreed upon protocol can 90 /// be retrieved with s2n_get_application_protocol set_alpn_preference<P: IntoIterator<Item = I>, I: AsRef<[u8]>>( &mut self, protocols: P, ) -> Result<&mut Self, Error>91 pub fn set_alpn_preference<P: IntoIterator<Item = I>, I: AsRef<[u8]>>( 92 &mut self, 93 protocols: P, 94 ) -> Result<&mut Self, Error> { 95 // reset the list 96 unsafe { 97 s2n_config_set_protocol_preferences(self.as_mut_ptr(), core::ptr::null(), 0) 98 .into_result() 99 }?; 100 101 for protocol in protocols { 102 self.append_alpn_preference(protocol.as_ref())?; 103 } 104 105 Ok(self) 106 } 107 108 /// Turns off x509 verification 109 /// 110 /// # Safety 111 /// This functionality will weaken the security of the connections. As such, it should only 112 /// be used in development environments where obtaining a valid certificate would not be possible. disable_x509_verification(&mut self) -> Result<&mut Self, Error>113 pub unsafe fn disable_x509_verification(&mut self) -> Result<&mut Self, Error> { 114 s2n_config_disable_x509_verification(self.as_mut_ptr()).into_result()?; 115 Ok(self) 116 } 117 load_pem(&mut self, certificate: &[u8], private_key: &[u8]) -> Result<&mut Self, Error>118 pub fn load_pem(&mut self, certificate: &[u8], private_key: &[u8]) -> Result<&mut Self, Error> { 119 let certificate = CString::new(certificate).map_err(|_| Error::InvalidInput)?; 120 let private_key = CString::new(private_key).map_err(|_| Error::InvalidInput)?; 121 unsafe { 122 s2n_config_add_cert_chain_and_key( 123 self.as_mut_ptr(), 124 certificate.as_ptr(), 125 private_key.as_ptr(), 126 ) 127 .into_result() 128 }?; 129 Ok(self) 130 } 131 trust_pem(&mut self, certificate: &[u8]) -> Result<&mut Self, Error>132 pub fn trust_pem(&mut self, certificate: &[u8]) -> Result<&mut Self, Error> { 133 let certificate = CString::new(certificate).map_err(|_| Error::InvalidInput)?; 134 unsafe { 135 s2n_config_add_pem_to_trust_store(self.as_mut_ptr(), certificate.as_ptr()).into_result() 136 }?; 137 Ok(self) 138 } 139 append_alpn_preference(&mut self, protocol: &[u8]) -> Result<&mut Self, Error>140 pub fn append_alpn_preference(&mut self, protocol: &[u8]) -> Result<&mut Self, Error> { 141 unsafe { 142 s2n_config_append_protocol_preference( 143 self.as_mut_ptr(), 144 protocol.as_ptr(), 145 protocol.len().try_into().map_err(|_| Error::InvalidInput)?, 146 ) 147 .into_result() 148 }?; 149 Ok(self) 150 } 151 152 /// # Safety 153 /// 154 /// The `context` pointer must live at least as long as the config set_verify_host_callback( &mut self, callback: s2n_verify_host_fn, context: *mut core::ffi::c_void, ) -> Result<&mut Self, Error>155 pub unsafe fn set_verify_host_callback( 156 &mut self, 157 callback: s2n_verify_host_fn, 158 context: *mut core::ffi::c_void, 159 ) -> Result<&mut Self, Error> { 160 s2n_config_set_verify_host_callback(self.as_mut_ptr(), callback, context).into_result()?; 161 Ok(self) 162 } 163 164 /// # Safety 165 /// 166 /// The `context` pointer must live at least as long as the config set_key_log_callback( &mut self, callback: s2n_key_log_fn, context: *mut core::ffi::c_void, ) -> Result<&mut Self, Error>167 pub unsafe fn set_key_log_callback( 168 &mut self, 169 callback: s2n_key_log_fn, 170 context: *mut core::ffi::c_void, 171 ) -> Result<&mut Self, Error> { 172 s2n_config_set_key_log_cb(self.as_mut_ptr(), callback, context).into_result()?; 173 Ok(self) 174 } 175 build(self) -> Result<Config, Error>176 pub fn build(self) -> Result<Config, Error> { 177 Ok(Config(Arc::new(self.0))) 178 } 179 as_mut_ptr(&mut self) -> *mut s2n_config180 fn as_mut_ptr(&mut self) -> *mut s2n_config { 181 self.0.as_mut_ptr() 182 } 183 } 184 185 #[cfg(feature = "quic")] 186 impl Builder { enable_quic(&mut self) -> Result<&mut Self, Error>187 pub fn enable_quic(&mut self) -> Result<&mut Self, Error> { 188 unsafe { s2n_tls_sys::s2n_config_enable_quic(self.as_mut_ptr()).into_result() }?; 189 Ok(self) 190 } 191 } 192