Skip to content

Commit

Permalink
refactor(mbedtls): sync with new C mbedtls API
Browse files Browse the repository at this point in the history
update src
- revert unnessary format changes
- add `SslStates`
- add special case handling in `Read` and `AsyncRead`
- update code to sync with new C mbedtls API
  - some fields become private and renamed with prefix: `private_`
  - some functions need RNG now:
    - Pk::from_private_key
    - Pk::private_from_ec_components
    - add `mbedtls_psa_external_get_random`

update tests
- add `hyper_async` test for testing async and hyper14
- update old tests code to sync with new C mbedtls API
- revert unnessary format changes
  • Loading branch information
Taowyoo committed Jun 26, 2023
1 parent c7bc4b6 commit efd9d18
Show file tree
Hide file tree
Showing 38 changed files with 3,519 additions and 2,600 deletions.
953 changes: 681 additions & 272 deletions Cargo.lock

Large diffs are not rendered by default.

19 changes: 8 additions & 11 deletions mbedtls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,36 @@ byteorder = { version = "1.0.0", default-features = false }
yasna = { version = "0.2", optional = true, features = ["num-bigint", "bit-vec"] }
num-bigint = { version = "0.2", optional = true }
bit-vec = { version = "0.5", optional = true }
cbc = { version = "0.1.2", optional = true }
rc2 = { version = "0.8.1", optional = true }
cfg-if = "1.0.0"
tokio = { version = "1.16.1", optional = true }

[target.x86_64-fortanix-unknown-sgx.dependencies]
rs-libc = "0.2.0"

[dependencies.mbedtls-sys-auto]
version = "2.26.0"
version = "3.4.0"
default-features = false
features = ["trusted_cert_callback", "threading"]
path = "../mbedtls-sys"

[dependencies.mbedtls-platform-support]
version = "0.1"
version = "0.2"
path = "../mbedtls-platform-support"

[dev-dependencies]
libc = "0.2.0"
rand = "0.4.0"
serde_cbor = "0.6"
hex = "0.3"
matches = "0.1.8"
hyper = { version = "0.10.16", default-features = false }
async-stream = "0.3.0"
futures = "0.3"
tracing = "0.1"
pin-project-lite = "0.2"
rstest = "0.17.0"
rstest_reuse = "0.5.0"
lazy_static = "1.4"
env_logger = "0.10"

[build-dependencies]
cc = "1.0"
Expand All @@ -66,17 +67,14 @@ debug = ["mbedtls-sys-auto/debug"]
no_std_deps = ["mbedtls-platform-support/spin", "serde/alloc"]
force_aesni_support = ["mbedtls-platform-support/force_aesni_support", "aesni"]
mpi_force_c_code = ["mbedtls-sys-auto/mpi_force_c_code"]
rdrand = []
rdrand = ["mbedtls-platform-support/rdrand"]
aesni = ["mbedtls-platform-support/aesni"]
zlib = ["mbedtls-sys-auto/zlib"]
time = ["mbedtls-platform-support/time"]
padlock = ["mbedtls-sys-auto/padlock"]
dsa = ["std", "yasna", "num-bigint", "bit-vec"]
pkcs12 = ["std", "yasna"]
pkcs12_rc2 = ["pkcs12", "rc2", "cbc"]
legacy_protocols = ["mbedtls-sys-auto/legacy_protocols"]
async = ["std", "tokio", "tokio/net", "tokio/io-util", "tokio/macros"]
async-rt = ["async", "tokio/rt", "tokio/sync", "tokio/rt-multi-thread"]
tls13 = ["mbedtls-sys-auto/tls13", "mbedtls-platform-support/tls13"]

[[example]]
name = "client"
Expand Down Expand Up @@ -110,7 +108,6 @@ required-features = ["std"]
name = "hyper"
required-features = ["std"]


[[test]]
name = "async_session"
path = "tests/async_session.rs"
Expand Down
3 changes: 2 additions & 1 deletion mbedtls/examples/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use mbedtls::Result as TlsResult;
mod support;
use support::entropy::entropy_new;
use support::keys;
use support::rand::test_rng;

fn listen<E, F: FnMut(TcpStream) -> Result<(), E>>(mut handle_client: F) -> Result<(), E> {
let sock = TcpListener::bind("127.0.0.1:8080").unwrap();
Expand All @@ -39,7 +40,7 @@ fn result_main() -> TlsResult<()> {
let entropy = entropy_new();
let rng = Arc::new(CtrDrbg::new(Arc::new(entropy), None)?);
let cert = Arc::new(Certificate::from_pem_multiple(keys::PEM_CERT.as_bytes())?);
let key = Arc::new(Pk::from_private_key(keys::PEM_KEY.as_bytes(), None)?);
let key = Arc::new(Pk::from_private_key(&mut test_rng(),keys::PEM_KEY.as_bytes(), None)?);
let mut config = Config::new(Endpoint::Server, Transport::Stream, Preset::Default);
config.set_rng(rng);
config.push_cert(cert, key)?;
Expand Down
13 changes: 3 additions & 10 deletions mbedtls/src/bignum/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,22 +133,15 @@ impl Mpi {
Ok(())
}

fn get_limb(&self, n: usize) -> mpi_uint {
if n < self.inner.n {
unsafe { *self.inner.p.offset(n as isize) }
} else {
// zero pad
0
}
}

pub fn as_u32(&self) -> Result<u32> {
if self.bit_length()? > 32 {
// Not exactly correct but close enough
return Err(codes::MpiBufferTooSmall.into());
}

Ok(self.get_limb(0) as u32)
let mut buf = [0u8; 4];
unsafe { mpi_write_binary(&self.inner, buf.as_mut_ptr(), buf.len()).into_result() }?;
Ok(u32::from_be_bytes(buf))
}

pub fn sign(&self) -> Sign {
Expand Down
141 changes: 129 additions & 12 deletions mbedtls/src/cipher/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ impl<O: Operation, T: Type> Cipher<O, T, Fresh> {

// Put together the structure to return
Ok(Cipher {
raw_cipher: raw_cipher,
raw_cipher,
padding: raw::CipherPadding::Pkcs7,
_op: PhantomData,
_type: PhantomData,
Expand Down Expand Up @@ -273,6 +273,27 @@ impl Cipher<Encryption, TraditionalNoIv, Fresh> {
}

impl Cipher<Encryption, Authenticated, AdditionalData> {
/// The authenticated encryption (AEAD/NIST_KW) function.
///
/// For AEAD modes, the tag will be appended to the ciphertext, as recommended by RFC 5116.
/// (NIST_KW doesn't have a separate tag.)
///
/// # Arguments
///
/// * `ad` - The additional data to authenticate.
/// * `plain` - The plaintext data to be encrypted and authenticated.
/// * `cipher_and_tag` - A mutable reference to a byte array where the ciphertext and authentication tag will be written.
/// * `tag_len` - The length of the tag to be generated.
///
/// # Returns
///
/// * `Result<usize>` - The length of the encrypted data on success.
///
/// # Errors
///
/// * `codes::CipherBadInputData` - For authenticated cipher mode plain_text length should be smaller than cipher length, except
/// AES KW and KWP cipher mode.
/// * Any other errors from underlying `mbedtls_cipher_auth_encrypt_ext` function.
pub fn encrypt_auth(
mut self,
ad: &[u8],
Expand All @@ -287,21 +308,58 @@ impl Cipher<Encryption, Authenticated, AdditionalData> {
))
}

/// The authenticated encryption (AEAD/NIST_KW) function.
///
/// For AEAD modes, the tag will be appended to the ciphertext, as recommended by RFC 5116.
/// (NIST_KW doesn't have a separate tag.)
///
/// # Arguments
///
/// * `ad` - The additional data to authenticate
/// * `data_with_tag` - The data to be encrypted and authenticated, along with space for the tag
/// * `tag_len` - The length of the tag to be generated
///
/// # Returns
///
/// * `Result<usize>` - The length of the encrypted data on success
///
/// # Errors
///
/// * `codes::CipherBadInputData` - If the size of `data_with_tag` minus `tag_len` is less than
/// or equal to zero
pub fn encrypt_auth_inplace(
mut self,
ad: &[u8],
data: &mut [u8],
tag: &mut [u8],
data_with_tag: &mut [u8],
tag_len: usize,
) -> Result<(usize, Cipher<Encryption, Authenticated, Finished>)> {
Ok((
self.raw_cipher
.encrypt_auth_inplace(ad, data, tag)?,
.encrypt_auth_inplace(ad, data_with_tag, tag_len)?,
self.change_state(),
))
}
}

impl Cipher<Decryption, Authenticated, AdditionalData> {
/// The authenticated decryption (AEAD/NIST_KW) function.
///
/// # Arguments
///
/// * `ad` - The additional data that was authenticated.
/// * `cipher_and_tag` - The ciphertext and authentication tag that were generated by the corresponding call to `encrypt_auth`.
/// * `plain_text` - A mutable reference to a byte array where the decrypted plaintext will be written.
/// * `tag_len` - The length of the tag.
///
/// # Returns
///
/// * `Result<usize>` - The length of the decrypted data on success.
///
/// # Errors
///
/// * `codes::CipherBadInputData` - For authenticated cipher mode plain_text length should be smaller than cipher length, except
/// AES KW and KWP cipher mode.
/// * Any other errors from underlying `mbedtls_cipher_auth_decrypt_ext` mbedtls function.
pub fn decrypt_auth(
mut self,
ad: &[u8],
Expand All @@ -316,15 +374,37 @@ impl Cipher<Decryption, Authenticated, AdditionalData> {
))
}

/// The authenticated decryption (AEAD/NIST_KW) function.
///
/// If the data is not authentic, then the output buffer is zeroed out to
/// prevent the unauthentic plaintext being used, making this interface safer.
///
/// For AEAD modes, the tag must be appended to the ciphertext, as recommended by RFC 5116.
/// (NIST_KW doesn't have a separate tag.)
///
/// # Arguments
///
/// * `ad` - The additional data to authenticate
/// * `data_with_tag` - The data to be decrypted and authenticated, along with space for the tag
/// * `tag_len` - The length of the tag to be generated
///
/// # Returns
///
/// * `Result<usize>` - The length of the decrypted data on success
///
/// # Errors
///
/// * `codes::CipherBadInputData` - If the size of `data_with_tag` minus `tag_len` is less than
/// or equal to zero
pub fn decrypt_auth_inplace(
mut self,
ad: &[u8],
data: &mut [u8],
tag: &[u8],
data_with_tag: &mut [u8],
tag_len: usize,
) -> Result<(usize, Cipher<Decryption, Authenticated, Finished>)> {
Ok((
self.raw_cipher
.decrypt_auth_inplace(ad, data, tag)?,
.decrypt_auth_inplace(ad, data_with_tag, tag_len)?,
self.change_state(),
))
}
Expand Down Expand Up @@ -437,6 +517,7 @@ fn ccm_inplace() {
let iv = [0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16];
let ad = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
let mut c = [0x20, 0x21, 0x22, 0x23, 0x0, 0x0, 0x0, 0x0];
let tag_len: usize = 4;
let validate_cipher = [0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d];
let validate_plain = [0x20, 0x21, 0x22, 0x23];

Expand All @@ -447,9 +528,8 @@ fn ccm_inplace() {
)
.unwrap();
let cipher = cipher.set_key_iv(&k, &iv).unwrap();
let (data, tag) = c.split_at_mut(4);
cipher
.encrypt_auth_inplace(&ad, data, tag)
.encrypt_auth_inplace(&ad, &mut c, tag_len)
.unwrap();
assert_eq!(c, validate_cipher);

Expand All @@ -460,9 +540,8 @@ fn ccm_inplace() {
)
.unwrap();
let cipher = cipher.set_key_iv(&k, &iv).unwrap();
let (data, tag) = c.split_at_mut(4);
cipher.decrypt_auth_inplace(&ad, data, tag).unwrap();
assert_eq!(validate_plain, data);
cipher.decrypt_auth_inplace(&ad, &mut c, tag_len).unwrap();
assert_eq!(validate_plain, c[..c.len() - tag_len]);
}

#[test]
Expand Down Expand Up @@ -504,3 +583,41 @@ fn aes_kwp() {
let out_len = cipher.decrypt_auth(&[], &c, &mut p_out, 0).unwrap().0;
assert_eq!(p, &p_out[..out_len]);
}

#[test]
fn aes_gcm() {
let k = [
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e,
0x4f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d,
0x4e, 0x4f,
];
let iv = [0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16];

let ad = [0x03, 0x04, 0x05];
let p = [0x20, 0x21, 0x22, 0x23];
let c = [0x01, 0x08, 0x55, 0x0f];
let t = [0x3f, 0xd9, 0x8e, 0x74];
let mut p_out = [0u8; 4];
let mut c_out = [0u8; 8];

let cipher = Cipher::<Encryption, Authenticated, Fresh>::new(
raw::CipherId::Aes,
raw::CipherMode::GCM,
(k.len() * 8) as _,
)
.unwrap();
let cipher = cipher.set_key_iv(&k, &iv).unwrap();

cipher.encrypt_auth(&ad, &p, &mut c_out, 4).unwrap();
assert_eq!(c, c_out[0..4]);
assert_eq!(t, c_out[4..8]);
let cipher = Cipher::<_, Authenticated, _>::new(
raw::CipherId::Aes,
raw::CipherMode::GCM,
(k.len() * 8) as _,
)
.unwrap();
let cipher = cipher.set_key_iv(&k, &iv).unwrap();
cipher.decrypt_auth(&ad, &c_out, &mut p_out, 4).unwrap();
assert_eq!(p, p_out);
}
Loading

0 comments on commit efd9d18

Please sign in to comment.