Commit c1f56954 authored by James Mayclin's avatar James Mayclin
Browse files

add peer temp key bindings

parent 8c219948
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -349,6 +349,7 @@ pub const SSL_CTRL_SET_ECDH_AUTO: c_int = 94;
pub const SSL_CTRL_SET_SIGALGS_LIST: c_int = 98;
#[cfg(ossl102)]
pub const SSL_CTRL_SET_VERIFY_CERT_STORE: c_int = 106;
pub const SSL_CTRL_GET_PEER_TMP_KEY: c_int = 109;
#[cfg(ossl110)]
pub const SSL_CTRL_GET_EXTMS_SUPPORT: c_int = 122;
#[cfg(any(ossl110, libressl261))]
@@ -359,6 +360,7 @@ pub const SSL_CTRL_SET_MAX_PROTO_VERSION: c_int = 124;
pub const SSL_CTRL_GET_MIN_PROTO_VERSION: c_int = 130;
#[cfg(any(ossl110g, libressl270))]
pub const SSL_CTRL_GET_MAX_PROTO_VERSION: c_int = 131;
pub const SSL_CTRL_GET_TMP_KEY: c_int = 133;

pub unsafe fn SSL_CTX_set_tmp_dh(ctx: *mut SSL_CTX, dh: *mut DH) -> c_long {
    SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_DH, 0, dh as *mut c_void)
@@ -507,6 +509,14 @@ cfg_if! {
    }
}

pub unsafe fn SSL_get_peer_tmp_key(ssl: *mut SSL, key: *mut *mut EVP_PKEY) -> c_int {
    SSL_ctrl(ssl, SSL_CTRL_GET_PEER_TMP_KEY, 0, key as *mut c_void) as c_int
}

pub unsafe fn SSL_get_tmp_key(ssl: *mut SSL, key: *mut *mut EVP_PKEY) -> c_int {
    SSL_ctrl(ssl, SSL_CTRL_GET_TMP_KEY, 0, key as *mut c_void) as c_int
}

#[cfg(ossl111)]
pub const SSL_CLIENT_HELLO_SUCCESS: c_int = 1;
#[cfg(ossl111)]
+32 −1
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ use crate::ex_data::Index;
use crate::hash::MessageDigest;
#[cfg(any(ossl110, libressl270))]
use crate::nid::Nid;
use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
use crate::pkey::{HasPrivate, PKey, PKeyRef, Params, Private, Public};
use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
use crate::ssl::bio::BioMethod;
use crate::ssl::callbacks::*;
@@ -3445,6 +3445,37 @@ impl SslRef {
    pub fn security_level(&self) -> u32 {
        unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
    }

    /// Get the temporary key provided by the peer that is used during key
    /// exchange.
    // We use an owned value because EVP_KEY free need to be called when it is
    // dropped
    #[corresponds(SSL_get_peer_tmp_key)]
    pub fn peer_temp_key(&self) -> Result<PKey<Public>, ErrorStack> {
        unsafe {
            let mut key = ptr::null_mut();
            match cvt(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
                Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
                Err(e) => Err(e),
            }
        }
    }

    /// Returns the temporary key from the local end of the connection that is
    /// used during key exchange.
    // We use an owned value because EVP_KEY free need to be called when it is
    // dropped
    #[corresponds(SSL_get_peer_tmp_key)]
    pub fn temp_key(&self) -> Result<PKey<Public>, ErrorStack> {
        unsafe {
            let mut key = ptr::null_mut();
            match cvt(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
                Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
                Err(e) => Err(e),
            }
        }
    }

}

/// An SSL stream midway through the handshake process.
+46 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ use crate::error::ErrorStack;
use crate::hash::MessageDigest;
#[cfg(not(boringssl))]
use crate::ocsp::{OcspResponse, OcspResponseStatus};
use crate::pkey::PKey;
use crate::pkey::{Id, PKey};
use crate::srtp::SrtpProfileId;
use crate::ssl::test::server::Server;
#[cfg(any(ossl110, ossl111, libressl261))]
@@ -322,6 +322,51 @@ fn state() {
    );
}

// when a connection uses ECDHE P-256 key exchange, then the temp key APIs
// return P-256 keys, and the peer and local keys are different.
#[test]
fn peer_temp_key_p384() {
    let mut server = Server::builder();
    server.ctx().set_groups_list("P-384").unwrap();
    let server = server.build();
    let s = server.client().connect();
    let peer_temp = s.ssl().peer_temp_key().unwrap();
    assert_eq!(peer_temp.id(), Id::EC);
    assert_eq!(peer_temp.bits(), 384);

    let local_temp = s.ssl().temp_key().unwrap();
    assert_eq!(local_temp.id(), Id::EC);
    assert_eq!(local_temp.bits(), 384);

    assert_ne!(
        peer_temp.ec_key().unwrap().public_key_to_der().unwrap(),
        local_temp.ec_key().unwrap().public_key_to_der().unwrap(),
    );
}

// when a connection uses RSA key exchange, then the peer (server) temp key is
// an Error because there is no temp key, and the local (client) temp key is the
// temp key sent in the initial key share.
#[test]
fn peer_temp_key_rsa() {
    let mut server = Server::builder();
    server.ctx().set_cipher_list("RSA").unwrap();
    // RSA key exchange is not allowed in TLS 1.3, so force the connection
    // to negotiate TLS 1.2
    server.ctx().set_max_proto_version(Some(SslVersion::TLS1_2)).unwrap();
    let server = server.build();
    let mut client = server.client();
    client.ctx().set_groups_list("P-521").unwrap();
    let s = client.connect();
    let peer_temp = s.ssl().peer_temp_key();
    assert!(peer_temp.is_err());

    // this is the temp key that the client sent in the initial key share
    let local_temp = s.ssl().temp_key().unwrap();
    assert_eq!(local_temp.id(), Id::EC);
    assert_eq!(local_temp.bits(), 521);
}

/// Tests that when both the client as well as the server use SRTP and their
/// lists of supported protocols have an overlap -- with only ONE protocol
/// being valid for both.