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