Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
27 changes: 1 addition & 26 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions mbedtls-sys/build/cmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ impl super::BuildConfig {
cmk.define("CMAKE_C_COMPILER_FORCED", "TRUE");
}

let target = std::env::var("TARGET").expect("TARGET environment variable should be set in build scripts");
// thumbv6m-none-eabi, thumbv7em-none-eabi, thumbv7em-none-eabihf, thumbv7m-none-eabi
// probably use arm-none-eabi-gcc which can cause the cmake compiler test to fail.
if target.starts_with("thumbv") && target.contains("none-eabi") {
// When building on Linux, -rdynamic flag is added automatically. Changing the
// CMAKE_SYSTEM_NAME to Generic avoids this.
cmk.define("CMAKE_SYSTEM_NAME", "Generic");
// The compiler test requires _exit which is not available. By just trying to compile
// a library, we can fix it.
cmk.define("CMAKE_TRY_COMPILE_TARGET_TYPE", "STATIC_LIBRARY");
}

let mut dst = cmk.build();

dst.push("build");
Expand Down
3 changes: 1 addition & 2 deletions mbedtls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ keywords = ["MbedTLS","mbed","TLS","SSL","cryptography"]

[dependencies]
bitflags = "1"
core_io = { version = "0.1", features = ["collections"], optional = true }
spin = { version = "0.4.0", default-features = false, optional = true }
serde = { version = "1.0.7", default-features = false, features = ["alloc"] }
serde_derive = "1.0.7"
Expand Down Expand Up @@ -57,7 +56,7 @@ cc = "1.0"
default = ["std", "aesni", "time", "padlock"]
std = ["byteorder/std", "mbedtls-sys-auto/std", "serde/std", "yasna"]
debug = ["mbedtls-sys-auto/debug"]
no_std_deps = ["core_io", "spin", "serde/alloc"]
no_std_deps = ["spin", "serde/alloc"]
force_aesni_support = ["mbedtls-sys-auto/custom_has_support", "mbedtls-sys-auto/aes_alt", "aesni"]
mpi_force_c_code = ["mbedtls-sys-auto/mpi_force_c_code"]
rdrand = []
Expand Down
12 changes: 9 additions & 3 deletions mbedtls/examples/client_dtls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// needed to have common code for `mod support` in unit and integrations tests
extern crate mbedtls;

use std::io::{self, stdin, stdout, Write};
use std::io::stdin;
use std::net::UdpSocket;
use std::sync::Arc;

Expand Down Expand Up @@ -40,8 +40,14 @@ fn result_main(addr: &str) -> TlsResult<()> {

let mut line = String::new();
stdin().read_line(&mut line).unwrap();
ctx.write_all(line.as_bytes()).unwrap();
io::copy(&mut ctx, &mut stdout()).unwrap();
ctx.send(line.as_bytes()).unwrap();
let mut resp = Vec::with_capacity(100);
let len = ctx.recv(&mut resp).unwrap();
if let Ok(s) = std::str::from_utf8(&resp[..len]) {
println!("{}", s);
} else {
eprintln!("Invalid UTF-8 received");
}
Ok(())
}

Expand Down
24 changes: 18 additions & 6 deletions mbedtls/src/cipher/raw/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,22 +339,34 @@ unsafe impl BytesSerde for des_context {}
unsafe impl BytesSerde for des3_context {}
unsafe impl BytesSerde for gcm_context {}

// If the C API changes, the serde implementation needs to be reviewed for correctness.
// If the C API changes, the serde implementation needs to be reviewed for correctness. The
// following (unused) functions will most probably fail to compile when this happens so a
// compilation failure here reminds us of reviewing the serde impl.

unsafe fn _check_cipher_context_t_size(ctx: cipher_context_t) -> [u8; 96] {
// The sizes of usize and isize as well as all pointer types will be dependent on the architecture
// we are building for. So to be platform independent, the expected sizes are calculated from the
// fixed-sized fields, the number and size of pointer-sized fields and some alignment bytes.

const _SIZE_OF_CIPHER_CONTEXT: usize = size_of::<usize>() + 2 * 4 + 2 * size_of::<usize>() + 16 + size_of::<usize>() + 16 + 3 * size_of::<usize>();
const _SIZE_OF_AES_CONTEXT: usize = 2 * size_of::<usize>() + 4 * 68;
const _SIZE_OF_DES_CONTEXT: usize = 4 * 32;
const _SIZE_OF_DES3_CONTEXT: usize = 4 * 96;
const _SIZE_OF_GCM_CONTEXT: usize = (_SIZE_OF_CIPHER_CONTEXT+7)/8*8 + 8 * 16 + 8 * 16 + 8 + 8 + 16 + 16 + 16 + 8; // first summand: cipher_context 8-byte aligned

unsafe fn _check_cipher_context_t_size(ctx: cipher_context_t) -> [u8; _SIZE_OF_CIPHER_CONTEXT] {
::core::mem::transmute(ctx)
}

unsafe fn _check_aes_context_size(ctx: aes_context) -> [u8; 288] {
unsafe fn _check_aes_context_size(ctx: aes_context) -> [u8; _SIZE_OF_AES_CONTEXT] {
::core::mem::transmute(ctx)
}

unsafe fn _check_des_context_size(ctx: des_context) -> [u8; 128] {
unsafe fn _check_des_context_size(ctx: des_context) -> [u8; _SIZE_OF_DES_CONTEXT] {
::core::mem::transmute(ctx)
}

unsafe fn _check_des3_context_size(ctx: des3_context) -> [u8; 384] {
unsafe fn _check_des3_context_size(ctx: des3_context) -> [u8; _SIZE_OF_DES3_CONTEXT] {
::core::mem::transmute(ctx)
}

unsafe fn _check_gcm_context_size(ctx: gcm_context) -> [u8; 424] { ::core::mem::transmute(ctx) }
unsafe fn _check_gcm_context_size(ctx: gcm_context) -> [u8; _SIZE_OF_GCM_CONTEXT] { ::core::mem::transmute(ctx) }
3 changes: 1 addition & 2 deletions mbedtls/src/private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,10 @@ pub unsafe fn cstr_to_slice<'a>(ptr: *const c_char) -> &'a [u8] {
::core::slice::from_raw_parts(ptr as *const _, strlen(ptr))
}

#[cfg(not(feature = "std"))]
use core_io::{Error as IoError, ErrorKind as IoErrorKind};
#[cfg(feature = "std")]
use std::io::{Error as IoError, ErrorKind as IoErrorKind};

#[cfg(feature = "std")]
pub fn error_to_io_error(e: Error) -> IoError {
IoError::new(IoErrorKind::Other, e.to_string())
}
49 changes: 36 additions & 13 deletions mbedtls/src/ssl/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ use {
std::sync::Arc,
};

#[cfg(not(feature = "std"))]
use core_io::{Read, Write, Result as IoResult};


use mbedtls_sys::types::raw_types::{c_int, c_uchar, c_void};
use mbedtls_sys::types::size_t;
use mbedtls_sys::*;
Expand All @@ -37,6 +33,7 @@ pub trait IoCallback {
fn data_ptr(&mut self) -> *mut c_void;
}

#[cfg(feature = "std")]
impl<IO: Read + Write> IoCallback for IO {
unsafe extern "C" fn call_recv(user_data: *mut c_void, data: *mut c_uchar, len: size_t) -> c_int {
let len = if len > (c_int::max_value() as size_t) {
Expand Down Expand Up @@ -488,6 +485,20 @@ impl<T> Context<T> {
}
}

impl<T: IoCallback> Context<T> {
pub fn recv(&mut self, buf: &mut [u8]) -> Result<usize> {
unsafe {
ssl_read(self.into(), buf.as_mut_ptr(), buf.len()).into_result().map(|r| r as usize)
}
}

pub fn send(&mut self, buf: &[u8]) -> Result<usize> {
unsafe {
ssl_write(self.into(), buf.as_ptr(), buf.len()).into_result().map(|w| w as usize)
}
}
}

impl<T> Drop for Context<T> {
fn drop(&mut self) {
unsafe {
Expand All @@ -497,29 +508,40 @@ impl<T> Drop for Context<T> {
}
}

impl<T: IoCallback> Read for Context<T> {
#[cfg(feature = "std")]
/// Implements [`std::io::Read`] whenever T implements `Read`, too. This ensures that
/// `Read`, which is designated for byte-oriented sources, is only implemented when the
/// underlying [`IoCallback`] is byte-oriented, too. Specifically, this means that it is implemented
/// for `Context<TcpStream>`, i.e. TLS connections but not for DTLS connections.
impl<T: IoCallback + Read> Read for Context<T> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
match unsafe { ssl_read(self.into(), buf.as_mut_ptr(), buf.len()).into_result() } {
match self.recv(buf) {
Err(Error::SslPeerCloseNotify) => Ok(0),
Err(e) => Err(crate::private::error_to_io_error(e)),
Ok(i) => Ok(i as usize),
Ok(i) => Ok(i),
}
}
}

impl<T: IoCallback> Write for Context<T> {
#[cfg(feature = "std")]
/// Implements [`std::io::Write`] whenever T implements `Write`, too. This ensures that
/// `Write`, which is designated for byte-oriented sinks, is only implemented when the
/// underlying [`IoCallback`] is byte-oriented, too. Specifically, this means that it is implemented
/// for `Context<TcpStream>`, i.e. TLS connections but not for DTLS connections.
impl<T: IoCallback + Write> Write for Context<T> {
fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
match unsafe { ssl_write(self.into(), buf.as_ptr(), buf.len()).into_result() } {
match self.send(buf) {
Err(Error::SslPeerCloseNotify) => Ok(0),
Err(e) => Err(crate::private::error_to_io_error(e)),
Ok(i) => Ok(i as usize),
Ok(i) => Ok(i),
}
}

fn flush(&mut self) -> IoResult<()> {
Ok(())
}
}

//
// Class exists only during SNI callback that is configured from Config.
// SNI Callback must provide input whose lifetime exceeds the SNI closure to avoid memory corruptions.
Expand Down Expand Up @@ -603,9 +625,6 @@ mod tests {
#[cfg(feature = "std")]
use std::io::{Read,Write, Result as IoResult};

#[cfg(not(feature = "std"))]
use core_io::{Read, Write, Result as IoResult};

use crate::ssl::context::{HandshakeContext, Context};
use crate::tests::TestTrait;

Expand All @@ -618,12 +637,14 @@ mod tests {
_buffer: core::ptr::NonNull<u8>,
}

#[cfg(feature = "std")]
impl Read for NonSendStream {
fn read(&mut self, _: &mut [u8]) -> IoResult<usize> {
unimplemented!()
}
}

#[cfg(feature = "std")]
impl Write for NonSendStream {
fn write(&mut self, _: &[u8]) -> IoResult<usize> {
unimplemented!()
Expand All @@ -638,12 +659,14 @@ mod tests {
_buffer: u8,
}

#[cfg(feature = "std")]
impl Read for SendStream {
fn read(&mut self, _: &mut [u8]) -> IoResult<usize> {
unimplemented!()
}
}

#[cfg(feature = "std")]
impl Write for SendStream {
fn write(&mut self, _: &[u8]) -> IoResult<usize> {
unimplemented!()
Expand Down
65 changes: 21 additions & 44 deletions mbedtls/src/x509/certificate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1012,58 +1012,35 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
let c_int2 = Certificate::from_pem(C_INT2.as_bytes()).unwrap();
let mut c_root = Certificate::from_pem_multiple(C_ROOT.as_bytes()).unwrap();

{
let mut chain = MbedtlsList::<Certificate>::new();
chain.push(c_leaf.clone());
chain.push(c_int1.clone());

let err = Certificate::verify(&chain, &mut c_root, None, None).unwrap_err();
assert_eq!(err, Error::X509CertVerifyFailed);

// try again after fixing the chain
chain.push(c_int2.clone());


let mut err_str = String::new();

let verify_callback = |_crt: &Certificate, _depth: i32, verify_flags: &mut VerifyError| {
verify_flags.remove(VerifyError::CERT_EXPIRED);
Ok(())
};
// Certificate C_INT2 is missing at the beginning so the verification should fail at first
let mut chain = MbedtlsList::<Certificate>::new();
chain.push(c_leaf.clone());
chain.push(c_int1.clone());

Certificate::verify(&chain, &mut c_root, None, None).unwrap();
let res = Certificate::verify_with_callback(&chain, &mut c_root, None, Some(&mut err_str), verify_callback);
// The certificates used for this test are expired so we remove the CERT_EXPIRED flag with the callback
let verify_callback = |_crt: &Certificate, _depth: i32, verify_flags: &mut VerifyError| {
verify_flags.remove(VerifyError::CERT_EXPIRED);
Ok(())
};

match res {
Ok(()) => (),
Err(e) => assert!(false, "Failed to verify, error: {}, err_str: {}", e, err_str),
};
let res = Certificate::verify_with_callback(&chain, &mut c_root, None, None, verify_callback);
match res {
Ok(_) => panic!("Certificate chain verification should have failed, but it succeeded"),
Err(err) => assert_eq!(err, Error::X509CertVerifyFailed),
}

{
let mut chain = MbedtlsList::<Certificate>::new();
chain.push(c_leaf.clone());
chain.push(c_int1.clone());
chain.push(c_int2.clone());

Certificate::verify(&chain, &mut c_root, None, None).unwrap();
// try again after fixing the chain
chain.push(c_int2.clone());

let verify_callback = |_crt: &Certificate, _depth: i32, verify_flags: &mut VerifyError| {
verify_flags.remove(VerifyError::CERT_EXPIRED);
Ok(())
};
let mut err_str = String::new();

let mut err_str = String::new();
let res = Certificate::verify_with_callback(&chain, &mut c_root, None, Some(&mut err_str), verify_callback);
let res = Certificate::verify_with_callback(&chain, &mut c_root, None, Some(&mut err_str), verify_callback);

match res {
Ok(()) => (),
Err(e) => assert!(false, "Failed to verify, error: {}, err_str: {}", e, err_str),
};
}
match res {
Ok(()) => (),
Err(e) => panic!("Failed to verify, error: {}, err_str: {}", e, err_str),
};
}



#[test]
fn clone_test() {
Expand Down
Loading