1use cfg_if::cfg_if;
2use foreign_types::ForeignType;
3use foreign_types::ForeignTypeRef;
4#[cfg(any(ossl111, not(osslconf = "OPENSSL_NO_PSK")))]
5use libc::c_char;
6#[cfg(ossl111)]
7use libc::size_t;
8use libc::{c_int, c_uchar, c_uint, c_void};
9#[cfg(any(ossl111, not(osslconf = "OPENSSL_NO_PSK")))]
10use std::ffi::CStr;
11use std::mem;
12use std::ptr;
13use std::slice;
14#[cfg(ossl111)]
15use std::str;
16use std::sync::Arc;
17
18use crate::dh::Dh;
19#[cfg(all(ossl101, not(ossl110)))]
20use crate::ec::EcKey;
21use crate::error::ErrorStack;
22use crate::pkey::Params;
23#[cfg(any(ossl102, libressl261))]
24use crate::ssl::AlpnError;
25use crate::ssl::{
26 try_get_session_ctx_index, SniError, Ssl, SslAlert, SslContext, SslContextRef, SslRef,
27 SslSession, SslSessionRef,
28};
29#[cfg(ossl111)]
30use crate::ssl::{ClientHelloResponse, ExtensionContext};
31#[cfg(ossl111)]
32use crate::util::ForeignTypeRefExt;
33#[cfg(ossl111)]
34use crate::x509::X509Ref;
35use crate::x509::{X509StoreContext, X509StoreContextRef};
36
37pub extern "C" fn raw_verify<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int
38where
39 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
40{
41 unsafe {
42 let ctx: &mut X509StoreContextRef = X509StoreContextRef::from_ptr_mut(ptr:x509_ctx);
43 let ssl_idx: Index = X509StoreContext::ssl_idx().expect(msg:"BUG: store context ssl index missing");
44 let verify_idx: Index = 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: *const F = ctx
49 .ex_data(ssl_idx)
50 .expect("BUG: store context missing ssl")
51 .ssl_context()
52 .ex_data(verify_idx)
53 .expect(msg:"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"))]
60pub 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
68where
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"))]
102pub 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
108where
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
140pub extern "C" fn ssl_raw_verify<F>(
141 preverify_ok: c_int,
142 x509_ctx: *mut ffi::X509_STORE_CTX,
143) -> c_int
144where
145 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
146{
147 unsafe {
148 let ctx: &mut X509StoreContextRef = X509StoreContextRef::from_ptr_mut(ptr:x509_ctx);
149 let ssl_idx: Index = X509StoreContext::ssl_idx().expect(msg:"BUG: store context ssl index missing");
150 let callback_idx: Index> = Ssl::cached_ex_index::<Arc<F>>();
151
152 let callback: Arc = ctx&Arc
153 .ex_data(ssl_idx)
154 .expect("BUG: store context missing ssl")
155 .ex_data(callback_idx)
156 .expect(msg:"BUG: ssl verify callback missing")
157 .clone();
158
159 callback(preverify_ok != 0, ctx) as c_int
160 }
161}
162
163pub extern "C" fn raw_sni<F>(ssl: *mut ffi::SSL, al: *mut c_int, arg: *mut c_void) -> c_int
164where
165 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
166{
167 unsafe {
168 let ssl: &mut SslRef = SslRef::from_ptr_mut(ptr:ssl);
169 let callback: *const F = arg as *const F;
170 let mut alert: SslAlert = SslAlert(*al);
171
172 let r: Result<(), SniError> = (*callback)(ssl, &mut alert);
173 *al = alert.0;
174 match r {
175 Ok(()) => ffi::SSL_TLSEXT_ERR_OK,
176 Err(e: SniError) => e.0,
177 }
178 }
179}
180
181#[cfg(any(ossl102, libressl261))]
182pub 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
190where
191 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
192{
193 unsafe {
194 let ssl: &mut SslRef = SslRef::from_ptr_mut(ptr:ssl);
195 let callback: *const F = ssl
196 .ssl_context()
197 .ex_data(SslContext::cached_ex_index::<F>())
198 .expect(msg:"BUG: alpn callback missing") as *const F;
199 #[allow(clippy::unnecessary_cast)]
200 let protos: &[u8] = slice::from_raw_parts(data:inbuf as *const u8, len:inlen as usize);
201
202 match (*callback)(ssl, protos) {
203 Ok(proto: &[u8]) => {
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: AlpnError) => e.0,
209 }
210 }
211}
212
213pub 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
218where
219 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
220{
221 let ssl: &mut SslRef = SslRef::from_ptr_mut(ptr:ssl);
222 let callback: *const F = ssl
223 .ssl_context()
224 .ex_data(SslContext::cached_ex_index::<F>())
225 .expect(msg:"BUG: tmp dh callback missing") as *const F;
226
227 match (*callback)(ssl, is_export != 0, keylength as u32) {
228 Ok(dh: Dh) => {
229 let ptr: *mut DH = dh.as_ptr();
230 mem::forget(dh);
231 ptr
232 }
233 Err(e: ErrorStack) => {
234 e.put();
235 ptr::null_mut()
236 }
237 }
238}
239
240#[cfg(all(ossl101, not(ossl110)))]
241pub 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
246where
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
268pub 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
273where
274 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
275{
276 let ssl: &mut SslRef = SslRef::from_ptr_mut(ptr:ssl);
277 let callback: Arc = ssl&Arc
278 .ex_data(Ssl::cached_ex_index::<Arc<F>>())
279 .expect(msg:"BUG: ssl tmp dh callback missing")
280 .clone();
281
282 match callback(ssl, is_export != 0, keylength as u32) {
283 Ok(dh: Dh) => {
284 let ptr: *mut DH = dh.as_ptr();
285 mem::forget(dh);
286 ptr
287 }
288 Err(e: ErrorStack) => {
289 e.put();
290 ptr::null_mut()
291 }
292 }
293}
294
295#[cfg(all(ossl101, not(ossl110)))]
296pub 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
301where
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
323pub unsafe extern "C" fn raw_tlsext_status<F>(ssl: *mut ffi::SSL, _: *mut c_void) -> c_int
324where
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
355pub unsafe extern "C" fn raw_new_session<F>(
356 ssl: *mut ffi::SSL,
357 session: *mut ffi::SSL_SESSION,
358) -> c_int
359where
360 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
361{
362 let session_ctx_index: &Index =
363 try_get_session_ctx_index().expect(msg:"BUG: session context index initialization failed");
364 let ssl: &mut SslRef = SslRef::from_ptr_mut(ptr:ssl);
365 let callback: *const F = ssl
366 .ex_data(*session_ctx_index)
367 .expect("BUG: session context missing")
368 .ex_data(SslContext::cached_ex_index::<F>())
369 .expect(msg:"BUG: new session callback missing") as *const F;
370 let session: SslSession = 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
378pub 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 = SslContextRef::from_ptr(ctx);
385 let callback: &F = ctx
386 .ex_data(SslContext::cached_ex_index::<F>())
387 .expect(msg:"BUG: remove session callback missing");
388 let session: &SslSessionRef = SslSessionRef::from_ptr(session);
389
390 callback(ctx, session)
391}
392
393cfg_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
401pub 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
407where
408 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
409{
410 let session_ctx_index: &Index =
411 try_get_session_ctx_index().expect(msg:"BUG: session context index initialization failed");
412 let ssl: &mut SslRef = SslRef::from_ptr_mut(ptr:ssl);
413 let callback: *const F = ssl
414 .ex_data(*session_ctx_index)
415 .expect("BUG: session context missing")
416 .ex_data(SslContext::cached_ex_index::<F>())
417 .expect(msg:"BUG: get session callback missing") as *const F;
418 #[allow(clippy::unnecessary_cast)]
419 let data: &[u8] = slice::from_raw_parts(data as *const u8, len as usize);
420
421 match (*callback)(ssl, data) {
422 Some(session: SslSession) => {
423 let p: *mut SSL_SESSION = session.as_ptr();
424 mem::forget(session);
425 *copy = 0;
426 p
427 }
428 None => ptr::null_mut(),
429 }
430}
431
432#[cfg(ossl111)]
433pub unsafe extern "C" fn raw_keylog<F>(ssl: *const ffi::SSL, line: *const c_char)
434where
435 F: Fn(&SslRef, &str) + 'static + Sync + Send,
436{
437 let ssl: &SslRef = SslRef::from_const_ptr(ssl);
438 let callback: &F = ssl
439 .ssl_context()
440 .ex_data(SslContext::cached_ex_index::<F>())
441 .expect(msg:"BUG: get session callback missing");
442 let line: &[u8] = CStr::from_ptr(line).to_bytes();
443 let line: &str = str::from_utf8_unchecked(line);
444
445 callback(ssl, line);
446}
447
448#[cfg(ossl111)]
449pub 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
454where
455 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
456{
457 let ssl: &mut SslRef = SslRef::from_ptr_mut(ptr:ssl);
458 let callback: *const F = ssl
459 .ssl_context()
460 .ex_data(SslContext::cached_ex_index::<F>())
461 .expect(msg:"BUG: stateless cookie generate callback missing") as *const F;
462 #[allow(clippy::unnecessary_cast)]
463 let slice: &mut [u8] = slice::from_raw_parts_mut(data:cookie as *mut u8, len:ffi::SSL_COOKIE_LENGTH as usize);
464 match (*callback)(ssl, slice) {
465 Ok(len: usize) => {
466 *cookie_len = len as size_t;
467 1
468 }
469 Err(e: ErrorStack) => {
470 e.put();
471 0
472 }
473 }
474}
475
476#[cfg(ossl111)]
477pub 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
482where
483 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
484{
485 let ssl: &mut SslRef = SslRef::from_ptr_mut(ptr:ssl);
486 let callback: *const F = ssl
487 .ssl_context()
488 .ex_data(SslContext::cached_ex_index::<F>())
489 .expect(msg:"BUG: stateless cookie verify callback missing") as *const F;
490 #[allow(clippy::unnecessary_cast)]
491 let slice: &[u8] = slice::from_raw_parts(data:cookie as *const c_uchar as *const u8, cookie_len);
492 (*callback)(ssl, slice) as c_int
493}
494
495#[cfg(not(boringssl))]
496pub 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
501where
502 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
503{
504 unsafe {
505 let ssl: &mut SslRef = SslRef::from_ptr_mut(ptr:ssl);
506 let callback: *const F = ssl
507 .ssl_context()
508 .ex_data(SslContext::cached_ex_index::<F>())
509 .expect(msg:"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: &mut [u8] =
514 slice::from_raw_parts_mut(data:cookie as *mut u8, len:ffi::DTLS1_COOKIE_LENGTH as usize - 1);
515 match (*callback)(ssl, slice) {
516 Ok(len: usize) => {
517 *cookie_len = len as c_uint;
518 1
519 }
520 Err(e: ErrorStack) => {
521 e.put();
522 0
523 }
524 }
525 }
526}
527
528#[cfg(not(boringssl))]
529cfg_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))]
538pub extern "C" fn raw_cookie_verify<F>(
539 ssl: *mut ffi::SSL,
540 cookie: CookiePtr,
541 cookie_len: c_uint,
542) -> c_int
543where
544 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
545{
546 unsafe {
547 let ssl: &mut SslRef = SslRef::from_ptr_mut(ptr:ssl);
548 let callback: *const F = ssl
549 .ssl_context()
550 .ex_data(SslContext::cached_ex_index::<F>())
551 .expect(msg:"BUG: cookie verify callback missing") as *const F;
552 #[allow(clippy::unnecessary_cast)]
553 let slice: &[u8] =
554 slice::from_raw_parts(data: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)]
560pub struct CustomExtAddState<T>(Option<T>);
561
562#[cfg(ossl111)]
563pub 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
574where
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)]
622pub 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: &mut SslRef = SslRef::from_ptr_mut(ptr:ssl);
633 let idx: Index> = Ssl::cached_ex_index::<CustomExtAddState<T>>();
634 if let Some(state: &mut CustomExtAddState) = ssl.ex_data_mut(index:idx) {
635 state.0 = None;
636 }
637 }
638}
639
640#[cfg(ossl111)]
641pub 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
652where
653 F: Fn(&mut SslRef, ExtensionContext, &[u8], Option<(usize, &X509Ref)>) -> Result<(), SslAlert>
654 + 'static
655 + Sync
656 + Send,
657{
658 unsafe {
659 let ssl: &mut SslRef = SslRef::from_ptr_mut(ptr:ssl);
660 let callback: *const F = ssl
661 .ssl_context()
662 .ex_data(SslContext::cached_ex_index::<F>())
663 .expect(msg:"BUG: custom ext parse callback missing") as *const F;
664 let ectx: ExtensionContext = ExtensionContext::from_bits_truncate(bits:context);
665 #[allow(clippy::unnecessary_cast)]
666 let slice: &[u8] = slice::from_raw_parts(data:input as *const u8, len:inlen);
667 let cert: Option<(usize, &X509Ref)> = 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: SslAlert) => {
675 *al = alert.0;
676 0
677 }
678 }
679 }
680}
681
682#[cfg(ossl111)]
683pub 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
688where
689 F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack>
690 + 'static
691 + Sync
692 + Send,
693{
694 let ssl: &mut SslRef = SslRef::from_ptr_mut(ptr:ssl);
695 let callback: *const F = arg as *const F;
696 let mut alert: SslAlert = SslAlert(*al);
697
698 let r: Result = (*callback)(ssl, &mut alert);
699 *al = alert.0;
700 match r {
701 Ok(c: ClientHelloResponse) => c.0,
702 Err(e: ErrorStack) => {
703 e.put();
704 ffi::SSL_CLIENT_HELLO_ERROR
705 }
706 }
707}
708