Add RFC 5705 support

This commit is contained in:
Steven Fackler 2018-02-23 22:04:57 -08:00
parent c1a106fc68
commit f72f35e9bd
3 changed files with 82 additions and 2 deletions

View File

@ -2406,6 +2406,16 @@ extern "C" {
ctx: *mut SSL, ctx: *mut SSL,
dh: unsafe extern "C" fn(ssl: *mut SSL, is_export: c_int, keylength: c_int) -> *mut DH, 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)))] #[cfg(not(any(osslconf = "OPENSSL_NO_COMP", libressl)))]
pub fn SSL_COMP_get_name(comp: *const COMP_METHOD) -> *const c_char; pub fn SSL_COMP_get_name(comp: *const COMP_METHOD) -> *const c_char;

View File

@ -59,8 +59,7 @@
//! ``` //! ```
use ffi; use ffi;
use foreign_types::{ForeignType, ForeignTypeRef, Opaque}; use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
use libc::{c_int, c_long, c_ulong, c_void}; use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_ulong, c_void};
use libc::{c_uchar, c_uint};
use std::any::TypeId; use std::any::TypeId;
use std::cmp; use std::cmp;
use std::collections::HashMap; use std::collections::HashMap;
@ -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. /// Sets the session to be used.
/// ///
/// This should be called before the handshake to attempt to reuse a previously established /// This should be called before the handshake to attempt to reuse a previously established

View File

@ -1278,6 +1278,48 @@ fn new_session_callback() {
assert!(CALLED_BACK.load(Ordering::SeqCst)); 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 _check_kinds() {
fn is_send<T: Send>() {} fn is_send<T: Send>() {}
fn is_sync<T: Sync>() {} fn is_sync<T: Sync>() {}