Skip to content
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

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions micro-rdk/src/esp32/certificate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ use esp_idf_svc::sys::{
mbedtls_pk_type_t_MBEDTLS_PK_ECKEY, mbedtls_pk_write_key_der, mbedtls_x509write_cert,
mbedtls_x509write_crt_der, mbedtls_x509write_crt_free, mbedtls_x509write_crt_init,
mbedtls_x509write_crt_set_issuer_key, mbedtls_x509write_crt_set_issuer_name,
mbedtls_x509write_crt_set_md_alg, mbedtls_x509write_crt_set_subject_key,
mbedtls_x509write_crt_set_subject_name, mbedtls_x509write_crt_set_validity,
mbedtls_x509write_crt_set_version, MBEDTLS_ERR_PK_BAD_INPUT_DATA, MBEDTLS_X509_CRT_VERSION_3,
SHA_TYPE_SHA2_256,
mbedtls_x509write_crt_set_md_alg, mbedtls_x509write_crt_set_serial_raw,
mbedtls_x509write_crt_set_subject_key, mbedtls_x509write_crt_set_subject_name,
mbedtls_x509write_crt_set_validity, mbedtls_x509write_crt_set_version,
MBEDTLS_ERR_PK_BAD_INPUT_DATA, MBEDTLS_X509_CRT_VERSION_3, SHA_TYPE_SHA2_256,
};

use crate::common::webrtc::certificate::{Certificate, Fingerprint};
Expand Down Expand Up @@ -173,7 +173,9 @@ impl GeneratedWebRtcCertificateBuilder {
}?;

// TODO(RSDK-10196): The `pk_ctx` field doesn't exist in ESP-IDF 5. Maybe it should be `private_kp_ctx`?
let ecp_keypair = self.kp_context.pk_ctx;
// we should use the mbedtls_ecp_keypair *mbedtls_pk_ec(const mbedtls_pk_context pk) but it's defined as static inline
// to access it we would need to change bindgen invocation to export it
let ecp_keypair = self.kp_context.private_pk_ctx;

unsafe {
MbedTLSError::to_unit_result(mbedtls_ecp_gen_key(
Expand Down Expand Up @@ -235,6 +237,15 @@ impl GeneratedWebRtcCertificateBuilder {
))
}?;

let mut serial_number = [0xAB_u8; 12];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

required now to generate a webrtc cert

unsafe {
MbedTLSError::to_unit_result(mbedtls_x509write_crt_set_serial_raw(
&mut self.crt_context as *mut mbedtls_x509write_cert,
serial_number.as_mut_ptr(),
serial_number.len(),
))
}?;

let mut work_buffer = vec![0_u8; 2048];

let ret = unsafe {
Expand Down
30 changes: 20 additions & 10 deletions micro-rdk/src/esp32/dtls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::{
io::{self, Read, Write},
marker::PhantomData,
pin::Pin,
ptr::NonNull,
rc::Rc,
task::{Context, Poll},
time::{Duration, Instant},
Expand All @@ -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;
Copy link
Member Author

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

Copy link
Member

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?

Copy link
Member

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?

Copy link
Member Author

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?

Copy link
Member Author

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

Copy link
Member

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.


extern "C" {
fn mbedtls_debug_set_threshold(level: c_int);
}
Expand All @@ -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
}
}
Expand All @@ -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
}
}
Expand Down Expand Up @@ -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);
Copy link
Member Author

Choose a reason for hiding this comment

The 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

Copy link
Member

Choose a reason for hiding this comment

The 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?

Copy link
Member Author

Choose a reason for hiding this comment

The 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()
};

Expand All @@ -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);
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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()
},
}
}
}
Expand Down