2 use foreign_types
::ForeignType
;
3 use foreign_types
::ForeignTypeRef
;
4 #[cfg(any(ossl111, not(osslconf = "OPENSSL_NO_PSK")))]
8 use libc
::{c_int, c_uchar, c_uint, c_void}
;
9 #[cfg(any(ossl111, not(osslconf = "OPENSSL_NO_PSK")))]
19 #[cfg(all(ossl101, not(ossl110)))]
21 use error
::ErrorStack
;
23 #[cfg(any(ossl102, libressl261))]
26 use ssl
::{ClientHelloResponse, ExtensionContext}
;
28 SniError
, Ssl
, SslAlert
, SslContext
, SslContextRef
, SslRef
, SslSession
, SslSessionRef
,
33 use x509
::{X509StoreContext, X509StoreContextRef}
;
35 pub extern "C" fn raw_verify
<F
>(preverify_ok
: c_int
, x509_ctx
: *mut ffi
::X509_STORE_CTX
) -> c_int
37 F
: Fn(bool
, &mut X509StoreContextRef
) -> bool
+ '
static + Sync
+ Send
,
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
>();
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
48 .expect("BUG: store context missing ssl")
51 .expect("BUG: verify callback missing") as *const F
;
53 (*verify
)(preverify_ok
!= 0, ctx
) as c_int
57 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
58 pub extern "C" fn raw_client_psk
<F
>(
61 identity
: *mut c_char
,
62 max_identity_len
: c_uint
,
67 F
: Fn(&mut SslRef
, Option
<&[u8]>, &mut [u8], &mut [u8]) -> Result
<usize, ErrorStack
>
73 let ssl
= SslRef
::from_ptr_mut(ssl
);
74 let callback_idx
= SslContext
::cached_ex_index
::<F
>();
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())
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,
98 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
99 pub extern "C" fn raw_server_psk
<F
>(
101 identity
: *const c_char
,
106 F
: Fn(&mut SslRef
, Option
<&[u8]>, &mut [u8]) -> Result
<usize, ErrorStack
>
112 let ssl
= SslRef
::from_ptr_mut(ssl
);
113 let callback_idx
= SslContext
::cached_ex_index
::<F
>();
117 .ex_data(callback_idx
)
118 .expect("BUG: psk callback missing") as *const F
;
119 let identity
= if identity
.is_null() {
122 Some(CStr
::from_ptr(identity
).to_bytes())
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,
136 pub extern "C" fn ssl_raw_verify
<F
>(
138 x509_ctx
: *mut ffi
::X509_STORE_CTX
,
141 F
: Fn(bool
, &mut X509StoreContextRef
) -> bool
+ '
static + Sync
+ Send
,
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
>>();
150 .expect("BUG: store context missing ssl")
151 .ex_data(callback_idx
)
152 .expect("BUG: ssl verify callback missing")
155 callback(preverify_ok
!= 0, ctx
) as c_int
159 pub extern "C" fn raw_sni
<F
>(ssl
: *mut ffi
::SSL
, al
: *mut c_int
, arg
: *mut c_void
) -> c_int
161 F
: Fn(&mut SslRef
, &mut SslAlert
) -> Result
<(), SniError
> + '
static + Sync
+ Send
,
164 let ssl
= SslRef
::from_ptr_mut(ssl
);
165 let callback
= arg
as *const F
;
166 let mut alert
= SslAlert(*al
);
168 let r
= (*callback
)(ssl
, &mut alert
);
171 Ok(()) => ffi
::SSL_TLSEXT_ERR_OK
,
177 #[cfg(any(ossl102, libressl261))]
178 pub extern "C" fn raw_alpn_select
<F
>(
180 out
: *mut *const c_uchar
,
181 outlen
: *mut c_uchar
,
182 inbuf
: *const c_uchar
,
187 F
: for<'a
> Fn(&mut SslRef
, &'a
[u8]) -> Result
<&'a
[u8], AlpnError
> + '
static + Sync
+ Send
,
190 let ssl
= SslRef
::from_ptr_mut(ssl
);
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);
197 match (*callback
)(ssl
, protos
) {
199 *out
= proto
.as_ptr() as *const c_uchar
;
200 *outlen
= proto
.len() as c_uchar
;
201 ffi
::SSL_TLSEXT_ERR_OK
208 pub unsafe extern "C" fn raw_tmp_dh
<F
>(
214 F
: Fn(&mut SslRef
, bool
, u32) -> Result
<Dh
<Params
>, ErrorStack
> + '
static + Sync
+ Send
,
216 let ssl
= SslRef
::from_ptr_mut(ssl
);
219 .ex_data(SslContext
::cached_ex_index
::<F
>())
220 .expect("BUG: tmp dh callback missing") as *const F
;
222 match (*callback
)(ssl
, is_export
!= 0, keylength
as u32) {
224 let ptr
= dh
.as_ptr();
235 #[cfg(all(ossl101, not(ossl110)))]
236 pub unsafe extern "C" fn raw_tmp_ecdh
<F
>(
240 ) -> *mut ffi
::EC_KEY
242 F
: Fn(&mut SslRef
, bool
, u32) -> Result
<EcKey
<Params
>, ErrorStack
> + '
static + Sync
+ Send
,
244 let ssl
= SslRef
::from_ptr_mut(ssl
);
247 .ex_data(SslContext
::cached_ex_index
::<F
>())
248 .expect("BUG: tmp ecdh callback missing") as *const F
;
250 match (*callback
)(ssl
, is_export
!= 0, keylength
as u32) {
252 let ptr
= ec_key
.as_ptr();
263 pub unsafe extern "C" fn raw_tmp_dh_ssl
<F
>(
269 F
: Fn(&mut SslRef
, bool
, u32) -> Result
<Dh
<Params
>, ErrorStack
> + '
static + Sync
+ Send
,
271 let ssl
= SslRef
::from_ptr_mut(ssl
);
273 .ex_data(Ssl
::cached_ex_index
::<Arc
<F
>>())
274 .expect("BUG: ssl tmp dh callback missing")
277 match callback(ssl
, is_export
!= 0, keylength
as u32) {
279 let ptr
= dh
.as_ptr();
290 #[cfg(all(ossl101, not(ossl110)))]
291 pub unsafe extern "C" fn raw_tmp_ecdh_ssl
<F
>(
295 ) -> *mut ffi
::EC_KEY
297 F
: Fn(&mut SslRef
, bool
, u32) -> Result
<EcKey
<Params
>, ErrorStack
> + '
static + Sync
+ Send
,
299 let ssl
= SslRef
::from_ptr_mut(ssl
);
301 .ex_data(Ssl
::cached_ex_index
::<Arc
<F
>>())
302 .expect("BUG: ssl tmp ecdh callback missing")
305 match callback(ssl
, is_export
!= 0, keylength
as u32) {
307 let ptr
= ec_key
.as_ptr();
318 pub unsafe extern "C" fn raw_tlsext_status
<F
>(ssl
: *mut ffi
::SSL
, _
: *mut c_void
) -> c_int
320 F
: Fn(&mut SslRef
) -> Result
<bool
, ErrorStack
> + '
static + Sync
+ Send
,
322 let ssl
= SslRef
::from_ptr_mut(ssl
);
325 .ex_data(SslContext
::cached_ex_index
::<F
>())
326 .expect("BUG: ocsp callback missing") as *const F
;
327 let ret
= (*callback
)(ssl
);
331 Ok(true) => ffi
::SSL_TLSEXT_ERR_OK
,
332 Ok(false) => ffi
::SSL_TLSEXT_ERR_NOACK
,
335 ffi
::SSL_TLSEXT_ERR_ALERT_FATAL
350 pub unsafe extern "C" fn raw_new_session
<F
>(
352 session
: *mut ffi
::SSL_SESSION
,
355 F
: Fn(&mut SslRef
, SslSession
) + '
static + Sync
+ Send
,
357 let ssl
= SslRef
::from_ptr_mut(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
);
365 (*callback
)(ssl
, session
);
367 // the return code doesn't indicate error vs success, but whether or not we consumed the session
371 pub unsafe extern "C" fn raw_remove_session
<F
>(
372 ctx
: *mut ffi
::SSL_CTX
,
373 session
: *mut ffi
::SSL_SESSION
,
375 F
: Fn(&SslContextRef
, &SslSessionRef
) + '
static + Sync
+ Send
,
377 let ctx
= SslContextRef
::from_ptr(ctx
);
379 .ex_data(SslContext
::cached_ex_index
::<F
>())
380 .expect("BUG: remove session callback missing");
381 let session
= SslSessionRef
::from_ptr(session
);
383 callback(ctx
, session
)
387 if #[cfg(any(ossl110, libressl280))] {
388 type DataPtr
= *const c_uchar
;
390 type DataPtr
= *mut c_uchar
;
394 pub unsafe extern "C" fn raw_get_session
<F
>(
399 ) -> *mut ffi
::SSL_SESSION
401 F
: Fn(&mut SslRef
, &[u8]) -> Option
<SslSession
> + '
static + Sync
+ Send
,
403 let ssl
= SslRef
::from_ptr_mut(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);
411 match (*callback
)(ssl
, data
) {
413 let p
= session
.as_ptr();
414 mem
::forget(session
);
418 None
=> ptr
::null_mut(),
423 pub unsafe extern "C" fn raw_keylog
<F
>(ssl
: *const ffi
::SSL
, line
: *const c_char
)
425 F
: Fn(&SslRef
, &str) + '
static + Sync
+ Send
,
427 let ssl
= SslRef
::from_ptr(ssl
as *mut _
);
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
);
439 pub unsafe extern "C" fn raw_stateless_cookie_generate
<F
>(
441 cookie
: *mut c_uchar
,
442 cookie_len
: *mut size_t
,
445 F
: Fn(&mut SslRef
, &mut [u8]) -> Result
<usize, ErrorStack
> + '
static + Sync
+ Send
,
447 let ssl
= SslRef
::from_ptr_mut(ssl
);
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
) {
455 *cookie_len
= len
as size_t
;
466 pub unsafe extern "C" fn raw_stateless_cookie_verify
<F
>(
468 cookie
: *const c_uchar
,
472 F
: Fn(&mut SslRef
, &[u8]) -> bool
+ '
static + Sync
+ Send
,
474 let ssl
= SslRef
::from_ptr_mut(ssl
);
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
483 pub extern "C" fn raw_cookie_generate
<F
>(
485 cookie
: *mut c_uchar
,
486 cookie_len
: *mut c_uint
,
489 F
: Fn(&mut SslRef
, &mut [u8]) -> Result
<usize, ErrorStack
> + '
static + Sync
+ Send
,
492 let ssl
= SslRef
::from_ptr_mut(ssl
);
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.
500 slice
::from_raw_parts_mut(cookie
as *mut u8, ffi
::DTLS1_COOKIE_LENGTH
as usize - 1);
501 match (*callback
)(ssl
, slice
) {
503 *cookie_len
= len
as c_uint
;
515 if #[cfg(any(ossl110, libressl280))] {
516 type CookiePtr
= *const c_uchar
;
518 type CookiePtr
= *mut c_uchar
;
522 pub extern "C" fn raw_cookie_verify
<F
>(
528 F
: Fn(&mut SslRef
, &[u8]) -> bool
+ '
static + Sync
+ Send
,
531 let ssl
= SslRef
::from_ptr_mut(ssl
);
534 .ex_data(SslContext
::cached_ex_index
::<F
>())
535 .expect("BUG: cookie verify callback missing") as *const F
;
537 slice
::from_raw_parts(cookie
as *const c_uchar
as *const u8, cookie_len
as usize);
538 (*callback
)(ssl
, slice
) as c_int
543 pub struct CustomExtAddState
<T
>(Option
<T
>);
546 pub extern "C" fn raw_custom_ext_add
<F
, T
>(
550 out
: *mut *const c_uchar
,
558 F
: Fn(&mut SslRef
, ExtensionContext
, Option
<(usize, &X509Ref
)>) -> Result
<Option
<T
>, SslAlert
>
562 T
: AsRef
<[u8]> + '
static + Sync
+ Send
,
565 let ssl
= SslRef
::from_ptr_mut(ssl
);
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
)))
576 match (*callback
)(ssl
, ectx
, cert
) {
579 *outlen
= buf
.as_ref().len();
580 *out
= buf
.as_ref().as_ptr();
582 let idx
= Ssl
::cached_ex_index
::<CustomExtAddState
<T
>>();
583 let mut buf
= Some(buf
);
584 let new
= match ssl
.ex_data_mut(idx
) {
586 state
.0 = buf
.take();
592 ssl
.set_ex_data(idx
, CustomExtAddState(buf
));
605 pub extern "C" fn raw_custom_ext_free
<T
>(
609 _
: *mut *const c_uchar
,
612 T
: '
static + Sync
+ Send
,
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
) {
624 pub extern "C" fn raw_custom_ext_parse
<F
>(
628 input
: *const c_uchar
,
636 F
: Fn(&mut SslRef
, ExtensionContext
, &[u8], Option
<(usize, &X509Ref
)>) -> Result
<(), SslAlert
>
642 let ssl
= SslRef
::from_ptr_mut(ssl
);
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
)))
654 match (*callback
)(ssl
, ectx
, slice
, cert
) {
665 pub unsafe extern "C" fn raw_client_hello
<F
>(
671 F
: Fn(&mut SslRef
, &mut SslAlert
) -> Result
<ClientHelloResponse
, ErrorStack
>
676 let ssl
= SslRef
::from_ptr_mut(ssl
);
677 let callback
= arg
as *const F
;
678 let mut alert
= SslAlert(*al
);
680 let r
= (*callback
)(ssl
, &mut alert
);
686 ffi
::SSL_CLIENT_HELLO_ERROR