]> git.proxmox.com Git - cargo.git/blob - vendor/openssl/src/ssl/callbacks.rs
New upstream version 0.47.0
[cargo.git] / vendor / openssl / src / ssl / callbacks.rs
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
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"))]
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"))]
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
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
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))]
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
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)))]
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
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)))]
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
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
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
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
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)]
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)]
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)]
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
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
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)]
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)]
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)]
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)]
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 }