Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend Cipher types #330

Merged
merged 9 commits into from
Oct 31, 2023
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
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion mbedtls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "mbedtls"
# We jumped from v0.9 to v0.12 because v0.10 and v0.11 were based on mbedtls 3.X, which
# we decided not to support.
version = "0.12.0"
version = "0.12.0-alpha.1"
authors = ["Jethro Beekman <jethro@fortanix.com>"]
build = "build.rs"
edition = "2018"
Expand Down
34 changes: 33 additions & 1 deletion mbedtls/src/cipher/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ pub enum Authenticated {}
impl Type for Authenticated {
fn is_valid_mode(mode: raw::CipherMode) -> bool {
match mode {
raw::CipherMode::GCM | raw::CipherMode::CCM | raw::CipherMode::KW | raw::CipherMode::KWP => true,
raw::CipherMode::GCM
| raw::CipherMode::CCM
| raw::CipherMode::KW
| raw::CipherMode::KWP
| raw::CipherMode::CHACHAPOLY => true,
_ => false,
}
}
Expand Down Expand Up @@ -457,3 +461,31 @@ 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);
}
78 changes: 55 additions & 23 deletions mbedtls/src/cipher/raw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mod serde;

define!(
#[c_ty(cipher_id_t)]
#[derive(Copy, Clone, Eq, PartialEq)]
enum CipherId {
None = CIPHER_ID_NONE,
Null = CIPHER_ID_NULL,
Expand All @@ -24,6 +25,7 @@ define!(
Blowfish = CIPHER_ID_BLOWFISH,
Arc4 = CIPHER_ID_ARC4,
Aria = CIPHER_ID_ARIA,
Chacha20 = CIPHER_ID_CHACHA20,
}
);

Expand All @@ -39,6 +41,7 @@ impl From<cipher_id_t> for CipherId {
CIPHER_ID_BLOWFISH => CipherId::Blowfish,
CIPHER_ID_ARC4 => CipherId::Arc4,
CIPHER_ID_ARIA => CipherId::Aria,
CIPHER_ID_CHACHA20 => CipherId::Chacha20,
// This should be replaced with TryFrom once it is stable.
_ => panic!("Invalid cipher_id_t"),
}
Expand All @@ -58,6 +61,8 @@ define!(
GCM = MODE_GCM,
STREAM = MODE_STREAM,
CCM = MODE_CCM,
XTS = MODE_XTS,
CHACHAPOLY = MODE_CHACHAPOLY,
KW = MODE_KW,
KWP = MODE_KWP,
}
Expand All @@ -75,6 +80,8 @@ impl From<cipher_mode_t> for CipherMode {
MODE_GCM => CipherMode::GCM,
MODE_STREAM => CipherMode::STREAM,
MODE_CCM => CipherMode::CCM,
MODE_XTS => CipherMode::XTS,
MODE_CHACHAPOLY => CipherMode::CHACHAPOLY,
MODE_KW => CipherMode::KW,
MODE_KWP => CipherMode::KWP,
// This should be replaced with TryFrom once it is stable.
Expand Down Expand Up @@ -135,6 +142,31 @@ define!(
Camellia128Ccm = CIPHER_CAMELLIA_128_CCM,
Camellia192Ccm = CIPHER_CAMELLIA_192_CCM,
Camellia256Ccm = CIPHER_CAMELLIA_256_CCM,
Aria128Ecb = CIPHER_ARIA_128_ECB,
Aria192Ecb = CIPHER_ARIA_192_ECB,
Aria256Ecb = CIPHER_ARIA_256_ECB,
Aria128Cbc = CIPHER_ARIA_128_CBC,
Aria192Cbc = CIPHER_ARIA_192_CBC,
Aria256Cbc = CIPHER_ARIA_256_CBC,
Aria128Cfb128 = CIPHER_ARIA_128_CFB128,
Aria192Cfb128 = CIPHER_ARIA_192_CFB128,
Aria256Cfb128 = CIPHER_ARIA_256_CFB128,
Aria128Ctr = CIPHER_ARIA_128_CTR,
Aria192Ctr = CIPHER_ARIA_192_CTR,
Aria256Ctr = CIPHER_ARIA_256_CTR,
Aria128Gcm = CIPHER_ARIA_128_GCM,
Aria192Gcm = CIPHER_ARIA_192_GCM,
Aria256Gcm = CIPHER_ARIA_256_GCM,
Aria128Ccm = CIPHER_ARIA_128_CCM,
Aria192Ccm = CIPHER_ARIA_192_CCM,
Aria256Ccm = CIPHER_ARIA_256_CCM,
Aes128Ofb = CIPHER_AES_128_OFB,
Aes192Ofb = CIPHER_AES_192_OFB,
Aes256Ofb = CIPHER_AES_256_OFB,
Aes128Xts = CIPHER_AES_128_XTS,
Aes256Xts = CIPHER_AES_256_XTS,
Chacha20 = CIPHER_CHACHA20,
Chacha20Poly1305 = CIPHER_CHACHA20_POLY1305,
Aes128Kw = CIPHER_AES_128_KW,
Aes192Kw = CIPHER_AES_192_KW,
Aes256Kw = CIPHER_AES_256_KW,
Expand Down Expand Up @@ -213,41 +245,41 @@ impl Cipher {
unsafe { cipher_update_ad(&mut self.inner, ad.as_ptr(), ad.len()).into_result_discard() }
}

pub fn update(&mut self, indata: &[u8], outdata: &mut [u8]) -> Result<usize> {
// Check that minimum required space is available in outdata buffer
let reqd_size = if unsafe { *self.inner.cipher_info }.mode == MODE_ECB {
pub fn update(&mut self, in_data: &[u8], out_data: &mut [u8]) -> Result<usize> {
// Check that minimum required space is available in out_data buffer
let required_size = if unsafe { *self.inner.cipher_info }.mode == MODE_ECB {
self.block_size()
} else {
indata.len() + self.block_size()
in_data.len() + self.block_size()
};

if outdata.len() < reqd_size {
if out_data.len() < required_size {
return Err(Error::CipherFullBlockExpected);
}

let mut olen = 0;
unsafe {
cipher_update(
&mut self.inner,
indata.as_ptr(),
indata.len(),
outdata.as_mut_ptr(),
in_data.as_ptr(),
in_data.len(),
out_data.as_mut_ptr(),
&mut olen,
)
.into_result()?;
}
Ok(olen)
}

pub fn finish(&mut self, outdata: &mut [u8]) -> Result<usize> {
// Check that minimum required space is available in outdata buffer
if outdata.len() < self.block_size() {
pub fn finish(&mut self, out_data: &mut [u8]) -> Result<usize> {
// Check that minimum required space is available in out_data buffer
if out_data.len() < self.block_size() {
return Err(Error::CipherFullBlockExpected);
}

let mut olen = 0;
unsafe {
cipher_finish(&mut self.inner, outdata.as_mut_ptr(), &mut olen).into_result()?;
cipher_finish(&mut self.inner, out_data.as_mut_ptr(), &mut olen).into_result()?;
}
Ok(olen)
}
Expand All @@ -274,7 +306,7 @@ impl Cipher {
unsafe { (*self.inner.cipher_info).mode.into() }
}

// Utility function to get mdoe for the selected / setup cipher_info
// Utility function to get mode for the selected / setup cipher_info
pub fn is_authenticated(&self) -> bool {
unsafe {
if (*self.inner.cipher_info).mode == MODE_GCM || (*self.inner.cipher_info).mode == MODE_CCM {
Expand Down Expand Up @@ -413,31 +445,31 @@ impl Cipher {
Ok(plain_len)
}

fn do_crypto(&mut self, indata: &[u8], outdata: &mut [u8]) -> Result<usize> {
fn do_crypto(&mut self, in_data: &[u8], out_data: &mut [u8]) -> Result<usize> {
self.reset()?;

// The total number of bytes writte to outdata so far. It's safe to
// The total number of bytes written to out_data so far. It's safe to
// use this as a start index for slicing: &slice[slice.len()..] will
// return an empty slice, it doesn't panic.
let mut total_len = 0;

if unsafe { *self.inner.cipher_info }.mode == MODE_ECB {
// ECB mode requires single-block updates
for chunk in indata.chunks(self.block_size()) {
let len = self.update(chunk, &mut outdata[total_len..])?;
for chunk in in_data.chunks(self.block_size()) {
let len = self.update(chunk, &mut out_data[total_len..])?;
total_len += len;
}
} else {
total_len = self.update(indata, outdata)?;
total_len += self.finish(&mut outdata[total_len..])?;
total_len = self.update(in_data, out_data)?;
total_len += self.finish(&mut out_data[total_len..])?;
}

Ok(total_len)
}

pub fn cmac(&mut self, key: &[u8], data: &[u8], outdata: &mut [u8]) -> Result<()> {
// Check that outdata buffer has enough space
if outdata.len() < self.block_size() {
pub fn cmac(&mut self, key: &[u8], data: &[u8], out_data: &mut [u8]) -> Result<()> {
// Check that out_data buffer has enough space
if out_data.len() < self.block_size() {
return Err(Error::CipherFullBlockExpected);
}
self.reset()?;
Expand All @@ -448,7 +480,7 @@ impl Cipher {
(key.len() * 8) as _,
data.as_ptr(),
data.len(),
outdata.as_mut_ptr(),
out_data.as_mut_ptr(),
)
.into_result()?;
}
Expand Down
6 changes: 6 additions & 0 deletions mbedtls/src/ecp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,12 @@ impl EcPoint {
}
}

pub fn from_binary_no_compress(group: &EcGroup, bin: &[u8]) -> Result<EcPoint> {
s-arash marked this conversation as resolved.
Show resolved Hide resolved
let mut ret = Self::init();
unsafe { ecp_point_read_binary(&group.inner, &mut ret.inner, bin.as_ptr(), bin.len()) }.into_result()?;
Ok(ret)
}

pub fn from_components(x: Mpi, y: Mpi) -> Result<EcPoint> {
let mut ret = Self::init();

Expand Down