Commit f72f35e9 authored by Steven Fackler's avatar Steven Fackler
Browse files

Add RFC 5705 support

parent c1a106fc
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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;
+30 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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
+42 −0
Original line number Diff line number Diff line
@@ -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>() {}