Loading openssl-sys/src/lib.rs +10 −0 Original line number Diff line number Diff line Loading @@ -2406,6 +2406,16 @@ extern "C" { ctx: *mut SSL, dh: unsafe extern "C" fn(ssl: *mut SSL, is_export: c_int, keylength: c_int) -> *mut DH, ); pub fn SSL_export_keying_material( s: *mut SSL, out: *mut c_uchar, olen: size_t, label: *const c_char, llen: size_t, context: *const c_uchar, contextlen: size_t, use_context: c_int, ) -> c_int; #[cfg(not(any(osslconf = "OPENSSL_NO_COMP", libressl)))] pub fn SSL_COMP_get_name(comp: *const COMP_METHOD) -> *const c_char; Loading openssl/src/ssl/mod.rs +30 −2 Original line number Diff line number Diff line Loading @@ -59,8 +59,7 @@ //! ``` use ffi; use foreign_types::{ForeignType, ForeignTypeRef, Opaque}; use libc::{c_int, c_long, c_ulong, c_void}; use libc::{c_uchar, c_uint}; use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_ulong, c_void}; use std::any::TypeId; use std::cmp; use std::collections::HashMap; Loading Loading @@ -2141,6 +2140,35 @@ impl SslRef { } } /// Derives keying material for application use in accordance to RFC 5705. /// /// This corresponds to [`SSL_export_keying_material`]. /// /// [`SSL_export_keying_material`]: https://www.openssl.org/docs/manmaster/man3/SSL_export_keying_material.html pub fn export_keying_material( &self, out: &mut [u8], label: &str, context: Option<&[u8]>, ) -> Result<(), ErrorStack> { unsafe { let (context, contextlen, use_context) = match context { Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1), None => (ptr::null(), 0, 0), }; cvt(ffi::SSL_export_keying_material( self.as_ptr(), out.as_mut_ptr() as *mut c_uchar, out.len(), label.as_ptr() as *const c_char, label.len(), context, contextlen, use_context, )).map(|_| ()) } } /// Sets the session to be used. /// /// This should be called before the handshake to attempt to reuse a previously established Loading openssl/src/ssl/test.rs +42 −0 Original line number Diff line number Diff line Loading @@ -1278,6 +1278,48 @@ fn new_session_callback() { assert!(CALLED_BACK.load(Ordering::SeqCst)); } #[test] fn keying_export() { let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let addr = listener.local_addr().unwrap(); let label = "EXPERIMENTAL test"; let context = b"my context"; let guard = thread::spawn(move || { let stream = listener.accept().unwrap().0; let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_certificate_file(&Path::new("test/cert.pem"), SslFiletype::PEM) .unwrap(); ctx.set_private_key_file(&Path::new("test/key.pem"), SslFiletype::PEM) .unwrap(); let ssl = Ssl::new(&ctx.build()).unwrap(); let stream = ssl.accept(stream).unwrap(); let mut buf = [0; 32]; stream .ssl() .export_keying_material(&mut buf, label, Some(context)) .unwrap(); buf }); let stream = TcpStream::connect(addr).unwrap(); let ctx = SslContext::builder(SslMethod::tls()).unwrap(); let ssl = Ssl::new(&ctx.build()).unwrap(); let stream = ssl.connect(stream).unwrap(); let mut buf = [1; 32]; stream .ssl() .export_keying_material(&mut buf, label, Some(context)) .unwrap(); let buf2 = guard.join().unwrap(); assert_eq!(buf, buf2); } fn _check_kinds() { fn is_send<T: Send>() {} fn is_sync<T: Sync>() {} Loading Loading
openssl-sys/src/lib.rs +10 −0 Original line number Diff line number Diff line Loading @@ -2406,6 +2406,16 @@ extern "C" { ctx: *mut SSL, dh: unsafe extern "C" fn(ssl: *mut SSL, is_export: c_int, keylength: c_int) -> *mut DH, ); pub fn SSL_export_keying_material( s: *mut SSL, out: *mut c_uchar, olen: size_t, label: *const c_char, llen: size_t, context: *const c_uchar, contextlen: size_t, use_context: c_int, ) -> c_int; #[cfg(not(any(osslconf = "OPENSSL_NO_COMP", libressl)))] pub fn SSL_COMP_get_name(comp: *const COMP_METHOD) -> *const c_char; Loading
openssl/src/ssl/mod.rs +30 −2 Original line number Diff line number Diff line Loading @@ -59,8 +59,7 @@ //! ``` use ffi; use foreign_types::{ForeignType, ForeignTypeRef, Opaque}; use libc::{c_int, c_long, c_ulong, c_void}; use libc::{c_uchar, c_uint}; use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_ulong, c_void}; use std::any::TypeId; use std::cmp; use std::collections::HashMap; Loading Loading @@ -2141,6 +2140,35 @@ impl SslRef { } } /// Derives keying material for application use in accordance to RFC 5705. /// /// This corresponds to [`SSL_export_keying_material`]. /// /// [`SSL_export_keying_material`]: https://www.openssl.org/docs/manmaster/man3/SSL_export_keying_material.html pub fn export_keying_material( &self, out: &mut [u8], label: &str, context: Option<&[u8]>, ) -> Result<(), ErrorStack> { unsafe { let (context, contextlen, use_context) = match context { Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1), None => (ptr::null(), 0, 0), }; cvt(ffi::SSL_export_keying_material( self.as_ptr(), out.as_mut_ptr() as *mut c_uchar, out.len(), label.as_ptr() as *const c_char, label.len(), context, contextlen, use_context, )).map(|_| ()) } } /// Sets the session to be used. /// /// This should be called before the handshake to attempt to reuse a previously established Loading
openssl/src/ssl/test.rs +42 −0 Original line number Diff line number Diff line Loading @@ -1278,6 +1278,48 @@ fn new_session_callback() { assert!(CALLED_BACK.load(Ordering::SeqCst)); } #[test] fn keying_export() { let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let addr = listener.local_addr().unwrap(); let label = "EXPERIMENTAL test"; let context = b"my context"; let guard = thread::spawn(move || { let stream = listener.accept().unwrap().0; let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_certificate_file(&Path::new("test/cert.pem"), SslFiletype::PEM) .unwrap(); ctx.set_private_key_file(&Path::new("test/key.pem"), SslFiletype::PEM) .unwrap(); let ssl = Ssl::new(&ctx.build()).unwrap(); let stream = ssl.accept(stream).unwrap(); let mut buf = [0; 32]; stream .ssl() .export_keying_material(&mut buf, label, Some(context)) .unwrap(); buf }); let stream = TcpStream::connect(addr).unwrap(); let ctx = SslContext::builder(SslMethod::tls()).unwrap(); let ssl = Ssl::new(&ctx.build()).unwrap(); let stream = ssl.connect(stream).unwrap(); let mut buf = [1; 32]; stream .ssl() .export_keying_material(&mut buf, label, Some(context)) .unwrap(); let buf2 = guard.join().unwrap(); assert_eq!(buf, buf2); } fn _check_kinds() { fn is_send<T: Send>() {} fn is_sync<T: Sync>() {} Loading