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