Skip to content

Commit 2ce3aa1

Browse files
author
Adrian Cruceru
committed
mbedTLS lifetimes to reference counting
1 parent fc8eeaf commit 2ce3aa1

28 files changed

+1689
-1251
lines changed

Cargo.lock

Lines changed: 225 additions & 226 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mbedtls/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ features = ["custom_printf", "trusted_cert_callback"]
3939
path = "../mbedtls-sys"
4040

4141
[dev-dependencies]
42-
libc = "0.2.0"
42+
libc = "0.2.69"
4343
rand = "0.4.0"
4444
serde_cbor = "0.6"
4545
hex = "0.3"

mbedtls/examples/client.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,29 @@ use mbedtls::ssl::config::{Endpoint, Preset, Transport};
1616
use mbedtls::ssl::{Config, Context};
1717
use mbedtls::x509::Certificate;
1818
use mbedtls::Result as TlsResult;
19+
use std::sync::Arc;
1920

2021
#[path = "../tests/support/mod.rs"]
2122
mod support;
2223
use support::entropy::entropy_new;
2324
use support::keys;
2425

2526
fn result_main(addr: &str) -> TlsResult<()> {
26-
let mut entropy = entropy_new();
27-
let mut rng = CtrDrbg::new(&mut entropy, None)?;
28-
let mut cert = Certificate::from_pem(keys::PEM_CERT)?;
27+
let entropy = Arc::new(entropy_new());
28+
let rng = Arc::new(CtrDrbg::new(entropy, None)?);
29+
let cert = Arc::new(Certificate::from_pem(keys::PEM_CERT)?);
2930
let mut config = Config::new(Endpoint::Client, Transport::Stream, Preset::Default);
30-
config.set_rng(Some(&mut rng));
31-
config.set_ca_list(Some(&mut *cert), None);
32-
let mut ctx = Context::new(&config)?;
31+
config.set_rng(rng);
32+
config.set_ca_list(cert, None);
33+
let mut ctx = Context::new(Arc::new(config));
3334

34-
let mut conn = TcpStream::connect(addr).unwrap();
35-
let mut session = ctx.establish(&mut conn, None)?;
35+
let conn = TcpStream::connect(addr).unwrap();
36+
ctx.establish(conn, None)?;
3637

3738
let mut line = String::new();
3839
stdin().read_line(&mut line).unwrap();
39-
session.write_all(line.as_bytes()).unwrap();
40-
io::copy(&mut session, &mut stdout()).unwrap();
40+
ctx.write_all(line.as_bytes()).unwrap();
41+
io::copy(&mut ctx, &mut stdout()).unwrap();
4142
Ok(())
4243
}
4344

mbedtls/examples/server.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use mbedtls::ssl::config::{Endpoint, Preset, Transport};
1717
use mbedtls::ssl::{Config, Context};
1818
use mbedtls::x509::Certificate;
1919
use mbedtls::Result as TlsResult;
20+
use std::sync::Arc;
2021

2122
#[path = "../tests/support/mod.rs"]
2223
mod support;
@@ -29,21 +30,25 @@ fn listen<E, F: FnMut(TcpStream) -> Result<(), E>>(mut handle_client: F) -> Resu
2930
println!("Connection from {}", conn.peer_addr().unwrap());
3031
handle_client(conn)?;
3132
}
33+
3234
Ok(())
3335
}
3436

3537
fn result_main() -> TlsResult<()> {
36-
let mut entropy = entropy_new();
37-
let mut rng = CtrDrbg::new(&mut entropy, None)?;
38-
let mut cert = Certificate::from_pem(keys::PEM_CERT)?;
39-
let mut key = Pk::from_private_key(keys::PEM_KEY, None)?;
38+
let entropy = entropy_new();
39+
let rng = Arc::new(CtrDrbg::new(Arc::new(entropy), None)?);
40+
let cert = Arc::new(Certificate::from_pem(keys::PEM_CERT)?);
41+
let key = Arc::new(Pk::from_private_key(keys::PEM_KEY, None)?);
4042
let mut config = Config::new(Endpoint::Server, Transport::Stream, Preset::Default);
41-
config.set_rng(Some(&mut rng));
42-
config.push_cert(&mut *cert, &mut key)?;
43-
let mut ctx = Context::new(&config)?;
43+
config.set_rng(rng);
44+
config.push_cert(cert, key)?;
45+
46+
let rc_config = Arc::new(config);
4447

45-
listen(|mut conn| {
46-
let mut session = BufReader::new(ctx.establish(&mut conn, None)?);
48+
listen(move |conn| {
49+
let mut ctx = Context::new(rc_config.clone());
50+
ctx.establish(conn, None)?;
51+
let mut session = BufReader::new(ctx);
4752
let mut line = Vec::new();
4853
session.read_until(b'\n', &mut line).unwrap();
4954
session.get_mut().write_all(&line).unwrap();

mbedtls/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* according to those terms. */
88

99
#![deny(warnings)]
10+
#![allow(dead_code)]
1011
#![allow(unused_doc_comments)]
1112
#![cfg_attr(not(feature = "std"), no_std)]
1213

@@ -163,3 +164,9 @@ pub unsafe extern "C" fn mbedtls_time(tp: *mut time_t) -> time_t {
163164
}
164165
timestamp
165166
}
167+
168+
// Debug not available in SGX
169+
#[cfg(not(target_env = "sgx"))]
170+
pub fn set_global_debug_threshold(threshold: i32) {
171+
unsafe { mbedtls_sys::debug_set_threshold(threshold); }
172+
}

mbedtls/src/pk/dhparam.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ define!(
1818
impl<'a> Into<ptr> {}
1919
);
2020

21+
impl Into<*mut mbedtls_sys::dhm_context> for &Dhm {
22+
fn into(self) -> *mut mbedtls_sys::dhm_context {
23+
&self.inner as *const _ as *mut _
24+
}
25+
}
26+
2127
impl Dhm {
2228
/// Takes both DER and PEM forms of FFDH parameters in `DHParams` format.
2329
///

mbedtls/src/pk/mod.rs

Lines changed: 103 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::hash::Type as MdType;
2222
use byteorder::{BigEndian, ByteOrder};
2323

2424
pub(crate) mod dhparam;
25-
mod ec;
25+
pub mod ec;
2626
mod rfc6979;
2727

2828
use self::rfc6979::Rfc6979Rng;
@@ -132,6 +132,7 @@ const CUSTOM_PK_INFO: pk_info_t = {
132132
}
133133
};
134134

135+
// If this changes then certificate.rs unsafe code in public_key needs to also change.
135136
define!(
136137
#[c_ty(pk_context)]
137138
#[repr(C)]
@@ -142,6 +143,97 @@ define!(
142143
impl<'a> UnsafeFrom<ptr> {}
143144
);
144145

146+
impl Into<*mut mbedtls_sys::pk_context> for &Pk {
147+
fn into(self) -> *mut mbedtls_sys::pk_context {
148+
&self.inner as *const _ as *mut _
149+
}
150+
}
151+
152+
153+
//
154+
// Thread safety analysis for Pk.
155+
//
156+
// A. Usage example of Pk.
157+
//
158+
// 1.1. Common use case is to to pass it as parameter to the SSL Config class.
159+
// 1.2. SSL Config class is then used by multiple Context classes (one for each connection)
160+
// 1.3. Context classes, handled by different threads will do calls towards Pk.
161+
//
162+
// Since this is a common use case for MbedTLS it should be thread safe if threading is enabled.
163+
//
164+
// B. Verifying thread safety.
165+
//
166+
// 1. Calls towards the specific Pk implementation are done via function pointers.
167+
//
168+
// - Example call towards Pk:
169+
// ../../../mbedtls-sys/vendor/library/ssl_srv.c:3707 - mbedtls_pk_decrypt( private_key, p, len, ...
170+
// - This calls a generic function pointer via:
171+
// ../../../mbedtls-sys/vendor/crypto/library/pk.c:475 - return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen,
172+
//
173+
// 2. Pk implementation types.
174+
//
175+
// - The function pointers are defined via function:
176+
// ../../../mbedtls-sys/vendor/crypto/library/pk.c:115 - mbedtls_pk_info_from_type
177+
// - They are as follows: mbedtls_rsa_info / mbedtls_eckey_info / mbedtls_ecdsa_info
178+
// - These are defined in:
179+
// ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:196
180+
//
181+
// C. Checking types one by one.
182+
//
183+
// 1. RSA: mbedtls_rsa_info at ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:196
184+
// This uses internal locks in: ../../../mbedtls-sys/vendor/crypto/library/rsa.c:718
185+
//
186+
// 2. ECKEY: mbedtls_eckey_info at ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:418
187+
// This does not use internal locks but avoids interior mutability.
188+
//
189+
// Function checks one by one:
190+
// - Only const access to context: eckey_check_pair, eckey_get_bitlen, eckey_can_do, eckey_check_pair
191+
//
192+
// - Const acccess / copies context to a stack based variable
193+
// eckey_verify_wrap, eckey_sign_wrap: ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:251
194+
// creates a stack ecdsa variable and uses ctx to initialize it.
195+
// ctx is passed as 'key', a const pointer to mbedtls_ecdsa_from_keypair( &ecdsa, ctx )
196+
// ../../../mbedtls-sys/vendor/crypto/library/ecdsa.c:819
197+
// int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key )
198+
// key does not mutate.
199+
//
200+
// - Ignored due to not defined: eckey_verify_rs_wrap, eckey_sign_rs_wrap
201+
// (Undefined - MBEDTLS_ECP_RESTARTABLE - ../../../mbedtls-sys/build/config.rs:173)
202+
//
203+
// - Only used when creating/freeing - which is safe by design - eckey_alloc_wrap / eckey_free_wrap
204+
//
205+
// 3. ECDSA: mbedtls_ecdsa_info at ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:729
206+
// This does not use internal locks but avoids interior mutability.
207+
//
208+
// - Const access / copies context to stack based variables:
209+
// ecdsa_verify_wrap: ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:544
210+
// This copies the public key on the stack - in buf[] and copies the group id and nbits.
211+
// That is done via: mbedtls_pk_write_pubkey( &p, buf, &key ) where key.pk_ctx = ctx;
212+
// And the key is a const parameter to mbedtls_pk_write_pubkey - ../../../mbedtls-sys/vendor/crypto/library/pkwrite.c:158
213+
//
214+
// - Const access with additional notes due to call stacks involved.
215+
//
216+
// ecdsa_sign_wrap: ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:657
217+
// mbedtls_ecdsa_write_signature ../../../mbedtls-sys/vendor/crypto/library/ecdsa.c:688
218+
// mbedtls_ecdsa_write_signature_restartable ../../../mbedtls-sys/vendor/crypto/library/ecdsa.c:640
219+
// MBEDTLS_ECDSA_DETERMINISTIC is not defined.
220+
// MBEDTLS_ECDSA_SIGN_ALT is not defined.
221+
// Passes grp to: ecdsa_sign_restartable: ../../../mbedtls-sys/vendor/crypto/library/ecdsa.c:253
222+
// Const access to group - reads parameters, passed as const to mbedtls_ecp_gen_privkey,
223+
// mbedtls_ecp_mul_restartable: ../../../mbedtls-sys/vendor/crypto/library/ecp.c:2351
224+
// MBEDTLS_ECP_INTERNAL_ALT is not defined. (otherwise it might not be safe depending on ecp_init/ecp_free) ../../../mbedtls-sys/build/config.rs:131
225+
// Passes as const to: mbedtls_ecp_check_privkey / mbedtls_ecp_check_pubkey / mbedtls_ecp_get_type( grp
226+
//
227+
// - Ignored due to not defined: ecdsa_verify_rs_wrap, ecdsa_sign_rs_wrap, ecdsa_rs_alloc, ecdsa_rs_free
228+
// (Undefined - MBEDTLS_ECP_RESTARTABLE - ../../../mbedtls-sys/build/config.rs:173)
229+
//
230+
// - Only const access to context: eckey_check_pair
231+
//
232+
// - Only used when creating/freeing - which is safe by design: ecdsa_alloc_wrap, ecdsa_free_wrap
233+
//
234+
#[cfg(feature = "threading")]
235+
unsafe impl Sync for Pk {}
236+
145237
impl Pk {
146238
/// Takes both DER and PEM forms of PKCS#1 or PKCS#8 encoded keys.
147239
///
@@ -323,11 +415,13 @@ impl Pk {
323415
.is_ok()
324416
}
325417

326-
getter!(
327-
/// Key length in bits
328-
len() -> usize = fn pk_get_bitlen
329-
);
330-
getter!(pk_type() -> Type = fn pk_get_type);
418+
pub fn len(&self) -> usize {
419+
unsafe { pk_get_bitlen(&self.inner) }
420+
}
421+
422+
pub fn pk_type(&self) -> Type {
423+
unsafe { pk_get_type(&self.inner).into() }
424+
}
331425

332426
pub fn curve(&self) -> Result<EcGroupId> {
333427
match self.pk_type() {
@@ -692,7 +786,7 @@ impl Pk {
692786
sig: &mut [u8],
693787
rng: &mut F,
694788
) -> Result<usize> {
695-
use crate::rng::RngCallback;
789+
use crate::rng::RngCallbackMut;
696790

697791
if self.pk_type() == Type::Ecdsa || self.pk_type() == Type::Eckey {
698792
if sig.len() < ECDSA_MAX_LEN {
@@ -717,8 +811,8 @@ impl Pk {
717811
hash.len(),
718812
sig.as_mut_ptr(),
719813
&mut ret,
720-
Some(Rfc6979Rng::call),
721-
rng.data_ptr(),
814+
Some(Rfc6979Rng::call_mut),
815+
rng.data_ptr_mut(),
722816
).into_result()?;
723817
};
724818
Ok(ret)

mbedtls/src/pk/rfc6979.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::alloc_prelude::*;
1212
use mbedtls_sys::types::raw_types::{c_int, c_uchar, c_void};
1313
use mbedtls_sys::types::size_t;
1414

15-
use crate::rng::{HmacDrbg, Random, RngCallback};
15+
use crate::rng::{HmacDrbg, Random, RngCallbackMut};
1616

1717
use crate::error::Result;
1818
use crate::bignum::Mpi;
@@ -67,7 +67,7 @@ fn generate_rfc6979_nonce(md: &MdInfo, x: &Mpi, q: &Mpi, digest_bytes: &[u8]) ->
6767
pub(crate) struct Rfc6979Rng {
6868
pub k: Vec<u8>,
6969
pub k_read: usize,
70-
pub rng: HmacDrbg<'static>,
70+
pub rng: HmacDrbg,
7171
}
7272

7373
/// An RNG which first outputs the k for RFC 6797 followed by random data
@@ -110,8 +110,8 @@ impl Rfc6979Rng {
110110
}
111111
}
112112

113-
impl RngCallback for Rfc6979Rng {
114-
unsafe extern "C" fn call(
113+
impl RngCallbackMut for Rfc6979Rng {
114+
unsafe extern "C" fn call_mut(
115115
user_data: *mut c_void,
116116
data_ptr: *mut c_uchar,
117117
len: size_t,
@@ -126,7 +126,7 @@ impl RngCallback for Rfc6979Rng {
126126
}
127127
}
128128

129-
fn data_ptr(&mut self) -> *mut c_void {
129+
fn data_ptr_mut(&mut self) -> *mut c_void {
130130
self as *const _ as *mut _
131131
}
132132
}

0 commit comments

Comments
 (0)