1 use cfg_if::cfg_if;
2 use foreign_types::ForeignType;
3 use foreign_types::ForeignTypeRef;
4 #[cfg(any(ossl111, not(osslconf = "OPENSSL_NO_PSK")))]
5 use libc::c_char;
6 #[cfg(ossl111)]
7 use libc::size_t;
8 use libc::{c_int, c_uchar, c_uint, c_void};
9 #[cfg(any(ossl111, not(osslconf = "OPENSSL_NO_PSK")))]
10 use std::ffi::CStr;
11 use std::mem;
12 use std::ptr;
13 use std::slice;
14 #[cfg(ossl111)]
15 use std::str;
16 use std::sync::Arc;
17 
18 use crate::dh::Dh;
19 #[cfg(all(ossl101, not(ossl110)))]
20 use crate::ec::EcKey;
21 use crate::error::ErrorStack;
22 use crate::pkey::Params;
23 #[cfg(any(ossl102, libressl261, boringssl))]
24 use crate::ssl::AlpnError;
25 use crate::ssl::{
26     try_get_session_ctx_index, SniError, Ssl, SslAlert, SslContext, SslContextRef, SslRef,
27     SslSession, SslSessionRef,
28 };
29 #[cfg(ossl111)]
30 use crate::ssl::{ClientHelloResponse, ExtensionContext};
31 #[cfg(ossl111)]
32 use crate::util::ForeignTypeRefExt;
33 #[cfg(ossl111)]
34 use crate::x509::X509Ref;
35 use crate::x509::{X509StoreContext, X509StoreContextRef};
36 
raw_verify<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int where F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,37 pub extern "C" fn raw_verify<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int
38 where
39     F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
40 {
41     unsafe {
42         let ctx = X509StoreContextRef::from_ptr_mut(x509_ctx);
43         let ssl_idx = X509StoreContext::ssl_idx().expect("BUG: store context ssl index missing");
44         let verify_idx = SslContext::cached_ex_index::<F>();
45 
46         // raw pointer shenanigans to break the borrow of ctx
47         // the callback can't mess with its own ex_data slot so this is safe
48         let verify = ctx
49             .ex_data(ssl_idx)
50             .expect("BUG: store context missing ssl")
51             .ssl_context()
52             .ex_data(verify_idx)
53             .expect("BUG: verify callback missing") as *const F;
54 
55         (*verify)(preverify_ok != 0, ctx) as c_int
56     }
57 }
58 
59 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
raw_client_psk<F>( ssl: *mut ffi::SSL, hint: *const c_char, identity: *mut c_char, max_identity_len: c_uint, psk: *mut c_uchar, max_psk_len: c_uint, ) -> c_uint where F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,60 pub extern "C" fn raw_client_psk<F>(
61     ssl: *mut ffi::SSL,
62     hint: *const c_char,
63     identity: *mut c_char,
64     max_identity_len: c_uint,
65     psk: *mut c_uchar,
66     max_psk_len: c_uint,
67 ) -> c_uint
68 where
69     F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
70         + 'static
71         + Sync
72         + Send,
73 {
74     unsafe {
75         let ssl = SslRef::from_ptr_mut(ssl);
76         let callback_idx = SslContext::cached_ex_index::<F>();
77 
78         let callback = ssl
79             .ssl_context()
80             .ex_data(callback_idx)
81             .expect("BUG: psk callback missing") as *const F;
82         let hint = if !hint.is_null() {
83             Some(CStr::from_ptr(hint).to_bytes())
84         } else {
85             None
86         };
87         // Give the callback mutable slices into which it can write the identity and psk.
88         let identity_sl = slice::from_raw_parts_mut(identity as *mut u8, max_identity_len as usize);
89         #[allow(clippy::unnecessary_cast)]
90         let psk_sl = slice::from_raw_parts_mut(psk as *mut u8, max_psk_len as usize);
91         match (*callback)(ssl, hint, identity_sl, psk_sl) {
92             Ok(psk_len) => psk_len as u32,
93             Err(e) => {
94                 e.put();
95                 0
96             }
97         }
98     }
99 }
100 
101 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
raw_server_psk<F>( ssl: *mut ffi::SSL, identity: *const c_char, psk: *mut c_uchar, max_psk_len: c_uint, ) -> c_uint where F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,102 pub extern "C" fn raw_server_psk<F>(
103     ssl: *mut ffi::SSL,
104     identity: *const c_char,
105     psk: *mut c_uchar,
106     max_psk_len: c_uint,
107 ) -> c_uint
108 where
109     F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
110         + 'static
111         + Sync
112         + Send,
113 {
114     unsafe {
115         let ssl = SslRef::from_ptr_mut(ssl);
116         let callback_idx = SslContext::cached_ex_index::<F>();
117 
118         let callback = ssl
119             .ssl_context()
120             .ex_data(callback_idx)
121             .expect("BUG: psk callback missing") as *const F;
122         let identity = if identity.is_null() {
123             None
124         } else {
125             Some(CStr::from_ptr(identity).to_bytes())
126         };
127         // Give the callback mutable slices into which it can write the psk.
128         #[allow(clippy::unnecessary_cast)]
129         let psk_sl = slice::from_raw_parts_mut(psk as *mut u8, max_psk_len as usize);
130         match (*callback)(ssl, identity, psk_sl) {
131             Ok(psk_len) => psk_len as u32,
132             Err(e) => {
133                 e.put();
134                 0
135             }
136         }
137     }
138 }
139 
ssl_raw_verify<F>( preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX, ) -> c_int where F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,140 pub extern "C" fn ssl_raw_verify<F>(
141     preverify_ok: c_int,
142     x509_ctx: *mut ffi::X509_STORE_CTX,
143 ) -> c_int
144 where
145     F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
146 {
147     unsafe {
148         let ctx = X509StoreContextRef::from_ptr_mut(x509_ctx);
149         let ssl_idx = X509StoreContext::ssl_idx().expect("BUG: store context ssl index missing");
150         let callback_idx = Ssl::cached_ex_index::<Arc<F>>();
151 
152         let callback = ctx
153             .ex_data(ssl_idx)
154             .expect("BUG: store context missing ssl")
155             .ex_data(callback_idx)
156             .expect("BUG: ssl verify callback missing")
157             .clone();
158 
159         callback(preverify_ok != 0, ctx) as c_int
160     }
161 }
162 
raw_sni<F>(ssl: *mut ffi::SSL, al: *mut c_int, arg: *mut c_void) -> c_int where F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,163 pub extern "C" fn raw_sni<F>(ssl: *mut ffi::SSL, al: *mut c_int, arg: *mut c_void) -> c_int
164 where
165     F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
166 {
167     unsafe {
168         let ssl = SslRef::from_ptr_mut(ssl);
169         let callback = arg as *const F;
170         let mut alert = SslAlert(*al);
171 
172         let r = (*callback)(ssl, &mut alert);
173         *al = alert.0;
174         match r {
175             Ok(()) => ffi::SSL_TLSEXT_ERR_OK,
176             Err(e) => e.0,
177         }
178     }
179 }
180 
181 #[cfg(any(ossl102, libressl261, boringssl))]
raw_alpn_select<F>( ssl: *mut ffi::SSL, out: *mut *const c_uchar, outlen: *mut c_uchar, inbuf: *const c_uchar, inlen: c_uint, _arg: *mut c_void, ) -> c_int where F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,182 pub extern "C" fn raw_alpn_select<F>(
183     ssl: *mut ffi::SSL,
184     out: *mut *const c_uchar,
185     outlen: *mut c_uchar,
186     inbuf: *const c_uchar,
187     inlen: c_uint,
188     _arg: *mut c_void,
189 ) -> c_int
190 where
191     F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
192 {
193     unsafe {
194         let ssl = SslRef::from_ptr_mut(ssl);
195         let callback = ssl
196             .ssl_context()
197             .ex_data(SslContext::cached_ex_index::<F>())
198             .expect("BUG: alpn callback missing") as *const F;
199         #[allow(clippy::unnecessary_cast)]
200         let protos = slice::from_raw_parts(inbuf as *const u8, inlen as usize);
201 
202         match (*callback)(ssl, protos) {
203             Ok(proto) => {
204                 *out = proto.as_ptr() as *const c_uchar;
205                 *outlen = proto.len() as c_uchar;
206                 ffi::SSL_TLSEXT_ERR_OK
207             }
208             Err(e) => e.0,
209         }
210     }
211 }
212 
raw_tmp_dh<F>( ssl: *mut ffi::SSL, is_export: c_int, keylength: c_int, ) -> *mut ffi::DH where F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,213 pub unsafe extern "C" fn raw_tmp_dh<F>(
214     ssl: *mut ffi::SSL,
215     is_export: c_int,
216     keylength: c_int,
217 ) -> *mut ffi::DH
218 where
219     F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
220 {
221     let ssl = SslRef::from_ptr_mut(ssl);
222     let callback = ssl
223         .ssl_context()
224         .ex_data(SslContext::cached_ex_index::<F>())
225         .expect("BUG: tmp dh callback missing") as *const F;
226 
227     match (*callback)(ssl, is_export != 0, keylength as u32) {
228         Ok(dh) => {
229             let ptr = dh.as_ptr();
230             mem::forget(dh);
231             ptr
232         }
233         Err(e) => {
234             e.put();
235             ptr::null_mut()
236         }
237     }
238 }
239 
240 #[cfg(all(ossl101, not(ossl110)))]
raw_tmp_ecdh<F>( ssl: *mut ffi::SSL, is_export: c_int, keylength: c_int, ) -> *mut ffi::EC_KEY where F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,241 pub unsafe extern "C" fn raw_tmp_ecdh<F>(
242     ssl: *mut ffi::SSL,
243     is_export: c_int,
244     keylength: c_int,
245 ) -> *mut ffi::EC_KEY
246 where
247     F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
248 {
249     let ssl = SslRef::from_ptr_mut(ssl);
250     let callback = ssl
251         .ssl_context()
252         .ex_data(SslContext::cached_ex_index::<F>())
253         .expect("BUG: tmp ecdh callback missing") as *const F;
254 
255     match (*callback)(ssl, is_export != 0, keylength as u32) {
256         Ok(ec_key) => {
257             let ptr = ec_key.as_ptr();
258             mem::forget(ec_key);
259             ptr
260         }
261         Err(e) => {
262             e.put();
263             ptr::null_mut()
264         }
265     }
266 }
267 
raw_tmp_dh_ssl<F>( ssl: *mut ffi::SSL, is_export: c_int, keylength: c_int, ) -> *mut ffi::DH where F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,268 pub unsafe extern "C" fn raw_tmp_dh_ssl<F>(
269     ssl: *mut ffi::SSL,
270     is_export: c_int,
271     keylength: c_int,
272 ) -> *mut ffi::DH
273 where
274     F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
275 {
276     let ssl = SslRef::from_ptr_mut(ssl);
277     let callback = ssl
278         .ex_data(Ssl::cached_ex_index::<Arc<F>>())
279         .expect("BUG: ssl tmp dh callback missing")
280         .clone();
281 
282     match callback(ssl, is_export != 0, keylength as u32) {
283         Ok(dh) => {
284             let ptr = dh.as_ptr();
285             mem::forget(dh);
286             ptr
287         }
288         Err(e) => {
289             e.put();
290             ptr::null_mut()
291         }
292     }
293 }
294 
295 #[cfg(all(ossl101, not(ossl110)))]
raw_tmp_ecdh_ssl<F>( ssl: *mut ffi::SSL, is_export: c_int, keylength: c_int, ) -> *mut ffi::EC_KEY where F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,296 pub unsafe extern "C" fn raw_tmp_ecdh_ssl<F>(
297     ssl: *mut ffi::SSL,
298     is_export: c_int,
299     keylength: c_int,
300 ) -> *mut ffi::EC_KEY
301 where
302     F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
303 {
304     let ssl = SslRef::from_ptr_mut(ssl);
305     let callback = ssl
306         .ex_data(Ssl::cached_ex_index::<Arc<F>>())
307         .expect("BUG: ssl tmp ecdh callback missing")
308         .clone();
309 
310     match callback(ssl, is_export != 0, keylength as u32) {
311         Ok(ec_key) => {
312             let ptr = ec_key.as_ptr();
313             mem::forget(ec_key);
314             ptr
315         }
316         Err(e) => {
317             e.put();
318             ptr::null_mut()
319         }
320     }
321 }
322 
raw_tlsext_status<F>(ssl: *mut ffi::SSL, _: *mut c_void) -> c_int where F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,323 pub unsafe extern "C" fn raw_tlsext_status<F>(ssl: *mut ffi::SSL, _: *mut c_void) -> c_int
324 where
325     F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
326 {
327     let ssl = SslRef::from_ptr_mut(ssl);
328     let callback = ssl
329         .ssl_context()
330         .ex_data(SslContext::cached_ex_index::<F>())
331         .expect("BUG: ocsp callback missing") as *const F;
332     let ret = (*callback)(ssl);
333 
334     if ssl.is_server() {
335         match ret {
336             Ok(true) => ffi::SSL_TLSEXT_ERR_OK,
337             Ok(false) => ffi::SSL_TLSEXT_ERR_NOACK,
338             Err(e) => {
339                 e.put();
340                 ffi::SSL_TLSEXT_ERR_ALERT_FATAL
341             }
342         }
343     } else {
344         match ret {
345             Ok(true) => 1,
346             Ok(false) => 0,
347             Err(e) => {
348                 e.put();
349                 -1
350             }
351         }
352     }
353 }
354 
raw_new_session<F>( ssl: *mut ffi::SSL, session: *mut ffi::SSL_SESSION, ) -> c_int where F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,355 pub unsafe extern "C" fn raw_new_session<F>(
356     ssl: *mut ffi::SSL,
357     session: *mut ffi::SSL_SESSION,
358 ) -> c_int
359 where
360     F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
361 {
362     let session_ctx_index =
363         try_get_session_ctx_index().expect("BUG: session context index initialization failed");
364     let ssl = SslRef::from_ptr_mut(ssl);
365     let callback = ssl
366         .ex_data(*session_ctx_index)
367         .expect("BUG: session context missing")
368         .ex_data(SslContext::cached_ex_index::<F>())
369         .expect("BUG: new session callback missing") as *const F;
370     let session = SslSession::from_ptr(session);
371 
372     (*callback)(ssl, session);
373 
374     // the return code doesn't indicate error vs success, but whether or not we consumed the session
375     1
376 }
377 
raw_remove_session<F>( ctx: *mut ffi::SSL_CTX, session: *mut ffi::SSL_SESSION, ) where F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,378 pub unsafe extern "C" fn raw_remove_session<F>(
379     ctx: *mut ffi::SSL_CTX,
380     session: *mut ffi::SSL_SESSION,
381 ) where
382     F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
383 {
384     let ctx = SslContextRef::from_ptr(ctx);
385     let callback = ctx
386         .ex_data(SslContext::cached_ex_index::<F>())
387         .expect("BUG: remove session callback missing");
388     let session = SslSessionRef::from_ptr(session);
389 
390     callback(ctx, session)
391 }
392 
393 cfg_if! {
394     if #[cfg(any(ossl110, libressl280, boringssl))] {
395         type DataPtr = *const c_uchar;
396     } else {
397         type DataPtr = *mut c_uchar;
398     }
399 }
400 
raw_get_session<F>( ssl: *mut ffi::SSL, data: DataPtr, len: c_int, copy: *mut c_int, ) -> *mut ffi::SSL_SESSION where F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,401 pub unsafe extern "C" fn raw_get_session<F>(
402     ssl: *mut ffi::SSL,
403     data: DataPtr,
404     len: c_int,
405     copy: *mut c_int,
406 ) -> *mut ffi::SSL_SESSION
407 where
408     F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
409 {
410     let session_ctx_index =
411         try_get_session_ctx_index().expect("BUG: session context index initialization failed");
412     let ssl = SslRef::from_ptr_mut(ssl);
413     let callback = ssl
414         .ex_data(*session_ctx_index)
415         .expect("BUG: session context missing")
416         .ex_data(SslContext::cached_ex_index::<F>())
417         .expect("BUG: get session callback missing") as *const F;
418     #[allow(clippy::unnecessary_cast)]
419     let data = slice::from_raw_parts(data as *const u8, len as usize);
420 
421     match (*callback)(ssl, data) {
422         Some(session) => {
423             let p = session.as_ptr();
424             mem::forget(session);
425             *copy = 0;
426             p
427         }
428         None => ptr::null_mut(),
429     }
430 }
431 
432 #[cfg(ossl111)]
raw_keylog<F>(ssl: *const ffi::SSL, line: *const c_char) where F: Fn(&SslRef, &str) + 'static + Sync + Send,433 pub unsafe extern "C" fn raw_keylog<F>(ssl: *const ffi::SSL, line: *const c_char)
434 where
435     F: Fn(&SslRef, &str) + 'static + Sync + Send,
436 {
437     let ssl = SslRef::from_const_ptr(ssl);
438     let callback = ssl
439         .ssl_context()
440         .ex_data(SslContext::cached_ex_index::<F>())
441         .expect("BUG: get session callback missing");
442     let line = CStr::from_ptr(line).to_bytes();
443     let line = str::from_utf8_unchecked(line);
444 
445     callback(ssl, line);
446 }
447 
448 #[cfg(ossl111)]
raw_stateless_cookie_generate<F>( ssl: *mut ffi::SSL, cookie: *mut c_uchar, cookie_len: *mut size_t, ) -> c_int where F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,449 pub unsafe extern "C" fn raw_stateless_cookie_generate<F>(
450     ssl: *mut ffi::SSL,
451     cookie: *mut c_uchar,
452     cookie_len: *mut size_t,
453 ) -> c_int
454 where
455     F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
456 {
457     let ssl = SslRef::from_ptr_mut(ssl);
458     let callback = ssl
459         .ssl_context()
460         .ex_data(SslContext::cached_ex_index::<F>())
461         .expect("BUG: stateless cookie generate callback missing") as *const F;
462     #[allow(clippy::unnecessary_cast)]
463     let slice = slice::from_raw_parts_mut(cookie as *mut u8, ffi::SSL_COOKIE_LENGTH as usize);
464     match (*callback)(ssl, slice) {
465         Ok(len) => {
466             *cookie_len = len as size_t;
467             1
468         }
469         Err(e) => {
470             e.put();
471             0
472         }
473     }
474 }
475 
476 #[cfg(ossl111)]
raw_stateless_cookie_verify<F>( ssl: *mut ffi::SSL, cookie: *const c_uchar, cookie_len: size_t, ) -> c_int where F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,477 pub unsafe extern "C" fn raw_stateless_cookie_verify<F>(
478     ssl: *mut ffi::SSL,
479     cookie: *const c_uchar,
480     cookie_len: size_t,
481 ) -> c_int
482 where
483     F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
484 {
485     let ssl = SslRef::from_ptr_mut(ssl);
486     let callback = ssl
487         .ssl_context()
488         .ex_data(SslContext::cached_ex_index::<F>())
489         .expect("BUG: stateless cookie verify callback missing") as *const F;
490     #[allow(clippy::unnecessary_cast)]
491     let slice = slice::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len);
492     (*callback)(ssl, slice) as c_int
493 }
494 
495 #[cfg(not(boringssl))]
raw_cookie_generate<F>( ssl: *mut ffi::SSL, cookie: *mut c_uchar, cookie_len: *mut c_uint, ) -> c_int where F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,496 pub extern "C" fn raw_cookie_generate<F>(
497     ssl: *mut ffi::SSL,
498     cookie: *mut c_uchar,
499     cookie_len: *mut c_uint,
500 ) -> c_int
501 where
502     F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
503 {
504     unsafe {
505         let ssl = SslRef::from_ptr_mut(ssl);
506         let callback = ssl
507             .ssl_context()
508             .ex_data(SslContext::cached_ex_index::<F>())
509             .expect("BUG: cookie generate callback missing") as *const F;
510         // We subtract 1 from DTLS1_COOKIE_LENGTH as the ostensible value, 256, is erroneous but retained for
511         // compatibility. See comments in dtls1.h.
512         #[allow(clippy::unnecessary_cast)]
513         let slice =
514             slice::from_raw_parts_mut(cookie as *mut u8, ffi::DTLS1_COOKIE_LENGTH as usize - 1);
515         match (*callback)(ssl, slice) {
516             Ok(len) => {
517                 *cookie_len = len as c_uint;
518                 1
519             }
520             Err(e) => {
521                 e.put();
522                 0
523             }
524         }
525     }
526 }
527 
528 #[cfg(not(boringssl))]
529 cfg_if! {
530     if #[cfg(any(ossl110, libressl280))] {
531         type CookiePtr = *const c_uchar;
532     } else {
533         type CookiePtr = *mut c_uchar;
534     }
535 }
536 
537 #[cfg(not(boringssl))]
raw_cookie_verify<F>( ssl: *mut ffi::SSL, cookie: CookiePtr, cookie_len: c_uint, ) -> c_int where F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,538 pub extern "C" fn raw_cookie_verify<F>(
539     ssl: *mut ffi::SSL,
540     cookie: CookiePtr,
541     cookie_len: c_uint,
542 ) -> c_int
543 where
544     F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
545 {
546     unsafe {
547         let ssl = SslRef::from_ptr_mut(ssl);
548         let callback = ssl
549             .ssl_context()
550             .ex_data(SslContext::cached_ex_index::<F>())
551             .expect("BUG: cookie verify callback missing") as *const F;
552         #[allow(clippy::unnecessary_cast)]
553         let slice =
554             slice::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len as usize);
555         (*callback)(ssl, slice) as c_int
556     }
557 }
558 
559 #[cfg(ossl111)]
560 pub struct CustomExtAddState<T>(Option<T>);
561 
562 #[cfg(ossl111)]
raw_custom_ext_add<F, T>( ssl: *mut ffi::SSL, _: c_uint, context: c_uint, out: *mut *const c_uchar, outlen: *mut size_t, x: *mut ffi::X509, chainidx: size_t, al: *mut c_int, _: *mut c_void, ) -> c_int where F: Fn(&mut SslRef, ExtensionContext, Option<(usize, &X509Ref)>) -> Result<Option<T>, SslAlert> + 'static + Sync + Send, T: AsRef<[u8]> + 'static + Sync + Send,563 pub extern "C" fn raw_custom_ext_add<F, T>(
564     ssl: *mut ffi::SSL,
565     _: c_uint,
566     context: c_uint,
567     out: *mut *const c_uchar,
568     outlen: *mut size_t,
569     x: *mut ffi::X509,
570     chainidx: size_t,
571     al: *mut c_int,
572     _: *mut c_void,
573 ) -> c_int
574 where
575     F: Fn(&mut SslRef, ExtensionContext, Option<(usize, &X509Ref)>) -> Result<Option<T>, SslAlert>
576         + 'static
577         + Sync
578         + Send,
579     T: AsRef<[u8]> + 'static + Sync + Send,
580 {
581     unsafe {
582         let ssl = SslRef::from_ptr_mut(ssl);
583         let callback = ssl
584             .ssl_context()
585             .ex_data(SslContext::cached_ex_index::<F>())
586             .expect("BUG: custom ext add callback missing") as *const F;
587         let ectx = ExtensionContext::from_bits_truncate(context);
588         let cert = if ectx.contains(ExtensionContext::TLS1_3_CERTIFICATE) {
589             Some((chainidx, X509Ref::from_ptr(x)))
590         } else {
591             None
592         };
593         match (*callback)(ssl, ectx, cert) {
594             Ok(None) => 0,
595             Ok(Some(buf)) => {
596                 *outlen = buf.as_ref().len();
597                 *out = buf.as_ref().as_ptr();
598 
599                 let idx = Ssl::cached_ex_index::<CustomExtAddState<T>>();
600                 let mut buf = Some(buf);
601                 let new = match ssl.ex_data_mut(idx) {
602                     Some(state) => {
603                         state.0 = buf.take();
604                         false
605                     }
606                     None => true,
607                 };
608                 if new {
609                     ssl.set_ex_data(idx, CustomExtAddState(buf));
610                 }
611                 1
612             }
613             Err(alert) => {
614                 *al = alert.0;
615                 -1
616             }
617         }
618     }
619 }
620 
621 #[cfg(ossl111)]
raw_custom_ext_free<T>( ssl: *mut ffi::SSL, _: c_uint, _: c_uint, _: *const c_uchar, _: *mut c_void, ) where T: 'static + Sync + Send,622 pub extern "C" fn raw_custom_ext_free<T>(
623     ssl: *mut ffi::SSL,
624     _: c_uint,
625     _: c_uint,
626     _: *const c_uchar,
627     _: *mut c_void,
628 ) where
629     T: 'static + Sync + Send,
630 {
631     unsafe {
632         let ssl = SslRef::from_ptr_mut(ssl);
633         let idx = Ssl::cached_ex_index::<CustomExtAddState<T>>();
634         if let Some(state) = ssl.ex_data_mut(idx) {
635             state.0 = None;
636         }
637     }
638 }
639 
640 #[cfg(ossl111)]
raw_custom_ext_parse<F>( ssl: *mut ffi::SSL, _: c_uint, context: c_uint, input: *const c_uchar, inlen: size_t, x: *mut ffi::X509, chainidx: size_t, al: *mut c_int, _: *mut c_void, ) -> c_int where F: Fn(&mut SslRef, ExtensionContext, &[u8], Option<(usize, &X509Ref)>) -> Result<(), SslAlert> + 'static + Sync + Send,641 pub extern "C" fn raw_custom_ext_parse<F>(
642     ssl: *mut ffi::SSL,
643     _: c_uint,
644     context: c_uint,
645     input: *const c_uchar,
646     inlen: size_t,
647     x: *mut ffi::X509,
648     chainidx: size_t,
649     al: *mut c_int,
650     _: *mut c_void,
651 ) -> c_int
652 where
653     F: Fn(&mut SslRef, ExtensionContext, &[u8], Option<(usize, &X509Ref)>) -> Result<(), SslAlert>
654         + 'static
655         + Sync
656         + Send,
657 {
658     unsafe {
659         let ssl = SslRef::from_ptr_mut(ssl);
660         let callback = ssl
661             .ssl_context()
662             .ex_data(SslContext::cached_ex_index::<F>())
663             .expect("BUG: custom ext parse callback missing") as *const F;
664         let ectx = ExtensionContext::from_bits_truncate(context);
665         #[allow(clippy::unnecessary_cast)]
666         let slice = slice::from_raw_parts(input as *const u8, inlen);
667         let cert = if ectx.contains(ExtensionContext::TLS1_3_CERTIFICATE) {
668             Some((chainidx, X509Ref::from_ptr(x)))
669         } else {
670             None
671         };
672         match (*callback)(ssl, ectx, slice, cert) {
673             Ok(()) => 1,
674             Err(alert) => {
675                 *al = alert.0;
676                 0
677             }
678         }
679     }
680 }
681 
682 #[cfg(ossl111)]
raw_client_hello<F>( ssl: *mut ffi::SSL, al: *mut c_int, arg: *mut c_void, ) -> c_int where F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack> + 'static + Sync + Send,683 pub unsafe extern "C" fn raw_client_hello<F>(
684     ssl: *mut ffi::SSL,
685     al: *mut c_int,
686     arg: *mut c_void,
687 ) -> c_int
688 where
689     F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack>
690         + 'static
691         + Sync
692         + Send,
693 {
694     let ssl = SslRef::from_ptr_mut(ssl);
695     let callback = arg as *const F;
696     let mut alert = SslAlert(*al);
697 
698     let r = (*callback)(ssl, &mut alert);
699     *al = alert.0;
700     match r {
701         Ok(c) => c.0,
702         Err(e) => {
703             e.put();
704             ffi::SSL_CLIENT_HELLO_ERROR
705         }
706     }
707 }
708