Skip to content

Commit

Permalink
add sni
Browse files Browse the repository at this point in the history
  • Loading branch information
axos88 committed Sep 26, 2022
1 parent 2496870 commit b551597
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 7 deletions.
52 changes: 45 additions & 7 deletions src/http/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ use crate::private::mutex::{Mutex, RawMutex};
pub struct CHttpsSslConfig(pub httpd_ssl_config_t);


#[cfg(all(esp_idf_esp_tls_server_sni_hook, esp_idf_comp_esp_http_server_enabled))]
use super::sni::*;

#[derive(Copy, Clone, Debug)]
pub struct Configuration {
pub http_port: u16,
Expand Down Expand Up @@ -92,7 +95,7 @@ impl From<&Configuration> for Newtype<httpd_config_t> {
}
}

#[derive(Debug)]
#[cfg_attr(not(esp_idf_esp_tls_server_sni_hook), derive(Debug))]
pub struct SslConfiguration<'a> {
pub http_configuration: Configuration,
pub client_verify_cert: Option<&'a str>,
Expand All @@ -103,17 +106,40 @@ pub struct SslConfiguration<'a> {
#[cfg(esp_idf_version_major = "5")]
pub use_secure_element: bool,
pub session_tickets: bool,

#[cfg(esp_idf_esp_tls_server_sni_hook)]
pub sni: Option<Box<dyn SNICB<'a>>>,
}

#[cfg(esp_idf_esp_tls_server_sni_hook)]
impl<'a> Debug for SslConfiguration<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {

let sni_s = if self.sni.is_some() {
"Some(..)"
} else { "None" };

f.write_fmt(format_args!(
"SslConfiguration {{ http_configuration = {:?}, client_verify_cert = {:?}, cacert = {:?}, prvtkey = {:?}, transport_mode_secure = {:?}, session_tickets = {:?}, use_secure_element = {:?}, sni = {:?} }}",
self.http_configuration,
self.client_verify_cert,
self.cacert,
self.prvtkey,
self.transport_mode_secure,
self.use_secure_element,
self.session_tickets,
sni_s
))
}
}


impl<'a> From<&SslConfiguration<'a>> for Newtype<httpd_config_t> {
fn from(conf: &SslConfiguration<'a>) -> Self {
Self::from(&conf.http_configuration)
}
}




#[cfg(esp_idf_version_major = "5")]
impl<'a> From<&SslConfiguration<'a>> for CHttpsSslConfig {
fn from(conf: &SslConfiguration) -> Self {
Expand All @@ -137,6 +163,10 @@ impl<'a> From<&SslConfiguration<'a>> for CHttpsSslConfig {
port_insecure: conf.http_configuration.http_port,
session_tickets: conf.session_tickets,
user_cb: None,
#[cfg(esp_idf_esp_tls_server_sni_hook)]
sni_callback: Some(sni_trampoline),
#[cfg(esp_idf_esp_tls_server_sni_hook)]
sni_callback_p_info: conf.sni.as_ref().map(|cb| cb as *const _ as *mut c_types::c_void).unwrap_or(ptr::null_mut() as _),
})
}
}
Expand All @@ -163,7 +193,11 @@ impl<'a> From<&SslConfiguration<'a>> for CHttpsSslConfig {
port_insecure: conf.http_configuration.http_port,
use_secure_element: false,
session_tickets: conf.session_tickets,
user_cb: None
user_cb: None,
#[cfg(esp_idf_esp_tls_server_sni_hook)]
sni_callback: Some(sni_trampoline),
#[cfg(esp_idf_esp_tls_server_sni_hook)]
sni_callback_p_info: conf.sni.as_ref().map(|cb| cb as *const _ as *mut c_types::c_void).unwrap_or(ptr::null_mut() as _),
})
}
}
Expand All @@ -176,7 +210,12 @@ impl<'a> Default for SslConfiguration<'a> {
cacert: None,
prvtkey: None,
transport_mode_secure: true,
session_tickets: false
session_tickets: false,
#[cfg(esp_idf_version_major = "5")]
use_secure_element: false,

#[cfg(esp_idf_esp_tls_server_sni_hook)]
sni: None
}
}
}
Expand Down Expand Up @@ -219,7 +258,6 @@ impl Drop for CHttpsSslConfig {
}
}


#[allow(non_upper_case_globals)]
impl From<Newtype<c_types::c_uint>> for Method {
fn from(method: Newtype<c_types::c_uint>) -> Self {
Expand Down
85 changes: 85 additions & 0 deletions src/http/sni.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use std::ffi::CStr;
use std::ptr;
use esp_idf_sys::*;
use log::*;

// Workaround for unstable feature 'trait_alias'
pub trait SNICB<'a>: FnMut(&'a str) -> SNIResult<'a> { }

// Workaround for unstable feature 'trait_alias'
impl<'a, T> SNICB<'a> for T
where T: FnMut(&'a str) -> SNIResult<'a> {
}

pub struct HandshakeServerCertificate<'a> {
pub pk: &'a mut mbedtls_pk_context,
pub cert: &'a mut mbedtls_x509_crt,
}

pub struct HandshakeCertifiacteAuthority<'a> {
pub ca: &'a mut mbedtls_x509_crt,
pub crl: &'a mut mbedtls_x509_crl,
}

pub struct HandshakeVerifyMode(c_types::c_int);

pub struct SNIResult<'a> {
server_certificate: Option<HandshakeServerCertificate<'a>>,
certificate_authority: Option<HandshakeCertifiacteAuthority<'a>>,
verify_mode: Option<HandshakeVerifyMode>
}

impl<'a> SNIResult<'a> {
pub fn new() -> SNIResult<'a> { SNIResult { server_certificate: None, certificate_authority: None, verify_mode: None }}

pub fn set_hs_server_certficate(mut self, pk: &'a mut mbedtls_pk_context, cert: &'a mut mbedtls_x509_crt) -> SNIResult<'a> {
self.server_certificate = Some(HandshakeServerCertificate { pk, cert });
self
}

pub fn set_hs_certificate_authority(mut self, ca: &'a mut mbedtls_x509_crt, crl: &'a mut mbedtls_x509_crl) -> SNIResult<'a> {
self.certificate_authority = Some(HandshakeCertifiacteAuthority { ca, crl });
self
}

pub fn set_hs_verify_mode(mut self, verify_mode: u32) -> SNIResult<'a> {
self.verify_mode = Some(HandshakeVerifyMode(verify_mode as _));
self
}
}

unsafe extern "C" fn f_rng(_arg: *mut c_types::c_void, ptr: *mut u8 , bytes: u32) -> i32 {
esp_fill_random(ptr as _, bytes);
bytes as _
}

pub(crate) unsafe extern "C" fn sni_trampoline<'a>(p_info: *mut c_types::c_void, ssl: *mut mbedtls_ssl_context, name: *const c_types::c_uchar, _len: c_types::c_uint) -> esp_err_t
{
let cb = &mut *(p_info as *mut Box<dyn SNICB<'a>>);

let name = CStr::from_ptr(name as _).to_str().unwrap();

let SNIResult { server_certificate, certificate_authority, verify_mode } = cb(name);

if let Some(HandshakeServerCertificate { pk, cert }) = server_certificate {
if let Err(err) = esp!(mbedtls_pk_check_pair(&mut cert.pk, pk, Some(f_rng), ptr::null_mut())) {
error!("Certificate and private key supplied by the SNI callback do not match: {:?}", err);
return err.code()
};

if let Err(err) = esp!(mbedtls_ssl_set_hs_own_cert(ssl, cert, pk)) {
error!("Could not set handshake certificate and private key: {:?}", err);
return err.code()
};
};

if let Some(HandshakeCertifiacteAuthority { ca, crl }) = certificate_authority {
mbedtls_ssl_set_hs_ca_chain(ssl, ca, crl)
};

if let Some(HandshakeVerifyMode(authmode)) = verify_mode {
mbedtls_ssl_set_hs_authmode(ssl, authmode)
};

return ESP_OK;
}

0 comments on commit b551597

Please sign in to comment.