1 // Copyright (C) 2018-2019, Cloudflare, Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright notice,
9 //       this list of conditions and the following disclaimer.
10 //
11 //     * Redistributions in binary form must reproduce the above copyright
12 //       notice, this list of conditions and the following disclaimer in the
13 //       documentation and/or other materials provided with the distribution.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 use std::ffi;
28 use std::ptr;
29 use std::slice;
30 
31 use std::io::Write;
32 
33 use libc::c_char;
34 use libc::c_int;
35 use libc::c_long;
36 use libc::c_uint;
37 use libc::c_void;
38 
39 use crate::Error;
40 use crate::Result;
41 
42 use crate::Connection;
43 use crate::ConnectionError;
44 
45 use crate::crypto;
46 use crate::octets;
47 use crate::packet;
48 
49 const TLS1_3_VERSION: u16 = 0x0304;
50 const TLS_ALERT_ERROR: u64 = 0x100;
51 
52 #[allow(non_camel_case_types)]
53 #[repr(transparent)]
54 struct SSL_METHOD(c_void);
55 
56 #[allow(non_camel_case_types)]
57 #[repr(transparent)]
58 struct SSL_CTX(c_void);
59 
60 #[allow(non_camel_case_types)]
61 #[repr(transparent)]
62 struct SSL(c_void);
63 
64 #[allow(non_camel_case_types)]
65 #[repr(transparent)]
66 struct SSL_CIPHER(c_void);
67 
68 #[allow(non_camel_case_types)]
69 #[repr(transparent)]
70 struct SSL_SESSION(c_void);
71 
72 #[allow(non_camel_case_types)]
73 #[repr(transparent)]
74 struct X509_VERIFY_PARAM(c_void);
75 
76 #[allow(non_camel_case_types)]
77 #[repr(transparent)]
78 #[cfg(windows)]
79 struct X509_STORE(c_void);
80 
81 #[allow(non_camel_case_types)]
82 #[repr(transparent)]
83 #[cfg(windows)]
84 struct X509(c_void);
85 
86 #[allow(non_camel_case_types)]
87 #[repr(transparent)]
88 struct STACK_OF(c_void);
89 
90 #[allow(non_camel_case_types)]
91 #[repr(transparent)]
92 struct CRYPTO_BUFFER(c_void);
93 
94 #[repr(C)]
95 #[allow(non_camel_case_types)]
96 struct SSL_QUIC_METHOD {
97     set_read_secret: extern fn(
98         ssl: *mut SSL,
99         level: crypto::Level,
100         cipher: *const SSL_CIPHER,
101         secret: *const u8,
102         secret_len: usize,
103     ) -> c_int,
104 
105     set_write_secret: extern fn(
106         ssl: *mut SSL,
107         level: crypto::Level,
108         cipher: *const SSL_CIPHER,
109         secret: *const u8,
110         secret_len: usize,
111     ) -> c_int,
112 
113     add_handshake_data: extern fn(
114         ssl: *mut SSL,
115         level: crypto::Level,
116         data: *const u8,
117         len: usize,
118     ) -> c_int,
119 
120     flush_flight: extern fn(ssl: *mut SSL) -> c_int,
121 
122     send_alert:
123         extern fn(ssl: *mut SSL, level: crypto::Level, alert: u8) -> c_int,
124 }
125 
126 lazy_static::lazy_static! {
127     static ref QUICHE_EX_DATA_INDEX: c_int = unsafe {
128         SSL_get_ex_new_index(0, ptr::null(), ptr::null(), ptr::null(), ptr::null())
129     };
130 }
131 
132 static QUICHE_STREAM_METHOD: SSL_QUIC_METHOD = SSL_QUIC_METHOD {
133     set_read_secret,
134     set_write_secret,
135     add_handshake_data,
136     flush_flight,
137     send_alert,
138 };
139 
140 pub struct Context(*mut SSL_CTX);
141 
142 impl Context {
new() -> Result<Context>143     pub fn new() -> Result<Context> {
144         unsafe {
145             let ctx_raw = SSL_CTX_new(TLS_method());
146 
147             let mut ctx = Context(ctx_raw);
148 
149             ctx.set_session_callback();
150 
151             ctx.load_ca_certs()?;
152 
153             Ok(ctx)
154         }
155     }
156 
new_handshake(&mut self) -> Result<Handshake>157     pub fn new_handshake(&mut self) -> Result<Handshake> {
158         unsafe {
159             let ssl = SSL_new(self.as_ptr());
160             Ok(Handshake(ssl))
161         }
162     }
163 
load_verify_locations_from_file(&mut self, file: &str) -> Result<()>164     pub fn load_verify_locations_from_file(&mut self, file: &str) -> Result<()> {
165         let file = ffi::CString::new(file).map_err(|_| Error::TlsFail)?;
166         map_result(unsafe {
167             SSL_CTX_load_verify_locations(
168                 self.as_ptr(),
169                 file.as_ptr(),
170                 std::ptr::null(),
171             )
172         })
173     }
174 
load_verify_locations_from_directory( &mut self, path: &str, ) -> Result<()>175     pub fn load_verify_locations_from_directory(
176         &mut self, path: &str,
177     ) -> Result<()> {
178         let path = ffi::CString::new(path).map_err(|_| Error::TlsFail)?;
179         map_result(unsafe {
180             SSL_CTX_load_verify_locations(
181                 self.as_ptr(),
182                 std::ptr::null(),
183                 path.as_ptr(),
184             )
185         })
186     }
187 
use_certificate_chain_file(&mut self, file: &str) -> Result<()>188     pub fn use_certificate_chain_file(&mut self, file: &str) -> Result<()> {
189         let cstr = ffi::CString::new(file).map_err(|_| Error::TlsFail)?;
190         map_result(unsafe {
191             SSL_CTX_use_certificate_chain_file(self.as_ptr(), cstr.as_ptr())
192         })
193     }
194 
use_privkey_file(&mut self, file: &str) -> Result<()>195     pub fn use_privkey_file(&mut self, file: &str) -> Result<()> {
196         let cstr = ffi::CString::new(file).map_err(|_| Error::TlsFail)?;
197         map_result(unsafe {
198             SSL_CTX_use_PrivateKey_file(self.as_ptr(), cstr.as_ptr(), 1)
199         })
200     }
201 
202     #[cfg(not(windows))]
load_ca_certs(&mut self) -> Result<()>203     fn load_ca_certs(&mut self) -> Result<()> {
204         unsafe { map_result(SSL_CTX_set_default_verify_paths(self.as_ptr())) }
205     }
206 
207     #[cfg(windows)]
load_ca_certs(&mut self) -> Result<()>208     fn load_ca_certs(&mut self) -> Result<()> {
209         unsafe {
210             let cstr = ffi::CString::new("Root").map_err(|_| Error::TlsFail)?;
211             let sys_store = winapi::um::wincrypt::CertOpenSystemStoreA(
212                 0,
213                 cstr.as_ptr() as winapi::um::winnt::LPCSTR,
214             );
215             if sys_store.is_null() {
216                 return Err(Error::TlsFail);
217             }
218 
219             let ctx_store = SSL_CTX_get_cert_store(self.as_ptr());
220             if ctx_store.is_null() {
221                 return Err(Error::TlsFail);
222             }
223 
224             let mut ctx_p = winapi::um::wincrypt::CertEnumCertificatesInStore(
225                 sys_store,
226                 ptr::null(),
227             );
228 
229             while !ctx_p.is_null() {
230                 let in_p = (*ctx_p).pbCertEncoded as *const u8;
231 
232                 let cert = d2i_X509(
233                     ptr::null_mut(),
234                     &in_p,
235                     (*ctx_p).cbCertEncoded as i32,
236                 );
237                 if !cert.is_null() {
238                     X509_STORE_add_cert(ctx_store, cert);
239                 }
240 
241                 X509_free(cert);
242 
243                 ctx_p = winapi::um::wincrypt::CertEnumCertificatesInStore(
244                     sys_store, ctx_p,
245                 );
246             }
247 
248             // tidy up
249             winapi::um::wincrypt::CertFreeCertificateContext(ctx_p);
250             winapi::um::wincrypt::CertCloseStore(sys_store, 0);
251         }
252 
253         Ok(())
254     }
255 
set_session_callback(&mut self)256     fn set_session_callback(&mut self) {
257         unsafe {
258             // This is needed to enable the session callback on the client. On
259             // the server it doesn't do anything.
260             SSL_CTX_set_session_cache_mode(
261                 self.as_ptr(),
262                 0x0001, // SSL_SESS_CACHE_CLIENT
263             );
264 
265             SSL_CTX_sess_set_new_cb(self.as_ptr(), new_session);
266         };
267     }
268 
set_verify(&mut self, verify: bool)269     pub fn set_verify(&mut self, verify: bool) {
270         let mode = if verify {
271             0x01 // SSL_VERIFY_PEER
272         } else {
273             0x00 // SSL_VERIFY_NONE
274         };
275 
276         unsafe {
277             SSL_CTX_set_verify(self.as_ptr(), mode, ptr::null());
278         }
279     }
280 
enable_keylog(&mut self)281     pub fn enable_keylog(&mut self) {
282         unsafe {
283             SSL_CTX_set_keylog_callback(self.as_ptr(), keylog);
284         }
285     }
286 
set_alpn(&mut self, v: &[Vec<u8>]) -> Result<()>287     pub fn set_alpn(&mut self, v: &[Vec<u8>]) -> Result<()> {
288         let mut protos: Vec<u8> = Vec::new();
289 
290         for proto in v {
291             protos.push(proto.len() as u8);
292             protos.append(&mut proto.clone());
293         }
294 
295         // Configure ALPN for servers.
296         unsafe {
297             SSL_CTX_set_alpn_select_cb(
298                 self.as_ptr(),
299                 select_alpn,
300                 ptr::null_mut(),
301             );
302         }
303 
304         // Configure ALPN for clients.
305         map_result_zero_is_success(unsafe {
306             SSL_CTX_set_alpn_protos(self.as_ptr(), protos.as_ptr(), protos.len())
307         })
308     }
309 
set_ticket_key(&mut self, key: &[u8]) -> Result<()>310     pub fn set_ticket_key(&mut self, key: &[u8]) -> Result<()> {
311         map_result(unsafe {
312             SSL_CTX_set_tlsext_ticket_keys(self.as_ptr(), key.as_ptr(), key.len())
313         })
314     }
315 
set_early_data_enabled(&mut self, enabled: bool)316     pub fn set_early_data_enabled(&mut self, enabled: bool) {
317         let enabled = if enabled { 1 } else { 0 };
318 
319         unsafe {
320             SSL_CTX_set_early_data_enabled(self.as_ptr(), enabled);
321         }
322     }
323 
as_ptr(&self) -> *mut SSL_CTX324     fn as_ptr(&self) -> *mut SSL_CTX {
325         self.0
326     }
327 }
328 
329 unsafe impl std::marker::Send for Context {}
330 
331 impl Drop for Context {
drop(&mut self)332     fn drop(&mut self) {
333         unsafe { SSL_CTX_free(self.as_ptr()) }
334     }
335 }
336 
337 pub struct Handshake(*mut SSL);
338 
339 impl Handshake {
340     #[cfg(feature = "ffi")]
from_ptr(ssl: *mut c_void) -> Handshake341     pub unsafe fn from_ptr(ssl: *mut c_void) -> Handshake {
342         let ssl = ssl as *mut SSL;
343         Handshake(ssl)
344     }
345 
get_error(&self, ret_code: c_int) -> c_int346     pub fn get_error(&self, ret_code: c_int) -> c_int {
347         unsafe { SSL_get_error(self.as_ptr(), ret_code) }
348     }
349 
init(&self, conn: &Connection) -> Result<()>350     pub fn init(&self, conn: &Connection) -> Result<()> {
351         self.set_state(conn.is_server);
352 
353         self.set_ex_data(*QUICHE_EX_DATA_INDEX, conn)?;
354 
355         self.set_min_proto_version(TLS1_3_VERSION);
356         self.set_max_proto_version(TLS1_3_VERSION);
357 
358         self.set_quic_method()?;
359 
360         // TODO: the early data context should include transport parameters and
361         // HTTP/3 SETTINGS in wire format.
362         self.set_quic_early_data_context(b"quiche")?;
363 
364         self.set_quiet_shutdown(true);
365 
366         Ok(())
367     }
368 
use_legacy_codepoint(&self, use_legacy: bool)369     pub fn use_legacy_codepoint(&self, use_legacy: bool) {
370         unsafe {
371             SSL_set_quic_use_legacy_codepoint(self.as_ptr(), use_legacy as c_int);
372         }
373     }
374 
set_state(&self, is_server: bool)375     pub fn set_state(&self, is_server: bool) {
376         unsafe {
377             if is_server {
378                 SSL_set_accept_state(self.as_ptr());
379             } else {
380                 SSL_set_connect_state(self.as_ptr());
381             }
382         }
383     }
384 
set_ex_data<T>(&self, idx: c_int, data: &T) -> Result<()>385     pub fn set_ex_data<T>(&self, idx: c_int, data: &T) -> Result<()> {
386         map_result(unsafe {
387             let ptr = data as *const T as *const c_void;
388             SSL_set_ex_data(self.as_ptr(), idx, ptr)
389         })
390     }
391 
set_quic_method(&self) -> Result<()>392     pub fn set_quic_method(&self) -> Result<()> {
393         map_result(unsafe {
394             SSL_set_quic_method(self.as_ptr(), &QUICHE_STREAM_METHOD)
395         })
396     }
397 
set_quic_early_data_context(&self, context: &[u8]) -> Result<()>398     pub fn set_quic_early_data_context(&self, context: &[u8]) -> Result<()> {
399         map_result(unsafe {
400             SSL_set_quic_early_data_context(
401                 self.as_ptr(),
402                 context.as_ptr(),
403                 context.len(),
404             )
405         })
406     }
407 
set_min_proto_version(&self, version: u16)408     pub fn set_min_proto_version(&self, version: u16) {
409         unsafe { SSL_set_min_proto_version(self.as_ptr(), version) }
410     }
411 
set_max_proto_version(&self, version: u16)412     pub fn set_max_proto_version(&self, version: u16) {
413         unsafe { SSL_set_max_proto_version(self.as_ptr(), version) }
414     }
415 
set_quiet_shutdown(&self, mode: bool)416     pub fn set_quiet_shutdown(&self, mode: bool) {
417         unsafe { SSL_set_quiet_shutdown(self.as_ptr(), if mode { 1 } else { 0 }) }
418     }
419 
set_host_name(&self, name: &str) -> Result<()>420     pub fn set_host_name(&self, name: &str) -> Result<()> {
421         let cstr = ffi::CString::new(name).map_err(|_| Error::TlsFail)?;
422         map_result_ssl(self, unsafe {
423             SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr())
424         })?;
425 
426         let param = unsafe { SSL_get0_param(self.as_ptr()) };
427 
428         map_result(unsafe {
429             X509_VERIFY_PARAM_set1_host(param, cstr.as_ptr(), name.len())
430         })
431     }
432 
set_quic_transport_params(&self, buf: &[u8]) -> Result<()>433     pub fn set_quic_transport_params(&self, buf: &[u8]) -> Result<()> {
434         map_result_ssl(self, unsafe {
435             SSL_set_quic_transport_params(self.as_ptr(), buf.as_ptr(), buf.len())
436         })
437     }
438 
439     #[cfg(test)]
set_options(&mut self, opts: u32)440     pub fn set_options(&mut self, opts: u32) {
441         unsafe {
442             SSL_set_options(self.as_ptr(), opts);
443         }
444     }
445 
quic_transport_params(&self) -> &[u8]446     pub fn quic_transport_params(&self) -> &[u8] {
447         let mut ptr: *const u8 = ptr::null();
448         let mut len: usize = 0;
449 
450         unsafe {
451             SSL_get_peer_quic_transport_params(self.as_ptr(), &mut ptr, &mut len);
452         }
453 
454         if len == 0 {
455             return &mut [];
456         }
457 
458         unsafe { slice::from_raw_parts(ptr, len) }
459     }
460 
alpn_protocol(&self) -> &[u8]461     pub fn alpn_protocol(&self) -> &[u8] {
462         let mut ptr: *const u8 = ptr::null();
463         let mut len: u32 = 0;
464 
465         unsafe {
466             SSL_get0_alpn_selected(self.as_ptr(), &mut ptr, &mut len);
467         }
468 
469         if len == 0 {
470             return &mut [];
471         }
472 
473         unsafe { slice::from_raw_parts(ptr, len as usize) }
474     }
475 
set_session(&self, session: &[u8]) -> Result<()>476     pub fn set_session(&self, session: &[u8]) -> Result<()> {
477         unsafe {
478             let ctx = SSL_get_SSL_CTX(self.as_ptr());
479 
480             if ctx.is_null() {
481                 return Err(Error::TlsFail);
482             }
483 
484             let session =
485                 SSL_SESSION_from_bytes(session.as_ptr(), session.len(), ctx);
486 
487             if session.is_null() {
488                 return Err(Error::TlsFail);
489             }
490 
491             let rc = SSL_set_session(self.as_ptr(), session);
492             SSL_SESSION_free(session);
493 
494             map_result(rc)
495         }
496     }
497 
provide_data(&self, level: crypto::Level, buf: &[u8]) -> Result<()>498     pub fn provide_data(&self, level: crypto::Level, buf: &[u8]) -> Result<()> {
499         map_result_ssl(self, unsafe {
500             SSL_provide_quic_data(self.as_ptr(), level, buf.as_ptr(), buf.len())
501         })
502     }
503 
do_handshake(&self) -> Result<()>504     pub fn do_handshake(&self) -> Result<()> {
505         map_result_ssl(self, unsafe { SSL_do_handshake(self.as_ptr()) })
506     }
507 
process_post_handshake(&self) -> Result<()>508     pub fn process_post_handshake(&self) -> Result<()> {
509         map_result_ssl(self, unsafe {
510             SSL_process_quic_post_handshake(self.as_ptr())
511         })
512     }
513 
reset_early_data_reject(&self)514     pub fn reset_early_data_reject(&self) {
515         unsafe { SSL_reset_early_data_reject(self.as_ptr()) };
516     }
517 
write_level(&self) -> crypto::Level518     pub fn write_level(&self) -> crypto::Level {
519         unsafe { SSL_quic_write_level(self.as_ptr()) }
520     }
521 
cipher(&self) -> Option<crypto::Algorithm>522     pub fn cipher(&self) -> Option<crypto::Algorithm> {
523         let cipher =
524             map_result_ptr(unsafe { SSL_get_current_cipher(self.as_ptr()) });
525 
526         get_cipher_from_ptr(cipher.ok()?).ok()
527     }
528 
curve(&self) -> Option<String>529     pub fn curve(&self) -> Option<String> {
530         let curve = unsafe {
531             let curve_id = SSL_get_curve_id(self.as_ptr());
532             if curve_id == 0 {
533                 return None;
534             }
535 
536             let curve_name = SSL_get_curve_name(curve_id);
537             match std::ffi::CStr::from_ptr(curve_name).to_str() {
538                 Ok(v) => v,
539 
540                 Err(_) => return None,
541             }
542         };
543 
544         Some(curve.to_string())
545     }
546 
sigalg(&self) -> Option<String>547     pub fn sigalg(&self) -> Option<String> {
548         let sigalg = unsafe {
549             let sigalg_id = SSL_get_peer_signature_algorithm(self.as_ptr());
550             if sigalg_id == 0 {
551                 return None;
552             }
553 
554             let sigalg_name = SSL_get_signature_algorithm_name(sigalg_id, 1);
555             match std::ffi::CStr::from_ptr(sigalg_name).to_str() {
556                 Ok(v) => v,
557 
558                 Err(_) => return None,
559             }
560         };
561 
562         Some(sigalg.to_string())
563     }
564 
peer_cert(&self) -> Option<Vec<u8>>565     pub fn peer_cert(&self) -> Option<Vec<u8>> {
566         let peer_cert = unsafe {
567             let chain =
568                 map_result_ptr(SSL_get0_peer_certificates(self.as_ptr())).ok()?;
569             if sk_num(chain) <= 0 {
570                 return None;
571             }
572 
573             let buffer =
574                 map_result_ptr(sk_value(chain, 0) as *const CRYPTO_BUFFER)
575                     .ok()?;
576             let out_len = CRYPTO_BUFFER_len(buffer);
577             if out_len == 0 {
578                 return None;
579             }
580 
581             let out = CRYPTO_BUFFER_data(buffer);
582             let der = slice::from_raw_parts(out, out_len as usize);
583             der.to_vec()
584         };
585 
586         Some(peer_cert)
587     }
588 
is_completed(&self) -> bool589     pub fn is_completed(&self) -> bool {
590         unsafe { SSL_in_init(self.as_ptr()) == 0 }
591     }
592 
is_resumed(&self) -> bool593     pub fn is_resumed(&self) -> bool {
594         unsafe { SSL_session_reused(self.as_ptr()) == 1 }
595     }
596 
is_in_early_data(&self) -> bool597     pub fn is_in_early_data(&self) -> bool {
598         unsafe { SSL_in_early_data(self.as_ptr()) == 1 }
599     }
600 
clear(&mut self) -> Result<()>601     pub fn clear(&mut self) -> Result<()> {
602         map_result_ssl(self, unsafe { SSL_clear(self.as_ptr()) })
603     }
604 
as_ptr(&self) -> *mut SSL605     fn as_ptr(&self) -> *mut SSL {
606         self.0
607     }
608 }
609 
610 unsafe impl std::marker::Send for Handshake {}
611 
612 impl Drop for Handshake {
drop(&mut self)613     fn drop(&mut self) {
614         unsafe { SSL_free(self.as_ptr()) }
615     }
616 }
617 
get_ex_data_from_ptr<'a, T>(ptr: *mut SSL, idx: c_int) -> Option<&'a mut T>618 fn get_ex_data_from_ptr<'a, T>(ptr: *mut SSL, idx: c_int) -> Option<&'a mut T> {
619     unsafe {
620         let data = SSL_get_ex_data(ptr, idx) as *mut T;
621         data.as_mut()
622     }
623 }
624 
get_cipher_from_ptr(cipher: *const SSL_CIPHER) -> Result<crypto::Algorithm>625 fn get_cipher_from_ptr(cipher: *const SSL_CIPHER) -> Result<crypto::Algorithm> {
626     let cipher_id = unsafe { SSL_CIPHER_get_id(cipher) };
627 
628     let alg = match cipher_id {
629         0x0300_1301 => crypto::Algorithm::AES128_GCM,
630         0x0300_1302 => crypto::Algorithm::AES256_GCM,
631         0x0300_1303 => crypto::Algorithm::ChaCha20_Poly1305,
632         _ => return Err(Error::TlsFail),
633     };
634 
635     Ok(alg)
636 }
637 
set_read_secret( ssl: *mut SSL, level: crypto::Level, cipher: *const SSL_CIPHER, secret: *const u8, secret_len: usize, ) -> c_int638 extern fn set_read_secret(
639     ssl: *mut SSL, level: crypto::Level, cipher: *const SSL_CIPHER,
640     secret: *const u8, secret_len: usize,
641 ) -> c_int {
642     let conn =
643         match get_ex_data_from_ptr::<Connection>(ssl, *QUICHE_EX_DATA_INDEX) {
644             Some(v) => v,
645 
646             None => return 0,
647         };
648 
649     trace!("{} set read secret lvl={:?}", conn.trace_id, level);
650 
651     let space = match level {
652         crypto::Level::Initial => &mut conn.pkt_num_spaces[packet::EPOCH_INITIAL],
653         crypto::Level::ZeroRTT =>
654             &mut conn.pkt_num_spaces[packet::EPOCH_APPLICATION],
655         crypto::Level::Handshake =>
656             &mut conn.pkt_num_spaces[packet::EPOCH_HANDSHAKE],
657         crypto::Level::OneRTT =>
658             &mut conn.pkt_num_spaces[packet::EPOCH_APPLICATION],
659     };
660 
661     let aead = match get_cipher_from_ptr(cipher) {
662         Ok(v) => v,
663 
664         Err(_) => return 0,
665     };
666 
667     // 0-RTT read secrets are present only on the server.
668     if level != crypto::Level::ZeroRTT || conn.is_server {
669         let secret = unsafe { slice::from_raw_parts(secret, secret_len) };
670 
671         let open = match crypto::Open::from_secret(aead, &secret) {
672             Ok(v) => v,
673 
674             Err(_) => return 0,
675         };
676 
677         if level == crypto::Level::ZeroRTT {
678             space.crypto_0rtt_open = Some(open);
679             return 1;
680         }
681 
682         space.crypto_open = Some(open);
683     }
684 
685     1
686 }
687 
set_write_secret( ssl: *mut SSL, level: crypto::Level, cipher: *const SSL_CIPHER, secret: *const u8, secret_len: usize, ) -> c_int688 extern fn set_write_secret(
689     ssl: *mut SSL, level: crypto::Level, cipher: *const SSL_CIPHER,
690     secret: *const u8, secret_len: usize,
691 ) -> c_int {
692     let conn =
693         match get_ex_data_from_ptr::<Connection>(ssl, *QUICHE_EX_DATA_INDEX) {
694             Some(v) => v,
695 
696             None => return 0,
697         };
698 
699     trace!("{} set write secret lvl={:?}", conn.trace_id, level);
700 
701     let space = match level {
702         crypto::Level::Initial => &mut conn.pkt_num_spaces[packet::EPOCH_INITIAL],
703         crypto::Level::ZeroRTT =>
704             &mut conn.pkt_num_spaces[packet::EPOCH_APPLICATION],
705         crypto::Level::Handshake =>
706             &mut conn.pkt_num_spaces[packet::EPOCH_HANDSHAKE],
707         crypto::Level::OneRTT =>
708             &mut conn.pkt_num_spaces[packet::EPOCH_APPLICATION],
709     };
710 
711     let aead = match get_cipher_from_ptr(cipher) {
712         Ok(v) => v,
713 
714         Err(_) => return 0,
715     };
716 
717     // 0-RTT write secrets are present only on the client.
718     if level != crypto::Level::ZeroRTT || !conn.is_server {
719         let secret = unsafe { slice::from_raw_parts(secret, secret_len) };
720 
721         let seal = match crypto::Seal::from_secret(aead, &secret) {
722             Ok(v) => v,
723 
724             Err(_) => return 0,
725         };
726 
727         space.crypto_seal = Some(seal);
728     }
729 
730     1
731 }
732 
add_handshake_data( ssl: *mut SSL, level: crypto::Level, data: *const u8, len: usize, ) -> c_int733 extern fn add_handshake_data(
734     ssl: *mut SSL, level: crypto::Level, data: *const u8, len: usize,
735 ) -> c_int {
736     let conn =
737         match get_ex_data_from_ptr::<Connection>(ssl, *QUICHE_EX_DATA_INDEX) {
738             Some(v) => v,
739 
740             None => return 0,
741         };
742 
743     trace!(
744         "{} write message lvl={:?} len={}",
745         conn.trace_id,
746         level,
747         len
748     );
749 
750     let buf = unsafe { slice::from_raw_parts(data, len) };
751 
752     let space = match level {
753         crypto::Level::Initial => &mut conn.pkt_num_spaces[packet::EPOCH_INITIAL],
754         crypto::Level::ZeroRTT => unreachable!(),
755         crypto::Level::Handshake =>
756             &mut conn.pkt_num_spaces[packet::EPOCH_HANDSHAKE],
757         crypto::Level::OneRTT =>
758             &mut conn.pkt_num_spaces[packet::EPOCH_APPLICATION],
759     };
760 
761     if space.crypto_stream.send.write(buf, false).is_err() {
762         return 0;
763     }
764 
765     1
766 }
767 
flush_flight(_ssl: *mut SSL) -> c_int768 extern fn flush_flight(_ssl: *mut SSL) -> c_int {
769     // We don't really need to anything here since the output packets are
770     // generated separately, when conn.send() is called.
771 
772     1
773 }
774 
send_alert(ssl: *mut SSL, level: crypto::Level, alert: u8) -> c_int775 extern fn send_alert(ssl: *mut SSL, level: crypto::Level, alert: u8) -> c_int {
776     let conn =
777         match get_ex_data_from_ptr::<Connection>(ssl, *QUICHE_EX_DATA_INDEX) {
778             Some(v) => v,
779 
780             None => return 0,
781         };
782 
783     trace!(
784         "{} send alert lvl={:?} alert={:x}",
785         conn.trace_id,
786         level,
787         alert
788     );
789 
790     let error: u64 = TLS_ALERT_ERROR + u64::from(alert);
791     conn.local_error = Some(ConnectionError {
792         is_app: false,
793         error_code: error,
794         reason: Vec::new(),
795     });
796 
797     1
798 }
799 
keylog(ssl: *mut SSL, line: *const c_char)800 extern fn keylog(ssl: *mut SSL, line: *const c_char) {
801     let conn =
802         match get_ex_data_from_ptr::<Connection>(ssl, *QUICHE_EX_DATA_INDEX) {
803             Some(v) => v,
804 
805             None => return,
806         };
807 
808     if let Some(keylog) = &mut conn.keylog {
809         let data = unsafe { ffi::CStr::from_ptr(line).to_bytes() };
810 
811         let mut full_line = Vec::with_capacity(data.len() + 1);
812         full_line.extend_from_slice(data);
813         full_line.push(b'\n');
814 
815         keylog.write_all(&full_line[..]).ok();
816     }
817 }
818 
select_alpn( ssl: *mut SSL, out: *mut *const u8, out_len: *mut u8, inp: *mut u8, in_len: c_uint, _arg: *mut c_void, ) -> c_int819 extern fn select_alpn(
820     ssl: *mut SSL, out: *mut *const u8, out_len: *mut u8, inp: *mut u8,
821     in_len: c_uint, _arg: *mut c_void,
822 ) -> c_int {
823     let conn =
824         match get_ex_data_from_ptr::<Connection>(ssl, *QUICHE_EX_DATA_INDEX) {
825             Some(v) => v,
826 
827             None => return 3, // SSL_TLSEXT_ERR_NOACK
828         };
829 
830     if conn.application_protos.is_empty() {
831         return 3; // SSL_TLSEXT_ERR_NOACK
832     }
833 
834     let mut protos = octets::Octets::with_slice(unsafe {
835         slice::from_raw_parts(inp, in_len as usize)
836     });
837 
838     while let Ok(proto) = protos.get_bytes_with_u8_length() {
839         let found = conn.application_protos.iter().any(|expected| {
840             trace!(
841                 "checking peer ALPN {:?} against {:?}",
842                 std::str::from_utf8(proto.as_ref()),
843                 std::str::from_utf8(expected.as_slice())
844             );
845 
846             if expected.len() == proto.len() &&
847                 expected.as_slice() == proto.as_ref()
848             {
849                 unsafe {
850                     *out = expected.as_slice().as_ptr();
851                     *out_len = expected.len() as u8;
852                 }
853 
854                 return true;
855             }
856 
857             false
858         });
859 
860         if found {
861             return 0; // SSL_TLSEXT_ERR_OK
862         }
863     }
864 
865     3 // SSL_TLSEXT_ERR_NOACK
866 }
867 
868 #[no_mangle]
new_session(ssl: *mut SSL, session: *mut SSL_SESSION) -> c_int869 extern fn new_session(ssl: *mut SSL, session: *mut SSL_SESSION) -> c_int {
870     let conn =
871         match get_ex_data_from_ptr::<Connection>(ssl, *QUICHE_EX_DATA_INDEX) {
872             Some(v) => v,
873 
874             None => return 0,
875         };
876 
877     let handshake = Handshake(ssl);
878     let peer_params = handshake.quic_transport_params();
879 
880     // Serialize session object into buffer.
881     let session_bytes = unsafe {
882         let mut out: *mut u8 = std::ptr::null_mut();
883         let mut out_len: usize = 0;
884 
885         if SSL_SESSION_to_bytes(session, &mut out, &mut out_len) == 0 {
886             return 0;
887         }
888 
889         let session_bytes = std::slice::from_raw_parts(out, out_len).to_vec();
890         OPENSSL_free(out as *mut c_void);
891 
892         session_bytes
893     };
894 
895     let mut buffer =
896         Vec::with_capacity(8 + peer_params.len() + 8 + session_bytes.len());
897 
898     let session_bytes_len = session_bytes.len() as u64;
899 
900     if buffer.write(&session_bytes_len.to_be_bytes()).is_err() {
901         std::mem::forget(handshake);
902         return 0;
903     }
904 
905     if buffer.write(&session_bytes).is_err() {
906         std::mem::forget(handshake);
907         return 0;
908     }
909 
910     let peer_params_len = peer_params.len() as u64;
911 
912     if buffer.write(&peer_params_len.to_be_bytes()).is_err() {
913         std::mem::forget(handshake);
914         return 0;
915     }
916 
917     if buffer.write(&peer_params).is_err() {
918         std::mem::forget(handshake);
919         return 0;
920     }
921 
922     conn.session = Some(buffer);
923 
924     // Prevent handshake from being freed, as we still need it.
925     std::mem::forget(handshake);
926 
927     0
928 }
929 
map_result(bssl_result: c_int) -> Result<()>930 fn map_result(bssl_result: c_int) -> Result<()> {
931     match bssl_result {
932         1 => Ok(()),
933         _ => Err(Error::TlsFail),
934     }
935 }
936 
map_result_zero_is_success(bssl_result: c_int) -> Result<()>937 fn map_result_zero_is_success(bssl_result: c_int) -> Result<()> {
938     match bssl_result {
939         0 => Ok(()),
940         _ => Err(Error::TlsFail),
941     }
942 }
943 
map_result_ptr<'a, T>(bssl_result: *const T) -> Result<&'a T>944 fn map_result_ptr<'a, T>(bssl_result: *const T) -> Result<&'a T> {
945     match unsafe { bssl_result.as_ref() } {
946         Some(v) => Ok(v),
947         None => Err(Error::TlsFail),
948     }
949 }
950 
map_result_ssl(ssl: &Handshake, bssl_result: c_int) -> Result<()>951 fn map_result_ssl(ssl: &Handshake, bssl_result: c_int) -> Result<()> {
952     match bssl_result {
953         1 => Ok(()),
954 
955         _ => {
956             let ssl_err = ssl.get_error(bssl_result);
957             match ssl_err {
958                 // SSL_ERROR_SSL
959                 1 => {
960                     log_ssl_error();
961 
962                     Err(Error::TlsFail)
963                 },
964 
965                 // SSL_ERROR_WANT_READ
966                 2 => Err(Error::Done),
967 
968                 // SSL_ERROR_WANT_WRITE
969                 3 => Err(Error::Done),
970 
971                 // SSL_ERROR_WANT_X509_LOOKUP
972                 4 => Err(Error::Done),
973 
974                 // SSL_ERROR_SYSCALL
975                 5 => Err(Error::TlsFail),
976 
977                 // SSL_ERROR_PENDING_SESSION
978                 11 => Err(Error::Done),
979 
980                 // SSL_ERROR_PENDING_CERTIFICATE
981                 12 => Err(Error::Done),
982 
983                 // SSL_ERROR_WANT_PRIVATE_KEY_OPERATION
984                 13 => Err(Error::Done),
985 
986                 // SSL_ERROR_PENDING_TICKET
987                 14 => Err(Error::Done),
988 
989                 // SSL_ERROR_EARLY_DATA_REJECTED
990                 15 => {
991                     ssl.reset_early_data_reject();
992                     Err(Error::Done)
993                 },
994 
995                 // SSL_ERROR_WANT_CERTIFICATE_VERIFY
996                 16 => Err(Error::Done),
997 
998                 _ => Err(Error::TlsFail),
999             }
1000         },
1001     }
1002 }
1003 
log_ssl_error()1004 fn log_ssl_error() {
1005     let err = [0; 1024];
1006 
1007     unsafe {
1008         let e = ERR_peek_error();
1009         ERR_error_string_n(e, err.as_ptr(), err.len());
1010     }
1011 
1012     trace!("{}", std::str::from_utf8(&err).unwrap());
1013 }
1014 
1015 extern {
1016     // SSL_METHOD
TLS_method() -> *const SSL_METHOD1017     fn TLS_method() -> *const SSL_METHOD;
1018 
1019     // SSL_CTX
SSL_CTX_new(method: *const SSL_METHOD) -> *mut SSL_CTX1020     fn SSL_CTX_new(method: *const SSL_METHOD) -> *mut SSL_CTX;
SSL_CTX_free(ctx: *mut SSL_CTX)1021     fn SSL_CTX_free(ctx: *mut SSL_CTX);
1022 
SSL_CTX_use_certificate_chain_file( ctx: *mut SSL_CTX, file: *const c_char, ) -> c_int1023     fn SSL_CTX_use_certificate_chain_file(
1024         ctx: *mut SSL_CTX, file: *const c_char,
1025     ) -> c_int;
1026 
SSL_CTX_use_PrivateKey_file( ctx: *mut SSL_CTX, file: *const c_char, ty: c_int, ) -> c_int1027     fn SSL_CTX_use_PrivateKey_file(
1028         ctx: *mut SSL_CTX, file: *const c_char, ty: c_int,
1029     ) -> c_int;
1030 
SSL_CTX_load_verify_locations( ctx: *mut SSL_CTX, file: *const c_char, path: *const c_char, ) -> c_int1031     fn SSL_CTX_load_verify_locations(
1032         ctx: *mut SSL_CTX, file: *const c_char, path: *const c_char,
1033     ) -> c_int;
1034 
1035     #[cfg(not(windows))]
SSL_CTX_set_default_verify_paths(ctx: *mut SSL_CTX) -> c_int1036     fn SSL_CTX_set_default_verify_paths(ctx: *mut SSL_CTX) -> c_int;
1037 
1038     #[cfg(windows)]
SSL_CTX_get_cert_store(ctx: *mut SSL_CTX) -> *mut X509_STORE1039     fn SSL_CTX_get_cert_store(ctx: *mut SSL_CTX) -> *mut X509_STORE;
1040 
SSL_CTX_set_verify(ctx: *mut SSL_CTX, mode: c_int, cb: *const c_void)1041     fn SSL_CTX_set_verify(ctx: *mut SSL_CTX, mode: c_int, cb: *const c_void);
1042 
SSL_CTX_set_keylog_callback( ctx: *mut SSL_CTX, cb: extern fn(ssl: *mut SSL, line: *const c_char), )1043     fn SSL_CTX_set_keylog_callback(
1044         ctx: *mut SSL_CTX, cb: extern fn(ssl: *mut SSL, line: *const c_char),
1045     );
1046 
SSL_CTX_set_tlsext_ticket_keys( ctx: *mut SSL_CTX, key: *const u8, key_len: usize, ) -> c_int1047     fn SSL_CTX_set_tlsext_ticket_keys(
1048         ctx: *mut SSL_CTX, key: *const u8, key_len: usize,
1049     ) -> c_int;
1050 
SSL_CTX_set_alpn_protos( ctx: *mut SSL_CTX, protos: *const u8, protos_len: usize, ) -> c_int1051     fn SSL_CTX_set_alpn_protos(
1052         ctx: *mut SSL_CTX, protos: *const u8, protos_len: usize,
1053     ) -> c_int;
1054 
SSL_CTX_set_alpn_select_cb( ctx: *mut SSL_CTX, cb: extern fn( ssl: *mut SSL, out: *mut *const u8, out_len: *mut u8, inp: *mut u8, in_len: c_uint, arg: *mut c_void, ) -> c_int, arg: *mut c_void, )1055     fn SSL_CTX_set_alpn_select_cb(
1056         ctx: *mut SSL_CTX,
1057         cb: extern fn(
1058             ssl: *mut SSL,
1059             out: *mut *const u8,
1060             out_len: *mut u8,
1061             inp: *mut u8,
1062             in_len: c_uint,
1063             arg: *mut c_void,
1064         ) -> c_int,
1065         arg: *mut c_void,
1066     );
1067 
SSL_CTX_set_early_data_enabled(ctx: *mut SSL_CTX, enabled: i32)1068     fn SSL_CTX_set_early_data_enabled(ctx: *mut SSL_CTX, enabled: i32);
1069 
SSL_CTX_set_session_cache_mode(ctx: *mut SSL_CTX, mode: c_int) -> c_int1070     fn SSL_CTX_set_session_cache_mode(ctx: *mut SSL_CTX, mode: c_int) -> c_int;
1071 
SSL_CTX_sess_set_new_cb( ctx: *mut SSL_CTX, cb: extern fn(ssl: *mut SSL, session: *mut SSL_SESSION) -> c_int, )1072     fn SSL_CTX_sess_set_new_cb(
1073         ctx: *mut SSL_CTX,
1074         cb: extern fn(ssl: *mut SSL, session: *mut SSL_SESSION) -> c_int,
1075     );
1076 
1077     // SSL
SSL_get_ex_new_index( argl: c_long, argp: *const c_void, unused: *const c_void, dup_unused: *const c_void, free_func: *const c_void, ) -> c_int1078     fn SSL_get_ex_new_index(
1079         argl: c_long, argp: *const c_void, unused: *const c_void,
1080         dup_unused: *const c_void, free_func: *const c_void,
1081     ) -> c_int;
1082 
SSL_new(ctx: *mut SSL_CTX) -> *mut SSL1083     fn SSL_new(ctx: *mut SSL_CTX) -> *mut SSL;
1084 
SSL_get_error(ssl: *mut SSL, ret_code: c_int) -> c_int1085     fn SSL_get_error(ssl: *mut SSL, ret_code: c_int) -> c_int;
1086 
SSL_set_accept_state(ssl: *mut SSL)1087     fn SSL_set_accept_state(ssl: *mut SSL);
SSL_set_connect_state(ssl: *mut SSL)1088     fn SSL_set_connect_state(ssl: *mut SSL);
1089 
SSL_get0_param(ssl: *mut SSL) -> *mut X509_VERIFY_PARAM1090     fn SSL_get0_param(ssl: *mut SSL) -> *mut X509_VERIFY_PARAM;
1091 
SSL_set_ex_data(ssl: *mut SSL, idx: c_int, ptr: *const c_void) -> c_int1092     fn SSL_set_ex_data(ssl: *mut SSL, idx: c_int, ptr: *const c_void) -> c_int;
SSL_get_ex_data(ssl: *mut SSL, idx: c_int) -> *mut c_void1093     fn SSL_get_ex_data(ssl: *mut SSL, idx: c_int) -> *mut c_void;
1094 
SSL_get_current_cipher(ssl: *mut SSL) -> *const SSL_CIPHER1095     fn SSL_get_current_cipher(ssl: *mut SSL) -> *const SSL_CIPHER;
1096 
SSL_get_curve_id(ssl: *mut SSL) -> u161097     fn SSL_get_curve_id(ssl: *mut SSL) -> u16;
SSL_get_curve_name(curve: u16) -> *const c_char1098     fn SSL_get_curve_name(curve: u16) -> *const c_char;
1099 
SSL_get_peer_signature_algorithm(ssl: *mut SSL) -> u161100     fn SSL_get_peer_signature_algorithm(ssl: *mut SSL) -> u16;
SSL_get_signature_algorithm_name( sigalg: u16, include_curve: i32, ) -> *const c_char1101     fn SSL_get_signature_algorithm_name(
1102         sigalg: u16, include_curve: i32,
1103     ) -> *const c_char;
1104 
SSL_set_session(ssl: *mut SSL, session: *mut SSL_SESSION) -> c_int1105     fn SSL_set_session(ssl: *mut SSL, session: *mut SSL_SESSION) -> c_int;
1106 
SSL_get_SSL_CTX(ssl: *mut SSL) -> *mut SSL_CTX1107     fn SSL_get_SSL_CTX(ssl: *mut SSL) -> *mut SSL_CTX;
1108 
SSL_get0_peer_certificates(ssl: *mut SSL) -> *const STACK_OF1109     fn SSL_get0_peer_certificates(ssl: *mut SSL) -> *const STACK_OF;
1110 
SSL_set_min_proto_version(ssl: *mut SSL, version: u16)1111     fn SSL_set_min_proto_version(ssl: *mut SSL, version: u16);
SSL_set_max_proto_version(ssl: *mut SSL, version: u16)1112     fn SSL_set_max_proto_version(ssl: *mut SSL, version: u16);
1113 
SSL_set_quiet_shutdown(ssl: *mut SSL, mode: c_int)1114     fn SSL_set_quiet_shutdown(ssl: *mut SSL, mode: c_int);
1115 
SSL_set_tlsext_host_name(ssl: *mut SSL, name: *const c_char) -> c_int1116     fn SSL_set_tlsext_host_name(ssl: *mut SSL, name: *const c_char) -> c_int;
1117 
SSL_set_quic_transport_params( ssl: *mut SSL, params: *const u8, params_len: usize, ) -> c_int1118     fn SSL_set_quic_transport_params(
1119         ssl: *mut SSL, params: *const u8, params_len: usize,
1120     ) -> c_int;
1121 
1122     #[cfg(test)]
SSL_set_options(ssl: *mut SSL, opts: u32) -> u321123     fn SSL_set_options(ssl: *mut SSL, opts: u32) -> u32;
1124 
SSL_set_quic_method( ssl: *mut SSL, quic_method: *const SSL_QUIC_METHOD, ) -> c_int1125     fn SSL_set_quic_method(
1126         ssl: *mut SSL, quic_method: *const SSL_QUIC_METHOD,
1127     ) -> c_int;
1128 
SSL_set_quic_use_legacy_codepoint(ssl: *mut SSL, use_legacy: c_int)1129     fn SSL_set_quic_use_legacy_codepoint(ssl: *mut SSL, use_legacy: c_int);
1130 
SSL_set_quic_early_data_context( ssl: *mut SSL, context: *const u8, context_len: usize, ) -> c_int1131     fn SSL_set_quic_early_data_context(
1132         ssl: *mut SSL, context: *const u8, context_len: usize,
1133     ) -> c_int;
1134 
SSL_get_peer_quic_transport_params( ssl: *mut SSL, out_params: *mut *const u8, out_params_len: *mut usize, )1135     fn SSL_get_peer_quic_transport_params(
1136         ssl: *mut SSL, out_params: *mut *const u8, out_params_len: *mut usize,
1137     );
1138 
SSL_get0_alpn_selected( ssl: *mut SSL, out: *mut *const u8, out_len: *mut u32, )1139     fn SSL_get0_alpn_selected(
1140         ssl: *mut SSL, out: *mut *const u8, out_len: *mut u32,
1141     );
1142 
SSL_provide_quic_data( ssl: *mut SSL, level: crypto::Level, data: *const u8, len: usize, ) -> c_int1143     fn SSL_provide_quic_data(
1144         ssl: *mut SSL, level: crypto::Level, data: *const u8, len: usize,
1145     ) -> c_int;
1146 
SSL_process_quic_post_handshake(ssl: *mut SSL) -> c_int1147     fn SSL_process_quic_post_handshake(ssl: *mut SSL) -> c_int;
1148 
SSL_reset_early_data_reject(ssl: *mut SSL)1149     fn SSL_reset_early_data_reject(ssl: *mut SSL);
1150 
SSL_do_handshake(ssl: *mut SSL) -> c_int1151     fn SSL_do_handshake(ssl: *mut SSL) -> c_int;
1152 
SSL_quic_write_level(ssl: *mut SSL) -> crypto::Level1153     fn SSL_quic_write_level(ssl: *mut SSL) -> crypto::Level;
1154 
SSL_session_reused(ssl: *mut SSL) -> c_int1155     fn SSL_session_reused(ssl: *mut SSL) -> c_int;
1156 
SSL_in_init(ssl: *mut SSL) -> c_int1157     fn SSL_in_init(ssl: *mut SSL) -> c_int;
1158 
SSL_in_early_data(ssl: *mut SSL) -> c_int1159     fn SSL_in_early_data(ssl: *mut SSL) -> c_int;
1160 
SSL_clear(ssl: *mut SSL) -> c_int1161     fn SSL_clear(ssl: *mut SSL) -> c_int;
1162 
SSL_free(ssl: *mut SSL)1163     fn SSL_free(ssl: *mut SSL);
1164 
1165     // SSL_CIPHER
SSL_CIPHER_get_id(cipher: *const SSL_CIPHER) -> c_uint1166     fn SSL_CIPHER_get_id(cipher: *const SSL_CIPHER) -> c_uint;
1167 
1168     // SSL_SESSION
SSL_SESSION_to_bytes( session: *const SSL_SESSION, out: *mut *mut u8, out_len: *mut usize, ) -> c_int1169     fn SSL_SESSION_to_bytes(
1170         session: *const SSL_SESSION, out: *mut *mut u8, out_len: *mut usize,
1171     ) -> c_int;
1172 
SSL_SESSION_from_bytes( input: *const u8, input_len: usize, ctx: *const SSL_CTX, ) -> *mut SSL_SESSION1173     fn SSL_SESSION_from_bytes(
1174         input: *const u8, input_len: usize, ctx: *const SSL_CTX,
1175     ) -> *mut SSL_SESSION;
1176 
SSL_SESSION_free(session: *mut SSL_SESSION)1177     fn SSL_SESSION_free(session: *mut SSL_SESSION);
1178 
1179     // X509_VERIFY_PARAM
X509_VERIFY_PARAM_set1_host( param: *mut X509_VERIFY_PARAM, name: *const c_char, namelen: usize, ) -> c_int1180     fn X509_VERIFY_PARAM_set1_host(
1181         param: *mut X509_VERIFY_PARAM, name: *const c_char, namelen: usize,
1182     ) -> c_int;
1183 
1184     // X509_STORE
1185     #[cfg(windows)]
X509_STORE_add_cert(ctx: *mut X509_STORE, x: *mut X509) -> c_int1186     fn X509_STORE_add_cert(ctx: *mut X509_STORE, x: *mut X509) -> c_int;
1187 
1188     // X509
1189     #[cfg(windows)]
X509_free(x: *mut X509)1190     fn X509_free(x: *mut X509);
1191     #[cfg(windows)]
d2i_X509(px: *mut X509, input: *const *const u8, len: c_int) -> *mut X5091192     fn d2i_X509(px: *mut X509, input: *const *const u8, len: c_int) -> *mut X509;
1193 
1194     // STACK_OF
sk_num(stack: *const STACK_OF) -> c_int1195     fn sk_num(stack: *const STACK_OF) -> c_int;
sk_value(stack: *const STACK_OF, idx: c_int) -> *mut c_void1196     fn sk_value(stack: *const STACK_OF, idx: c_int) -> *mut c_void;
1197 
1198     // CRYPTO_BUFFER
CRYPTO_BUFFER_len(buffer: *const CRYPTO_BUFFER) -> usize1199     fn CRYPTO_BUFFER_len(buffer: *const CRYPTO_BUFFER) -> usize;
CRYPTO_BUFFER_data(buffer: *const CRYPTO_BUFFER) -> *const u81200     fn CRYPTO_BUFFER_data(buffer: *const CRYPTO_BUFFER) -> *const u8;
1201 
1202     // ERR
ERR_peek_error() -> c_uint1203     fn ERR_peek_error() -> c_uint;
1204 
ERR_error_string_n(err: c_uint, buf: *const u8, len: usize)1205     fn ERR_error_string_n(err: c_uint, buf: *const u8, len: usize);
1206 
1207     // OPENSSL
OPENSSL_free(ptr: *mut c_void)1208     fn OPENSSL_free(ptr: *mut c_void);
1209 }
1210