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