Skip to content

Commit

Permalink
Initial changes for async support
Browse files Browse the repository at this point in the history
  • Loading branch information
Adrian Cruceru committed Feb 8, 2022
1 parent c5b103f commit 4086897
Show file tree
Hide file tree
Showing 6 changed files with 262 additions and 93 deletions.
27 changes: 27 additions & 0 deletions mbedtls/src/pk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,11 @@ impl Pk {
sig: &mut [u8],
rng: &mut F,
) -> Result<usize> {
// If hash or sig are allowed with size 0 (&[]) then mbedtls will attempt to auto-detect size and cause an invalid write.
if hash.len() == 0 || sig.len() == 0 {
return Err(Error::PkBadInputData)
}

match self.pk_type() {
Type::Rsa | Type::RsaAlt | Type::RsassaPss => {
if sig.len() < (self.len() / 8) {
Expand Down Expand Up @@ -868,6 +873,11 @@ impl Pk {
sig: &mut [u8],
rng: &mut F,
) -> Result<usize> {
// If hash or sig are allowed with size 0 (&[]) then mbedtls will attempt to auto-detect size and cause an invalid write.
if hash.len() == 0 || sig.len() == 0 {
return Err(Error::PkBadInputData)
}

use crate::rng::RngCallbackMut;

if self.pk_type() == Type::Ecdsa || self.pk_type() == Type::Eckey {
Expand Down Expand Up @@ -913,6 +923,11 @@ impl Pk {
}

pub fn verify(&mut self, md: MdType, hash: &[u8], sig: &[u8]) -> Result<()> {
// If hash or sig are allowed with size 0 (&[]) then mbedtls will attempt to auto-detect size and cause an invalid write.
if hash.len() == 0 || sig.len() == 0 {
return Err(Error::PkBadInputData)
}

unsafe {
pk_verify(
&mut self.inner,
Expand Down Expand Up @@ -1274,6 +1289,18 @@ iy6KC991zzvaWY/Ys+q/84Afqa+0qJKQnPuy/7F5GkVdQA/lfbhi
)
.unwrap();
pk.verify(digest, data, &signature[0..len]).unwrap();

assert_eq!(pk.verify(digest, data, &[]).unwrap_err(), Error::PkBadInputData);
assert_eq!(pk.verify(digest, &[], &signature[0..len]).unwrap_err(), Error::PkBadInputData);


let mut dummy_sig = vec![];
assert_eq!(pk.sign(digest, data, &mut dummy_sig, &mut crate::test_support::rand::test_rng()).unwrap_err(), Error::PkBadInputData);
assert_eq!(pk.sign(digest, &[], &mut signature, &mut crate::test_support::rand::test_rng()).unwrap_err(), Error::PkBadInputData);

assert_eq!(pk.sign_deterministic(digest, data, &mut dummy_sig, &mut crate::test_support::rand::test_rng()).unwrap_err(), Error::PkBadInputData);
assert_eq!(pk.sign_deterministic(digest, &[], &mut signature, &mut crate::test_support::rand::test_rng()).unwrap_err(), Error::PkBadInputData);

}
}

Expand Down
31 changes: 28 additions & 3 deletions mbedtls/src/rng/ctr_drbg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ use mbedtls_sys::types::size_t;
#[cfg(not(feature = "std"))]
use crate::alloc_prelude::*;
use crate::error::{IntoResult, Result};
use crate::rng::{EntropyCallback, RngCallback, RngCallbackMut};
use crate::rng::{EntropyCallback, EntropyCallbackMut, RngCallback, RngCallbackMut};

enum EntropyHolder {
Shared(Arc<dyn EntropyCallback + 'static>),
Unique(Box<dyn EntropyCallbackMut + 'static>),
}

define!(
// `ctr_drbg_context` inlines an `aes_context`, which is immovable. See
Expand All @@ -30,7 +35,7 @@ define!(
#[c_box_ty(ctr_drbg_context)]
#[repr(C)]
struct CtrDrbg {
entropy: Arc<dyn EntropyCallback + 'static>,
entropy: EntropyHolder,
};
const drop: fn(&mut Self) = ctr_drbg_free;
impl<'a> Into<ptr> {}
Expand Down Expand Up @@ -63,8 +68,28 @@ impl CtrDrbg {
).into_result()?;
}

Ok(CtrDrbg { inner, entropy })
Ok(CtrDrbg { inner, entropy: EntropyHolder::Shared(entropy) })
}

pub fn with_mut_entropy<T: EntropyCallbackMut + 'static>(entropy: T, additional_entropy: Option<&[u8]>) -> Result<Self> {
let mut inner = Box::new(ctr_drbg_context::default());

// We take sole ownership of entropy, all access is guarded via mutexes.
let mut entropy = Box::new(entropy);
unsafe {
ctr_drbg_init(&mut *inner);
ctr_drbg_seed(
&mut *inner,
Some(T::call_mut),
entropy.data_ptr_mut(),
additional_entropy.map(<[_]>::as_ptr).unwrap_or(::core::ptr::null()),
additional_entropy.map(<[_]>::len).unwrap_or(0)
).into_result()?;
}

Ok(CtrDrbg { inner, entropy: EntropyHolder::Unique(entropy) })
}


pub fn prediction_resistance(&self) -> bool {
if self.inner.prediction_resistance == CTR_DRBG_PR_OFF {
Expand Down
66 changes: 56 additions & 10 deletions mbedtls/src/ssl/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,44 @@ callback!(DbgCallback: Fn(i32, Cow<'_, str>, i32, Cow<'_, str>) -> ());
callback!(SniCallback: Fn(&mut HandshakeContext, &[u8]) -> Result<()>);
callback!(CaCallback: Fn(&MbedtlsList<Certificate>) -> Result<MbedtlsList<Certificate>>);


#[repr(transparent)]
pub struct NullTerminatedStrList {
c: Vec<*mut c_char>,
}

unsafe impl Send for NullTerminatedStrList {}
unsafe impl Sync for NullTerminatedStrList {}

impl NullTerminatedStrList {
#[cfg(feature = "std")]
pub fn new(list: &[&str]) -> Result<Self> {
let vec = list.iter().map(|v| ::std::ffi::CString::new(*v).map_err(|_| Error::SslBadInputData)).collect::<Result<Vec<::std::ffi::CString>>>()?;

let mut c : Vec<*mut c_char> = vec.into_iter().map(|v| v.into_raw()).collect();
c.push(core::ptr::null_mut());

Ok(NullTerminatedStrList { c })
}

pub fn as_ptr(&self) -> *const *const c_char {
self.c.as_ptr() as *const _
}
}

#[cfg(feature = "std")]
impl Drop for NullTerminatedStrList {
fn drop(&mut self) {
for i in self.c.iter() {
unsafe {
if !(*i).is_null() {
let _ = ::std::ffi::CString::from_raw(*i);
}
}
}
}
}

define!(
#[c_ty(ssl_config)]
#[repr(C)]
Expand All @@ -116,9 +154,7 @@ define!(

ciphersuites: Vec<Arc<Vec<c_int>>>,
curves: Option<Arc<Vec<ecp_group_id>>>,

#[allow(dead_code)]
dhm: Option<Arc<Dhm>>,
protocols: Option<Arc<NullTerminatedStrList>>,

verify_callback: Option<Arc<dyn VerifyCallback + 'static>>,
#[cfg(feature = "std")]
Expand Down Expand Up @@ -154,7 +190,7 @@ impl Config {
rng: None,
ciphersuites: vec![],
curves: None,
dhm: None,
protocols: None,
verify_callback: None,
#[cfg(feature = "std")]
dbg_callback: None,
Expand Down Expand Up @@ -184,6 +220,18 @@ impl Config {
self.ciphersuites.push(list);
}

/// Set the supported Application Layer Protocols.
pub fn set_alpn_protocols(&mut self, protocols: Arc<NullTerminatedStrList>) -> Result<()> {
unsafe {
ssl_conf_alpn_protocols(&mut self.inner, protocols.as_ptr() as *mut _)
.into_result()
.map(|_| ())?;
}

self.protocols = Some(protocols);
Ok(())
}

pub fn set_ciphersuites_for_version(&mut self, list: Arc<Vec<c_int>>, major: c_int, minor: c_int) {
Self::check_c_list(&list);
unsafe { ssl_conf_ciphersuites_for_version(self.into(), list.as_ptr(), major, minor) }
Expand Down Expand Up @@ -232,13 +280,13 @@ impl Config {
/// Takes both DER and PEM forms of FFDH parameters in `DHParams` format.
///
/// When calling on PEM-encoded data, `params` must be NULL-terminated
pub fn set_dh_params(&mut self, dhm: Arc<Dhm>) -> Result<()> {
pub fn set_dh_params(&mut self, dhm: &Dhm) -> Result<()> {
unsafe {
// This copies the dhm parameters and does not store any pointer to it
ssl_conf_dh_param_ctx(self.into(), dhm.inner_ffi_mut())
.into_result()
.map(|_| ())?;
}
self.dhm = Some(dhm);
Ok(())
}

Expand Down Expand Up @@ -316,12 +364,10 @@ impl Config {
// - We can pointer cast to it to allow storing additional objects.
//
let cb = &mut *(closure as *mut F);
let context = UnsafeFrom::from(ctx).unwrap();

let mut ctx = HandshakeContext::init(context);
let ctx = UnsafeFrom::from(ctx).unwrap();

let name = from_raw_parts(name, name_len);
match cb(&mut ctx, name) {
match cb(ctx, name) {
Ok(()) => 0,
Err(_) => -1,
}
Expand Down
Loading

0 comments on commit 4086897

Please sign in to comment.