-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TLS & DTLS fixes #445
TLS & DTLS fixes #445
Changes from 6 commits
d37eae8
b0e0f61
f9c8f06
49898b1
3108d92
a30ae7a
88b73ad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ use std::{ | |
io::{self, Read, Write}, | ||
marker::PhantomData, | ||
pin::Pin, | ||
ptr::NonNull, | ||
rc::Rc, | ||
task::{Context, Poll}, | ||
time::{Duration, Instant}, | ||
|
@@ -29,19 +30,22 @@ use crate::esp32::esp_idf_svc::sys::{ | |
mbedtls_ssl_config_init, mbedtls_ssl_context, mbedtls_ssl_free, mbedtls_ssl_handshake, | ||
mbedtls_ssl_init, mbedtls_ssl_read, mbedtls_ssl_set_bio, mbedtls_ssl_set_timer_cb, | ||
mbedtls_ssl_setup, mbedtls_ssl_write, mbedtls_x509_crt, mbedtls_x509_crt_free, | ||
mbedtls_x509_crt_init, mbedtls_x509_crt_parse_der, MBEDTLS_ERR_NET_RECV_FAILED, | ||
MBEDTLS_ERR_NET_SEND_FAILED, MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY, MBEDTLS_ERR_SSL_TIMEOUT, | ||
MBEDTLS_ERR_SSL_WANT_READ, MBEDTLS_ERR_SSL_WANT_WRITE, MBEDTLS_SSL_IS_SERVER, | ||
MBEDTLS_SSL_PRESET_DEFAULT, MBEDTLS_SSL_TRANSPORT_DATAGRAM, | ||
mbedtls_x509_crt_init, mbedtls_x509_crt_parse_der, MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY, | ||
MBEDTLS_ERR_SSL_TIMEOUT, MBEDTLS_ERR_SSL_WANT_READ, MBEDTLS_ERR_SSL_WANT_WRITE, | ||
MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_PRESET_DEFAULT, MBEDTLS_SSL_TRANSPORT_DATAGRAM, | ||
}; | ||
use async_io::Timer; | ||
use core::ffi::CStr; | ||
use esp_idf_svc::sys::esp_tls_get_ssl_context; | ||
use futures_lite::{AsyncRead, AsyncWrite, Future}; | ||
use log::{log, Level}; | ||
use thiserror::Error; | ||
|
||
use super::tcp::Esp32TLSContext; | ||
|
||
const MBEDTLS_ERR_NET_SEND_FAILED: i32 = -0x4E; | ||
const MBEDTLS_ERR_NET_RECV_FAILED: i32 = -0x4C; | ||
|
||
extern "C" { | ||
fn mbedtls_debug_set_threshold(level: c_int); | ||
} | ||
|
@@ -62,7 +66,6 @@ unsafe extern "C" fn mbedtls_net_write<S: AsyncWrite>( | |
if state.error.as_ref().unwrap().kind() == std::io::ErrorKind::WouldBlock { | ||
return MBEDTLS_ERR_SSL_WANT_WRITE; | ||
} | ||
// TODO(RSDK-10189): This constant is not exported in ESP-IDF 5 | ||
MBEDTLS_ERR_NET_SEND_FAILED | ||
} | ||
} | ||
|
@@ -87,7 +90,7 @@ unsafe extern "C" fn mbedtls_net_read<S: AsyncRead>( | |
if state.error.as_ref().unwrap().kind() == std::io::ErrorKind::WouldBlock { | ||
return MBEDTLS_ERR_SSL_WANT_READ; | ||
} | ||
// TODO(RSDK-10189): This constant is not exported in ESP-IDF 5 | ||
|
||
MBEDTLS_ERR_NET_RECV_FAILED | ||
} | ||
} | ||
|
@@ -228,7 +231,7 @@ extern "C" fn mbedtls_timing_dtls_set_delay<S>( | |
} else if let Some(ssl_ctx) = ctx.ssl_ctx { | ||
let (_, cx) = unsafe { | ||
// TODO(RSDK-10196): The `p_bio` field doesn't exist in ESP-IDF 5. Maybe it should be `private_p_bio`? | ||
let state = SSLStreamInner::<S>::from_raw((*ssl_ctx).p_bio); | ||
let state = SSLStreamInner::<S>::from_raw((*ssl_ctx).private_p_bio); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we shouldn't do that. We could use a user_data field in the ssl context struct alternatively (it is private as well) however it's accessor functions are inline and therefore not exported by bindgen There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this hinting that we are somehow misusing mbedtls, that we suddenly need access to "private" state? Or do you think this is more a flaw in the rust bindings, in that we can't make use of the user_data field? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. bindgen doesn't export inlined functions. MbedTLS discourage accessing private field directly I think they just want some stable API |
||
state.as_parts() | ||
}; | ||
|
||
|
@@ -251,7 +254,7 @@ extern "C" fn mbedtls_timing_get_delay<S>(data: *mut c_void) -> c_int { | |
if let Some(ssl_ctx) = ctx.ssl_ctx { | ||
let (_, cx) = unsafe { | ||
// TODO(RSDK-10196): The `p_bio` field doesn't exist in ESP-IDF 5. Maybe it should be `private_p_bio`? | ||
let state = SSLStreamInner::<S>::from_raw((*ssl_ctx).p_bio); | ||
let state = SSLStreamInner::<S>::from_raw((*ssl_ctx).private_p_bio); | ||
state.as_parts() | ||
}; | ||
ctx.poll_delay(cx); | ||
|
@@ -332,6 +335,8 @@ impl DtlsSSLContext { | |
certificate.get_der_keypair().len(), | ||
std::ptr::null(), | ||
0, | ||
Some(mbedtls_entropy_func), | ||
self.dtls_entropy.as_mut() as *mut mbedtls_entropy_context as *mut _, | ||
) | ||
}; | ||
if ret != 0 { | ||
|
@@ -420,7 +425,6 @@ impl DtlsSSLContext { | |
if ret != 0 { | ||
return Err(SSLError::SSLConfigFailure(ret)); | ||
} | ||
|
||
unsafe { | ||
self.timer_ctx.ssl_ctx = Some(self.ssl_ctx.as_mut()); | ||
mbedtls_ssl_set_timer_cb( | ||
|
@@ -511,7 +515,13 @@ impl SSLContext { | |
match self { | ||
SSLContext::DtlsSSLContext(context) => context.ssl_ctx.as_mut(), | ||
// TODO(RSDK-10198): The `ssl` field here no longer works in ESP-IDF 5 | ||
SSLContext::Esp32TLSContext(context) => unsafe { &mut (*(**context)).ssl }, // potentially needs read_unaligned | ||
SSLContext::Esp32TLSContext(context) => unsafe { | ||
NonNull::<mbedtls_ssl_context>::new( | ||
esp_tls_get_ssl_context(**context) as *mut mbedtls_ssl_context | ||
) | ||
.expect("ssl context pointer is null") | ||
.as_ptr() | ||
}, | ||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,8 +3,8 @@ use async_io::Async; | |
|
||
use esp_idf_svc::sys::{ | ||
esp, esp_crt_bundle_attach, esp_tls_cfg, esp_tls_cfg_server, esp_tls_conn_destroy, | ||
esp_tls_init, esp_tls_role_ESP_TLS_CLIENT, esp_tls_role_ESP_TLS_SERVER, esp_tls_t, | ||
mbedtls_ssl_conf_read_timeout, EspError, | ||
esp_tls_get_ssl_context, esp_tls_init, esp_tls_server_session_create, esp_tls_t, | ||
mbedtls_ssl_conf_read_timeout, mbedtls_ssl_config, mbedtls_ssl_context, EspError, | ||
}; | ||
use futures_lite::FutureExt; | ||
use futures_lite::{ready, AsyncRead, AsyncWrite, Future}; | ||
|
@@ -98,11 +98,12 @@ impl Esp32ServerConfig { | |
}, | ||
serverkey_password: std::ptr::null(), | ||
serverkey_password_len: 0_u32, | ||
..Default::default() | ||
}); | ||
Self { cfg, alpn_proto } | ||
} | ||
fn get_cfg_ptr(&self) -> *const esp_tls_cfg_server { | ||
&*self.cfg as *const _ | ||
fn get_cfg_ptr_mut(&mut self) -> *mut esp_tls_cfg_server { | ||
&mut *self.cfg as *mut _ | ||
} | ||
} | ||
|
||
|
@@ -143,13 +144,13 @@ impl Esp32ClientConfig { | |
use_global_ca_store: false, | ||
skip_common_name: false, | ||
keep_alive_cfg: std::ptr::null_mut(), | ||
psk_hint_key: std::ptr::null(), | ||
crt_bundle_attach: Some(esp_crt_bundle_attach), | ||
ds_data: std::ptr::null_mut(), | ||
if_name: std::ptr::null_mut(), | ||
is_plain_tcp: false, | ||
timeout_ms: 50000, | ||
common_name: std::ptr::null(), | ||
..Default::default() | ||
}); | ||
Self { cfg, alpn_proto } | ||
} | ||
|
@@ -204,26 +205,17 @@ impl<IO> Esp32Accept<IO> | |
where | ||
IO: AsyncRead + AsyncWrite + Unpin + AsRawFd, | ||
{ | ||
fn new(stream: IO, cfg: Esp32ServerConfig) -> Result<Self, std::io::Error> { | ||
fn new(stream: IO, mut cfg: Esp32ServerConfig) -> Result<Self, std::io::Error> { | ||
let tls_context = Esp32TLSContext::new()?; | ||
unsafe { | ||
std::ptr::write_unaligned( | ||
// TODO(RSDK-10201): The field `role` is not found when using ESP-IDF 5 | ||
std::ptr::addr_of_mut!((*(*tls_context)).role), | ||
esp_tls_role_ESP_TLS_SERVER, | ||
) | ||
}; | ||
// TODO(RSDK-10201): The field `sockfd` is not found when using ESP-IDF 5 | ||
unsafe { std::ptr::write_unaligned(std::ptr::addr_of_mut!((*(*tls_context)).sockfd), -1) }; | ||
unsafe { | ||
esp!(esp_create_mbedtls_handle( | ||
std::ptr::null_mut(), | ||
0, | ||
cfg.get_cfg_ptr() as *const c_void, | ||
esp!(esp_tls_server_session_create( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice to see the |
||
cfg.get_cfg_ptr_mut(), | ||
stream.as_raw_fd(), | ||
*tls_context | ||
)) | ||
.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))? | ||
}; | ||
} | ||
.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))?; | ||
|
||
let io = AsyncSSLStream::new(SSLContext::Esp32TLSContext(tls_context), stream).unwrap(); | ||
Ok(Self { | ||
cfg: Arc::new(cfg), | ||
|
@@ -330,15 +322,6 @@ where | |
fn new(stream: IO, cfg: Esp32ClientConfig, addr: &Uri) -> Result<Self, std::io::Error> { | ||
let tls_context = Esp32TLSContext::new()?; | ||
|
||
unsafe { | ||
std::ptr::write_unaligned( | ||
// TODO(RSDK-10201): The field `role` is not found when using ESP-IDF 5 | ||
std::ptr::addr_of_mut!((*(*tls_context)).role), | ||
esp_tls_role_ESP_TLS_CLIENT, | ||
) | ||
}; | ||
// TODO(RSDK-10201): The field `sockfd` is not found when using ESP-IDF 5 | ||
unsafe { std::ptr::write_unaligned(std::ptr::addr_of_mut!((*(*tls_context)).sockfd), -1) }; | ||
let host = CString::new(addr.host().unwrap()).unwrap(); | ||
unsafe { | ||
esp!(esp_create_mbedtls_handle( | ||
|
@@ -352,8 +335,8 @@ where | |
|
||
unsafe { | ||
mbedtls_ssl_conf_read_timeout( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. edit : it's doable but I hate it. I want to remove it unless there is a strong opinion against There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why don't you like it? what's the implication of us not having it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd like answers to Matt's questions too. Are you proposing removing setting the SSL read timeout entirely, rather than accessing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the ssl read timeout was useful to detect states where a connection was dropped but for some reason our stack assumed it was still alive. if this particular bug resurface then we should re introduce it |
||
// TODO(RSDK-10201): The field `conf` is not found when using ESP-IDF 5 | ||
std::ptr::addr_of_mut!((*(*tls_context)).conf), | ||
(*(esp_tls_get_ssl_context(*tls_context) as *mut mbedtls_ssl_context)).private_conf | ||
as *mut mbedtls_ssl_config, | ||
30 * 1000, | ||
); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
had to manually add them, not sure if esp-rs will update their code to include these symbols
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did file an issue upstream with them: https://github.com/viamrobotics/micro-rdk/pull/445/files, but at the time we weren't prioritizing ESP-IDF 5 and following up fell off my todo list. Do you want me to re-engage with them and see if they are willing to make a fix?
Also, do you have any thoughts on the package they indicated: https://github.com/esp-rs/esp-mbedtls?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either way, can we add a comment here explaining why we are doing this, and maybe referencing the upstream issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you link the issue URL?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
esp-mbedtls doesn't look mature but if someone wants to try happy to let them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, sorry, somehow I posted the link to this review. I meant to post a link to esp-rs/esp-idf-sys#361.