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