Skip to content

Commit 51ad965

Browse files
bors[bot]Adrian Cruceru
and
Adrian Cruceru
authored
Merge #182
182: Initial changes for async support r=jethrogb a=AdrianCX Splitting #163 into separate parts. Also rebased since `@raoulstrackx` already helped with some pieces of the PR above. Code does the following: - Minor update to comments on Pk (revisited the latest code to check if any issues, none found) - verify with sig len 0 makes mbedtls assume default siglen and potentially overflow instead of stopping. - EntropyHolder can have different sources, either shared or not (request from another older PR) - Ported ALPN changes from `@mzohreva` branch - NullTerminatedList - Split off HandshakeContext and made it a sort of base class to Context so we can use it safely. (lots of ideas from `@jethrogb` here) - Made Context < T > as opposed to using Any, makes life easier for async and a lot of other use cases. Co-authored-by: Adrian Cruceru <[email protected]>
2 parents c5b103f + 0044496 commit 51ad965

File tree

5 files changed

+250
-94
lines changed

5 files changed

+250
-94
lines changed

mbedtls/src/pk/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,11 @@ impl Pk {
832832
sig: &mut [u8],
833833
rng: &mut F,
834834
) -> Result<usize> {
835+
// If hash or sig are allowed with size 0 (&[]) then mbedtls will attempt to auto-detect size and cause an invalid write.
836+
if hash.len() == 0 || sig.len() == 0 {
837+
return Err(Error::PkBadInputData)
838+
}
839+
835840
match self.pk_type() {
836841
Type::Rsa | Type::RsaAlt | Type::RsassaPss => {
837842
if sig.len() < (self.len() / 8) {
@@ -868,6 +873,11 @@ impl Pk {
868873
sig: &mut [u8],
869874
rng: &mut F,
870875
) -> Result<usize> {
876+
// If hash or sig are allowed with size 0 (&[]) then mbedtls will attempt to auto-detect size and cause an invalid write.
877+
if hash.len() == 0 || sig.len() == 0 {
878+
return Err(Error::PkBadInputData)
879+
}
880+
871881
use crate::rng::RngCallbackMut;
872882

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

915925
pub fn verify(&mut self, md: MdType, hash: &[u8], sig: &[u8]) -> Result<()> {
926+
// If hash or sig are allowed with size 0 (&[]) then mbedtls will attempt to auto-detect size and cause an invalid write.
927+
if hash.len() == 0 || sig.len() == 0 {
928+
return Err(Error::PkBadInputData)
929+
}
930+
916931
unsafe {
917932
pk_verify(
918933
&mut self.inner,
@@ -1274,6 +1289,18 @@ iy6KC991zzvaWY/Ys+q/84Afqa+0qJKQnPuy/7F5GkVdQA/lfbhi
12741289
)
12751290
.unwrap();
12761291
pk.verify(digest, data, &signature[0..len]).unwrap();
1292+
1293+
assert_eq!(pk.verify(digest, data, &[]).unwrap_err(), Error::PkBadInputData);
1294+
assert_eq!(pk.verify(digest, &[], &signature[0..len]).unwrap_err(), Error::PkBadInputData);
1295+
1296+
1297+
let mut dummy_sig = [];
1298+
assert_eq!(pk.sign(digest, data, &mut dummy_sig, &mut crate::test_support::rand::test_rng()).unwrap_err(), Error::PkBadInputData);
1299+
assert_eq!(pk.sign(digest, &[], &mut signature, &mut crate::test_support::rand::test_rng()).unwrap_err(), Error::PkBadInputData);
1300+
1301+
assert_eq!(pk.sign_deterministic(digest, data, &mut dummy_sig, &mut crate::test_support::rand::test_rng()).unwrap_err(), Error::PkBadInputData);
1302+
assert_eq!(pk.sign_deterministic(digest, &[], &mut signature, &mut crate::test_support::rand::test_rng()).unwrap_err(), Error::PkBadInputData);
1303+
12771304
}
12781305
}
12791306

mbedtls/src/rng/ctr_drbg.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ use mbedtls_sys::types::size_t;
1717
#[cfg(not(feature = "std"))]
1818
use crate::alloc_prelude::*;
1919
use crate::error::{IntoResult, Result};
20-
use crate::rng::{EntropyCallback, RngCallback, RngCallbackMut};
20+
use crate::rng::{EntropyCallback, EntropyCallbackMut, RngCallback, RngCallbackMut};
21+
22+
enum EntropyHolder {
23+
Shared(Arc<dyn EntropyCallback + 'static>),
24+
Unique(Box<dyn EntropyCallbackMut + 'static>),
25+
}
2126

2227
define!(
2328
// `ctr_drbg_context` inlines an `aes_context`, which is immovable. See
@@ -30,7 +35,7 @@ define!(
3035
#[c_box_ty(ctr_drbg_context)]
3136
#[repr(C)]
3237
struct CtrDrbg {
33-
entropy: Arc<dyn EntropyCallback + 'static>,
38+
entropy: EntropyHolder,
3439
};
3540
const drop: fn(&mut Self) = ctr_drbg_free;
3641
impl<'a> Into<ptr> {}
@@ -63,8 +68,28 @@ impl CtrDrbg {
6368
).into_result()?;
6469
}
6570

66-
Ok(CtrDrbg { inner, entropy })
71+
Ok(CtrDrbg { inner, entropy: EntropyHolder::Shared(entropy) })
72+
}
73+
74+
pub fn with_mut_entropy<T: EntropyCallbackMut + 'static>(entropy: T, additional_entropy: Option<&[u8]>) -> Result<Self> {
75+
let mut inner = Box::new(ctr_drbg_context::default());
76+
77+
// We take sole ownership of entropy, all access is guarded via mutexes.
78+
let mut entropy = Box::new(entropy);
79+
unsafe {
80+
ctr_drbg_init(&mut *inner);
81+
ctr_drbg_seed(
82+
&mut *inner,
83+
Some(T::call_mut),
84+
entropy.data_ptr_mut(),
85+
additional_entropy.map(<[_]>::as_ptr).unwrap_or(::core::ptr::null()),
86+
additional_entropy.map(<[_]>::len).unwrap_or(0)
87+
).into_result()?;
88+
}
89+
90+
Ok(CtrDrbg { inner, entropy: EntropyHolder::Unique(entropy) })
6791
}
92+
6893

6994
pub fn prediction_resistance(&self) -> bool {
7095
if self.inner.prediction_resistance == CTR_DRBG_PR_OFF {

mbedtls/src/ssl/config.rs

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,46 @@ callback!(DbgCallback: Fn(i32, Cow<'_, str>, i32, Cow<'_, str>) -> ());
100100
callback!(SniCallback: Fn(&mut HandshakeContext, &[u8]) -> Result<()>);
101101
callback!(CaCallback: Fn(&MbedtlsList<Certificate>) -> Result<MbedtlsList<Certificate>>);
102102

103+
104+
#[repr(transparent)]
105+
pub struct NullTerminatedStrList {
106+
c: Vec<*mut c_char>,
107+
}
108+
109+
unsafe impl Send for NullTerminatedStrList {}
110+
unsafe impl Sync for NullTerminatedStrList {}
111+
112+
impl NullTerminatedStrList {
113+
#[cfg(feature = "std")]
114+
pub fn new(list: &[&str]) -> Result<Self> {
115+
let mut ret = NullTerminatedStrList { c: Vec::with_capacity(list.len() + 1) };
116+
117+
for item in list {
118+
ret.c.push(::std::ffi::CString::new(*item).map_err(|_| Error::SslBadInputData)?.into_raw());
119+
}
120+
121+
ret.c.push(core::ptr::null_mut());
122+
Ok(ret)
123+
}
124+
125+
pub fn as_ptr(&self) -> *const *const c_char {
126+
self.c.as_ptr() as *const _
127+
}
128+
}
129+
130+
#[cfg(feature = "std")]
131+
impl Drop for NullTerminatedStrList {
132+
fn drop(&mut self) {
133+
for i in self.c.iter() {
134+
unsafe {
135+
if !(*i).is_null() {
136+
let _ = ::std::ffi::CString::from_raw(*i);
137+
}
138+
}
139+
}
140+
}
141+
}
142+
103143
define!(
104144
#[c_ty(ssl_config)]
105145
#[repr(C)]
@@ -116,9 +156,7 @@ define!(
116156

117157
ciphersuites: Vec<Arc<Vec<c_int>>>,
118158
curves: Option<Arc<Vec<ecp_group_id>>>,
119-
120-
#[allow(dead_code)]
121-
dhm: Option<Arc<Dhm>>,
159+
protocols: Option<Arc<NullTerminatedStrList>>,
122160

123161
verify_callback: Option<Arc<dyn VerifyCallback + 'static>>,
124162
#[cfg(feature = "std")]
@@ -154,7 +192,7 @@ impl Config {
154192
rng: None,
155193
ciphersuites: vec![],
156194
curves: None,
157-
dhm: None,
195+
protocols: None,
158196
verify_callback: None,
159197
#[cfg(feature = "std")]
160198
dbg_callback: None,
@@ -184,6 +222,18 @@ impl Config {
184222
self.ciphersuites.push(list);
185223
}
186224

225+
/// Set the supported Application Layer Protocols.
226+
pub fn set_alpn_protocols(&mut self, protocols: Arc<NullTerminatedStrList>) -> Result<()> {
227+
unsafe {
228+
ssl_conf_alpn_protocols(&mut self.inner, protocols.as_ptr() as *mut _)
229+
.into_result()
230+
.map(|_| ())?;
231+
}
232+
233+
self.protocols = Some(protocols);
234+
Ok(())
235+
}
236+
187237
pub fn set_ciphersuites_for_version(&mut self, list: Arc<Vec<c_int>>, major: c_int, minor: c_int) {
188238
Self::check_c_list(&list);
189239
unsafe { ssl_conf_ciphersuites_for_version(self.into(), list.as_ptr(), major, minor) }
@@ -232,13 +282,13 @@ impl Config {
232282
/// Takes both DER and PEM forms of FFDH parameters in `DHParams` format.
233283
///
234284
/// When calling on PEM-encoded data, `params` must be NULL-terminated
235-
pub fn set_dh_params(&mut self, dhm: Arc<Dhm>) -> Result<()> {
285+
pub fn set_dh_params(&mut self, dhm: &Dhm) -> Result<()> {
236286
unsafe {
287+
// This copies the dhm parameters and does not store any pointer to it
237288
ssl_conf_dh_param_ctx(self.into(), dhm.inner_ffi_mut())
238289
.into_result()
239290
.map(|_| ())?;
240291
}
241-
self.dhm = Some(dhm);
242292
Ok(())
243293
}
244294

@@ -316,12 +366,10 @@ impl Config {
316366
// - We can pointer cast to it to allow storing additional objects.
317367
//
318368
let cb = &mut *(closure as *mut F);
319-
let context = UnsafeFrom::from(ctx).unwrap();
320-
321-
let mut ctx = HandshakeContext::init(context);
369+
let ctx = UnsafeFrom::from(ctx).unwrap();
322370

323371
let name = from_raw_parts(name, name_len);
324-
match cb(&mut ctx, name) {
372+
match cb(ctx, name) {
325373
Ok(()) => 0,
326374
Err(_) => -1,
327375
}

0 commit comments

Comments
 (0)