diff options
Diffstat (limited to 'rust/vendor/aes/src/ni/aes256.rs')
-rw-r--r-- | rust/vendor/aes/src/ni/aes256.rs | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/rust/vendor/aes/src/ni/aes256.rs b/rust/vendor/aes/src/ni/aes256.rs new file mode 100644 index 0000000..9a752c1 --- /dev/null +++ b/rust/vendor/aes/src/ni/aes256.rs @@ -0,0 +1,177 @@ +use super::{ + arch::*, + utils::{aesdec8, aesdeclast8, aesenc8, aesenclast8, load8, store8, xor8, U128x8}, +}; +use crate::{Block, ParBlocks}; +use cipher::{ + consts::{U16, U32, U8}, + generic_array::GenericArray, + BlockCipher, BlockDecrypt, BlockEncrypt, NewBlockCipher, +}; + +mod expand; +#[cfg(test)] +mod test_expand; + +/// AES-256 round keys +type RoundKeys = [__m128i; 15]; + +/// AES-256 block cipher +#[derive(Clone)] +pub struct Aes256 { + encrypt_keys: RoundKeys, + decrypt_keys: RoundKeys, +} + +impl Aes256 { + #[inline(always)] + pub(crate) fn encrypt8(&self, mut blocks: U128x8) -> U128x8 { + #[inline] + #[target_feature(enable = "aes")] + unsafe fn aesni256_encrypt8(keys: &RoundKeys, blocks: &mut U128x8) { + xor8(blocks, keys[0]); + aesenc8(blocks, keys[1]); + aesenc8(blocks, keys[2]); + aesenc8(blocks, keys[3]); + aesenc8(blocks, keys[4]); + aesenc8(blocks, keys[5]); + aesenc8(blocks, keys[6]); + aesenc8(blocks, keys[7]); + aesenc8(blocks, keys[8]); + aesenc8(blocks, keys[9]); + aesenc8(blocks, keys[10]); + aesenc8(blocks, keys[11]); + aesenc8(blocks, keys[12]); + aesenc8(blocks, keys[13]); + aesenclast8(blocks, keys[14]); + } + unsafe { aesni256_encrypt8(&self.encrypt_keys, &mut blocks) }; + blocks + } + + #[inline(always)] + pub(crate) fn encrypt(&self, block: __m128i) -> __m128i { + #[inline] + #[target_feature(enable = "aes")] + unsafe fn aesni256_encrypt1(keys: &RoundKeys, mut block: __m128i) -> __m128i { + block = _mm_xor_si128(block, keys[0]); + block = _mm_aesenc_si128(block, keys[1]); + block = _mm_aesenc_si128(block, keys[2]); + block = _mm_aesenc_si128(block, keys[3]); + block = _mm_aesenc_si128(block, keys[4]); + block = _mm_aesenc_si128(block, keys[5]); + block = _mm_aesenc_si128(block, keys[6]); + block = _mm_aesenc_si128(block, keys[7]); + block = _mm_aesenc_si128(block, keys[8]); + block = _mm_aesenc_si128(block, keys[9]); + block = _mm_aesenc_si128(block, keys[10]); + block = _mm_aesenc_si128(block, keys[11]); + block = _mm_aesenc_si128(block, keys[12]); + block = _mm_aesenc_si128(block, keys[13]); + _mm_aesenclast_si128(block, keys[14]) + } + unsafe { aesni256_encrypt1(&self.encrypt_keys, block) } + } +} + +impl NewBlockCipher for Aes256 { + type KeySize = U32; + + #[inline] + fn new(key: &GenericArray<u8, U32>) -> Self { + let key = unsafe { &*(key as *const _ as *const [u8; 32]) }; + let (encrypt_keys, decrypt_keys) = expand::expand(key); + Self { + encrypt_keys, + decrypt_keys, + } + } +} + +impl BlockCipher for Aes256 { + type BlockSize = U16; + type ParBlocks = U8; +} + +impl BlockEncrypt for Aes256 { + #[inline] + fn encrypt_block(&self, block: &mut Block) { + // Safety: `loadu` and `storeu` support unaligned access + #[allow(clippy::cast_ptr_alignment)] + unsafe { + let b = _mm_loadu_si128(block.as_ptr() as *const __m128i); + let b = self.encrypt(b); + _mm_storeu_si128(block.as_mut_ptr() as *mut __m128i, b); + } + } + + #[inline] + fn encrypt_par_blocks(&self, blocks: &mut ParBlocks) { + let b = self.encrypt8(load8(blocks)); + store8(blocks, b); + } +} + +impl BlockDecrypt for Aes256 { + #[inline] + fn decrypt_block(&self, block: &mut Block) { + #[inline] + #[target_feature(enable = "aes")] + unsafe fn aes256_decrypt1(block: &mut Block, keys: &RoundKeys) { + // Safety: `loadu` and `storeu` support unaligned access + #[allow(clippy::cast_ptr_alignment)] + let mut b = _mm_loadu_si128(block.as_ptr() as *const __m128i); + + b = _mm_xor_si128(b, keys[14]); + b = _mm_aesdec_si128(b, keys[13]); + b = _mm_aesdec_si128(b, keys[12]); + b = _mm_aesdec_si128(b, keys[11]); + b = _mm_aesdec_si128(b, keys[10]); + b = _mm_aesdec_si128(b, keys[9]); + b = _mm_aesdec_si128(b, keys[8]); + b = _mm_aesdec_si128(b, keys[7]); + b = _mm_aesdec_si128(b, keys[6]); + b = _mm_aesdec_si128(b, keys[5]); + b = _mm_aesdec_si128(b, keys[4]); + b = _mm_aesdec_si128(b, keys[3]); + b = _mm_aesdec_si128(b, keys[2]); + b = _mm_aesdec_si128(b, keys[1]); + b = _mm_aesdeclast_si128(b, keys[0]); + + // Safety: `loadu` and `storeu` support unaligned access + #[allow(clippy::cast_ptr_alignment)] + _mm_storeu_si128(block.as_mut_ptr() as *mut __m128i, b); + } + + unsafe { aes256_decrypt1(block, &self.decrypt_keys) } + } + + #[inline] + fn decrypt_par_blocks(&self, blocks: &mut ParBlocks) { + #[inline] + #[target_feature(enable = "aes")] + unsafe fn aes256_decrypt8(blocks: &mut ParBlocks, keys: &RoundKeys) { + let mut b = load8(blocks); + xor8(&mut b, keys[14]); + aesdec8(&mut b, keys[13]); + aesdec8(&mut b, keys[12]); + aesdec8(&mut b, keys[11]); + aesdec8(&mut b, keys[10]); + aesdec8(&mut b, keys[9]); + aesdec8(&mut b, keys[8]); + aesdec8(&mut b, keys[7]); + aesdec8(&mut b, keys[6]); + aesdec8(&mut b, keys[5]); + aesdec8(&mut b, keys[4]); + aesdec8(&mut b, keys[3]); + aesdec8(&mut b, keys[2]); + aesdec8(&mut b, keys[1]); + aesdeclast8(&mut b, keys[0]); + store8(blocks, b); + } + + unsafe { aes256_decrypt8(blocks, &self.decrypt_keys) } + } +} + +opaque_debug::implement!(Aes256); |