Add support for AES-OCB mode
This commit is contained in:
parent
e446d819e3
commit
963e3994a5
|
|
@ -21,6 +21,12 @@ pub const EVP_CTRL_GCM_SET_IVLEN: c_int = 0x9;
|
||||||
pub const EVP_CTRL_GCM_GET_TAG: c_int = 0x10;
|
pub const EVP_CTRL_GCM_GET_TAG: c_int = 0x10;
|
||||||
pub const EVP_CTRL_GCM_SET_TAG: c_int = 0x11;
|
pub const EVP_CTRL_GCM_SET_TAG: c_int = 0x11;
|
||||||
|
|
||||||
|
// Keeping above for backwards compatability
|
||||||
|
pub const EVP_CTRL_AEAD_SET_IVLEN: c_int = EVP_CTRL_GCM_SET_IVLEN;
|
||||||
|
pub const EVP_CTRL_AEAD_GET_TAG: c_int = EVP_CTRL_GCM_GET_TAG;
|
||||||
|
pub const EVP_CTRL_AEAD_SET_TAG: c_int = EVP_CTRL_GCM_SET_TAG;
|
||||||
|
|
||||||
|
|
||||||
pub unsafe fn EVP_get_digestbynid(type_: c_int) -> *const EVP_MD {
|
pub unsafe fn EVP_get_digestbynid(type_: c_int) -> *const EVP_MD {
|
||||||
EVP_get_digestbyname(OBJ_nid2sn(type_))
|
EVP_get_digestbyname(OBJ_nid2sn(type_))
|
||||||
}
|
}
|
||||||
|
|
@ -275,6 +281,7 @@ extern "C" {
|
||||||
pub fn EVP_aes_128_gcm() -> *const EVP_CIPHER;
|
pub fn EVP_aes_128_gcm() -> *const EVP_CIPHER;
|
||||||
pub fn EVP_aes_128_xts() -> *const EVP_CIPHER;
|
pub fn EVP_aes_128_xts() -> *const EVP_CIPHER;
|
||||||
pub fn EVP_aes_128_ofb() -> *const EVP_CIPHER;
|
pub fn EVP_aes_128_ofb() -> *const EVP_CIPHER;
|
||||||
|
pub fn EVP_aes_128_ocb() -> *const EVP_CIPHER;
|
||||||
pub fn EVP_aes_192_ecb() -> *const EVP_CIPHER;
|
pub fn EVP_aes_192_ecb() -> *const EVP_CIPHER;
|
||||||
pub fn EVP_aes_192_cbc() -> *const EVP_CIPHER;
|
pub fn EVP_aes_192_cbc() -> *const EVP_CIPHER;
|
||||||
pub fn EVP_aes_192_cfb1() -> *const EVP_CIPHER;
|
pub fn EVP_aes_192_cfb1() -> *const EVP_CIPHER;
|
||||||
|
|
@ -284,6 +291,7 @@ extern "C" {
|
||||||
pub fn EVP_aes_192_ccm() -> *const EVP_CIPHER;
|
pub fn EVP_aes_192_ccm() -> *const EVP_CIPHER;
|
||||||
pub fn EVP_aes_192_gcm() -> *const EVP_CIPHER;
|
pub fn EVP_aes_192_gcm() -> *const EVP_CIPHER;
|
||||||
pub fn EVP_aes_192_ofb() -> *const EVP_CIPHER;
|
pub fn EVP_aes_192_ofb() -> *const EVP_CIPHER;
|
||||||
|
pub fn EVP_aes_192_ocb() -> *const EVP_CIPHER;
|
||||||
pub fn EVP_aes_256_ecb() -> *const EVP_CIPHER;
|
pub fn EVP_aes_256_ecb() -> *const EVP_CIPHER;
|
||||||
pub fn EVP_aes_256_cbc() -> *const EVP_CIPHER;
|
pub fn EVP_aes_256_cbc() -> *const EVP_CIPHER;
|
||||||
pub fn EVP_aes_256_cfb1() -> *const EVP_CIPHER;
|
pub fn EVP_aes_256_cfb1() -> *const EVP_CIPHER;
|
||||||
|
|
@ -294,6 +302,7 @@ extern "C" {
|
||||||
pub fn EVP_aes_256_gcm() -> *const EVP_CIPHER;
|
pub fn EVP_aes_256_gcm() -> *const EVP_CIPHER;
|
||||||
pub fn EVP_aes_256_xts() -> *const EVP_CIPHER;
|
pub fn EVP_aes_256_xts() -> *const EVP_CIPHER;
|
||||||
pub fn EVP_aes_256_ofb() -> *const EVP_CIPHER;
|
pub fn EVP_aes_256_ofb() -> *const EVP_CIPHER;
|
||||||
|
pub fn EVP_aes_256_ocb() -> *const EVP_CIPHER;
|
||||||
#[cfg(ossl110)]
|
#[cfg(ossl110)]
|
||||||
pub fn EVP_chacha20() -> *const ::EVP_CIPHER;
|
pub fn EVP_chacha20() -> *const ::EVP_CIPHER;
|
||||||
#[cfg(ossl110)]
|
#[cfg(ossl110)]
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,10 @@ impl Cipher {
|
||||||
unsafe { Cipher(ffi::EVP_aes_128_ofb()) }
|
unsafe { Cipher(ffi::EVP_aes_128_ofb()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn aes_128_ocb() -> Cipher {
|
||||||
|
unsafe { Cipher(ffi::EVP_aes_128_ocb()) }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn aes_192_ecb() -> Cipher {
|
pub fn aes_192_ecb() -> Cipher {
|
||||||
unsafe { Cipher(ffi::EVP_aes_192_ecb()) }
|
unsafe { Cipher(ffi::EVP_aes_192_ecb()) }
|
||||||
}
|
}
|
||||||
|
|
@ -166,6 +170,10 @@ impl Cipher {
|
||||||
unsafe { Cipher(ffi::EVP_aes_192_ofb()) }
|
unsafe { Cipher(ffi::EVP_aes_192_ofb()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn aes_192_ocb() -> Cipher {
|
||||||
|
unsafe { Cipher(ffi::EVP_aes_192_ocb()) }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn aes_256_ecb() -> Cipher {
|
pub fn aes_256_ecb() -> Cipher {
|
||||||
unsafe { Cipher(ffi::EVP_aes_256_ecb()) }
|
unsafe { Cipher(ffi::EVP_aes_256_ecb()) }
|
||||||
}
|
}
|
||||||
|
|
@ -206,6 +214,10 @@ impl Cipher {
|
||||||
unsafe { Cipher(ffi::EVP_aes_256_ofb()) }
|
unsafe { Cipher(ffi::EVP_aes_256_ofb()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn aes_256_ocb() -> Cipher {
|
||||||
|
unsafe { Cipher(ffi::EVP_aes_256_ocb()) }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bf_cbc() -> Cipher {
|
pub fn bf_cbc() -> Cipher {
|
||||||
unsafe { Cipher(ffi::EVP_bf_cbc()) }
|
unsafe { Cipher(ffi::EVP_bf_cbc()) }
|
||||||
}
|
}
|
||||||
|
|
@ -298,6 +310,13 @@ impl Cipher {
|
||||||
// NOTE: OpenSSL returns pointers to static structs, which makes this work as expected
|
// NOTE: OpenSSL returns pointers to static structs, which makes this work as expected
|
||||||
*self == Cipher::aes_128_ccm() || *self == Cipher::aes_256_ccm()
|
*self == Cipher::aes_128_ccm() || *self == Cipher::aes_256_ccm()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Determines whether the cipher is using OCB mode
|
||||||
|
fn is_ocb(&self) -> bool {
|
||||||
|
*self == Cipher::aes_128_ocb() ||
|
||||||
|
*self == Cipher::aes_192_ocb() ||
|
||||||
|
*self == Cipher::aes_256_ocb()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Sync for Cipher {}
|
unsafe impl Sync for Cipher {}
|
||||||
|
|
@ -421,7 +440,7 @@ impl Crypter {
|
||||||
assert!(iv.len() <= c_int::max_value() as usize);
|
assert!(iv.len() <= c_int::max_value() as usize);
|
||||||
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
||||||
crypter.ctx,
|
crypter.ctx,
|
||||||
ffi::EVP_CTRL_GCM_SET_IVLEN,
|
ffi::EVP_CTRL_AEAD_SET_IVLEN,
|
||||||
iv.len() as c_int,
|
iv.len() as c_int,
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
))?;
|
))?;
|
||||||
|
|
@ -463,7 +482,7 @@ impl Crypter {
|
||||||
// NB: this constant is actually more general than just GCM.
|
// NB: this constant is actually more general than just GCM.
|
||||||
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
||||||
self.ctx,
|
self.ctx,
|
||||||
ffi::EVP_CTRL_GCM_SET_TAG,
|
ffi::EVP_CTRL_AEAD_SET_TAG,
|
||||||
tag.len() as c_int,
|
tag.len() as c_int,
|
||||||
tag.as_ptr() as *mut _,
|
tag.as_ptr() as *mut _,
|
||||||
))
|
))
|
||||||
|
|
@ -481,7 +500,7 @@ impl Crypter {
|
||||||
// NB: this constant is actually more general than just GCM.
|
// NB: this constant is actually more general than just GCM.
|
||||||
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
||||||
self.ctx,
|
self.ctx,
|
||||||
ffi::EVP_CTRL_GCM_SET_TAG,
|
ffi::EVP_CTRL_AEAD_SET_TAG,
|
||||||
tag_len as c_int,
|
tag_len as c_int,
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
))
|
))
|
||||||
|
|
@ -607,7 +626,7 @@ impl Crypter {
|
||||||
assert!(tag.len() <= c_int::max_value() as usize);
|
assert!(tag.len() <= c_int::max_value() as usize);
|
||||||
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
||||||
self.ctx,
|
self.ctx,
|
||||||
ffi::EVP_CTRL_GCM_GET_TAG,
|
ffi::EVP_CTRL_AEAD_GET_TAG,
|
||||||
tag.len() as c_int,
|
tag.len() as c_int,
|
||||||
tag.as_mut_ptr() as *mut _,
|
tag.as_mut_ptr() as *mut _,
|
||||||
))
|
))
|
||||||
|
|
@ -736,9 +755,12 @@ pub fn encrypt_aead(
|
||||||
let mut c = Crypter::new(t, Mode::Encrypt, key, iv)?;
|
let mut c = Crypter::new(t, Mode::Encrypt, key, iv)?;
|
||||||
let mut out = vec![0; data.len() + t.block_size()];
|
let mut out = vec![0; data.len() + t.block_size()];
|
||||||
|
|
||||||
if t.is_ccm() {
|
let is_ccm = t.is_ccm();
|
||||||
|
if is_ccm || t.is_ocb() {
|
||||||
c.set_tag_len(tag.len())?;
|
c.set_tag_len(tag.len())?;
|
||||||
c.set_data_len(data.len())?;
|
if is_ccm {
|
||||||
|
c.set_data_len(data.len())?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.aad_update(aad)?;
|
c.aad_update(aad)?;
|
||||||
|
|
@ -764,9 +786,12 @@ pub fn decrypt_aead(
|
||||||
let mut c = Crypter::new(t, Mode::Decrypt, key, iv)?;
|
let mut c = Crypter::new(t, Mode::Decrypt, key, iv)?;
|
||||||
let mut out = vec![0; data.len() + t.block_size()];
|
let mut out = vec![0; data.len() + t.block_size()];
|
||||||
|
|
||||||
if t.is_ccm() {
|
let is_ccm = t.is_ccm();
|
||||||
|
if is_ccm || t.is_ocb() {
|
||||||
c.set_tag(tag)?;
|
c.set_tag(tag)?;
|
||||||
c.set_data_len(data.len())?;
|
if is_ccm {
|
||||||
|
c.set_data_len(data.len())?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.aad_update(aad)?;
|
c.aad_update(aad)?;
|
||||||
|
|
@ -1387,6 +1412,60 @@ mod tests {
|
||||||
assert!(out.is_err());
|
assert!(out.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_aes_128_ocb() {
|
||||||
|
let key = "000102030405060708090a0b0c0d0e0f";
|
||||||
|
let aad = "0001020304050607";
|
||||||
|
let tag = "16dc76a46d47e1ead537209e8a96d14e";
|
||||||
|
let iv = "000102030405060708090a0b";
|
||||||
|
let pt = "0001020304050607";
|
||||||
|
let ct = "92b657130a74b85a";
|
||||||
|
|
||||||
|
let mut actual_tag = [0; 16];
|
||||||
|
let out = encrypt_aead(
|
||||||
|
Cipher::aes_128_ocb(),
|
||||||
|
&Vec::from_hex(key).unwrap(),
|
||||||
|
Some(&Vec::from_hex(iv).unwrap()),
|
||||||
|
&Vec::from_hex(aad).unwrap(),
|
||||||
|
&Vec::from_hex(pt).unwrap(),
|
||||||
|
&mut actual_tag,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(ct, hex::encode(out));
|
||||||
|
assert_eq!(tag, hex::encode(actual_tag));
|
||||||
|
|
||||||
|
let out = decrypt_aead(
|
||||||
|
Cipher::aes_128_ocb(),
|
||||||
|
&Vec::from_hex(key).unwrap(),
|
||||||
|
Some(&Vec::from_hex(iv).unwrap()),
|
||||||
|
&Vec::from_hex(aad).unwrap(),
|
||||||
|
&Vec::from_hex(ct).unwrap(),
|
||||||
|
&Vec::from_hex(tag).unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(pt, hex::encode(out));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_aes_128_ocb_fail() {
|
||||||
|
let key = "000102030405060708090a0b0c0d0e0f";
|
||||||
|
let aad = "0001020304050607";
|
||||||
|
let tag = "16dc76a46d47e1ead537209e8a96d14e";
|
||||||
|
let iv = "000000000405060708090a0b";
|
||||||
|
let ct = "92b657130a74b85a";
|
||||||
|
|
||||||
|
let out = decrypt_aead(
|
||||||
|
Cipher::aes_128_ocb(),
|
||||||
|
&Vec::from_hex(key).unwrap(),
|
||||||
|
Some(&Vec::from_hex(iv).unwrap()),
|
||||||
|
&Vec::from_hex(aad).unwrap(),
|
||||||
|
&Vec::from_hex(ct).unwrap(),
|
||||||
|
&Vec::from_hex(tag).unwrap(),
|
||||||
|
);
|
||||||
|
assert!(out.is_err());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(ossl110))]
|
#[cfg(any(ossl110))]
|
||||||
fn test_chacha20() {
|
fn test_chacha20() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue