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_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 {
|
||||
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_xts() -> *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_cbc() -> *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_gcm() -> *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_cbc() -> *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_xts() -> *const EVP_CIPHER;
|
||||
pub fn EVP_aes_256_ofb() -> *const EVP_CIPHER;
|
||||
pub fn EVP_aes_256_ocb() -> *const EVP_CIPHER;
|
||||
#[cfg(ossl110)]
|
||||
pub fn EVP_chacha20() -> *const ::EVP_CIPHER;
|
||||
#[cfg(ossl110)]
|
||||
|
|
|
|||
|
|
@ -130,6 +130,10 @@ impl Cipher {
|
|||
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 {
|
||||
unsafe { Cipher(ffi::EVP_aes_192_ecb()) }
|
||||
}
|
||||
|
|
@ -166,6 +170,10 @@ impl Cipher {
|
|||
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 {
|
||||
unsafe { Cipher(ffi::EVP_aes_256_ecb()) }
|
||||
}
|
||||
|
|
@ -206,6 +214,10 @@ impl Cipher {
|
|||
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 {
|
||||
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
|
||||
*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 {}
|
||||
|
|
@ -421,7 +440,7 @@ impl Crypter {
|
|||
assert!(iv.len() <= c_int::max_value() as usize);
|
||||
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
||||
crypter.ctx,
|
||||
ffi::EVP_CTRL_GCM_SET_IVLEN,
|
||||
ffi::EVP_CTRL_AEAD_SET_IVLEN,
|
||||
iv.len() as c_int,
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
|
|
@ -463,7 +482,7 @@ impl Crypter {
|
|||
// NB: this constant is actually more general than just GCM.
|
||||
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
||||
self.ctx,
|
||||
ffi::EVP_CTRL_GCM_SET_TAG,
|
||||
ffi::EVP_CTRL_AEAD_SET_TAG,
|
||||
tag.len() as c_int,
|
||||
tag.as_ptr() as *mut _,
|
||||
))
|
||||
|
|
@ -481,7 +500,7 @@ impl Crypter {
|
|||
// NB: this constant is actually more general than just GCM.
|
||||
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
||||
self.ctx,
|
||||
ffi::EVP_CTRL_GCM_SET_TAG,
|
||||
ffi::EVP_CTRL_AEAD_SET_TAG,
|
||||
tag_len as c_int,
|
||||
ptr::null_mut(),
|
||||
))
|
||||
|
|
@ -607,7 +626,7 @@ impl Crypter {
|
|||
assert!(tag.len() <= c_int::max_value() as usize);
|
||||
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
||||
self.ctx,
|
||||
ffi::EVP_CTRL_GCM_GET_TAG,
|
||||
ffi::EVP_CTRL_AEAD_GET_TAG,
|
||||
tag.len() as c_int,
|
||||
tag.as_mut_ptr() as *mut _,
|
||||
))
|
||||
|
|
@ -736,10 +755,13 @@ pub fn encrypt_aead(
|
|||
let mut c = Crypter::new(t, Mode::Encrypt, key, iv)?;
|
||||
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())?;
|
||||
if is_ccm {
|
||||
c.set_data_len(data.len())?;
|
||||
}
|
||||
}
|
||||
|
||||
c.aad_update(aad)?;
|
||||
let count = c.update(data, &mut out)?;
|
||||
|
|
@ -764,10 +786,13 @@ pub fn decrypt_aead(
|
|||
let mut c = Crypter::new(t, Mode::Decrypt, key, iv)?;
|
||||
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)?;
|
||||
if is_ccm {
|
||||
c.set_data_len(data.len())?;
|
||||
}
|
||||
}
|
||||
|
||||
c.aad_update(aad)?;
|
||||
let count = c.update(data, &mut out)?;
|
||||
|
|
@ -1387,6 +1412,60 @@ mod tests {
|
|||
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]
|
||||
#[cfg(any(ossl110))]
|
||||
fn test_chacha20() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue