use core;
mod asm_impl;
use self::asm_impl::*;
pub fn cmac_128(key: &[u8;16], data: &[u8]) -> [u8;16] {
let mut ks=[0u32;AES_MAX_EXP_KEY_SIZE];
unsafe{intel_aes_encrypt_init_128(key,&mut ks)};
let first_len=if data.len()==0 {
0
} else {
(data.len()-1)&!(AES_BLOCK_SIZE-1)
};
let (data,last)=data.split_at(first_len);
let mut last_block=[0u8;AES_BLOCK_SIZE];
let k1_or_k2=if last.len()==16 { 0u8 } else { 1u8 };
for (dst,src) in last_block.iter_mut().zip(last.iter().chain(&[0x80][..])) {
*dst=*src;
}
let _tmp1: u64;
let _tmp2: u64;
let mut out=[0u8;16];
unsafe{asm!("
// Load key schedule
movdqu 0x00($0), %xmm2
movdqu 0x10($0), %xmm3
movdqu 0x20($0), %xmm4
movdqu 0x30($0), %xmm5
movdqu 0x40($0), %xmm6
movdqu 0x50($0), %xmm7
movdqu 0x60($0), %xmm8
movdqu 0x70($0), %xmm9
movdqu 0x80($0), %xmm10
movdqu 0x90($0), %xmm11
movdqu 0xa0($0), %xmm12
// Set initial (zero) block
mov $$-16, %rax
pxor %xmm1, %xmm1
0: /* aes */
pxor %xmm2, %xmm1
aesenc %xmm3, %xmm1
aesenc %xmm4, %xmm1
aesenc %xmm5, %xmm1
aesenc %xmm6, %xmm1
aesenc %xmm7, %xmm1
aesenc %xmm8, %xmm1
aesenc %xmm9, %xmm1
aesenc %xmm10, %xmm1
aesenc %xmm11, %xmm1
aesenclast %xmm12, %xmm1
addq $$16, %rax
jnz 1f /* not_initial_block */
/* initial_block */
// Store encrypted zero-block (k0)
movdqa %xmm1, %xmm13
pxor %xmm1, %xmm1
1: /* not_initial_block */
cmpq $7, %rax
je 2f /* last_block */
ja 5f /* after_last_block */
movdqu ($1, %rax), %xmm0
pxor %xmm0, %xmm1
jmp 0b /* aes */
2: /* last_block */
movq %xmm13,$0
bswap $0
pextrq $$1,%xmm13,$1
bswap $1
// Calculate k1
shl $$1,$1
rcl $$1,$0
jnc 3f /* skip_xor1 */
xor $$0x87,$1
3: /* skip_xor1 */
test $6, $6
jz 4f /* skip_k2 */
// Calculate k2
shl $$1,$1
rcl $$1,$0
jnc 4f /* skip_xor2 */
xor $$0x87,$1
4: /* skip_xor2, skip_k2 */
bswap $0
movq $0,%xmm13
bswap $1
pinsrq $$1,$1,%xmm13
// Load last block
movdqu ($5), %xmm0
pxor %xmm13, %xmm1
pxor %xmm0, %xmm1
jmp 0b /* aes */
5: /* after_last_block */
movdqu %xmm1, ($4)"
: "=r"(_tmp1),"=r"(_tmp2)
: "0"(ks.as_ptr()),"1"(data.as_ptr()),"r"(out.as_mut_ptr()),
"r"(last_block.as_ptr()),"r"(k1_or_k2),"r"(first_len)
: "rax","xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7","xmm8",
"xmm9","xmm10","xmm11","xmm12","xmm13","memory"
)};
out
}
#[derive(PartialEq,Eq)]
enum State {
New,
Aad,
AadFinal,
Encrypting,
Decrypting,
Done,
}
pub struct AesGcm {
gctx: GcmContext,
a_len: usize,
m_len: usize,
state: State,
}
impl Clone for AesGcm {
fn clone(&self) -> Self {
if self.state!=State::New { panic!("Can't clone in this state") };
AesGcm{gctx:self.gctx.clone(),a_len:0,m_len:0,state:State::New}
}
}
impl AesGcm {
pub fn new(k: &[u8], iv: &[u8]) -> AesGcm {
let mut gctx=GcmContext::new();
match k.len() {
16 => {unsafe{intel_aes_encrypt_init_128(k.as_ptr() as *const _,&mut gctx.ks.ks)};gctx.ks.nr=10}
24 => {unsafe{intel_aes_encrypt_init_192(k.as_ptr() as *const _,&mut gctx.ks.ks)};gctx.ks.nr=12}
32 => {unsafe{intel_aes_encrypt_init_256(k.as_ptr() as *const _,&mut gctx.ks.ks)};gctx.ks.nr=14}
_ => panic!("Invalid AES keysize!")
};
unsafe{intel_aes_gcmINIT(&mut gctx.htbl,&gctx.ks.ks,gctx.ks.nr)};
if iv.len()==12 {
unsafe{core::ptr::copy(iv.as_ptr(),gctx.ctr.as_mut_ptr(),12)};
gctx.ctr[15]=1;
} else {
panic!("Only 96-bit IV supported!")
}
let mut out=[0u8;AES_BLOCK_SIZE];
unsafe{intel_aes_gcmENC([0u8;AES_BLOCK_SIZE].as_ptr(),out.as_mut_ptr(),&mut gctx,AES_BLOCK_SIZE)};
gctx.x0=out;
gctx.t=[0u8;AES_BLOCK_SIZE];
AesGcm{gctx:gctx,a_len:0,m_len:0,state:State::New}
}
pub fn aad(&mut self, mut data: &[u8]) {
match self.state { State::New | State::Aad => {}, _ => panic!("Can't add AAD in this state") };
self.a_len+=data.len();
let partial=data.len()%AES_BLOCK_SIZE;
let mut data2=[0u8;AES_BLOCK_SIZE];
if partial!=0 {
let (a,b)=data.split_at(data.len()-partial);
data=a;
unsafe{core::ptr::copy(b.as_ptr(),data2.as_mut_ptr(),partial)};
self.state=State::AadFinal;
} else {
self.state=State::Aad;
}
unsafe{
intel_aes_gcmAAD(&self.gctx.htbl,data.as_ptr(),data.len(),&mut self.gctx.t);
if partial!=0 {
intel_aes_gcmAAD(&self.gctx.htbl,data2.as_ptr(),data2.len(),&mut self.gctx.t);
}
}
}
pub fn encrypt(&mut self, plaintext: &[u8], ciphertext: &mut [u8]) {
assert_eq!(plaintext.len(),ciphertext.len());
match self.state { State::Decrypting | State::Done => panic!("Can't encrypt in this state"), _ => {} };
if plaintext.len()%AES_BLOCK_SIZE == 0 {
self.state=State::Encrypting;
} else {
self.state=State::Done;
}
self.m_len+=plaintext.len();
unsafe{intel_aes_gcmENC(plaintext.as_ptr(),ciphertext.as_mut_ptr(),&mut self.gctx,plaintext.len())};
}
pub fn decrypt(&mut self, ciphertext: &[u8], plaintext: &mut [u8]) {
assert_eq!(plaintext.len(),ciphertext.len());
match self.state { State::Encrypting | State::Done => panic!("Can't decrypt in this state"), _ => {} };
if plaintext.len()%AES_BLOCK_SIZE == 0 {
self.state=State::Decrypting;
} else {
self.state=State::Done;
}
self.m_len+=plaintext.len();
unsafe{intel_aes_gcmDEC(ciphertext.as_ptr(),plaintext.as_mut_ptr(),&mut self.gctx,plaintext.len())};
}
pub fn tag(&self) -> [u8;16] {
let mut tag=[0u8;AES_BLOCK_SIZE];
unsafe{intel_aes_gcmTAG(&self.gctx.htbl,&self.gctx.t,self.m_len,self.a_len,&self.gctx.x0,&mut tag)};
return tag;
}
}
#[cfg(test)]
mod tests {
use super::{cmac_128,AesGcm};
use core::iter::repeat;
use collections::Vec;
fn hex_to_num(ascii: u8) -> u8 {
match ascii {
b'0' ... b'9' => ascii-b'0',
b'A' ... b'F' => ascii-b'A'+10,
b'a' ... b'f' => ascii-b'a'+10,
_ => panic!("Not hex!")
}
}
fn hex_to_bytes(raw_hex: &str) -> Vec<u8> {
raw_hex.as_bytes().chunks(2).map(|b|(hex_to_num(b[0])<<4) + hex_to_num(b[1])).collect()
}
struct TestVector {
key: Vec<u8>,
iv: Vec<u8>,
plain_text: Vec<u8>,
cipher_text: Vec<u8>,
aad: Vec<u8>,
tag: Vec<u8>,
}
fn gcm_test_vectors() -> [TestVector; 5] {
[
TestVector {
key: hex_to_bytes("00000000000000000000000000000000"),
iv: hex_to_bytes("000000000000000000000000"),
plain_text: hex_to_bytes(""),
cipher_text: hex_to_bytes(""),
aad: hex_to_bytes(""),
tag: hex_to_bytes("58e2fccefa7e3061367f1d57a4e7455a")
},
TestVector {
key: hex_to_bytes("00000000000000000000000000000000"),
iv: hex_to_bytes("000000000000000000000000"),
plain_text: hex_to_bytes("00000000000000000000000000000000"),
cipher_text: hex_to_bytes("0388dace60b6a392f328c2b971b2fe78"),
aad: hex_to_bytes(""),
tag: hex_to_bytes("ab6e47d42cec13bdf53a67b21257bddf")
},
TestVector {
key: hex_to_bytes("feffe9928665731c6d6a8f9467308308"),
iv: hex_to_bytes("cafebabefacedbaddecaf888"),
plain_text: hex_to_bytes("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"),
cipher_text: hex_to_bytes("42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091"),
aad: hex_to_bytes("feedfacedeadbeeffeedfacedeadbeefabaddad2"),
tag: hex_to_bytes("5bc94fbc3221a5db94fae95ae7121a47")
},
TestVector {
key: hex_to_bytes("feffe9928665731c6d6a8f9467308308feffe9928665731c"),
iv: hex_to_bytes("cafebabefacedbaddecaf888"),
plain_text: hex_to_bytes("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"),
cipher_text: hex_to_bytes("3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710"),
aad: hex_to_bytes("feedfacedeadbeeffeedfacedeadbeefabaddad2"),
tag: hex_to_bytes("2519498e80f1478f37ba55bd6d27618c")
},
TestVector {
key: hex_to_bytes("feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308"),
iv: hex_to_bytes("cafebabefacedbaddecaf888"),
plain_text: hex_to_bytes("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"),
cipher_text: hex_to_bytes("522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662"),
aad: hex_to_bytes("feedfacedeadbeeffeedfacedeadbeefabaddad2"),
tag: hex_to_bytes("76fc6ece0f4e1768cddf8853bb2d551b")
},
]
}
fn cmac_test_vectors() -> [TestVector; 37] {
[
TestVector {
key: hex_to_bytes("2b7e151628aed2a6abf7158809cf4f3c"),
plain_text: hex_to_bytes(""),
tag: hex_to_bytes("bb1d6929e95937287fa37d129b756746"),
iv: Vec::with_capacity(0),
cipher_text: Vec::with_capacity(0),
aad: Vec::with_capacity(0),
},
TestVector {
key: hex_to_bytes("2b7e151628aed2a6abf7158809cf4f3c"),
plain_text: hex_to_bytes("6bc1bee22e409f96e93d7e117393172a"),
tag: hex_to_bytes("070a16b46b4d4144f79bdd9dd04a287c"),
iv: Vec::with_capacity(0),
cipher_text: Vec::with_capacity(0),
aad: Vec::with_capacity(0),
},
TestVector {
key: hex_to_bytes("2b7e151628aed2a6abf7158809cf4f3c"),
plain_text: hex_to_bytes("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411"),
tag: hex_to_bytes("dfa66747de9ae63030ca32611497c827"),
iv: Vec::with_capacity(0),
cipher_text: Vec::with_capacity(0),
aad: Vec::with_capacity(0),
},
TestVector {
key: hex_to_bytes("2b7e151628aed2a6abf7158809cf4f3c"),
plain_text: hex_to_bytes("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"),
tag: hex_to_bytes("51f0bebf7e3b9d92fc49741779363cfe"),
iv: Vec::with_capacity(0),
cipher_text: Vec::with_capacity(0),
aad: Vec::with_capacity(0),
},
TestVector{key:hex_to_bytes("5acc2951d3644f648fc73267895c8151"), plain_text:hex_to_bytes("8a"), tag:hex_to_bytes("8ca3202a393aaf356695c17a909a2023"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("d659299047f932ad129391258918ce52"), plain_text:hex_to_bytes("b46c"), tag:hex_to_bytes("1f1169ad1896a6734c604ee6fb4713f9"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("260829e2cbec93aa19b11d08a08dd8fa"), plain_text:hex_to_bytes("79cf56"), tag:hex_to_bytes("e76debc24beb76004bc649aae90f1a3e"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("c7235f4489eb97f594eb85a3dc95e0a6"), plain_text:hex_to_bytes("3c7368fb"), tag:hex_to_bytes("83b0b0b9d4dc0ee08a368b788d97d3db"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("98adf2c1ae8d14c7f3178135c5a9e74b"), plain_text:hex_to_bytes("0f50448532"), tag:hex_to_bytes("cc571b3d73a608c56756590c59fc941c"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("0a1c812701e438fff5c99a2e0ac28dcb"), plain_text:hex_to_bytes("63f2a1f8e8ba"), tag:hex_to_bytes("81891feefb770015eeb0479e4d7aa1cc"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("686826aa8bb22aaedde12e852702549c"), plain_text:hex_to_bytes("36063a41936875"), tag:hex_to_bytes("637a35dba9c5b998cdbec17d960c01ba"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("aeae7313625e74842e1ad81aa94a3173"), plain_text:hex_to_bytes("9bd1cf1455f1a1fe"), tag:hex_to_bytes("2210ca367a65fea5b5aed49072e51fcc"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("b9a104da123f6d82c9756144c9b83c67"), plain_text:hex_to_bytes("e63e3bf6b2785de2c7"), tag:hex_to_bytes("65c1b064d0c2553f58d6651489bfb51b"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("6a9535bb9bb2a5879ea6a1363e44adc3"), plain_text:hex_to_bytes("ecc21529048f0977304e"), tag:hex_to_bytes("46cfb8be17ffee08549f84b81b6ea0bc"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("d31eb8efde214a9a6bd92346467c8b82"), plain_text:hex_to_bytes("24565c728e953d73d1e2b3"), tag:hex_to_bytes("d71e021d0749c2e1098a721320ce14b5"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("9a06c2db615b1202463475713ec53b91"), plain_text:hex_to_bytes("5c40d7694cba83dcdef9f27b"), tag:hex_to_bytes("540f259e95178c10ea0a2ab59b8bd417"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("ae8075821f82fdf179f06325c7fc2467"), plain_text:hex_to_bytes("9df605c7d2ea03473a7cdc83d3"), tag:hex_to_bytes("dce24066a2395db4fea2c93abcf963d0"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("b5b17c457c0edd460807d5e5942a3287"), plain_text:hex_to_bytes("5e2bd863605800cfb183705ffe12"), tag:hex_to_bytes("eeafc0770d9b7b842f4c54b54376d87d"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("9f49903af819989506889c6fbcd477c1"), plain_text:hex_to_bytes("4372a702b6161b3c020a6078523c25"), tag:hex_to_bytes("57da254e39cc770ae12c5e0b8066668e"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("222c2cbcc3309189157fedc7a7086936"), plain_text:hex_to_bytes("4c9f074836948c6a6f2451c6aba68c5e"), tag:hex_to_bytes("ea038e3857fae7add29a8c8635b2a9f5"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("065049fd7d4356e9aa30d6bec36a6389"), plain_text:hex_to_bytes("8cf58fc3471c9c806051c208eb5da42277"), tag:hex_to_bytes("73f466a29bdc877e3d9e70c782dae6bb"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("b235d901227108a52d9e199a2fa3246d"), plain_text:hex_to_bytes("f18c65ea776ddee640c2d770b383fae226e6"), tag:hex_to_bytes("35574b059a8449774a9f76068ce722d0"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("ddc3085a0e5b3d9496553063fe37be0f"), plain_text:hex_to_bytes("6fa02b897afd43db981f891a964e0dd3a7e910"), tag:hex_to_bytes("788a8a78c0c7465ed4e353742d830289"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("010866a39c7f6b35975584ca8faaa4a4"), plain_text:hex_to_bytes("73da5e1e1763f0fd4272784fb245412a8af98ea7"), tag:hex_to_bytes("ea41dae0779af77ce5c70b5072b09db8"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("f642124f81b5239f30a056d32f09a7ec"), plain_text:hex_to_bytes("d642f3dd853aa78952106b8a7f349ffa2f3ed0176e"), tag:hex_to_bytes("b576327d22a32e849011238369d74587"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("e54972a31a37d7b68e200f55757b8f26"), plain_text:hex_to_bytes("88f8aef13fdd0cafbd0cfb7fbc1238d6c8d797f4bc8c"), tag:hex_to_bytes("4d80534d763f3275362fe2a7d4f4d8ad"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("9d9fe248489ef5a8fb4bb721c3e62b3f"), plain_text:hex_to_bytes("9290820e669d228d40fdb37c73ecb952b05e1d206de20b"), tag:hex_to_bytes("20bc4e2ac3888a83680d2e285641002c"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("537fd9eb4c8d972e07aca49edca78c3b"), plain_text:hex_to_bytes("5355cdac27da9e65473b3f548d2c3eb8e92f1dc0f2a81c01"), tag:hex_to_bytes("d342ddee5a95365ef9084f119b05e031"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("abeb891353e7eca082f83d05a368c399"), plain_text:hex_to_bytes("b03d47932fefc42f8a86e6f6de74f07f12583a2b532244eb94"), tag:hex_to_bytes("b3480fa14d25496e1a4c97818b11a486"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("4e65612078dff2372f627269915e1cff"), plain_text:hex_to_bytes("1163fa80546fe7b3da0df719b814c53533a585b6ad3c6aa557dd"), tag:hex_to_bytes("0453ee0dd228ec41dcffe6426bb61e12"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("b3b3545f59a2857762173c216be7ffd2"), plain_text:hex_to_bytes("a9c363237c7fd7f579a2fb7f6e3c7771b33e66ed0465a46aae1024"), tag:hex_to_bytes("98112aa3036ed6c69af0c2031e9e7c45"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("d1962d899c81cddcf1200d777459bd59"), plain_text:hex_to_bytes("ec7966c65e7e13e4c6083950d9c426e9ccacaf98623d7cd79b3106fb"), tag:hex_to_bytes("cd258ae726671b6265363aac91a365e3"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("258fe26621083194d84330a1f3dbc415"), plain_text:hex_to_bytes("d8bdacd885d73a17ddf4d9de1f43398500710d9f565565ab91945a792b"), tag:hex_to_bytes("c8e232e1221b231d8fd059df9af62312"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("2735631c78a507334dd5f16605abe014"), plain_text:hex_to_bytes("631b721ed9d44a610bba32f23b3c2f6117091fd13814469ef55e83b80f9c"), tag:hex_to_bytes("4e9dd5295518313a0c302dff019b55a8"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("529123009f8a3b96efe7565eed7c2829"), plain_text:hex_to_bytes("cc1f8ff0e93ec8f949f6785df890b25964ecd511b5a4af4ad4b0deba3516ef"), tag:hex_to_bytes("e89f8401a25904cea71b9e0a179a4f03"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("ad6acc48b3d71a2151ff598fc4b9cea2"), plain_text:hex_to_bytes("4f5290e1c2392a9a2d304e1718adc51a406419fd72c50c081bd4d86fcc2727c1"), tag:hex_to_bytes("3cc498b05aa41100aef1aa6f54703445"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
TestVector{key:hex_to_bytes("ba0efc383ab24c5e15264ba313de2f0c"), plain_text:hex_to_bytes("87af4789c661cae8866caa0f2e3374de2ff49e763dde89b07582bb98fe3782168e"), tag:hex_to_bytes("26666396851beb7efa1845df630b609f"), iv: Vec::with_capacity(0), cipher_text: Vec::with_capacity(0), aad: Vec::with_capacity(0),},
]
}
#[test]
fn aes_cmac_test() {
for item in cmac_test_vectors().iter() {
assert_eq!(item.key.len(),16);
let mut key=[0u8;16];
for (s,d) in item.key.iter().zip(key.iter_mut()) { *d=*s }
assert_eq!(&cmac_128(&key,&item.plain_text)[..], &item.tag[..]);
}
}
#[test]
fn aes_gcm_test() {
for item in gcm_test_vectors().iter() {
let mut cipher = AesGcm::new(&item.key, &item.iv);
cipher.aad(&item.aad);
let mut out: Vec<u8> = repeat(0).take(item.plain_text.len()).collect();
cipher.encrypt(&item.plain_text, &mut out[..]);
let out_tag=cipher.tag();
assert_eq!(out, item.cipher_text);
assert_eq!(&out_tag[..], &item.tag[..]);
}
}
#[test]
fn aes_gcm_large() {
let mut v1=Vec::<u8>::with_capacity(0);
v1.resize(4096,0);
let mut v2=v1.clone();
let mut key=[0u8;16];
let mut iv=[0u8;12];
let mut aes1=AesGcm::new(&key,&iv);
let mut aes2=aes1.clone();
aes1.decrypt(&v1,&mut v2);
aes2.encrypt(&v2,&mut v1);
assert!(v1.iter().all(|&i|i==0));
}
#[test]
fn aes_gcm_decrypt_test() {
for item in gcm_test_vectors().iter() {
let mut decipher = AesGcm::new(&item.key, &item.iv);
decipher.aad(&item.aad);
let mut out: Vec<u8> = repeat(0).take(item.plain_text.len()).collect();
decipher.decrypt(&item.cipher_text, &mut out[..]);
let out_tag=decipher.tag();
assert_eq!(out, item.plain_text);
assert_eq!(&out_tag[..], &item.tag[..]);
}
}
}