• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 libc::c_char;
32 use libc::c_int;
33 use libc::c_long;
34 use libc::c_uint;
35 use libc::c_void;
36 
37 use crate::Error;
38 use crate::Result;
39 
40 use crate::Connection;
41 
42 use crate::crypto;
43 use crate::octets;
44 use crate::packet;
45 
46 const TLS1_3_VERSION: u16 = 0x0304;
47 const TLS_ALERT_ERROR: u64 = 0x100;
48 
49 #[allow(non_camel_case_types)]
50 #[repr(transparent)]
51 struct SSL_METHOD(c_void);
52 
53 #[allow(non_camel_case_types)]
54 #[repr(transparent)]
55 struct SSL_CTX(c_void);
56 
57 #[allow(non_camel_case_types)]
58 #[repr(transparent)]
59 struct SSL(c_void);
60 
61 #[allow(non_camel_case_types)]
62 #[repr(transparent)]
63 struct SSL_CIPHER(c_void);
64 
65 #[allow(non_camel_case_types)]
66 #[repr(transparent)]
67 struct X509_VERIFY_PARAM(c_void);
68 
69 #[allow(non_camel_case_types)]
70 #[repr(transparent)]
71 #[cfg(windows)]
72 struct X509_STORE(c_void);
73 
74 #[allow(non_camel_case_types)]
75 #[repr(transparent)]
76 struct X509(c_void);
77 
78 #[repr(C)]
79 #[allow(non_camel_case_types)]
80 struct SSL_QUIC_METHOD {
81     set_read_secret: extern fn(
82         ssl: *mut SSL,
83         level: crypto::Level,
84         cipher: *const SSL_CIPHER,
85         secret: *const u8,
86         secret_len: usize,
87     ) -> c_int,
88 
89     set_write_secret: extern fn(
90         ssl: *mut SSL,
91         level: crypto::Level,
92         cipher: *const SSL_CIPHER,
93         secret: *const u8,
94         secret_len: usize,
95     ) -> c_int,
96 
97     add_handshake_data: extern fn(
98         ssl: *mut SSL,
99         level: crypto::Level,
100         data: *const u8,
101         len: usize,
102     ) -> c_int,
103 
104     flush_flight: extern fn(ssl: *mut SSL) -> c_int,
105 
106     send_alert:
107         extern fn(ssl: *mut SSL, level: crypto::Level, alert: u8) -> c_int,
108 }
109 
110 lazy_static::lazy_static! {
111     static ref QUICHE_EX_DATA_INDEX: c_int = unsafe {
112         SSL_get_ex_new_index(0, ptr::null(), ptr::null(), ptr::null(), ptr::null())
113     };
114 }
115 
116 static QUICHE_STREAM_METHOD: SSL_QUIC_METHOD = SSL_QUIC_METHOD {
117     set_read_secret,
118     set_write_secret,
119     add_handshake_data,
120     flush_flight,
121     send_alert,
122 };
123 
124 pub struct Context(*mut SSL_CTX);
125 
126 impl Context {
new() -> Result<Context>127     pub fn new() -> Result<Context> {
128         unsafe {
129             let ctx_raw = SSL_CTX_new(TLS_method());
130 
131             let mut ctx = Context(ctx_raw);
132 
133             ctx.load_ca_certs()?;
134 
135             Ok(ctx)
136         }
137     }
138 
new_handshake(&mut self) -> Result<Handshake>139     pub fn new_handshake(&mut self) -> Result<Handshake> {
140         unsafe {
141             let ssl = SSL_new(self.as_ptr());
142             Ok(Handshake(ssl))
143         }
144     }
145 
load_verify_locations_from_file(&mut self, file: &str) -> Result<()>146     pub fn load_verify_locations_from_file(&mut self, file: &str) -> Result<()> {
147         let file = ffi::CString::new(file).map_err(|_| Error::TlsFail)?;
148         map_result(unsafe {
149             SSL_CTX_load_verify_locations(
150                 self.as_ptr(),
151                 file.as_ptr(),
152                 std::ptr::null(),
153             )
154         })
155     }
156 
load_verify_locations_from_directory( &mut self, path: &str, ) -> Result<()>157     pub fn load_verify_locations_from_directory(
158         &mut self, path: &str,
159     ) -> Result<()> {
160         let path = ffi::CString::new(path).map_err(|_| Error::TlsFail)?;
161         map_result(unsafe {
162             SSL_CTX_load_verify_locations(
163                 self.as_ptr(),
164                 std::ptr::null(),
165                 path.as_ptr(),
166             )
167         })
168     }
169 
use_certificate_chain_file(&mut self, file: &str) -> Result<()>170     pub fn use_certificate_chain_file(&mut self, file: &str) -> Result<()> {
171         let cstr = ffi::CString::new(file).map_err(|_| Error::TlsFail)?;
172         map_result(unsafe {
173             SSL_CTX_use_certificate_chain_file(self.as_ptr(), cstr.as_ptr())
174         })
175     }
176 
use_privkey_file(&mut self, file: &str) -> Result<()>177     pub fn use_privkey_file(&mut self, file: &str) -> Result<()> {
178         let cstr = ffi::CString::new(file).map_err(|_| Error::TlsFail)?;
179         map_result(unsafe {
180             SSL_CTX_use_PrivateKey_file(self.as_ptr(), cstr.as_ptr(), 1)
181         })
182     }
183 
184     #[cfg(not(windows))]
load_ca_certs(&mut self) -> Result<()>185     fn load_ca_certs(&mut self) -> Result<()> {
186         unsafe { map_result(SSL_CTX_set_default_verify_paths(self.as_ptr())) }
187     }
188 
189     #[cfg(windows)]
load_ca_certs(&mut self) -> Result<()>190     fn load_ca_certs(&mut self) -> Result<()> {
191         unsafe {
192             let cstr = ffi::CString::new("Root").map_err(|_| Error::TlsFail)?;
193             let sys_store = winapi::um::wincrypt::CertOpenSystemStoreA(
194                 0,
195                 cstr.as_ptr() as winapi::um::winnt::LPCSTR,
196             );
197             if sys_store.is_null() {
198                 return Err(Error::TlsFail);
199             }
200 
201             let ctx_store = SSL_CTX_get_cert_store(self.as_ptr());
202             if ctx_store.is_null() {
203                 return Err(Error::TlsFail);
204             }
205 
206             let mut ctx_p = winapi::um::wincrypt::CertEnumCertificatesInStore(
207                 sys_store,
208                 ptr::null(),
209             );
210 
211             while !ctx_p.is_null() {
212                 let in_p = (*ctx_p).pbCertEncoded as *const u8;
213 
214                 let cert = d2i_X509(
215                     ptr::null_mut(),
216                     &in_p,
217                     (*ctx_p).cbCertEncoded as i32,
218                 );
219                 if !cert.is_null() {
220                     X509_STORE_add_cert(ctx_store, cert);
221                 }
222 
223                 X509_free(cert);
224 
225                 ctx_p = winapi::um::wincrypt::CertEnumCertificatesInStore(
226                     sys_store, ctx_p,
227                 );
228             }
229 
230             // tidy up
231             winapi::um::wincrypt::CertFreeCertificateContext(ctx_p);
232             winapi::um::wincrypt::CertCloseStore(sys_store, 0);
233         }
234 
235         Ok(())
236     }
237 
set_verify(&mut self, verify: bool)238     pub fn set_verify(&mut self, verify: bool) {
239         let mode = if verify {
240             0x01 // SSL_VERIFY_PEER
241         } else {
242             0x00 // SSL_VERIFY_NONE
243         };
244 
245         unsafe {
246             SSL_CTX_set_verify(self.as_ptr(), mode, ptr::null());
247         }
248     }
249 
enable_keylog(&mut self)250     pub fn enable_keylog(&mut self) {
251         unsafe {
252             SSL_CTX_set_keylog_callback(self.as_ptr(), keylog);
253         }
254     }
255 
set_alpn(&mut self, v: &[Vec<u8>]) -> Result<()>256     pub fn set_alpn(&mut self, v: &[Vec<u8>]) -> Result<()> {
257         let mut protos: Vec<u8> = Vec::new();
258 
259         for proto in v {
260             protos.push(proto.len() as u8);
261             protos.append(&mut proto.clone());
262         }
263 
264         // Configure ALPN for servers.
265         unsafe {
266             SSL_CTX_set_alpn_select_cb(
267                 self.as_ptr(),
268                 select_alpn,
269                 ptr::null_mut(),
270             );
271         }
272 
273         // Configure ALPN for clients.
274         map_result_zero_is_success(unsafe {
275             SSL_CTX_set_alpn_protos(self.as_ptr(), protos.as_ptr(), protos.len())
276         })
277     }
278 
set_early_data_enabled(&mut self, enabled: bool)279     pub fn set_early_data_enabled(&mut self, enabled: bool) {
280         let enabled = if enabled { 1 } else { 0 };
281 
282         unsafe {
283             SSL_CTX_set_early_data_enabled(self.as_ptr(), enabled);
284         }
285     }
286 
as_ptr(&self) -> *mut SSL_CTX287     fn as_ptr(&self) -> *mut SSL_CTX {
288         self.0
289     }
290 }
291 
292 unsafe impl std::marker::Send for Context {}
293 
294 impl Drop for Context {
drop(&mut self)295     fn drop(&mut self) {
296         unsafe { SSL_CTX_free(self.as_ptr()) }
297     }
298 }
299 
300 pub struct Handshake(*mut SSL);
301 
302 impl Handshake {
from_ptr(ssl: *mut c_void) -> Handshake303     pub unsafe fn from_ptr(ssl: *mut c_void) -> Handshake {
304         let ssl = ssl as *mut SSL;
305         Handshake(ssl)
306     }
307 
get_error(&self, ret_code: c_int) -> c_int308     pub fn get_error(&self, ret_code: c_int) -> c_int {
309         unsafe { SSL_get_error(self.as_ptr(), ret_code) }
310     }
311 
init(&self, conn: &Connection) -> Result<()>312     pub fn init(&self, conn: &Connection) -> Result<()> {
313         self.set_state(conn.is_server);
314 
315         self.set_ex_data(*QUICHE_EX_DATA_INDEX, conn)?;
316 
317         self.set_min_proto_version(TLS1_3_VERSION);
318         self.set_max_proto_version(TLS1_3_VERSION);
319 
320         self.set_quic_method()?;
321 
322         // TODO: the early data context should include transport parameters and
323         // HTTP/3 SETTINGS in wire format.
324         self.set_quic_early_data_context(b"quiche")?;
325 
326         self.set_quiet_shutdown(true);
327 
328         Ok(())
329     }
330 
set_state(&self, is_server: bool)331     pub fn set_state(&self, is_server: bool) {
332         unsafe {
333             if is_server {
334                 SSL_set_accept_state(self.as_ptr());
335             } else {
336                 SSL_set_connect_state(self.as_ptr());
337             }
338         }
339     }
340 
set_ex_data<T>(&self, idx: c_int, data: &T) -> Result<()>341     pub fn set_ex_data<T>(&self, idx: c_int, data: &T) -> Result<()> {
342         map_result(unsafe {
343             let ptr = data as *const T as *const c_void;
344             SSL_set_ex_data(self.as_ptr(), idx, ptr)
345         })
346     }
347 
set_quic_method(&self) -> Result<()>348     pub fn set_quic_method(&self) -> Result<()> {
349         map_result(unsafe {
350             SSL_set_quic_method(self.as_ptr(), &QUICHE_STREAM_METHOD)
351         })
352     }
353 
set_quic_early_data_context(&self, context: &[u8]) -> Result<()>354     pub fn set_quic_early_data_context(&self, context: &[u8]) -> Result<()> {
355         map_result(unsafe {
356             SSL_set_quic_early_data_context(
357                 self.as_ptr(),
358                 context.as_ptr(),
359                 context.len(),
360             )
361         })
362     }
363 
set_min_proto_version(&self, version: u16)364     pub fn set_min_proto_version(&self, version: u16) {
365         unsafe { SSL_set_min_proto_version(self.as_ptr(), version) }
366     }
367 
set_max_proto_version(&self, version: u16)368     pub fn set_max_proto_version(&self, version: u16) {
369         unsafe { SSL_set_max_proto_version(self.as_ptr(), version) }
370     }
371 
set_quiet_shutdown(&self, mode: bool)372     pub fn set_quiet_shutdown(&self, mode: bool) {
373         unsafe { SSL_set_quiet_shutdown(self.as_ptr(), if mode { 1 } else { 0 }) }
374     }
375 
set_host_name(&self, name: &str) -> Result<()>376     pub fn set_host_name(&self, name: &str) -> Result<()> {
377         let cstr = ffi::CString::new(name).map_err(|_| Error::TlsFail)?;
378         map_result_ssl(self, unsafe {
379             SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr())
380         })?;
381 
382         let param = unsafe { SSL_get0_param(self.as_ptr()) };
383 
384         map_result(unsafe {
385             X509_VERIFY_PARAM_set1_host(param, cstr.as_ptr(), name.len())
386         })
387     }
388 
set_quic_transport_params(&self, buf: &[u8]) -> Result<()>389     pub fn set_quic_transport_params(&self, buf: &[u8]) -> Result<()> {
390         map_result_ssl(self, unsafe {
391             SSL_set_quic_transport_params(self.as_ptr(), buf.as_ptr(), buf.len())
392         })
393     }
394 
quic_transport_params(&self) -> &[u8]395     pub fn quic_transport_params(&self) -> &[u8] {
396         let mut ptr: *const u8 = ptr::null();
397         let mut len: usize = 0;
398 
399         unsafe {
400             SSL_get_peer_quic_transport_params(self.as_ptr(), &mut ptr, &mut len);
401         }
402 
403         if len == 0 {
404             return &mut [];
405         }
406 
407         unsafe { slice::from_raw_parts(ptr, len) }
408     }
409 
alpn_protocol(&self) -> &[u8]410     pub fn alpn_protocol(&self) -> &[u8] {
411         let mut ptr: *const u8 = ptr::null();
412         let mut len: u32 = 0;
413 
414         unsafe {
415             SSL_get0_alpn_selected(self.as_ptr(), &mut ptr, &mut len);
416         }
417 
418         if len == 0 {
419             return &mut [];
420         }
421 
422         unsafe { slice::from_raw_parts(ptr, len as usize) }
423     }
424 
provide_data(&self, level: crypto::Level, buf: &[u8]) -> Result<()>425     pub fn provide_data(&self, level: crypto::Level, buf: &[u8]) -> Result<()> {
426         map_result_ssl(self, unsafe {
427             SSL_provide_quic_data(self.as_ptr(), level, buf.as_ptr(), buf.len())
428         })
429     }
430 
do_handshake(&self) -> Result<()>431     pub fn do_handshake(&self) -> Result<()> {
432         map_result_ssl(self, unsafe { SSL_do_handshake(self.as_ptr()) })
433     }
434 
write_level(&self) -> crypto::Level435     pub fn write_level(&self) -> crypto::Level {
436         unsafe { SSL_quic_write_level(self.as_ptr()) }
437     }
438 
cipher(&self) -> Option<crypto::Algorithm>439     pub fn cipher(&self) -> Option<crypto::Algorithm> {
440         let cipher =
441             map_result_ptr(unsafe { SSL_get_current_cipher(self.as_ptr()) });
442 
443         get_cipher_from_ptr(cipher.ok()?).ok()
444     }
445 
curve(&self) -> Option<String>446     pub fn curve(&self) -> Option<String> {
447         let curve = unsafe {
448             let curve_id = SSL_get_curve_id(self.as_ptr());
449             if curve_id == 0 {
450                 return None;
451             }
452 
453             let curve_name = SSL_get_curve_name(curve_id);
454             match std::ffi::CStr::from_ptr(curve_name).to_str() {
455                 Ok(v) => v,
456 
457                 Err(_) => return None,
458             }
459         };
460 
461         Some(curve.to_string())
462     }
463 
sigalg(&self) -> Option<String>464     pub fn sigalg(&self) -> Option<String> {
465         let sigalg = unsafe {
466             let sigalg_id = SSL_get_peer_signature_algorithm(self.as_ptr());
467             if sigalg_id == 0 {
468                 return None;
469             }
470 
471             let sigalg_name = SSL_get_signature_algorithm_name(sigalg_id, 1);
472             match std::ffi::CStr::from_ptr(sigalg_name).to_str() {
473                 Ok(v) => v,
474 
475                 Err(_) => return None,
476             }
477         };
478 
479         Some(sigalg.to_string())
480     }
481 
peer_cert(&self) -> Option<Vec<u8>>482     pub fn peer_cert(&self) -> Option<Vec<u8>> {
483         let peer_cert = unsafe {
484             let mut out: *mut libc::c_uchar = ptr::null_mut();
485 
486             let x509 = SSL_get_peer_certificate(self.as_ptr());
487             if x509.is_null() {
488                 return None;
489             }
490 
491             let out_len = i2d_X509(x509, &mut out);
492             if out_len <= 0 {
493                 return None;
494             }
495 
496             let der = slice::from_raw_parts(out, out_len as usize);
497             let der = der.to_vec();
498 
499             OPENSSL_free(out as *mut c_void);
500 
501             der
502         };
503 
504         Some(peer_cert)
505     }
506 
is_completed(&self) -> bool507     pub fn is_completed(&self) -> bool {
508         unsafe { SSL_in_init(self.as_ptr()) == 0 }
509     }
510 
is_resumed(&self) -> bool511     pub fn is_resumed(&self) -> bool {
512         unsafe { SSL_session_reused(self.as_ptr()) == 1 }
513     }
514 
is_in_early_data(&self) -> bool515     pub fn is_in_early_data(&self) -> bool {
516         unsafe { SSL_in_early_data(self.as_ptr()) == 1 }
517     }
518 
clear(&mut self) -> Result<()>519     pub fn clear(&mut self) -> Result<()> {
520         map_result_ssl(self, unsafe { SSL_clear(self.as_ptr()) })
521     }
522 
as_ptr(&self) -> *mut SSL523     fn as_ptr(&self) -> *mut SSL {
524         self.0
525     }
526 }
527 
528 unsafe impl std::marker::Send for Handshake {}
529 
530 impl Drop for Handshake {
drop(&mut self)531     fn drop(&mut self) {
532         unsafe { SSL_free(self.as_ptr()) }
533     }
534 }
535 
get_ex_data_from_ptr<'a, T>(ptr: *mut SSL, idx: c_int) -> Option<&'a mut T>536 fn get_ex_data_from_ptr<'a, T>(ptr: *mut SSL, idx: c_int) -> Option<&'a mut T> {
537     unsafe {
538         let data = SSL_get_ex_data(ptr, idx) as *mut T;
539         data.as_mut()
540     }
541 }
542 
get_cipher_from_ptr(cipher: *const SSL_CIPHER) -> Result<crypto::Algorithm>543 fn get_cipher_from_ptr(cipher: *const SSL_CIPHER) -> Result<crypto::Algorithm> {
544     let cipher_id = unsafe { SSL_CIPHER_get_id(cipher) };
545 
546     let alg = match cipher_id {
547         0x0300_1301 => crypto::Algorithm::AES128_GCM,
548         0x0300_1302 => crypto::Algorithm::AES256_GCM,
549         0x0300_1303 => crypto::Algorithm::ChaCha20_Poly1305,
550         _ => return Err(Error::TlsFail),
551     };
552 
553     Ok(alg)
554 }
555 
set_read_secret( ssl: *mut SSL, level: crypto::Level, cipher: *const SSL_CIPHER, secret: *const u8, secret_len: usize, ) -> c_int556 extern fn set_read_secret(
557     ssl: *mut SSL, level: crypto::Level, cipher: *const SSL_CIPHER,
558     secret: *const u8, secret_len: usize,
559 ) -> c_int {
560     let conn =
561         match get_ex_data_from_ptr::<Connection>(ssl, *QUICHE_EX_DATA_INDEX) {
562             Some(v) => v,
563 
564             None => return 0,
565         };
566 
567     trace!("{} set read secret lvl={:?}", conn.trace_id, level);
568 
569     let space = match level {
570         crypto::Level::Initial => &mut conn.pkt_num_spaces[packet::EPOCH_INITIAL],
571         crypto::Level::ZeroRTT =>
572             &mut conn.pkt_num_spaces[packet::EPOCH_APPLICATION],
573         crypto::Level::Handshake =>
574             &mut conn.pkt_num_spaces[packet::EPOCH_HANDSHAKE],
575         crypto::Level::OneRTT =>
576             &mut conn.pkt_num_spaces[packet::EPOCH_APPLICATION],
577     };
578 
579     let aead = match get_cipher_from_ptr(cipher) {
580         Ok(v) => v,
581 
582         Err(_) => return 0,
583     };
584 
585     // 0-RTT read secrets are present only on the server.
586     if level != crypto::Level::ZeroRTT || conn.is_server {
587         let secret = unsafe { slice::from_raw_parts(secret, secret_len) };
588 
589         let open = match crypto::Open::from_secret(aead, &secret) {
590             Ok(v) => v,
591 
592             Err(_) => return 0,
593         };
594 
595         if level == crypto::Level::ZeroRTT {
596             space.crypto_0rtt_open = Some(open);
597             return 1;
598         }
599 
600         space.crypto_open = Some(open);
601     }
602 
603     1
604 }
605 
set_write_secret( ssl: *mut SSL, level: crypto::Level, cipher: *const SSL_CIPHER, secret: *const u8, secret_len: usize, ) -> c_int606 extern fn set_write_secret(
607     ssl: *mut SSL, level: crypto::Level, cipher: *const SSL_CIPHER,
608     secret: *const u8, secret_len: usize,
609 ) -> c_int {
610     let conn =
611         match get_ex_data_from_ptr::<Connection>(ssl, *QUICHE_EX_DATA_INDEX) {
612             Some(v) => v,
613 
614             None => return 0,
615         };
616 
617     trace!("{} set write secret lvl={:?}", conn.trace_id, level);
618 
619     let space = match level {
620         crypto::Level::Initial => &mut conn.pkt_num_spaces[packet::EPOCH_INITIAL],
621         crypto::Level::ZeroRTT =>
622             &mut conn.pkt_num_spaces[packet::EPOCH_APPLICATION],
623         crypto::Level::Handshake =>
624             &mut conn.pkt_num_spaces[packet::EPOCH_HANDSHAKE],
625         crypto::Level::OneRTT =>
626             &mut conn.pkt_num_spaces[packet::EPOCH_APPLICATION],
627     };
628 
629     let aead = match get_cipher_from_ptr(cipher) {
630         Ok(v) => v,
631 
632         Err(_) => return 0,
633     };
634 
635     // 0-RTT write secrets are present only on the client.
636     if level != crypto::Level::ZeroRTT || !conn.is_server {
637         let secret = unsafe { slice::from_raw_parts(secret, secret_len) };
638 
639         let seal = match crypto::Seal::from_secret(aead, &secret) {
640             Ok(v) => v,
641 
642             Err(_) => return 0,
643         };
644 
645         space.crypto_seal = Some(seal);
646     }
647 
648     1
649 }
650 
add_handshake_data( ssl: *mut SSL, level: crypto::Level, data: *const u8, len: usize, ) -> c_int651 extern fn add_handshake_data(
652     ssl: *mut SSL, level: crypto::Level, data: *const u8, len: usize,
653 ) -> c_int {
654     let conn =
655         match get_ex_data_from_ptr::<Connection>(ssl, *QUICHE_EX_DATA_INDEX) {
656             Some(v) => v,
657 
658             None => return 0,
659         };
660 
661     trace!(
662         "{} write message lvl={:?} len={}",
663         conn.trace_id,
664         level,
665         len
666     );
667 
668     let buf = unsafe { slice::from_raw_parts(data, len) };
669 
670     let space = match level {
671         crypto::Level::Initial => &mut conn.pkt_num_spaces[packet::EPOCH_INITIAL],
672         crypto::Level::ZeroRTT => unreachable!(),
673         crypto::Level::Handshake =>
674             &mut conn.pkt_num_spaces[packet::EPOCH_HANDSHAKE],
675         crypto::Level::OneRTT =>
676             &mut conn.pkt_num_spaces[packet::EPOCH_APPLICATION],
677     };
678 
679     if space.crypto_stream.send.push_slice(buf, false).is_err() {
680         return 0;
681     }
682 
683     1
684 }
685 
flush_flight(_ssl: *mut SSL) -> c_int686 extern fn flush_flight(_ssl: *mut SSL) -> c_int {
687     // We don't really need to anything here since the output packets are
688     // generated separately, when conn.send() is called.
689 
690     1
691 }
692 
send_alert(ssl: *mut SSL, level: crypto::Level, alert: u8) -> c_int693 extern fn send_alert(ssl: *mut SSL, level: crypto::Level, alert: u8) -> c_int {
694     let conn =
695         match get_ex_data_from_ptr::<Connection>(ssl, *QUICHE_EX_DATA_INDEX) {
696             Some(v) => v,
697 
698             None => return 0,
699         };
700 
701     trace!(
702         "{} send alert lvl={:?} alert={:x}",
703         conn.trace_id,
704         level,
705         alert
706     );
707 
708     let error: u64 = TLS_ALERT_ERROR + u64::from(alert);
709     conn.error = Some(error);
710 
711     1
712 }
713 
keylog(ssl: *mut SSL, line: *const c_char)714 extern fn keylog(ssl: *mut SSL, line: *const c_char) {
715     let conn =
716         match get_ex_data_from_ptr::<Connection>(ssl, *QUICHE_EX_DATA_INDEX) {
717             Some(v) => v,
718 
719             None => return,
720         };
721 
722     if let Some(keylog) = &mut conn.keylog {
723         let data = unsafe { ffi::CStr::from_ptr(line).to_bytes() };
724 
725         let mut full_line = Vec::with_capacity(data.len() + 1);
726         full_line.extend_from_slice(data);
727         full_line.push(b'\n');
728 
729         keylog.write_all(&full_line[..]).ok();
730     }
731 }
732 
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_int733 extern fn select_alpn(
734     ssl: *mut SSL, out: *mut *const u8, out_len: *mut u8, inp: *mut u8,
735     in_len: c_uint, _arg: *mut c_void,
736 ) -> c_int {
737     let conn =
738         match get_ex_data_from_ptr::<Connection>(ssl, *QUICHE_EX_DATA_INDEX) {
739             Some(v) => v,
740 
741             None => return 3, // SSL_TLSEXT_ERR_NOACK
742         };
743 
744     if conn.application_protos.is_empty() {
745         return 3; // SSL_TLSEXT_ERR_NOACK
746     }
747 
748     let mut protos = octets::Octets::with_slice(unsafe {
749         slice::from_raw_parts(inp, in_len as usize)
750     });
751 
752     while let Ok(proto) = protos.get_bytes_with_u8_length() {
753         let found = conn.application_protos.iter().any(|expected| {
754             trace!(
755                 "checking peer ALPN {:?} against {:?}",
756                 std::str::from_utf8(proto.as_ref()),
757                 std::str::from_utf8(expected.as_slice())
758             );
759 
760             if expected.len() == proto.len() &&
761                 expected.as_slice() == proto.as_ref()
762             {
763                 unsafe {
764                     *out = expected.as_slice().as_ptr();
765                     *out_len = expected.len() as u8;
766                 }
767 
768                 return true;
769             }
770 
771             false
772         });
773 
774         if found {
775             return 0; // SSL_TLSEXT_ERR_OK
776         }
777     }
778 
779     3 // SSL_TLSEXT_ERR_NOACK
780 }
781 
map_result(bssl_result: c_int) -> Result<()>782 fn map_result(bssl_result: c_int) -> Result<()> {
783     match bssl_result {
784         1 => Ok(()),
785         _ => Err(Error::TlsFail),
786     }
787 }
788 
map_result_zero_is_success(bssl_result: c_int) -> Result<()>789 fn map_result_zero_is_success(bssl_result: c_int) -> Result<()> {
790     match bssl_result {
791         0 => Ok(()),
792         _ => Err(Error::TlsFail),
793     }
794 }
795 
map_result_ptr<'a, T>(bssl_result: *const T) -> Result<&'a T>796 fn map_result_ptr<'a, T>(bssl_result: *const T) -> Result<&'a T> {
797     match unsafe { bssl_result.as_ref() } {
798         Some(v) => Ok(v),
799         None => Err(Error::TlsFail),
800     }
801 }
802 
map_result_ssl(ssl: &Handshake, bssl_result: c_int) -> Result<()>803 fn map_result_ssl(ssl: &Handshake, bssl_result: c_int) -> Result<()> {
804     match bssl_result {
805         1 => Ok(()),
806 
807         _ => {
808             let ssl_err = ssl.get_error(bssl_result);
809             match ssl_err {
810                 // SSL_ERROR_SSL
811                 1 => {
812                     log_ssl_error();
813 
814                     Err(Error::TlsFail)
815                 },
816 
817                 // SSL_ERROR_WANT_READ
818                 2 => Err(Error::Done),
819 
820                 // SSL_ERROR_WANT_WRITE
821                 3 => Err(Error::Done),
822 
823                 // SSL_ERROR_WANT_X509_LOOKUP
824                 4 => Err(Error::Done),
825 
826                 // SSL_ERROR_SYSCALL
827                 5 => Err(Error::TlsFail),
828 
829                 // SSL_ERROR_PENDING_CERTIFICATE
830                 12 => Err(Error::Done),
831 
832                 // SSL_ERROR_WANT_PRIVATE_KEY_OPERATION
833                 13 => Err(Error::Done),
834 
835                 // SSL_ERROR_PENDING_TICKET
836                 14 => Err(Error::Done),
837 
838                 _ => Err(Error::TlsFail),
839             }
840         },
841     }
842 }
843 
log_ssl_error()844 fn log_ssl_error() {
845     let err = [0; 1024];
846 
847     unsafe {
848         let e = ERR_peek_error();
849         ERR_error_string_n(e, err.as_ptr(), err.len());
850     }
851 
852     trace!("{}", std::str::from_utf8(&err).unwrap());
853 }
854 
855 extern {
856     // SSL_METHOD
TLS_method() -> *const SSL_METHOD857     fn TLS_method() -> *const SSL_METHOD;
858 
859     // SSL_CTX
SSL_CTX_new(method: *const SSL_METHOD) -> *mut SSL_CTX860     fn SSL_CTX_new(method: *const SSL_METHOD) -> *mut SSL_CTX;
SSL_CTX_free(ctx: *mut SSL_CTX)861     fn SSL_CTX_free(ctx: *mut SSL_CTX);
862 
SSL_CTX_use_certificate_chain_file( ctx: *mut SSL_CTX, file: *const c_char, ) -> c_int863     fn SSL_CTX_use_certificate_chain_file(
864         ctx: *mut SSL_CTX, file: *const c_char,
865     ) -> c_int;
866 
SSL_CTX_use_PrivateKey_file( ctx: *mut SSL_CTX, file: *const c_char, ty: c_int, ) -> c_int867     fn SSL_CTX_use_PrivateKey_file(
868         ctx: *mut SSL_CTX, file: *const c_char, ty: c_int,
869     ) -> c_int;
870 
SSL_CTX_load_verify_locations( ctx: *mut SSL_CTX, file: *const c_char, path: *const c_char, ) -> c_int871     fn SSL_CTX_load_verify_locations(
872         ctx: *mut SSL_CTX, file: *const c_char, path: *const c_char,
873     ) -> c_int;
874 
875     #[cfg(not(windows))]
SSL_CTX_set_default_verify_paths(ctx: *mut SSL_CTX) -> c_int876     fn SSL_CTX_set_default_verify_paths(ctx: *mut SSL_CTX) -> c_int;
877 
878     #[cfg(windows)]
SSL_CTX_get_cert_store(ctx: *mut SSL_CTX) -> *mut X509_STORE879     fn SSL_CTX_get_cert_store(ctx: *mut SSL_CTX) -> *mut X509_STORE;
880 
SSL_CTX_set_verify(ctx: *mut SSL_CTX, mode: c_int, cb: *const c_void)881     fn SSL_CTX_set_verify(ctx: *mut SSL_CTX, mode: c_int, cb: *const c_void);
882 
SSL_CTX_set_keylog_callback( ctx: *mut SSL_CTX, cb: extern fn(ssl: *mut SSL, line: *const c_char), )883     fn SSL_CTX_set_keylog_callback(
884         ctx: *mut SSL_CTX, cb: extern fn(ssl: *mut SSL, line: *const c_char),
885     );
886 
SSL_CTX_set_alpn_protos( ctx: *mut SSL_CTX, protos: *const u8, protos_len: usize, ) -> c_int887     fn SSL_CTX_set_alpn_protos(
888         ctx: *mut SSL_CTX, protos: *const u8, protos_len: usize,
889     ) -> c_int;
890 
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, )891     fn SSL_CTX_set_alpn_select_cb(
892         ctx: *mut SSL_CTX,
893         cb: extern fn(
894             ssl: *mut SSL,
895             out: *mut *const u8,
896             out_len: *mut u8,
897             inp: *mut u8,
898             in_len: c_uint,
899             arg: *mut c_void,
900         ) -> c_int,
901         arg: *mut c_void,
902     );
903 
SSL_CTX_set_early_data_enabled(ctx: *mut SSL_CTX, enabled: i32)904     fn SSL_CTX_set_early_data_enabled(ctx: *mut SSL_CTX, enabled: i32);
905 
906     // 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_int907     fn SSL_get_ex_new_index(
908         argl: c_long, argp: *const c_void, unused: *const c_void,
909         dup_unused: *const c_void, free_func: *const c_void,
910     ) -> c_int;
911 
SSL_new(ctx: *mut SSL_CTX) -> *mut SSL912     fn SSL_new(ctx: *mut SSL_CTX) -> *mut SSL;
913 
SSL_get_error(ssl: *mut SSL, ret_code: c_int) -> c_int914     fn SSL_get_error(ssl: *mut SSL, ret_code: c_int) -> c_int;
915 
SSL_set_accept_state(ssl: *mut SSL)916     fn SSL_set_accept_state(ssl: *mut SSL);
SSL_set_connect_state(ssl: *mut SSL)917     fn SSL_set_connect_state(ssl: *mut SSL);
918 
SSL_get0_param(ssl: *mut SSL) -> *mut X509_VERIFY_PARAM919     fn SSL_get0_param(ssl: *mut SSL) -> *mut X509_VERIFY_PARAM;
920 
SSL_set_ex_data(ssl: *mut SSL, idx: c_int, ptr: *const c_void) -> c_int921     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_void922     fn SSL_get_ex_data(ssl: *mut SSL, idx: c_int) -> *mut c_void;
923 
SSL_get_current_cipher(ssl: *mut SSL) -> *const SSL_CIPHER924     fn SSL_get_current_cipher(ssl: *mut SSL) -> *const SSL_CIPHER;
925 
SSL_get_curve_id(ssl: *mut SSL) -> u16926     fn SSL_get_curve_id(ssl: *mut SSL) -> u16;
SSL_get_curve_name(curve: u16) -> *const c_char927     fn SSL_get_curve_name(curve: u16) -> *const c_char;
928 
SSL_get_peer_signature_algorithm(ssl: *mut SSL) -> u16929     fn SSL_get_peer_signature_algorithm(ssl: *mut SSL) -> u16;
SSL_get_signature_algorithm_name( sigalg: u16, include_curve: i32, ) -> *const c_char930     fn SSL_get_signature_algorithm_name(
931         sigalg: u16, include_curve: i32,
932     ) -> *const c_char;
933 
SSL_get_peer_certificate(ssl: *mut SSL) -> *const X509934     fn SSL_get_peer_certificate(ssl: *mut SSL) -> *const X509;
935 
SSL_set_min_proto_version(ssl: *mut SSL, version: u16)936     fn SSL_set_min_proto_version(ssl: *mut SSL, version: u16);
SSL_set_max_proto_version(ssl: *mut SSL, version: u16)937     fn SSL_set_max_proto_version(ssl: *mut SSL, version: u16);
938 
SSL_set_quiet_shutdown(ssl: *mut SSL, mode: c_int)939     fn SSL_set_quiet_shutdown(ssl: *mut SSL, mode: c_int);
940 
SSL_set_tlsext_host_name(ssl: *mut SSL, name: *const c_char) -> c_int941     fn SSL_set_tlsext_host_name(ssl: *mut SSL, name: *const c_char) -> c_int;
942 
SSL_set_quic_transport_params( ssl: *mut SSL, params: *const u8, params_len: usize, ) -> c_int943     fn SSL_set_quic_transport_params(
944         ssl: *mut SSL, params: *const u8, params_len: usize,
945     ) -> c_int;
946 
SSL_set_quic_method( ssl: *mut SSL, quic_method: *const SSL_QUIC_METHOD, ) -> c_int947     fn SSL_set_quic_method(
948         ssl: *mut SSL, quic_method: *const SSL_QUIC_METHOD,
949     ) -> c_int;
950 
SSL_set_quic_early_data_context( ssl: *mut SSL, context: *const u8, context_len: usize, ) -> c_int951     fn SSL_set_quic_early_data_context(
952         ssl: *mut SSL, context: *const u8, context_len: usize,
953     ) -> c_int;
954 
SSL_get_peer_quic_transport_params( ssl: *mut SSL, out_params: *mut *const u8, out_params_len: *mut usize, )955     fn SSL_get_peer_quic_transport_params(
956         ssl: *mut SSL, out_params: *mut *const u8, out_params_len: *mut usize,
957     );
958 
SSL_get0_alpn_selected( ssl: *mut SSL, out: *mut *const u8, out_len: *mut u32, )959     fn SSL_get0_alpn_selected(
960         ssl: *mut SSL, out: *mut *const u8, out_len: *mut u32,
961     );
962 
SSL_provide_quic_data( ssl: *mut SSL, level: crypto::Level, data: *const u8, len: usize, ) -> c_int963     fn SSL_provide_quic_data(
964         ssl: *mut SSL, level: crypto::Level, data: *const u8, len: usize,
965     ) -> c_int;
966 
SSL_do_handshake(ssl: *mut SSL) -> c_int967     fn SSL_do_handshake(ssl: *mut SSL) -> c_int;
968 
SSL_quic_write_level(ssl: *mut SSL) -> crypto::Level969     fn SSL_quic_write_level(ssl: *mut SSL) -> crypto::Level;
970 
SSL_session_reused(ssl: *mut SSL) -> c_int971     fn SSL_session_reused(ssl: *mut SSL) -> c_int;
972 
SSL_in_init(ssl: *mut SSL) -> c_int973     fn SSL_in_init(ssl: *mut SSL) -> c_int;
974 
SSL_in_early_data(ssl: *mut SSL) -> c_int975     fn SSL_in_early_data(ssl: *mut SSL) -> c_int;
976 
SSL_clear(ssl: *mut SSL) -> c_int977     fn SSL_clear(ssl: *mut SSL) -> c_int;
978 
SSL_free(ssl: *mut SSL)979     fn SSL_free(ssl: *mut SSL);
980 
981     // SSL_CIPHER
SSL_CIPHER_get_id(cipher: *const SSL_CIPHER) -> c_uint982     fn SSL_CIPHER_get_id(cipher: *const SSL_CIPHER) -> c_uint;
983 
984     // X509_VERIFY_PARAM
X509_VERIFY_PARAM_set1_host( param: *mut X509_VERIFY_PARAM, name: *const c_char, namelen: usize, ) -> c_int985     fn X509_VERIFY_PARAM_set1_host(
986         param: *mut X509_VERIFY_PARAM, name: *const c_char, namelen: usize,
987     ) -> c_int;
988 
989     // X509_STORE
990     #[cfg(windows)]
X509_STORE_add_cert(ctx: *mut X509_STORE, x: *mut X509) -> c_int991     fn X509_STORE_add_cert(ctx: *mut X509_STORE, x: *mut X509) -> c_int;
992 
993     // X509
994     #[cfg(windows)]
X509_free(x: *mut X509)995     fn X509_free(x: *mut X509);
996     #[cfg(windows)]
d2i_X509(px: *mut X509, input: *const *const u8, len: c_int) -> *mut X509997     fn d2i_X509(px: *mut X509, input: *const *const u8, len: c_int) -> *mut X509;
998 
i2d_X509(px: *const X509, out: *mut *mut u8) -> c_int999     fn i2d_X509(px: *const X509, out: *mut *mut u8) -> c_int;
1000 
1001     // ERR
ERR_peek_error() -> c_uint1002     fn ERR_peek_error() -> c_uint;
1003 
ERR_error_string_n(err: c_uint, buf: *const u8, len: usize)1004     fn ERR_error_string_n(err: c_uint, buf: *const u8, len: usize);
1005 
1006     // OPENSSL
OPENSSL_free(ptr: *mut c_void)1007     fn OPENSSL_free(ptr: *mut c_void);
1008 }
1009