rust: add AES benchmark against soft_aes

This commit is contained in:
Wladimir J. van der Laan 2020-05-01 12:25:24 +00:00
parent e080a03821
commit 6b907fd033
3 changed files with 121 additions and 6 deletions

View File

@ -11,3 +11,4 @@ riscv = "0.5"
riscv-rt = "0.6" riscv-rt = "0.6"
hex-literal = "0.2" hex-literal = "0.2"
sha2 = { version = "0.8", default-features = false } sha2 = { version = "0.8", default-features = false }
aes-soft = { version = "0.3" }

View File

@ -17,6 +17,8 @@ use k210_shared::timing::clock;
use riscv::asm; use riscv::asm;
use riscv_rt::entry; use riscv_rt::entry;
use sha2::{Sha256, Digest}; use sha2::{Sha256, Digest};
use aes_soft::block_cipher_trait::generic_array::GenericArray;
use aes_soft::block_cipher_trait::BlockCipher;
struct AESTestVec { struct AESTestVec {
cipher_mode: cipher_mode, cipher_mode: cipher_mode,
@ -436,7 +438,7 @@ fn main() -> ! {
tv.aad, tv.aad,
tv.pt, tv.pt,
&mut ct_out, &mut ct_out,
&mut tag_out, Some(&mut tag_out),
); );
if &ct_out[0..tv.ct.len()] == tv.ct { if &ct_out[0..tv.ct.len()] == tv.ct {
@ -473,7 +475,7 @@ fn main() -> ! {
tv.aad, tv.aad,
&ct_out[0..tv.ct.len()], &ct_out[0..tv.ct.len()],
&mut pt_out, &mut pt_out,
&mut tag_out2, Some(&mut tag_out2),
); );
write!(stdout, " ").unwrap(); write!(stdout, " ").unwrap();
@ -549,7 +551,7 @@ fn main() -> ! {
// "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno" repeated 65,535 times // "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno" repeated 65,535 times
// (this is shorter than the given test vector as it is the maximum that the SHA256 engine // (this is shorter than the given test vector as it is the maximum that the SHA256 engine
// supports, 65536 SHA blocks) // supports, 65536 SHA blocks including padding)
{ {
let expected = hex!("929156a9422e05b71655509e8e9e7292d65d540a7342c94df3e121cedd407dfe"); let expected = hex!("929156a9422e05b71655509e8e9e7292d65d540a7342c94df3e121cedd407dfe");
let s = b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"; let s = b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno";
@ -604,6 +606,49 @@ fn main() -> ! {
writeln!(stdout).unwrap(); writeln!(stdout).unwrap();
} }
// Try iterator-based AES
// let indata = [0, 0, 0, 0, 0, 0, 0, 0];
let size = 256 * 1024;
write!(stdout, "AES128 hw, 32bit ({} bytes): ", size).unwrap();
let time_start = clock();
let mut o = aes::run_iter32(
aes,
cipher_mode::ECB,
encrypt_sel::ENCRYPTION,
&hex!("00000000000000000000000000000000"),
&hex!(""),
&hex!(""),
//indata.iter().copied(),
iter::repeat(0).take(size / 4),
size,
);
for _ in 0..size / 16 {
// ;
// write!(stdout, "{:08x} ", o.next().unwrap()).unwrap();
assert!(o.next().unwrap() == 0xd44be966);
assert!(o.next().unwrap() == 0x3b2c8aef);
assert!(o.next().unwrap() == 0x59fa4c88);
assert!(o.next().unwrap() == 0x2e2b34ca);
}
// writeln!(stdout).unwrap();
o.finish(None);
let time_end = clock();
writeln!(stdout, "({} kB/s)", (size as u64) * 1_000 / (time_end - time_start)).unwrap();
write!(stdout, "AES128 sw ({} bytes): ", size).unwrap();
let time_start = clock();
let key = GenericArray::from_slice(&[0u8; 16]);
let cipher = aes_soft::Aes128::new(&key);
let expect = GenericArray::clone_from_slice(&[0x66, 0xe9, 0x4b, 0xd4, 0xef, 0x8a, 0x2c, 0x3b, 0x88, 0x4c, 0xfa, 0x59, 0xca, 0x34, 0x2b, 0x2e]);
for _ in 0..size / 16 { // per block
let mut block = GenericArray::clone_from_slice(&[0u8; 16]);
cipher.encrypt_block(&mut block);
// writeln!(stdout, "{:?}", block).unwrap();
assert!(block == expect);
}
let time_end = clock();
writeln!(stdout, "({} kB/s)", (size as u64) * 1_000 / (time_end - time_start)).unwrap();
loop { loop {
unsafe { asm::wfi(); } unsafe { asm::wfi(); }
} }

View File

@ -95,7 +95,7 @@ fn setup(
fn finish( fn finish(
aes: &mut pac::AES, aes: &mut pac::AES,
cipher_mode: cipher_mode, cipher_mode: cipher_mode,
tag: &mut [u8], tag: Option<&mut [u8]>,
) { ) {
unsafe { unsafe {
if cipher_mode == cipher_mode::GCM { if cipher_mode == cipher_mode::GCM {
@ -115,7 +115,7 @@ fn finish(
atomic::compiler_fence(Ordering::SeqCst) atomic::compiler_fence(Ordering::SeqCst)
} }
if tag.len() != 0 { if let Some(tag) = tag {
for i in 0..4 { for i in 0..4 {
let val = aes.gcm_out_tag[3 - i].read().bits(); let val = aes.gcm_out_tag[3 - i].read().bits();
tag[i*4..i*4+4].copy_from_slice(&val.to_be_bytes()); tag[i*4..i*4+4].copy_from_slice(&val.to_be_bytes());
@ -150,7 +150,7 @@ pub fn run(
aad: &[u8], aad: &[u8],
ind: &[u8], ind: &[u8],
outd: &mut [u8], outd: &mut [u8],
tag: &mut [u8], tag: Option<&mut [u8]>,
) )
{ {
setup(aes, cipher_mode, encrypt_sel, key, iv, aad, ind.len()); setup(aes, cipher_mode, encrypt_sel, key, iv, aad, ind.len());
@ -174,3 +174,72 @@ pub fn run(
finish(aes, cipher_mode, tag); finish(aes, cipher_mode, tag);
} }
/** Iterator-based interface. */
pub struct OutIterator<'a, I>
where I: Iterator<Item=u32> {
aes: &'a mut pac::AES,
cipher_mode: cipher_mode,
ind: I,
len: usize,
iptr: usize,
optr: usize,
}
impl <'a, I> Iterator for OutIterator<'a, I>
where I: Iterator<Item=u32> {
type Item = u32;
fn next(&mut self) -> Option<u32> {
if self.optr >= self.len {
None
} else {
unsafe {
while self.iptr < self.len && self.aes.data_in_flag.read().data_in_flag() == DATA_IN_FLAG_A::CAN_INPUT {
let val = self.ind.next().unwrap();
self.aes.text_data.write(|w| w.bits(val));
self.iptr += 4;
}
while self.aes.data_out_flag.read().data_out_flag() != DATA_OUT_FLAG_A::CAN_OUTPUT {
atomic::compiler_fence(Ordering::SeqCst)
}
self.optr += 4;
Some(self.aes.out_data.read().bits())
}
}
}
}
impl <'a, I> OutIterator<'a, I>
where I: Iterator<Item=u32> {
pub fn finish(&mut self, tag: Option<&mut [u8]>) {
assert!(self.iptr >= self.len && self.optr >= self.len);
finish(self.aes, self.cipher_mode, tag);
}
}
/** Run AES algorithm as an iterator over 32-bit little-endian items,
* returning 32-bit little-endian items.
*/
pub fn run_iter32<'a, X>(
aes: &'a mut pac::AES,
cipher_mode: cipher_mode,
encrypt_sel: encrypt_sel,
key: &[u8],
iv: &[u8],
aad: &[u8],
ind: X,
len: usize,
) -> OutIterator<'a, X>
where X: Iterator<Item = u32> {
setup(aes, cipher_mode, encrypt_sel, key, iv, aad, len);
OutIterator {
aes,
cipher_mode,
ind: ind,
len,
iptr: 0,
optr: 0,
}
}