#[macro_use] extern crate failure; extern crate typenum; extern crate generic_array; extern crate libc; use failure::Error; use typenum::{U15, U32}; use generic_array::{GenericArray, ArrayLength}; use libc::c_uchar; #[repr(C)] #[derive(Debug, Copy, Clone, Default)] pub struct AES_state { pub slice: [u16; 8], } #[repr(C)] #[derive(Debug, Copy, Clone, Default)] pub struct AES256_ctx { pub rk: [AES_state; 15], } #[link_name = "ctaes"] extern "C" { pub fn AES256_init(ctx: *mut AES256_ctx, key32: *const c_uchar); pub fn AES256_encrypt( ctx: *const AES256_ctx, blocks: usize, cipher16: *mut c_uchar, plain16: *const c_uchar, ); pub fn AES256_decrypt( ctx: *const AES256_ctx, blocks: usize, plain16: *mut c_uchar, cipher16: *const c_uchar, ); } #[derive(Debug, Copy, Clone, Default)] pub struct AESGCMState(pub [u16; 8]); impl AESGCMState { fn as_c_repr(&self) -> AES_state { AES_state { slice: self.0 } } fn from_c_repr(repr: AES_state) -> AESGCMState { AESGCMState(repr.slice) } } #[derive(Debug, Copy, Clone, Default)] pub struct AESGCM256(pub GenericArray); impl AESGCM256 { fn as_c_repr(&self) -> AES256_ctx { let mut arr = [AES_state::default(); 15]; for i in 0..15 { arr[i] = self.0[i].as_c_repr(); } AES256_ctx { rk: arr } } fn from_c_repr(repr: AES256_ctx) -> AESGCM256 { let mut arr = GenericArray::::default(); for i in 0..15 { arr[i] = AESGCMState::from_c_repr(repr.rk[i]); } AESGCM256(arr) } } pub trait AESGCMCipher { type Ctx; type KeySize: ArrayLength; fn new(key: GenericArray) -> Self; fn encrypt(&mut self, plain: &[u8]) -> Result, Error>; fn decrypt(&mut self, ciph: &[u8]) -> Result, Error>; } pub type AES256GCMKey = GenericArray; impl AESGCMCipher for AESGCM256 { type Ctx = AESGCM256; type KeySize = U32; fn new(key: AES256GCMKey) -> Self { let mut ctx = AES256_ctx::default(); unsafe { AES256_init(&mut ctx, key.as_slice().as_ptr()); } AESGCM256::from_c_repr(ctx) } fn encrypt(&mut self, plain: &[u8]) -> Result, Error> { let ctx = self.as_c_repr(); let len = plain.len(); if len % 16 != 0 { return Err(format_err!("invalid length")); } let blocks = len / 16; let mut ciph = Vec::new(); for _ in 0..blocks { ciph.extend_from_slice(&[0u8; 16][..]); } unsafe { AES256_encrypt(&ctx, blocks, ciph.as_mut_ptr(), plain.as_ptr()); } Ok(ciph) } fn decrypt(&mut self, ciph: &[u8]) -> Result, Error> { let ctx = self.as_c_repr(); let len = ciph.len(); if len % 16 != 0 { return Err(format_err!("invalid length")); } let blocks = len / 16; let mut plain = Vec::new(); for _ in 0..blocks { plain.extend_from_slice(&[0u8; 16][..]); } unsafe { AES256_decrypt(&ctx, blocks, plain.as_mut_ptr(), ciph.as_ptr()); } Ok(plain) } } #[cfg(test)] mod tests { extern crate hex; use super::*; fn test_vectors() -> Vec<(String, String, String)> { vec![ ( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f".to_string(), "00112233445566778899aabbccddeeff".to_string(), "8ea2b7ca516745bfeafc49904b496089".to_string() ), ( "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4".to_string(), "6bc1bee22e409f96e93d7e117393172a".to_string(), "f3eed1bdb5d2a03c064b5a7e3db181f8".to_string() ), ( "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4".to_string(), "ae2d8a571e03ac9c9eb76fac45af8e51".to_string(), "591ccb10d410ed26dc5ba74a31362870".to_string() ), ( "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4".to_string(), "30c81c46a35ce411e5fbc1191a0a52ef".to_string(), "b6ed21b99ca6f4f9f153e7b1beafed1d".to_string() ), ( "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4".to_string(), "f69f2445df4f9b17ad2b417be66c3710".to_string(), "23304b7a39f9f3ff067d8d8f9e24ecc7".to_string() ), ] } #[test] fn aes_gcm_encrypt_test_vectors() { for v in test_vectors() { let key = *AES256GCMKey::from_slice(hex::decode(v.0).unwrap().as_slice()); let mut cipher = AESGCM256::new(key); let res = cipher.encrypt(hex::decode(v.1).unwrap().as_slice()).unwrap(); let test = hex::decode(v.2).unwrap(); assert_eq!(res, test.as_slice()) } } #[test] fn aes_gcm_decrypt_test_vectors() { for v in test_vectors() { let key = *AES256GCMKey::from_slice(hex::decode(v.0).unwrap().as_slice()); let mut cipher = AESGCM256::new(key); let res = cipher.decrypt(hex::decode(v.2).unwrap().as_slice()).unwrap(); let test = hex::decode(v.1).unwrap(); assert_eq!(res, test.as_slice()) } } }