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