Skip to content

Commit 59c6060

Browse files
bors[bot]Adrian CruceruTaowyoo
authored
Merge #226
226: Rebased Acruceru/mbedtls8 async support r=Taowyoo a=Taowyoo This is the successor of #163, except the commits in original PR. Following changes are added: - Add async tests to CI 2023-03-15 update: According to #163 (comment) Here are some to-dos in this PR: - [x] remove 'migration_mode' feature - [x] Since changing 'sign' from '&mut self' to '&self' was something that was in-progress, need to either revert to '&mut self' or check that assumption is valid. Regarding this: ```rust pub fn sign<F: Random>( &self, ``` Following two tasks could be put in another PR&issue - Performance tests (compare to 0.7 under same scenario, should give similar numbers) - Additional unit tests / run tests with valgrind. Co-authored-by: Adrian Cruceru <[email protected]> Co-authored-by: Yuxiang Cao <[email protected]>
2 parents 7f1d694 + 267bfff commit 59c6060

15 files changed

+1629
-47
lines changed

Cargo.lock

+512-10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
[workspace]
22
members = ["mbedtls", "mbedtls-sys"]
33
resolver = "2"
4+
5+
[patch.crates-io]
6+
mio = { git = "https://github.com/mzohreva/mio", branch = "mz/sgx-port-0.7.6" }
7+
tokio = { git = "https://github.com/mzohreva/tokio", branch = "mz/sgx-port-0.3.4" }
8+

ct.sh

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ if [ "$TRAVIS_RUST_VERSION" == "stable" ] || [ "$TRAVIS_RUST_VERSION" == "beta"
3333
cargo test --features pkcs12 --target $TARGET
3434
cargo test --features pkcs12_rc2 --target $TARGET
3535
cargo test --features dsa --target $TARGET
36+
cargo test --test hyper13 --features=std,async-rt --target $TARGET
37+
cargo test --test async_session --features=async-rt --target $TARGET
3638

3739
# If zlib is installed, test the zlib feature
3840
if [ -n "$ZLIB_INSTALLED" ]; then

mbedtls-sys/Cargo.toml

+2-3
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,8 @@ quote = "1.0.9"
4242
# * strstr/strlen/strncpy/strncmp/strcmp/snprintf
4343
# * memmove/memcpy/memcmp/memset
4444
# * rand/printf (used only for self tests. optionally use custom_printf)
45-
default = ["std", "debug", "threading", "zlib", "time", "aesni", "padlock", "legacy_protocols"]
46-
std = ["debug"] # deprecated automatic enabling of debug, can be removed on major version bump
47-
debug = []
45+
default = ["std", "threading", "zlib", "time", "aesni", "padlock", "legacy_protocols"]
46+
std = [] # deprecated automatic enabling of debug, can be removed on major version bump
4847
custom_printf = []
4948
custom_has_support = []
5049
aes_alt = []

mbedtls/Cargo.toml

+19-2
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,14 @@ bit-vec = { version = "0.5", optional = true }
2929
block-modes = { version = "0.3", optional = true }
3030
rc2 = { version = "0.3", optional = true }
3131
cfg-if = "1.0.0"
32+
tokio = { version = "0.3.4", optional = true }
3233

3334
[target.x86_64-fortanix-unknown-sgx.dependencies]
3435
rs-libc = "0.2.0"
3536
chrono = "0.4"
3637

3738
[dependencies.mbedtls-sys-auto]
38-
version = "2.25.0"
39+
version = "2.28.0"
3940
default-features = false
4041
features = ["custom_printf", "trusted_cert_callback", "threading"]
4142
path = "../mbedtls-sys"
@@ -47,6 +48,11 @@ serde_cbor = "0.6"
4748
hex = "0.3"
4849
matches = "0.1.8"
4950
hyper = { version = "0.10.16", default-features = false }
51+
hyper13 = { package = "hyper", version = "0.13", default-features = false, features = ["stream"] }
52+
tokio-02 = { package = "tokio", version = "0.2", default-features = false }
53+
async-stream = "0.3.0"
54+
futures = "0.3"
55+
tracing = "0.1"
5056

5157
[build-dependencies]
5258
cc = "1.0"
@@ -55,7 +61,7 @@ cc = "1.0"
5561
# Features are documented in the README
5662
default = ["std", "aesni", "time", "padlock"]
5763
std = ["byteorder/std", "mbedtls-sys-auto/std", "serde/std", "yasna"]
58-
debug = ["mbedtls-sys-auto/debug"]
64+
debug = []
5965
no_std_deps = ["spin", "serde/alloc"]
6066
force_aesni_support = ["mbedtls-sys-auto/custom_has_support", "mbedtls-sys-auto/aes_alt", "aesni"]
6167
mpi_force_c_code = ["mbedtls-sys-auto/mpi_force_c_code"]
@@ -68,6 +74,8 @@ dsa = ["std", "yasna", "num-bigint", "bit-vec"]
6874
pkcs12 = ["std", "yasna"]
6975
pkcs12_rc2 = ["pkcs12", "rc2", "block-modes"]
7076
legacy_protocols = ["mbedtls-sys-auto/legacy_protocols"]
77+
async = ["std", "tokio","tokio/net","tokio/io-util", "tokio/macros"]
78+
async-rt = ["async", "tokio/rt", "tokio/sync", "tokio/rt-multi-thread"]
7179

7280
[[example]]
7381
name = "client"
@@ -100,3 +108,12 @@ required-features = ["std"]
100108
[[test]]
101109
name = "hyper"
102110
required-features = ["std"]
111+
112+
[[test]]
113+
name = "hyper13"
114+
required-features = ["std", "async-rt"]
115+
116+
[[test]]
117+
name = "async_session"
118+
path = "tests/async_session.rs"
119+
required-features = ["async-rt"]

mbedtls/src/pk/dsa/mod.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,13 @@ fn sample_secret_value<F: Random>(upper_bound: &Mpi, rng: &mut F) -> Result<Mpi>
217217
Ok(c)
218218
}
219219

220-
fn encode_dsa_signature(r: &Mpi, s: &Mpi) -> Result<Vec<u8>> {
221-
let r = BigUint::from_bytes_be(&r.to_binary()?);
222-
let s = BigUint::from_bytes_be(&s.to_binary()?);
220+
pub fn encode_dsa_signature(r: &Mpi, s: &Mpi) -> Result<Vec<u8>> {
221+
serialize_signature(&r.to_binary()?, &s.to_binary()?)
222+
}
223+
224+
pub fn serialize_signature(r: &[u8], s: &[u8]) -> Result<Vec<u8>> {
225+
let r = BigUint::from_bytes_be(r);
226+
let s = BigUint::from_bytes_be(s);
223227

224228
Ok(yasna::construct_der(|w| {
225229
w.write_sequence(|w| {
@@ -229,6 +233,18 @@ fn encode_dsa_signature(r: &Mpi, s: &Mpi) -> Result<Vec<u8>> {
229233
}))
230234
}
231235

236+
pub fn deserialize_signature(signature: &Vec<u8>) -> Result<(Vec<u8>, Vec<u8>)> {
237+
let (r,s) = yasna::parse_der(signature, |r| {
238+
r.read_sequence(|rdr| {
239+
let r = rdr.next().read_biguint()?;
240+
let s = rdr.next().read_biguint()?;
241+
Ok((r,s))
242+
})
243+
}).map_err(|_| Error::X509InvalidSignature)?;
244+
245+
Ok((r.to_bytes_be(), s.to_bytes_be()))
246+
}
247+
232248
impl DsaPrivateKey {
233249
pub fn from_components(params: DsaParams, x: Mpi) -> Result<Self> {
234250
if x <= Mpi::new(1)? || x >= params.q {

mbedtls/src/pk/mod.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ define!(
163163
// B. Verifying thread safety.
164164
//
165165
// 1. Calls towards the specific Pk implementation are done via function pointers.
166-
//
166+
//
167167
// - Example call towards Pk:
168168
// ../../../mbedtls-sys/vendor/library/ssl_srv.c:3707 - mbedtls_pk_decrypt( private_key, p, len, ...
169169
// - This calls a generic function pointer via:
@@ -174,7 +174,7 @@ define!(
174174
// - The function pointers are defined via function:
175175
// ../../../mbedtls-sys/vendor/crypto/library/pk.c:115 - mbedtls_pk_info_from_type
176176
// - They are as follows: mbedtls_rsa_info / mbedtls_eckey_info / mbedtls_ecdsa_info
177-
// - These are defined in:
177+
// - These are defined in:
178178
// ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:196
179179
//
180180
// C. Checking types one by one.
@@ -211,8 +211,8 @@ define!(
211211
// And the key is a const parameter to mbedtls_pk_write_pubkey - ../../../mbedtls-sys/vendor/crypto/library/pkwrite.c:158
212212
//
213213
// - Const access with additional notes due to call stacks involved.
214-
//
215214
// ecdsa_sign_wrap: ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:657
215+
//
216216
// mbedtls_ecdsa_write_signature ../../../mbedtls-sys/vendor/crypto/library/ecdsa.c:688
217217
// mbedtls_ecdsa_write_signature_restartable ../../../mbedtls-sys/vendor/crypto/library/ecdsa.c:640
218218
// MBEDTLS_ECDSA_DETERMINISTIC is not defined.
@@ -222,7 +222,7 @@ define!(
222222
// mbedtls_ecp_mul_restartable: ../../../mbedtls-sys/vendor/crypto/library/ecp.c:2351
223223
// 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
224224
// Passes as const to: mbedtls_ecp_check_privkey / mbedtls_ecp_check_pubkey / mbedtls_ecp_get_type( grp
225-
//
225+
//
226226
// - Ignored due to not defined: ecdsa_verify_rs_wrap, ecdsa_sign_rs_wrap, ecdsa_rs_alloc, ecdsa_rs_free
227227
// (Undefined - MBEDTLS_ECP_RESTARTABLE - ../../../mbedtls-sys/build/config.rs:173)
228228
//
@@ -927,7 +927,7 @@ impl Pk {
927927
if hash.len() == 0 || sig.len() == 0 {
928928
return Err(Error::PkBadInputData)
929929
}
930-
930+
931931
unsafe {
932932
pk_verify(
933933
&mut self.inner,
@@ -1297,7 +1297,7 @@ iy6KC991zzvaWY/Ys+q/84Afqa+0qJKQnPuy/7F5GkVdQA/lfbhi
12971297
let mut dummy_sig = [];
12981298
assert_eq!(pk.sign(digest, data, &mut dummy_sig, &mut crate::test_support::rand::test_rng()).unwrap_err(), Error::PkBadInputData);
12991299
assert_eq!(pk.sign(digest, &[], &mut signature, &mut crate::test_support::rand::test_rng()).unwrap_err(), Error::PkBadInputData);
1300-
1300+
13011301
assert_eq!(pk.sign_deterministic(digest, data, &mut dummy_sig, &mut crate::test_support::rand::test_rng()).unwrap_err(), Error::PkBadInputData);
13021302
assert_eq!(pk.sign_deterministic(digest, &[], &mut signature, &mut crate::test_support::rand::test_rng()).unwrap_err(), Error::PkBadInputData);
13031303

mbedtls/src/ssl/async_utils.rs

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/* Copyright (c) Fortanix, Inc.
2+
*
3+
* Licensed under the GNU General Public License, version 2 <LICENSE-GPL or
4+
* https://www.gnu.org/licenses/gpl-2.0.html> or the Apache License, Version
5+
* 2.0 <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>, at your
6+
* option. This file may not be copied, modified, or distributed except
7+
* according to those terms. */
8+
9+
#![cfg(all(feature = "std", feature = "async"))]
10+
11+
use std::cell::Cell;
12+
use std::ptr::null_mut;
13+
use std::rc::Rc;
14+
use std::task::{Context as TaskContext, Poll};
15+
16+
17+
#[cfg(not(feature = "std"))]
18+
use core_io::{Error as IoError, Result as IoResult, ErrorKind as IoErrorKind};
19+
#[cfg(feature = "std")]
20+
use std::io::{Error as IoError, Result as IoResult, ErrorKind as IoErrorKind};
21+
22+
23+
#[derive(Clone)]
24+
pub struct ErasedContext(Rc<Cell<*mut ()>>);
25+
26+
unsafe impl Send for ErasedContext {}
27+
28+
impl ErasedContext {
29+
pub fn new() -> Self {
30+
Self(Rc::new(Cell::new(null_mut())))
31+
}
32+
33+
pub unsafe fn get(&self) -> Option<&mut TaskContext<'_>> {
34+
let ptr = self.0.get();
35+
if ptr.is_null() {
36+
None
37+
} else {
38+
Some(&mut *(ptr as *mut _))
39+
}
40+
}
41+
42+
pub fn set(&self, cx: &mut TaskContext<'_>) {
43+
self.0.set(cx as *mut _ as *mut ());
44+
}
45+
46+
pub fn clear(&self) {
47+
self.0.set(null_mut());
48+
}
49+
}
50+
51+
// mbedtls_ssl_write() has some weird semantics w.r.t non-blocking I/O:
52+
//
53+
// > When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ, it must be
54+
// > called later **with the same arguments**, until it returns a value greater
55+
// > than or equal to 0. When the function returns MBEDTLS_ERR_SSL_WANT_WRITE
56+
// > there may be some partial data in the output buffer, however this is not
57+
// > yet sent.
58+
//
59+
// WriteTracker is used to ensure we pass the same data in that scenario.
60+
//
61+
// Reference:
62+
// https://tls.mbed.org/api/ssl_8h.html#a5bbda87d484de82df730758b475f32e5
63+
pub struct WriteTracker {
64+
pending: Option<Box<DigestAndLen>>,
65+
}
66+
67+
struct DigestAndLen {
68+
#[cfg(debug_assertions)]
69+
digest: [u8; 20], // SHA-1
70+
len: usize,
71+
}
72+
73+
impl WriteTracker {
74+
fn new() -> Self {
75+
WriteTracker {
76+
pending: None,
77+
}
78+
}
79+
80+
#[cfg(debug_assertions)]
81+
fn digest(buf: &[u8]) -> [u8; 20] {
82+
use crate::hash::{Md, Type};
83+
let mut out = [0u8; 20];
84+
let res = Md::hash(Type::Sha1, buf, &mut out[..]);
85+
assert_eq!(res, Ok(out.len()));
86+
out
87+
}
88+
89+
pub fn adjust_buf<'a>(&self, buf: &'a [u8]) -> IoResult<&'a [u8]> {
90+
match self.pending.as_ref() {
91+
None => Ok(buf),
92+
Some(pending) => {
93+
if pending.len <= buf.len() {
94+
let buf = &buf[..pending.len];
95+
96+
// We only do this check in debug mode since it's an expensive check.
97+
#[cfg(debug_assertions)]
98+
if Self::digest(buf) == pending.digest {
99+
return Ok(buf);
100+
}
101+
102+
#[cfg(not(debug_assertions))]
103+
return Ok(buf);
104+
}
105+
Err(IoError::new(
106+
IoErrorKind::Other,
107+
"mbedtls expects the same data if the previous call to poll_write() returned Poll::Pending"
108+
))
109+
},
110+
}
111+
}
112+
113+
pub fn post_write(&mut self, buf: &[u8], res: &Poll<IoResult<usize>>) {
114+
match res {
115+
&Poll::Pending => {
116+
if self.pending.is_none() {
117+
self.pending = Some(Box::new(DigestAndLen {
118+
#[cfg(debug_assertions)]
119+
digest: Self::digest(buf),
120+
len: buf.len(),
121+
}));
122+
}
123+
},
124+
_ => {
125+
self.pending = None;
126+
}
127+
}
128+
}
129+
}
130+
131+
pub struct IoAdapter<S> {
132+
pub inner: S,
133+
pub ecx: ErasedContext,
134+
pub write_tracker: WriteTracker,
135+
}
136+
137+
impl<S> IoAdapter<S> {
138+
pub fn new(stream: S) -> Self {
139+
Self {
140+
inner: stream,
141+
ecx: ErasedContext::new(),
142+
write_tracker: WriteTracker::new(),
143+
}
144+
}
145+
}

0 commit comments

Comments
 (0)