1use std::ffi;
28use std::ptr;
29use std::slice;
30
31use std::io::Write;
32
33use std::sync::LazyLock;
34
35use libc::c_char;
36use libc::c_int;
37use libc::c_uint;
38use libc::c_void;
39
40use crate::Error;
41use crate::Result;
42
43use crate::Connection;
44use crate::ConnectionError;
45
46use crate::crypto;
47use crate::packet;
48
49const TLS1_3_VERSION: u16 = 0x0304;
50const TLS_ALERT_ERROR: u64 = 0x100;
51const INTERNAL_ERROR: u64 = 0x01;
52
53#[allow(non_camel_case_types)]
54#[repr(transparent)]
55struct SSL_METHOD {
56 _unused: c_void,
57}
58
59#[allow(non_camel_case_types)]
60#[repr(transparent)]
61struct SSL_CTX {
62 _unused: c_void,
63}
64
65#[allow(non_camel_case_types)]
66#[repr(transparent)]
67struct SSL {
68 _unused: c_void,
69}
70
71#[allow(non_camel_case_types)]
72#[repr(transparent)]
73struct SSL_CIPHER {
74 _unused: c_void,
75}
76
77#[allow(non_camel_case_types)]
78#[repr(transparent)]
79struct SSL_SESSION {
80 _unused: c_void,
81}
82
83#[allow(non_camel_case_types)]
84#[repr(transparent)]
85struct X509_VERIFY_PARAM {
86 _unused: c_void,
87}
88
89#[allow(non_camel_case_types)]
90#[repr(transparent)]
91#[cfg(windows)]
92struct X509_STORE {
93 _unused: c_void,
94}
95
96#[allow(non_camel_case_types)]
97#[repr(transparent)]
98struct X509_STORE_CTX {
99 _unused: c_void,
100}
101
102#[allow(non_camel_case_types)]
103#[repr(transparent)]
104#[cfg(windows)]
105struct X509 {
106 _unused: c_void,
107}
108
109#[allow(non_camel_case_types)]
110#[repr(transparent)]
111struct STACK_OF {
112 _unused: c_void,
113}
114
115#[cfg(test)]
116#[repr(C)]
117#[allow(non_camel_case_types)]
118#[allow(dead_code)]
119enum ssl_private_key_result_t {
120 ssl_private_key_success,
121 ssl_private_key_retry,
122 ssl_private_key_failure,
123}
124
125pub static QUICHE_EX_DATA_INDEX: LazyLock<c_int> = LazyLock::new(|| unsafe {
127 SSL_get_ex_new_index(0, ptr::null(), ptr::null(), ptr::null(), ptr::null())
128});
129
130pub struct Context(*mut SSL_CTX);
131
132impl Context {
133 pub fn new() -> Result<Context> {
136 unsafe {
137 let ctx_raw = SSL_CTX_new(TLS_method());
138
139 let mut ctx = Context(ctx_raw);
140
141 ctx.set_session_callback();
142
143 ctx.load_ca_certs()?;
144
145 Ok(ctx)
146 }
147 }
148
149 #[cfg(feature = "boringssl-boring-crate")]
150 pub fn from_boring(
151 ssl_ctx_builder: boring::ssl::SslContextBuilder,
152 ) -> Context {
153 use foreign_types_shared::ForeignType;
154
155 let mut ctx = Context(ssl_ctx_builder.build().into_ptr() as _);
156 ctx.set_session_callback();
157
158 ctx
159 }
160
161 pub fn new_handshake(&mut self) -> Result<Handshake> {
162 unsafe {
163 let ssl = SSL_new(self.as_mut_ptr());
164 Ok(Handshake::new(ssl))
165 }
166 }
167
168 pub fn load_verify_locations_from_file(&mut self, file: &str) -> Result<()> {
169 let file = ffi::CString::new(file).map_err(|_| Error::TlsFail)?;
170 map_result(unsafe {
171 SSL_CTX_load_verify_locations(
172 self.as_mut_ptr(),
173 file.as_ptr(),
174 std::ptr::null(),
175 )
176 })
177 }
178
179 pub fn load_verify_locations_from_directory(
180 &mut self, path: &str,
181 ) -> Result<()> {
182 let path = ffi::CString::new(path).map_err(|_| Error::TlsFail)?;
183 map_result(unsafe {
184 SSL_CTX_load_verify_locations(
185 self.as_mut_ptr(),
186 std::ptr::null(),
187 path.as_ptr(),
188 )
189 })
190 }
191
192 pub fn use_certificate_chain_file(&mut self, file: &str) -> Result<()> {
193 let cstr = ffi::CString::new(file).map_err(|_| Error::TlsFail)?;
194 map_result(unsafe {
195 SSL_CTX_use_certificate_chain_file(self.as_mut_ptr(), cstr.as_ptr())
196 })
197 }
198
199 pub fn use_privkey_file(&mut self, file: &str) -> Result<()> {
200 let cstr = ffi::CString::new(file).map_err(|_| Error::TlsFail)?;
201 map_result(unsafe {
202 SSL_CTX_use_PrivateKey_file(self.as_mut_ptr(), cstr.as_ptr(), 1)
203 })
204 }
205
206 #[cfg(not(windows))]
207 fn load_ca_certs(&mut self) -> Result<()> {
208 unsafe { map_result(SSL_CTX_set_default_verify_paths(self.as_mut_ptr())) }
209 }
210
211 #[cfg(windows)]
212 fn load_ca_certs(&mut self) -> Result<()> {
213 unsafe {
214 let cstr = ffi::CString::new("Root").map_err(|_| Error::TlsFail)?;
215 let sys_store =
216 windows_sys::Win32::Security::Cryptography::CertOpenSystemStoreA(
217 0,
218 cstr.as_ptr() as windows_sys::core::PCSTR,
219 );
220 if sys_store.is_null() {
221 return Err(Error::TlsFail);
222 }
223
224 let ctx_store = SSL_CTX_get_cert_store(self.as_mut_ptr());
225 if ctx_store.is_null() {
226 return Err(Error::TlsFail);
227 }
228
229 let mut ctx_p = windows_sys::Win32::Security::Cryptography::CertEnumCertificatesInStore(
230 sys_store,
231 ptr::null(),
232 );
233
234 while !ctx_p.is_null() {
235 let in_p = (*ctx_p).pbCertEncoded as *const u8;
236
237 let cert = d2i_X509(
238 ptr::null_mut(),
239 &in_p,
240 (*ctx_p).cbCertEncoded as i32,
241 );
242 if !cert.is_null() {
243 X509_STORE_add_cert(ctx_store, cert);
244 }
245
246 X509_free(cert);
247
248 ctx_p = windows_sys::Win32::Security::Cryptography::CertEnumCertificatesInStore(
249 sys_store, ctx_p,
250 );
251 }
252
253 windows_sys::Win32::Security::Cryptography::CertFreeCertificateContext(ctx_p);
255 windows_sys::Win32::Security::Cryptography::CertCloseStore(
256 sys_store, 0,
257 );
258 }
259
260 Ok(())
261 }
262
263 fn set_session_callback(&mut self) {
264 unsafe {
265 SSL_CTX_set_session_cache_mode(
268 self.as_mut_ptr(),
269 0x0001, );
271
272 SSL_CTX_sess_set_new_cb(self.as_mut_ptr(), Some(new_session));
273 };
274 }
275
276 pub fn set_verify(&mut self, verify: bool) {
277 let mode = i32::from(verify);
280
281 unsafe {
284 SSL_CTX_set_verify(self.as_mut_ptr(), mode, None);
285 }
286 }
287
288 pub fn enable_keylog(&mut self) {
289 unsafe {
290 SSL_CTX_set_keylog_callback(self.as_mut_ptr(), Some(keylog));
291 }
292 }
293
294 pub fn set_alpn(&mut self, v: &[&[u8]]) -> Result<()> {
295 let mut protos: Vec<u8> = Vec::new();
296
297 for proto in v {
298 protos.push(proto.len() as u8);
299 protos.extend_from_slice(proto);
300 }
301
302 unsafe {
304 SSL_CTX_set_alpn_select_cb(
305 self.as_mut_ptr(),
306 Some(select_alpn),
307 ptr::null_mut(),
308 );
309 }
310
311 map_result_zero_is_success(unsafe {
313 SSL_CTX_set_alpn_protos(
314 self.as_mut_ptr(),
315 protos.as_ptr(),
316 protos.len(),
317 )
318 })
319 }
320
321 pub fn set_ticket_key(&mut self, key: &[u8]) -> Result<()> {
322 map_result(unsafe {
323 SSL_CTX_set_tlsext_ticket_keys(
324 self.as_mut_ptr(),
325 key.as_ptr(),
326 key.len(),
327 )
328 })
329 }
330
331 fn as_mut_ptr(&mut self) -> *mut SSL_CTX {
332 self.0
333 }
334}
335
336unsafe impl std::marker::Send for Context {}
342unsafe impl std::marker::Sync for Context {}
343
344impl Drop for Context {
345 fn drop(&mut self) {
346 unsafe { SSL_CTX_free(self.as_mut_ptr()) }
347 }
348}
349
350pub struct Handshake {
351 ptr: *mut SSL,
353 provided_data_outstanding: bool,
356}
357
358impl Handshake {
359 #[cfg(feature = "ffi")]
362 pub unsafe fn from_ptr(ssl: *mut c_void) -> Handshake {
363 Handshake::new(ssl as *mut SSL)
364 }
365
366 fn new(ptr: *mut SSL) -> Handshake {
367 Handshake {
368 ptr,
369 provided_data_outstanding: false,
370 }
371 }
372
373 pub fn get_error(&self, ret_code: c_int) -> c_int {
374 unsafe { SSL_get_error(self.as_ptr(), ret_code) }
375 }
376
377 pub fn init(&mut self, is_server: bool) -> Result<()> {
378 self.set_state(is_server);
379
380 self.set_min_proto_version(TLS1_3_VERSION)?;
381 self.set_max_proto_version(TLS1_3_VERSION)?;
382
383 self.set_quic_method()?;
384
385 self.set_quic_early_data_context(b"quiche")?;
388
389 self.set_quiet_shutdown(true);
390
391 Ok(())
392 }
393
394 pub fn use_legacy_codepoint(&mut self, use_legacy: bool) {
395 unsafe {
396 SSL_set_quic_use_legacy_codepoint(
397 self.as_mut_ptr(),
398 use_legacy as c_int,
399 );
400 }
401 }
402
403 pub fn set_state(&mut self, is_server: bool) {
404 unsafe {
405 if is_server {
406 SSL_set_accept_state(self.as_mut_ptr());
407 } else {
408 SSL_set_connect_state(self.as_mut_ptr());
409 }
410 }
411 }
412
413 pub fn set_ex_data<T>(&mut self, idx: c_int, data: *const T) -> Result<()> {
414 map_result(unsafe {
415 let ptr = data as *mut c_void;
416 SSL_set_ex_data(self.as_mut_ptr(), idx, ptr)
417 })
418 }
419
420 pub fn set_quic_method(&mut self) -> Result<()> {
421 map_result(unsafe {
422 SSL_set_quic_method(self.as_mut_ptr(), &QUICHE_STREAM_METHOD)
423 })
424 }
425
426 pub fn set_min_proto_version(&mut self, version: u16) -> Result<()> {
427 map_result(unsafe {
428 SSL_set_min_proto_version(self.as_mut_ptr(), version)
429 })
430 }
431
432 pub fn set_max_proto_version(&mut self, version: u16) -> Result<()> {
433 map_result(unsafe {
434 SSL_set_max_proto_version(self.as_mut_ptr(), version)
435 })
436 }
437
438 pub fn set_quiet_shutdown(&mut self, mode: bool) {
439 unsafe { SSL_set_quiet_shutdown(self.as_mut_ptr(), i32::from(mode)) }
440 }
441
442 pub fn set_host_name(&mut self, name: &str) -> Result<()> {
443 let cstr = ffi::CString::new(name).map_err(|_| Error::TlsFail)?;
444 let rc =
445 unsafe { SSL_set_tlsext_host_name(self.as_mut_ptr(), cstr.as_ptr()) };
446 self.map_result_ssl(rc)?;
447
448 let param = unsafe { SSL_get0_param(self.as_mut_ptr()) };
449
450 map_result(unsafe {
451 X509_VERIFY_PARAM_set1_host(param, cstr.as_ptr(), name.len())
452 })
453 }
454
455 pub fn set_quic_transport_params(&mut self, buf: &[u8]) -> Result<()> {
456 let rc = unsafe {
457 SSL_set_quic_transport_params(
458 self.as_mut_ptr(),
459 buf.as_ptr(),
460 buf.len(),
461 )
462 };
463 self.map_result_ssl(rc)
464 }
465
466 pub fn quic_transport_params(&self) -> &[u8] {
467 let mut ptr: *const u8 = ptr::null();
468 let mut len: usize = 0;
469
470 unsafe {
471 SSL_get_peer_quic_transport_params(self.as_ptr(), &mut ptr, &mut len);
472 }
473
474 if len == 0 {
475 return &mut [];
476 }
477
478 unsafe { slice::from_raw_parts(ptr, len) }
479 }
480
481 pub fn alpn_protocol(&self) -> &[u8] {
482 let mut ptr: *const u8 = ptr::null();
483 let mut len: u32 = 0;
484
485 unsafe {
486 SSL_get0_alpn_selected(self.as_ptr(), &mut ptr, &mut len);
487 }
488
489 if len == 0 {
490 return &mut [];
491 }
492
493 unsafe { slice::from_raw_parts(ptr, len as usize) }
494 }
495
496 pub fn server_name(&self) -> Option<&str> {
497 let s = unsafe {
498 let ptr = SSL_get_servername(
499 self.as_ptr(),
500 0, );
502
503 if ptr.is_null() {
504 return None;
505 }
506
507 ffi::CStr::from_ptr(ptr)
508 };
509
510 s.to_str().ok()
511 }
512
513 pub fn provide_data(
514 &mut self, level: crypto::Level, buf: &[u8],
515 ) -> Result<()> {
516 self.provided_data_outstanding = true;
517 let rc = unsafe {
518 SSL_provide_quic_data(
519 self.as_mut_ptr(),
520 level,
521 buf.as_ptr(),
522 buf.len(),
523 )
524 };
525 self.map_result_ssl(rc)
526 }
527
528 pub fn do_handshake(&mut self, ex_data: &mut ExData) -> Result<()> {
529 self.set_ex_data(*QUICHE_EX_DATA_INDEX, ex_data)?;
530 let rc = unsafe { SSL_do_handshake(self.as_mut_ptr()) };
531 self.set_ex_data::<Connection>(*QUICHE_EX_DATA_INDEX, std::ptr::null())?;
532
533 self.set_transport_error(ex_data, rc);
534 self.map_result_ssl(rc)
535 }
536
537 pub fn process_post_handshake(&mut self, ex_data: &mut ExData) -> Result<()> {
538 if !self.provided_data_outstanding {
541 return Ok(());
542 }
543 self.provided_data_outstanding = false;
544
545 self.set_ex_data(*QUICHE_EX_DATA_INDEX, ex_data)?;
546 let rc = unsafe { SSL_process_quic_post_handshake(self.as_mut_ptr()) };
547 self.set_ex_data::<Connection>(*QUICHE_EX_DATA_INDEX, std::ptr::null())?;
548
549 self.set_transport_error(ex_data, rc);
550 self.map_result_ssl(rc)
551 }
552
553 pub fn write_level(&self) -> crypto::Level {
554 unsafe { SSL_quic_write_level(self.as_ptr()) }
555 }
556
557 pub fn cipher(&self) -> Option<crypto::Algorithm> {
558 let cipher =
559 map_result_ptr(unsafe { SSL_get_current_cipher(self.as_ptr()) });
560
561 get_cipher_from_ptr(cipher.ok()?).ok()
562 }
563
564 #[cfg(test)]
565 pub fn set_options(&mut self, opts: u32) {
566 unsafe {
567 SSL_set_options(self.as_mut_ptr(), opts);
568 }
569 }
570
571 pub fn is_completed(&self) -> bool {
572 unsafe { SSL_in_init(self.as_ptr()) == 0 }
573 }
574
575 pub fn is_resumed(&self) -> bool {
576 unsafe { SSL_session_reused(self.as_ptr()) == 1 }
577 }
578
579 pub fn clear(&mut self) -> Result<()> {
580 let rc = unsafe { SSL_clear(self.as_mut_ptr()) };
581 self.map_result_ssl(rc)
582 }
583
584 fn as_ptr(&self) -> *const SSL {
585 self.ptr
586 }
587
588 fn as_mut_ptr(&mut self) -> *mut SSL {
589 self.ptr
590 }
591
592 fn map_result_ssl(&mut self, bssl_result: c_int) -> Result<()> {
593 match bssl_result {
594 1 => Ok(()),
595
596 _ => {
597 let ssl_err = self.get_error(bssl_result);
598 match ssl_err {
599 1 => {
601 log_ssl_error();
602
603 Err(Error::TlsFail)
604 },
605
606 2 => Err(Error::Done),
608
609 3 => Err(Error::Done),
611
612 4 => Err(Error::Done),
614
615 5 => Err(Error::TlsFail),
617
618 11 => Err(Error::Done),
620
621 12 => Err(Error::Done),
623
624 13 => Err(Error::Done),
626
627 14 => Err(Error::Done),
629
630 15 => {
632 self.reset_early_data_reject();
633 Err(Error::Done)
634 },
635
636 16 => Err(Error::Done),
638
639 _ => Err(Error::TlsFail),
640 }
641 },
642 }
643 }
644
645 fn set_transport_error(&mut self, ex_data: &mut ExData, bssl_result: c_int) {
646 if self.get_error(bssl_result) == 1 {
648 if ex_data.local_error.is_none() {
652 *ex_data.local_error = Some(ConnectionError {
653 is_app: false,
654 error_code: INTERNAL_ERROR,
655 reason: Vec::new(),
656 })
657 }
658 }
659 }
660
661 #[cfg(feature = "boringssl-boring-crate")]
662 pub(crate) fn ssl_mut(&mut self) -> &mut boring::ssl::SslRef {
663 use foreign_types_shared::ForeignTypeRef;
664
665 unsafe { boring::ssl::SslRef::from_ptr_mut(self.as_mut_ptr() as _) }
666 }
667}
668
669unsafe impl std::marker::Send for Handshake {}
675unsafe impl std::marker::Sync for Handshake {}
676
677impl Drop for Handshake {
678 fn drop(&mut self) {
679 unsafe { SSL_free(self.as_mut_ptr()) }
680 }
681}
682
683pub struct ExData<'a> {
684 pub application_protos: &'a Vec<Vec<u8>>,
685
686 pub pkt_num_spaces: &'a mut [packet::PktNumSpace; packet::Epoch::count()],
687
688 pub session: &'a mut Option<Vec<u8>>,
689
690 pub local_error: &'a mut Option<super::ConnectionError>,
691
692 pub keylog: Option<&'a mut Box<dyn std::io::Write + Send + Sync>>,
693
694 pub trace_id: &'a str,
695
696 pub recovery_config: crate::recovery::RecoveryConfig,
697
698 pub is_server: bool,
699}
700
701impl<'a> ExData<'a> {
702 fn from_ssl_ptr(ptr: *const SSL) -> Option<&'a mut Self> {
703 get_ex_data_from_ptr::<ExData>(ptr, *QUICHE_EX_DATA_INDEX)
704 }
705
706 #[cfg(feature = "boringssl-boring-crate")]
707 pub fn from_ssl_ref(ssl: &mut boring::ssl::SslRef) -> Option<&mut Self> {
708 use boring::ex_data::Index;
709
710 let idx: Index<boring::ssl::Ssl, ExData> =
713 unsafe { Index::from_raw(*QUICHE_EX_DATA_INDEX) };
714
715 ssl.ex_data_mut(idx)
716 }
717}
718
719fn get_ex_data_from_ptr<'a, T>(ptr: *const SSL, idx: c_int) -> Option<&'a mut T> {
720 unsafe {
721 let data = SSL_get_ex_data(ptr, idx) as *mut T;
722 data.as_mut()
723 }
724}
725
726fn get_cipher_from_ptr(cipher: *const SSL_CIPHER) -> Result<crypto::Algorithm> {
727 let cipher_id = unsafe { SSL_CIPHER_get_id(cipher) };
728
729 let alg = match cipher_id {
730 0x0300_1301 => crypto::Algorithm::AES128_GCM,
731 0x0300_1302 => crypto::Algorithm::AES256_GCM,
732 0x0300_1303 => crypto::Algorithm::ChaCha20_Poly1305,
733 _ => return Err(Error::TlsFail),
734 };
735
736 Ok(alg)
737}
738
739extern "C" fn set_read_secret(
740 ssl: *mut SSL, level: crypto::Level, cipher: *const SSL_CIPHER,
741 secret: *const u8, secret_len: usize,
742) -> c_int {
743 let ex_data = match ExData::from_ssl_ptr(ssl) {
744 Some(v) => v,
745
746 None => return 0,
747 };
748
749 trace!("{} set read secret lvl={:?}", ex_data.trace_id, level);
750
751 let space = match level {
752 crypto::Level::Initial =>
753 &mut ex_data.pkt_num_spaces[packet::Epoch::Initial],
754 crypto::Level::ZeroRTT =>
755 &mut ex_data.pkt_num_spaces[packet::Epoch::Application],
756 crypto::Level::Handshake =>
757 &mut ex_data.pkt_num_spaces[packet::Epoch::Handshake],
758 crypto::Level::OneRTT =>
759 &mut ex_data.pkt_num_spaces[packet::Epoch::Application],
760 };
761
762 let aead = match get_cipher_from_ptr(cipher) {
763 Ok(v) => v,
764
765 Err(_) => return 0,
766 };
767
768 if level != crypto::Level::ZeroRTT || ex_data.is_server {
770 let secret = unsafe { slice::from_raw_parts(secret, secret_len) };
771
772 let open = match crypto::Open::from_secret(aead, secret) {
773 Ok(v) => v,
774
775 Err(_) => return 0,
776 };
777
778 if level == crypto::Level::ZeroRTT {
779 space.crypto_0rtt_open = Some(open);
780 return 1;
781 }
782
783 space.crypto_open = Some(open);
784 }
785
786 1
787}
788
789extern "C" fn set_write_secret(
790 ssl: *mut SSL, level: crypto::Level, cipher: *const SSL_CIPHER,
791 secret: *const u8, secret_len: usize,
792) -> c_int {
793 let ex_data = match ExData::from_ssl_ptr(ssl) {
794 Some(v) => v,
795
796 None => return 0,
797 };
798
799 trace!("{} set write secret lvl={:?}", ex_data.trace_id, level);
800
801 let space = match level {
802 crypto::Level::Initial =>
803 &mut ex_data.pkt_num_spaces[packet::Epoch::Initial],
804 crypto::Level::ZeroRTT =>
805 &mut ex_data.pkt_num_spaces[packet::Epoch::Application],
806 crypto::Level::Handshake =>
807 &mut ex_data.pkt_num_spaces[packet::Epoch::Handshake],
808 crypto::Level::OneRTT =>
809 &mut ex_data.pkt_num_spaces[packet::Epoch::Application],
810 };
811
812 let aead = match get_cipher_from_ptr(cipher) {
813 Ok(v) => v,
814
815 Err(_) => return 0,
816 };
817
818 if level != crypto::Level::ZeroRTT || !ex_data.is_server {
820 let secret = unsafe { slice::from_raw_parts(secret, secret_len) };
821
822 let seal = match crypto::Seal::from_secret(aead, secret) {
823 Ok(v) => v,
824
825 Err(_) => return 0,
826 };
827
828 space.crypto_seal = Some(seal);
829 }
830
831 1
832}
833
834extern "C" fn add_handshake_data(
835 ssl: *mut SSL, level: crypto::Level, data: *const u8, len: usize,
836) -> c_int {
837 let ex_data = match ExData::from_ssl_ptr(ssl) {
838 Some(v) => v,
839
840 None => return 0,
841 };
842
843 trace!(
844 "{} write message lvl={:?} len={}",
845 ex_data.trace_id,
846 level,
847 len
848 );
849
850 let buf = unsafe { slice::from_raw_parts(data, len) };
851
852 let space = match level {
853 crypto::Level::Initial =>
854 &mut ex_data.pkt_num_spaces[packet::Epoch::Initial],
855 crypto::Level::ZeroRTT => unreachable!(),
856 crypto::Level::Handshake =>
857 &mut ex_data.pkt_num_spaces[packet::Epoch::Handshake],
858 crypto::Level::OneRTT =>
859 &mut ex_data.pkt_num_spaces[packet::Epoch::Application],
860 };
861
862 if space.crypto_stream.send.write(buf, false).is_err() {
863 return 0;
864 }
865
866 1
867}
868
869extern "C" fn flush_flight(_ssl: *mut SSL) -> c_int {
870 1
874}
875
876extern "C" fn send_alert(
877 ssl: *mut SSL, level: crypto::Level, alert: u8,
878) -> c_int {
879 let ex_data = match ExData::from_ssl_ptr(ssl) {
880 Some(v) => v,
881
882 None => return 0,
883 };
884
885 trace!(
886 "{} send alert lvl={:?} alert={:x}",
887 ex_data.trace_id,
888 level,
889 alert
890 );
891
892 let error: u64 = TLS_ALERT_ERROR + u64::from(alert);
893 *ex_data.local_error = Some(ConnectionError {
894 is_app: false,
895 error_code: error,
896 reason: Vec::new(),
897 });
898
899 1
900}
901
902extern "C" fn keylog(ssl: *const SSL, line: *const c_char) {
903 let ex_data = match ExData::from_ssl_ptr(ssl) {
904 Some(v) => v,
905
906 None => return,
907 };
908
909 if let Some(keylog) = &mut ex_data.keylog {
910 let data = unsafe { ffi::CStr::from_ptr(line).to_bytes() };
911
912 let mut full_line = Vec::with_capacity(data.len() + 1);
913 full_line.extend_from_slice(data);
914 full_line.push(b'\n');
915
916 keylog.write_all(&full_line[..]).ok();
917 keylog.flush().ok();
918 }
919}
920
921extern "C" fn select_alpn(
922 ssl: *mut SSL, out: *mut *const u8, out_len: *mut u8, inp: *mut u8,
923 in_len: c_uint, _arg: *mut c_void,
924) -> c_int {
925 let ex_data = match ExData::from_ssl_ptr(ssl) {
937 Some(v) => v,
938
939 None => return TLS_ERROR,
940 };
941
942 if ex_data.application_protos.is_empty() {
943 return TLS_ERROR;
944 }
945
946 let mut protos = octets::Octets::with_slice(unsafe {
947 slice::from_raw_parts(inp, in_len as usize)
948 });
949
950 while let Ok(proto) = protos.get_bytes_with_u8_length() {
951 let found = ex_data.application_protos.iter().any(|expected| {
952 trace!(
953 "checking peer ALPN {:?} against {:?}",
954 std::str::from_utf8(proto.as_ref()),
955 std::str::from_utf8(expected.as_slice())
956 );
957
958 if expected.len() == proto.len() &&
959 expected.as_slice() == proto.as_ref()
960 {
961 unsafe {
962 *out = expected.as_slice().as_ptr();
963 *out_len = expected.len() as u8;
964 }
965
966 return true;
967 }
968
969 false
970 });
971
972 if found {
973 return 0; }
975 }
976
977 TLS_ERROR
978}
979
980extern "C" fn new_session(ssl: *mut SSL, session: *mut SSL_SESSION) -> c_int {
981 let ex_data = match ExData::from_ssl_ptr(ssl) {
982 Some(v) => v,
983
984 None => return 0,
985 };
986
987 let handshake = Handshake::new(ssl);
988 let peer_params = handshake.quic_transport_params();
989
990 let session_bytes = match get_session_bytes(session) {
992 Ok(v) => v,
993 Err(_) => return 0,
994 };
995
996 let mut buffer =
997 Vec::with_capacity(8 + peer_params.len() + 8 + session_bytes.len());
998
999 let session_bytes_len = session_bytes.len() as u64;
1000
1001 if buffer.write(&session_bytes_len.to_be_bytes()).is_err() {
1002 std::mem::forget(handshake);
1003 return 0;
1004 }
1005
1006 if buffer.write(&session_bytes).is_err() {
1007 std::mem::forget(handshake);
1008 return 0;
1009 }
1010
1011 let peer_params_len = peer_params.len() as u64;
1012
1013 if buffer.write(&peer_params_len.to_be_bytes()).is_err() {
1014 std::mem::forget(handshake);
1015 return 0;
1016 }
1017
1018 if buffer.write(peer_params).is_err() {
1019 std::mem::forget(handshake);
1020 return 0;
1021 }
1022
1023 *ex_data.session = Some(buffer);
1024
1025 std::mem::forget(handshake);
1027
1028 0
1029}
1030
1031pub fn map_result(bssl_result: c_int) -> Result<()> {
1032 match bssl_result {
1033 1 => Ok(()),
1034 _ => Err(Error::TlsFail),
1035 }
1036}
1037
1038pub fn map_result_zero_is_success(bssl_result: c_int) -> Result<()> {
1039 match bssl_result {
1040 0 => Ok(()),
1041 _ => Err(Error::TlsFail),
1042 }
1043}
1044
1045pub fn map_result_ptr<'a, T>(bssl_result: *const T) -> Result<&'a T> {
1046 match unsafe { bssl_result.as_ref() } {
1047 Some(v) => Ok(v),
1048 None => Err(Error::TlsFail),
1049 }
1050}
1051
1052fn log_ssl_error() {
1053 let mut err = [0u8; 1024];
1054
1055 unsafe {
1056 let e = ERR_peek_error();
1057 ERR_error_string_n(e, err.as_mut_ptr() as *mut c_char, err.len());
1058 }
1059
1060 let cstr = ffi::CStr::from_bytes_until_nul(&err)
1061 .expect("ERR_error_string_n should write a null terminated string");
1062
1063 trace!(
1064 "{}",
1065 cstr.to_str()
1066 .expect("ERR_error_string_n should create a valid UTF-8 message")
1067 );
1068}
1069
1070extern "C" {
1071 fn TLS_method() -> *const SSL_METHOD;
1076
1077 fn SSL_CTX_new(method: *const SSL_METHOD) -> *mut SSL_CTX;
1079 fn SSL_CTX_free(ctx: *mut SSL_CTX);
1080
1081 fn SSL_CTX_use_certificate_chain_file(
1082 ctx: *mut SSL_CTX, file: *const c_char,
1083 ) -> c_int;
1084
1085 fn SSL_CTX_use_PrivateKey_file(
1086 ctx: *mut SSL_CTX, file: *const c_char, ty: c_int,
1087 ) -> c_int;
1088
1089 fn SSL_CTX_load_verify_locations(
1090 ctx: *mut SSL_CTX, file: *const c_char, path: *const c_char,
1091 ) -> c_int;
1092
1093 #[cfg(not(windows))]
1094 fn SSL_CTX_set_default_verify_paths(ctx: *mut SSL_CTX) -> c_int;
1095
1096 #[cfg(windows)]
1097 fn SSL_CTX_get_cert_store(ctx: *mut SSL_CTX) -> *mut X509_STORE;
1098
1099 fn SSL_CTX_set_verify(
1100 ctx: *mut SSL_CTX, mode: c_int,
1101 cb: Option<
1102 unsafe extern "C" fn(
1103 ok: c_int,
1104 store_ctx: *mut X509_STORE_CTX,
1105 ) -> c_int,
1106 >,
1107 );
1108
1109 fn SSL_CTX_set_keylog_callback(
1110 ctx: *mut SSL_CTX,
1111 cb: Option<unsafe extern "C" fn(ssl: *const SSL, line: *const c_char)>,
1112 );
1113
1114 fn SSL_CTX_set_alpn_protos(
1115 ctx: *mut SSL_CTX, protos: *const u8, protos_len: usize,
1116 ) -> c_int;
1117
1118 fn SSL_CTX_set_alpn_select_cb(
1119 ctx: *mut SSL_CTX,
1120 cb: Option<
1121 unsafe extern "C" fn(
1122 ssl: *mut SSL,
1123 out: *mut *const u8,
1124 out_len: *mut u8,
1125 inp: *mut u8,
1126 in_len: c_uint,
1127 arg: *mut c_void,
1128 ) -> c_int,
1129 >,
1130 arg: *mut c_void,
1131 );
1132
1133 fn SSL_CTX_sess_set_new_cb(
1134 ctx: *mut SSL_CTX,
1135 cb: Option<
1136 unsafe extern "C" fn(
1137 ssl: *mut SSL,
1138 session: *mut SSL_SESSION,
1139 ) -> c_int,
1140 >,
1141 );
1142
1143 fn SSL_new(ctx: *mut SSL_CTX) -> *mut SSL;
1144
1145 fn SSL_get_error(ssl: *const SSL, ret_code: c_int) -> c_int;
1146
1147 fn SSL_set_accept_state(ssl: *mut SSL);
1148 fn SSL_set_connect_state(ssl: *mut SSL);
1149
1150 fn SSL_get0_param(ssl: *mut SSL) -> *mut X509_VERIFY_PARAM;
1151
1152 fn SSL_set_ex_data(ssl: *mut SSL, idx: c_int, ptr: *mut c_void) -> c_int;
1153 fn SSL_get_ex_data(ssl: *const SSL, idx: c_int) -> *mut c_void;
1154
1155 fn SSL_get_current_cipher(ssl: *const SSL) -> *const SSL_CIPHER;
1156
1157 fn SSL_set_session(ssl: *mut SSL, session: *mut SSL_SESSION) -> c_int;
1158
1159 fn SSL_get_SSL_CTX(ssl: *const SSL) -> *mut SSL_CTX;
1160
1161 fn SSL_set_quiet_shutdown(ssl: *mut SSL, mode: c_int);
1162
1163 fn SSL_set_quic_transport_params(
1164 ssl: *mut SSL, params: *const u8, params_len: usize,
1165 ) -> c_int;
1166
1167 fn SSL_set_quic_method(
1168 ssl: *mut SSL, quic_method: *const SSL_QUIC_METHOD,
1169 ) -> c_int;
1170
1171 fn SSL_set_quic_use_legacy_codepoint(ssl: *mut SSL, use_legacy: c_int);
1172
1173 #[cfg(test)]
1174 fn SSL_set_options(ssl: *mut SSL, opts: u32) -> u32;
1175
1176 fn SSL_get_peer_quic_transport_params(
1177 ssl: *const SSL, out_params: *mut *const u8, out_params_len: *mut usize,
1178 );
1179
1180 fn SSL_get0_alpn_selected(
1181 ssl: *const SSL, out: *mut *const u8, out_len: *mut u32,
1182 );
1183
1184 fn SSL_get_servername(ssl: *const SSL, ty: c_int) -> *const c_char;
1185
1186 fn SSL_provide_quic_data(
1187 ssl: *mut SSL, level: crypto::Level, data: *const u8, len: usize,
1188 ) -> c_int;
1189
1190 fn SSL_process_quic_post_handshake(ssl: *mut SSL) -> c_int;
1191
1192 fn SSL_do_handshake(ssl: *mut SSL) -> c_int;
1193
1194 fn SSL_quic_write_level(ssl: *const SSL) -> crypto::Level;
1195
1196 fn SSL_session_reused(ssl: *const SSL) -> c_int;
1197
1198 fn SSL_in_init(ssl: *const SSL) -> c_int;
1199
1200 fn SSL_clear(ssl: *mut SSL) -> c_int;
1201
1202 fn SSL_free(ssl: *mut SSL);
1203
1204 fn SSL_CIPHER_get_id(cipher: *const SSL_CIPHER) -> c_uint;
1206
1207 fn SSL_SESSION_free(session: *mut SSL_SESSION);
1210
1211 fn X509_VERIFY_PARAM_set1_host(
1213 param: *mut X509_VERIFY_PARAM, name: *const c_char, namelen: usize,
1214 ) -> c_int;
1215
1216 #[cfg(windows)]
1218 fn X509_STORE_add_cert(ctx: *mut X509_STORE, x: *mut X509) -> c_int;
1219
1220 #[cfg(windows)]
1222 fn X509_free(x: *mut X509);
1223 #[cfg(windows)]
1224 fn d2i_X509(px: *mut X509, input: *const *const u8, len: c_int) -> *mut X509;
1225
1226 fn ERR_peek_error() -> c_uint;
1228
1229 fn ERR_error_string_n(err: c_uint, buf: *mut c_char, len: usize);
1230
1231 #[allow(dead_code)]
1233 fn OPENSSL_free(ptr: *mut c_void);
1234
1235}
1236
1237#[cfg(not(feature = "openssl"))]
1238mod boringssl;
1239#[cfg(not(feature = "openssl"))]
1240use boringssl::*;
1241
1242#[cfg(feature = "openssl")]
1243mod openssl_quictls;
1244#[cfg(feature = "openssl")]
1245use openssl_quictls::*;