use std::ptr::{ copy_nonoverlapping, copy };
use crate::number::{ IntUnion, LongUnion, LongerUnion };
macro_rules! GF_mul {
($a:expr, $b:expr) => {
{
let mut a = $a;
let mut b = $b;
let mut ret = 0_u8;
while b != 0
{
if (b & 1 == 1)
{ ret ^= a; }
if (a & 0b1000_0000 != 0)
{ a = (a << 1) ^ (IRREDUCIBLE as u8); }
else
{ a <<= 1; }
b >>= 1;
}
ret
}
};
}
macro_rules! GF_is_candidate {
($a:expr) => {
{
let a_1 = $a;
let a_2 = GF_mul!(a_1, a_1);
let a_4 = GF_mul!(a_2, a_2);
let a_8 = GF_mul!(a_4, a_4);
let a_16 = GF_mul!(a_8, a_8);
let a_32 = GF_mul!(a_16, a_16);
let a_3 = GF_mul!(a_1, a_2);
let mut ret = GF_mul!(a_3, a_4);
ret = GF_mul!(ret, a_8);
if ret == 1
{
false
}
else
{
ret = GF_mul!(a_3, a_16);
ret = GF_mul!(ret, a_32);
if ret == 1
{
false
}
else
{
ret = GF_mul!(a_1, a_4);
ret = GF_mul!(ret, a_16);
ret = GF_mul!(ret, a_32);
ret != 1
}
}
}
};
}
macro_rules! GF_generator {
() => {
{
let mut ret = 0_u8;
let mut j = 2_u16;
while j < 256
{
if GF_is_candidate!(j as u8)
{
ret = j as u8;
break;
}
j += 1;
}
ret
}
};
}
macro_rules! GF_inverse_of {
($a:expr) => {
{
let mut ret = 0_u8;
let mut inv = 255_u8;
while inv > 1
{
if GF_mul!($a, inv) == 1
{
ret = inv;
break;
}
inv -= 1;
}
ret
}
}
}
macro_rules! make_SBOX {
() => {
{
let mut out = [0_u8; 256];
let mut p = 1_u8;
let mut q = 1_u8;
let generator = GF_generator!();
let inverse = GF_inverse_of!(generator);
let mut j = 255_u16;
while j > 0
{
p = GF_mul!(p, generator);
q = GF_mul!(q, inverse);
let mut transformed = 0_u8;
let mut i = 0_u8;
while i < 8
{
let affine_u8 = (AFFINE_MUL >> (i << 3)) as u8;
let bits = affine_u8 & q;
if bits.count_ones() & 1 == 1
{ transformed |= 1 << i; }
i += 1;
}
out[p as usize] = transformed ^ AFFINE_ADD;
if p == 1
{ break; }
j -= 1;
}
out[0] = AFFINE_ADD;
out
}
};
}
macro_rules! make_INV_SBOX {
() => {
{
let mut out = [0_u8; 256];
let mut i = 0_u16;
while i < 256
{
out[Self::SBOX[i as usize] as usize] = i as u8;
i += 1;
}
out
}
}
}
macro_rules! make_INV_MC {
() => {
{
let mut aug = [[0_u8; 4]; 4];
let mut inv = [[0_u8; 4]; 4];
let mut i = 0_usize;
let mut j: usize;
while i < 4
{
j = 0;
while j < 4
{
aug[i][j] = Self::MC[i][j];
j += 1;
}
inv[i][i] = 1;
i += 1;
}
let generator = GF_generator!();
let inverse = GF_inverse_of!(generator);
let mut row = 0_usize;
while row < 4
{
let mut pivot = aug[row][row];
if pivot == 0
{
i = row + 1;
while i < 4
{
if aug[i][row] != 0
{
j = 0;
while j < 4
{
(aug[row][j], aug[i][j]) = (aug[i][j], aug[row][j]);
(inv[row][j], inv[i][j]) = (inv[i][j], inv[row][j]);
j += 1;
}
pivot = aug[row][row];
break;
}
i += 1;
}
if pivot == 0
{ panic!("Singular Matrix"); }
}
let mut p = 1_u8;
let mut q = 1_u8;
while p != pivot
{
p = GF_mul!(p, generator);
q = GF_mul!(q, inverse);
}
j = 0;
while j < 4
{
aug[row][j] = GF_mul!(aug[row][j], q);
inv[row][j] = GF_mul!(inv[row][j], q);
j += 1;
}
let mut r = 0;
while r < 4
{
if r != row
{
let factor = aug[r][row];
j = 0;
while j < 4
{
inv[r][j] ^= GF_mul!(inv[row][j], factor);
aug[r][j] ^= GF_mul!(aug[row][j], factor);
j += 1;
}
}
r += 1;
}
row += 1;
}
inv
}
}
}
macro_rules! make_RC_ARRAY {
() => {
{
let mut out = [0u32; ROUND];
let round = [ RC0.to_le(), RC1.to_le(), RC2.to_le(), RC3.to_le(), RC4.to_le(),
RC5.to_le(), RC6.to_le(), RC7.to_le(), RC8.to_le(), RC9.to_le() ];
let nr = if ROUND <= 10 { ROUND } else { 10 };
let mut i = 0;
while i < nr
{
out[i] = round[i];
i += 1;
}
while i < ROUND
{
out[i] = (GF_mul!(out[i-1].to_le() as u8, 2) as u32).to_le();
i += 1;
}
out
}
}
}
#[allow(non_camel_case_types)]
pub type Rijndael_32_32 = Rijndael_Generic<7, 1, 1>;
#[allow(non_camel_case_types)]
pub type Rijndael_64_64 = Rijndael_Generic<8, 2, 2>;
#[allow(non_camel_case_types)]
pub type Rijndael_512_512 = Rijndael_Generic<22, 16, 16>;
#[allow(non_camel_case_types)]
pub type Rijndael_512_384 = Rijndael_Generic<18, 16, 12>;
#[allow(non_camel_case_types)]
pub type Rijndael_512_256 = Rijndael_Generic<14, 16, 8>;
#[allow(non_camel_case_types)]
pub type Rijndael_512_192 = Rijndael_Generic<14, 16, 6>;
#[allow(non_camel_case_types)]
pub type Rijndael_512_128 = Rijndael_Generic<14, 16, 4>;
#[allow(non_camel_case_types)]
pub type Rijndael_384_512 = Rijndael_Generic<22, 12, 16>;
#[allow(non_camel_case_types)]
pub type Rijndael_384_384 = Rijndael_Generic<18, 12, 12>;
#[allow(non_camel_case_types)]
pub type Rijndael_384_256 = Rijndael_Generic<14, 12, 8>;
#[allow(non_camel_case_types)]
pub type Rijndael_384_192 = Rijndael_Generic<14, 12, 6>;
#[allow(non_camel_case_types)]
pub type Rijndael_384_128 = Rijndael_Generic<14, 12, 4>;
#[allow(non_camel_case_types)]
pub type Rijndael_256_512 = Rijndael_Generic<22, 8, 16>;
#[allow(non_camel_case_types)]
pub type Rijndael_256_384 = Rijndael_Generic<18, 8, 12>;
#[allow(non_camel_case_types)]
pub type Rijndael_256_256 = Rijndael_Generic<14, 8, 8>;
#[allow(non_camel_case_types)]
pub type Rijndael_256_192 = Rijndael_Generic<14, 8, 6>;
#[allow(non_camel_case_types)]
pub type Rijndael_256_128 = Rijndael_Generic<14, 8, 4>;
#[allow(non_camel_case_types)]
pub type Rijndael_192_512 = Rijndael_Generic<22, 6, 16>;
#[allow(non_camel_case_types)]
pub type Rijndael_192_384 = Rijndael_Generic<18, 6, 12>;
#[allow(non_camel_case_types)]
pub type Rijndael_192_256 = Rijndael_Generic<14, 6, 8>;
#[allow(non_camel_case_types)]
pub type Rijndael_192_192 = Rijndael_Generic<12, 6, 6>;
#[allow(non_camel_case_types)]
pub type Rijndael_192_128 = Rijndael_Generic<12, 6, 4>;
#[allow(non_camel_case_types)]
pub type Rijndael_128_512 = Rijndael_Generic<22, 4, 16>;
#[allow(non_camel_case_types)]
pub type Rijndael_128_384 = Rijndael_Generic<18, 4, 12>;
#[allow(non_camel_case_types)]
pub type Rijndael_128_256 = Rijndael_Generic<14, 4, 8>;
#[allow(non_camel_case_types)]
pub type Rijndael_128_192 = Rijndael_Generic<12, 4, 6>;
#[allow(non_camel_case_types)]
pub type Rijndael_128_128 = Rijndael_Generic;
#[allow(non_camel_case_types)]
pub type AES_256 = Rijndael_Generic<14, 4, 8>;
#[allow(non_camel_case_types)]
pub type AES_192 = Rijndael_Generic<12, 4, 6>;
#[allow(non_camel_case_types)]
pub type AES_128 = Rijndael_Generic;
#[allow(non_camel_case_types)]
#[derive(Debug, Clone)]
pub struct Rijndael_Generic<const ROUND: usize = 10, const NB: usize = 4, const NK: usize = 4,
const IRREDUCIBLE: u8 = 0b_0001_1011,
const AFFINE_MUL: u64 = 0b_11111000_01111100_00111110_00011111_10001111_11000111_11100011_11110001,
const AFFINE_ADD: u8 = 0b_01100011,
const SR0: usize = 0, const SR1: usize = 1, const SR2: usize = 2, const SR3: usize = 3,
const MC00: u8 = 2, const MC01: u8 = 3, const MC02: u8 = 1, const MC03: u8 = 1,
const MC10: u8 = 1, const MC11: u8 = 2, const MC12: u8 = 3, const MC13: u8 = 1,
const MC20: u8 = 1, const MC21: u8 = 1, const MC22: u8 = 2, const MC23: u8 = 3,
const MC30: u8 = 3, const MC31: u8 = 1, const MC32: u8 = 1, const MC33: u8 = 2,
const RC0: u32 = 0b_0000_0001, const RC1: u32 = 0b_0000_0010, const RC2: u32 = 0b_0000_0100,
const RC3: u32 = 0b_0000_1000, const RC4: u32 = 0b_0001_0000, const RC5: u32 = 0b_0010_0000,
const RC6: u32 = 0b_0100_0000, const RC7: u32 = 0b_1000_0000, const RC8: u32 = 0b_0001_1011,
const RC9: u32 = 0b_001_10110, const ROT: u32 = 1>
{
key: [IntUnion; NK],
block: [[u8; NB]; 4],
round_key: Vec<[IntUnion; NB]>,
enc: fn (s: &mut Self, message: &[IntUnion; NB]) -> [IntUnion; NB],
dec: fn (s: &mut Self, cipher: &[IntUnion; NB]) -> [IntUnion; NB],
}
impl <const ROUND: usize, const NB: usize, const NK: usize, const IRREDUCIBLE: u8, const AFFINE_MUL: u64,
const AFFINE_ADD: u8, const SR0: usize, const SR1: usize, const SR2: usize, const SR3: usize,
const MC00: u8, const MC01: u8, const MC02: u8, const MC03: u8,
const MC10: u8, const MC11: u8, const MC12: u8, const MC13: u8,
const MC20: u8, const MC21: u8, const MC22: u8, const MC23: u8,
const MC30: u8, const MC31: u8, const MC32: u8, const MC33: u8,
const RC0: u32, const RC1: u32, const RC2: u32, const RC3: u32, const RC4: u32,
const RC5: u32, const RC6: u32, const RC7: u32, const RC8: u32, const RC9: u32, const ROT: u32>
Rijndael_Generic<ROUND, NB, NK, IRREDUCIBLE, AFFINE_MUL, AFFINE_ADD, SR0, SR1, SR2, SR3,
MC00, MC01, MC02, MC03, MC10, MC11, MC12, MC13, MC20, MC21, MC22, MC23, MC30, MC31, MC32, MC33,
RC0, RC1, RC2, RC3, RC4, RC5, RC6, RC7, RC8, RC9, ROT>
{
pub(super) const BLOCK_SIZE: usize = 4 * NB;
const SUCCESS: u8 = !0;
const FAILURE: u8 = 0;
const SBOX: [u8; 256] = make_SBOX!();
const INV_SBOX: [u8; 256] = make_INV_SBOX!();
const SR: [usize; 4] = [SR0, SR1, SR2, SR3];
const MC: [[u8; 4]; 4] = [ [ MC00, MC01, MC02, MC03 ],
[ MC10, MC11, MC12, MC13 ],
[ MC20, MC21, MC22, MC23 ],
[ MC30, MC31, MC32, MC33 ] ];
const INV_MC: [[u8; 4]; 4] = make_INV_MC!();
const RC: [u32; ROUND] = make_RC_ARRAY!();
#[allow(non_upper_case_globals)]
const method_shift_rows: fn (&mut Self) = if (SR0 == 0) && (SR1 == 1) && (SR2 == 2) && (SR3 == 3)
{ Self::optimal_shift_rows }
else
{ Self::shift_rows };
#[allow(non_upper_case_globals)]
const method_inv_shift_rows: fn (&mut Self) = if (SR0 == 0) && (SR1 == 1) && (SR2 == 2) && (SR3 == 3)
{ Self::optimal_inv_shift_rows }
else
{ Self::inv_shift_rows };
#[allow(non_upper_case_globals)]
const method_make_round_keys: fn (&mut Self) = if NK > 6
{
if NK == NB
{ Self::make_round_keys_nk_greater_than_6_and_nk_equal_to_nb }
else
{ Self::make_round_keys_nk_greater_than_6_and_nk_diff_from_nb }
}
else
{
if NK == NB
{ Self::make_round_keys_nk_up_to_6_and_nk_equal_to_nb }
else
{ Self::make_round_keys_nk_up_to_6_and_nk_diff_from_nb }
};
#[allow(non_upper_case_globals)]
const method_mix_columns: fn (&mut Self) = if (MC00 == 2) && (MC01 == 3) && (MC02 == 1) && (MC03 == 1)
&& (MC10 == 1) && (MC11 == 2) && (MC12 == 3) && (MC13 == 1)
&& (MC20 == 1) && (MC21 == 1) && (MC22 == 2) && (MC23 == 3)
&& (MC30 == 3) && (MC31 == 1) && (MC32 == 1) && (MC33 == 2)
{ Self::optimal_mix_columns }
else
{ Self::mix_columns };
pub fn new() -> Self
{
let mut rijndael = Self
{
key: [IntUnion::new(); NK],
block: [[0_u8; NB]; 4],
round_key: vec![[IntUnion::new(); NB]; ROUND + 1],
enc: Self::encrypt_unit,
dec: Self::decrypt_unit,
};
Self::method_make_round_keys(&mut rijndael);
rijndael
}
#[inline]
pub fn box_new() -> Box<Self>
{
Box::new(Self::new())
}
pub fn new_with_key<const K: usize>(key: &[u8; K]) -> Self
{
let mut rijndael = Self
{
key: [IntUnion::new(); NK],
block: [[0_u8; NB]; 4],
round_key: vec![[IntUnion::new(); NB]; ROUND + 1],
enc: Self::encrypt_unit,
dec: Self::decrypt_unit,
};
rijndael.set_key(key);
rijndael
}
pub fn new_with_key_u128(key: u128) -> Self
{
let mut rijndael = Self
{
key: [IntUnion::new(); NK],
block: [[0_u8; NB]; 4],
round_key: vec![[IntUnion::new(); NB]; ROUND + 1],
enc: Self::encrypt_unit,
dec: Self::decrypt_unit,
};
rijndael.set_key_u128(key);
rijndael
}
#[inline]
pub fn encryptor_with_key<const K: usize>(key: &[u8; K]) -> Self
{
Self::new_with_key(key)
}
#[inline]
pub fn encryptor_with_key_u128(key: u128) -> Self
{
Self::new_with_key_u128(key)
}
pub fn decryptor_with_key<const K: usize>(key: &[u8; K]) -> Self
{
let mut rijndael = Self::new_with_key(key);
rijndael.turn_inverse();
rijndael
}
pub fn decryptor_with_key_u128(key: u128) -> Self
{
let mut rijndael = Self::new_with_key_u128(key);
rijndael.turn_inverse();
rijndael
}
pub fn get_key(&mut self) -> [u32; NK]
{
let mut key = [0_u32; NK];
unsafe { copy_nonoverlapping(self.key.as_ptr() as *const u32,
&mut key as *mut u32, NK); }
key
}
pub fn get_key_u128(&self) -> u128
{
let len = if 16 < NK * 4 { 16 } else { NK * 4 };
let mut key = 0_u128;
unsafe { copy_nonoverlapping(self.key.as_ptr() as *const u8,
&mut key as *mut u128 as *mut u8, len); }
key
}
pub fn set_key<const K: usize>(&mut self, key: &[u8; K])
{
let len = if K < NK * 4 { K } else { NK * 4 };
unsafe {
copy_nonoverlapping(key.as_ptr(), self.key.as_mut_ptr() as *mut u8, len);
}
Self::method_make_round_keys(self);
}
pub fn set_key_u128(&mut self, key: u128)
{
let len = if 16 < NK * 4 { 16 } else { NK * 4 };
unsafe {
copy_nonoverlapping(&key as *const u128 as *const u8,
self.key.as_mut_ptr() as *mut u8, len);
}
Self::method_make_round_keys(self);
}
pub(crate) fn set_original_key(&mut self, key: &[u32; NK])
{
for i in 0..NK
{ self.key[i].set(key[i]); }
}
pub(crate) fn move_to_next_key(&mut self)
{
let mut key = self.get_key();
let mut carry = 1;
let mut old: u32;
for i in 0..NK
{
old = key[i];
key[i] = key[i].wrapping_add(carry);
carry = if key[i] < old {1} else {0};
}
self.set_original_key(&key);
}
#[inline]
pub fn turn_inverse(&mut self)
{
(self.enc, self.dec) = (self.dec, self.enc);
}
pub fn turn_encryptor(&mut self)
{
self.enc = Self::encrypt_unit;
self.dec = Self::decrypt_unit;
}
pub fn turn_decryptor(&mut self)
{
self.enc = Self::decrypt_unit;
self.dec = Self::encrypt_unit;
}
pub fn encrypt_unit(&mut self, message: &[IntUnion; NB]) -> [IntUnion; NB]
{
self.set_block(message);
self.encrypt_block();
self.get_block()
}
pub fn encrypt_u128(&mut self, message: u128) -> u128
{
self.set_block_u128(message);
self.encrypt_block();
self.get_block_u128()
}
pub fn encrypt_u64(&mut self, message: u64) -> u64
{
self.set_block_u64(message);
self.encrypt_block();
self.get_block_u64()
}
pub fn encrypt_u32(&mut self, message: u32) -> u32
{
self.set_block_u32(message);
self.encrypt_block();
self.get_block_u32()
}
pub fn decrypt_unit(&mut self, cipher: &[IntUnion; NB]) -> [IntUnion; NB]
{
self.set_block(cipher);
self.decrypt_block();
self.get_block()
}
pub fn decrypt_u128(&mut self, cipher: u128) -> u128
{
self.set_block_u128(cipher);
self.decrypt_block();
self.get_block_u128()
}
pub fn decrypt_u64(&mut self, cipher: u64) -> u64
{
self.set_block_u64(cipher);
self.decrypt_block();
self.get_block_u64()
}
pub fn decrypt_u32(&mut self, cipher: u32) -> u32
{
self.set_block_u32(cipher);
self.decrypt_block();
self.get_block_u32()
}
#[inline]
pub(super) fn _encrypt(&mut self, message: &[IntUnion; NB]) -> [IntUnion; NB]
{
(self.enc)(self, message)
}
#[inline]
pub(super) fn _decrypt(&mut self, cipher: &[IntUnion; NB]) -> [IntUnion; NB]
{
(self.dec)(self, cipher)
}
pub fn encrypt_array_unit<const N: usize>(&mut self, message: &[[IntUnion; NB]; N], cipher: &mut [[IntUnion; NB]; N])
{
for i in 0..N
{
self.set_block(&message[i]);
self.encrypt_block();
cipher[i] = self.get_block();
}
}
pub fn encrypt_array_u128<const N: usize>(&mut self, message: &[u128; N], cipher: &mut [u128; N])
{
for i in 0..N
{
self.set_block_u128(message[i]);
self.encrypt_block();
cipher[i] = self.get_block_u128();
}
}
pub fn encrypt_array_u64<const N: usize>(&mut self, message: &[u64; N], cipher: &mut [u64; N])
{
for i in 0..N
{
self.set_block_u64(message[i]);
self.encrypt_block();
cipher[i] = self.get_block_u64();
}
}
pub fn encrypt_array_u32<const N: usize>(&mut self, message: &[u32; N], cipher: &mut [u32; N])
{
for i in 0..N
{
self.set_block_u32(message[i]);
self.encrypt_block();
cipher[i] = self.get_block_u32();
}
}
pub fn decrypt_array_unit<const N: usize>(&mut self, cipher: &[[IntUnion; NB]; N], message: &mut [[IntUnion; NB]; N])
{
for i in 0..N
{
self.set_block(&cipher[i]);
self.decrypt_block();
message[i] = self.get_block();
}
}
pub fn decrypt_array_u128<const N: usize>(&mut self, cipher: &[u128; N], message: &mut [u128; N])
{
for i in 0..N
{
self.set_block_u128(cipher[i]);
self.decrypt_block();
message[i] = self.get_block_u128();
}
}
pub fn decrypt_array_u64<const N: usize>(&mut self, cipher: &[u64; N], message: &mut [u64; N])
{
for i in 0..N
{
self.set_block_u64(cipher[i]);
self.decrypt_block();
message[i] = self.get_block_u64();
}
}
pub fn decrypt_array_u32<const N: usize>(&mut self, cipher: &[u32; N], message: &mut [u32; N])
{
for i in 0..N
{
self.set_block_u32(cipher[i]);
self.decrypt_block();
message[i] = self.get_block_u32();
}
}
#[inline]
pub fn is_successful(&self) -> bool
{
self.block[0][0] == Self::SUCCESS
}
#[inline]
pub fn is_failed(&self) -> bool
{
self.block[0][0] == Self::FAILURE
}
#[inline]
pub(super) fn set_successful(&mut self)
{
self.block[0][0] = Self::SUCCESS;
}
#[inline]
pub(super) fn set_failed(&mut self)
{
self.block[0][0] = Self::FAILURE;
}
#[inline]
pub fn get_desirable_round() -> usize
{
6 + if NB > NK { NB } else { NK }
}
fn encrypt_block(&mut self)
{
self.add_round_key(0);
for round in 1..ROUND
{
self.sub_bytes();
Self::method_shift_rows(self);
Self::method_mix_columns(self);
self.add_round_key(round);
}
self.sub_bytes();
Self::method_shift_rows(self);
self.add_round_key(ROUND);
}
fn sub_bytes(&mut self)
{
for i in 0..4
{
for j in 0..NB
{
self.block[i][j] = Self::SBOX[self.block[i][j] as usize];
}
}
}
fn optimal_shift_rows(&mut self)
{
let mut tmp = [0_u8; 3];
let tmp_ptr = tmp.as_mut_ptr();
for i in 1..4
{
unsafe {
let j = i % NB;
let ptr_block_0 = self.block[i].as_mut_ptr();
let ptr_block_i = self.block[i].as_ptr().add(j);
let ptr_block_nb_i = self.block[i].as_mut_ptr().add(NB - j);
copy_nonoverlapping(ptr_block_0, tmp_ptr, j);
copy(ptr_block_i, ptr_block_0, NB - j);
copy_nonoverlapping(tmp_ptr, ptr_block_nb_i, j);
}
}
}
fn shift_rows(&mut self)
{
let mut tmp = [0_u8; NB];
let tmp_ptr = tmp.as_mut_ptr();
for i in 0..4
{
unsafe {
let j = Self::SR[i] % NB;
let ptr_block_0 = self.block[i].as_mut_ptr();
let ptr_block_i = self.block[i].as_ptr().add(j);
let ptr_block_nb_i = self.block[i].as_mut_ptr().add(NB - j);
copy_nonoverlapping(ptr_block_0, tmp_ptr, j);
copy(ptr_block_i, ptr_block_0, NB - j);
copy_nonoverlapping(tmp_ptr, ptr_block_nb_i, j);
}
}
}
fn optimal_mix_columns(&mut self)
{
let mut new_block = [[0_u8; NB]; 4];
for col in 0..NB
{
new_block[0][col] = GF_mul!(2, self.block[0][col]) ^ GF_mul!(3, self.block[1][col])
^ self.block[2][col] ^ self.block[3][col];
new_block[1][col] = self.block[0][col] ^ GF_mul!(2, self.block[1][col])
^ GF_mul!(3, self.block[2][col]) ^ self.block[3][col];
new_block[2][col] = self.block[0][col] ^ self.block[1][col]
^ GF_mul!(2, self.block[2][col]) ^ GF_mul!(3, self.block[3][col]);
new_block[3][col] = GF_mul!(3, self.block[0][col]) ^ self.block[1][col]
^ self.block[2][col] ^ GF_mul!(2, self.block[3][col]);
}
self.block = new_block;
}
fn mix_columns(&mut self)
{
let mut new_block = [[0_u8; NB]; 4];
for row in 0..4
{
for col in 0..NB
{
for i in 0..4
{
new_block[row][col] ^= GF_mul!(Self::MC[row][i], self.block[i][col]);
}
}
}
self.block = new_block;
}
fn add_round_key(&mut self, round: usize)
{
for i in 0..4
{
for j in 0..NB
{
self.block[i][j] ^= self.round_key[round][j].get_ubyte_(i);
}
}
}
fn decrypt_block(&mut self)
{
self.add_round_key(ROUND);
let mut round = ROUND-1;
while round > 0
{
Self::method_inv_shift_rows(self);
self.inv_sub_bytes();
self.add_round_key(round);
self.inv_mix_columns();
round -= 1;
}
Self::method_inv_shift_rows(self);
self.inv_sub_bytes();
self.add_round_key(round);
}
fn inv_sub_bytes(&mut self)
{
for i in 0..4
{
for j in 0..NB
{
self.block[i][j] = Self::INV_SBOX[self.block[i][j] as usize];
}
}
}
fn optimal_inv_shift_rows(&mut self)
{
let mut tmp = [0_u8; 3];
let tmp_ptr = tmp.as_mut_ptr();
for i in 1..4
{
unsafe {
let j = i % NB;
let ptr_block_0 = self.block[i].as_mut_ptr();
let ptr_block_i = self.block[i].as_mut_ptr().add(j);
let ptr_block_nb_i = self.block[i].as_ptr().add(NB - j);
copy_nonoverlapping(ptr_block_nb_i, tmp_ptr, j);
copy(ptr_block_0, ptr_block_i, NB - j);
copy_nonoverlapping(tmp_ptr, ptr_block_0, j);
}
}
}
fn inv_shift_rows(&mut self)
{
let mut tmp = [0_u8; NB];
let tmp_ptr = tmp.as_mut_ptr();
for i in 0..4
{
unsafe {
let j = Self::SR[i] % NB;
let ptr_block_0 = self.block[i].as_mut_ptr();
let ptr_block_i = self.block[i].as_mut_ptr().add(j);
let ptr_block_nb_i = self.block[i].as_ptr().add(NB - j);
copy_nonoverlapping(ptr_block_nb_i, tmp_ptr, j);
copy(ptr_block_0, ptr_block_i, NB - j);
copy_nonoverlapping(tmp_ptr, ptr_block_0, j);
}
}
}
fn inv_mix_columns(&mut self)
{
let mut new_block = [[0_u8; NB]; 4];
for row in 0..4
{
for col in 0..NB
{
for i in 0..4
{
new_block[row][col] ^= GF_mul!(Self::INV_MC[row][i], self.block[i][col]);
}
}
}
self.block = new_block;
}
fn make_round_keys_nk_up_to_6_and_nk_equal_to_nb(&mut self)
{
self.set_zeroth_round_key();
for round in 1..=ROUND
{
let mut tmp = self.round_key[round-1][NB-1];
#[cfg(target_endian = "little")] { tmp = tmp.rotate_right(8 * ROT); }
#[cfg(target_endian = "big")] { tmp = tmp.rotate_left(8 * ROT); }
for j in 0..4
{ tmp.set_ubyte_(j, Self::SBOX[tmp.get_ubyte_(j) as usize]); }
tmp.set(tmp.get() ^ Self::RC[round-1]);
self.round_key[round][0] = tmp ^ self.round_key[round-1][0];
for i in 1..NB
{ self.round_key[round][i] = self.round_key[round][i-1] ^ self.round_key[round-1][i]; }
}
}
fn make_round_keys_nk_greater_than_6_and_nk_equal_to_nb(&mut self)
{
self.set_zeroth_round_key();
for round in 1..=ROUND
{
let mut tmp = self.round_key[round-1][NB-1];
#[cfg(target_endian = "little")] { tmp = tmp.rotate_right(8 * ROT); }
#[cfg(target_endian = "big")] { tmp = tmp.rotate_left(8 * ROT); }
for j in 0..4
{ tmp.set_ubyte_(j, Self::SBOX[tmp.get_ubyte_(j) as usize]); }
tmp.set(tmp.get() ^ Self::RC[round-1]);
self.round_key[round][0] = tmp ^ self.round_key[round-1][0];
for i in 1..3
{ self.round_key[round][0] = self.round_key[round][i-1] ^ self.round_key[round-1][i]; }
tmp = self.round_key[round][3];
for j in 0..4
{ tmp.set_ubyte_(j, Self::SBOX[tmp.get_ubyte_(j) as usize]); }
self.round_key[round][4] = tmp ^ self.round_key[round-1][4];
for i in 5..NB
{ self.round_key[round][i] = self.round_key[round][i-1] ^ self.round_key[round-1][i]; }
}
}
fn make_round_keys_nk_up_to_6_and_nk_diff_from_nb(&mut self)
{
self.set_zeroth_round_key();
let mut round = NK / NB;
let mut cc = NK % NB;
let mut idx = NK;
let mut rc_round = 0;
while (round <= ROUND) && (rc_round < ROUND)
{
let mut tmp = if cc == 0 { self.round_key[round-1][NB-1] } else { self.round_key[round][cc-1] };
if idx % NK == 0
{
#[cfg(target_endian = "little")] { tmp = tmp.rotate_right(8 * ROT); }
#[cfg(target_endian = "big")] { tmp = tmp.rotate_left(8 * ROT); }
for j in 0..4
{ tmp.set_ubyte_(j, Self::SBOX[tmp.get_ubyte_(j) as usize]); }
tmp.set(tmp.get() ^ Self::RC[rc_round]);
rc_round += 1;
}
if cc < NK
{
let rrr = (idx - NK) / NB;
let ccc = (idx - NK) % NB;
self.round_key[round][cc] = tmp ^ self.round_key[rrr][ccc];
}
else
{
self.round_key[round][cc] = tmp ^ self.round_key[round][cc-NK];
}
if cc == NB - 1
{
cc = 0;
round += 1;
}
else
{
cc += 1;
}
idx += 1;
}
}
fn make_round_keys_nk_greater_than_6_and_nk_diff_from_nb(&mut self)
{
self.set_zeroth_round_key();
let mut round = NK / NB;
let mut cc = NK % NB;
let mut idx = NK;
let mut rc_round = 0;
while (round <= ROUND) && (rc_round < ROUND)
{
let mut tmp = if cc == 0 { self.round_key[round-1][NB-1] } else { self.round_key[round][cc-1] };
if idx % NK == 0
{
#[cfg(target_endian = "little")] { tmp = tmp.rotate_right(8 * ROT); }
#[cfg(target_endian = "big")] { tmp = tmp.rotate_left(8 * ROT); }
for j in 0..4
{ tmp.set_ubyte_(j, Self::SBOX[tmp.get_ubyte_(j) as usize]); }
tmp.set(tmp.get() ^ Self::RC[rc_round]);
rc_round += 1;
}
else if idx % NK == 4
{
let rrr = (idx - NK) / NB;
let ccc = (idx - NK) % NB;
for j in 0..4
{ tmp.set_ubyte_(j, Self::SBOX[tmp.get_ubyte_(j) as usize]); }
self.round_key[round][cc] = tmp ^ self.round_key[rrr][ccc];
}
if cc < NK
{
let rrr = (idx - NK) / NB;
let ccc = (idx - NK) % NB;
self.round_key[round][cc] = tmp ^ self.round_key[rrr][ccc];
}
else
{
self.round_key[round][cc] = tmp ^ self.round_key[round][cc-NK];
}
if cc < NB - 1
{
cc += 1;
}
else
{
cc = 0;
round += 1;
}
idx += 1;
}
}
#[inline]
fn set_zeroth_round_key(&mut self)
{
unsafe {
copy_nonoverlapping(self.key.as_ptr() as *const u8,
self.round_key.as_mut_ptr() as *mut u8, NK * 4);
}
}
fn get_block(&self) -> [IntUnion; NB]
{
let mut block = [IntUnion::new(); NB];
for j in 0..NB
{
for i in 0..4
{
block[j].set_ubyte_(i, self.block[i][j]);
}
}
block
}
fn get_block_u128(&self) -> u128
{
let nb = if 4 < NB {4} else {NB};
let mut block = LongerUnion::new();
let mut idx = 0;
for j in 0..nb
{
for i in 0..4
{
block.set_ubyte_(idx, self.block[i][j]);
idx += 1;
}
}
block.get()
}
fn get_block_u64(&self) -> u64
{
let nb = if 2 < NB {2} else {NB};
let mut block = LongUnion::new();
let mut idx = 0;
for j in 0..nb
{
for i in 0..4
{
block.set_ubyte_(idx, self.block[i][j]);
idx += 1;
}
}
block.get()
}
fn get_block_u32(&self) -> u32
{
let mut block = IntUnion::new();
let mut idx = 0;
for i in 0..4
{
block.set_ubyte_(idx, self.block[i][0]);
idx += 1;
}
block.get()
}
fn set_block(&mut self, block: &[IntUnion; NB])
{
for j in 0..NB
{
for i in 0..4
{
self.block[i][j] = block[j].get_ubyte_(i);
}
}
}
fn set_block_u128(&mut self, block: u128)
{
let nb = if 4 < NB {4} else {NB};
let block_union = LongerUnion::new_with(block);
let mut idx = 0;
for j in 0..nb
{
for i in 0..4
{
self.block[i][j] = block_union.get_ubyte_(idx);
idx += 1;
}
}
}
fn set_block_u64(&mut self, block: u64)
{
let nb = if 2 < NB {2} else {NB};
let block_union = LongUnion::new_with(block);
let mut idx = 0;
for j in 0..nb
{
for i in 0..4
{
self.block[i][j] = block_union.get_ubyte_(idx);
idx += 1;
}
}
}
fn set_block_u32(&mut self, block: u32)
{
let block_union = IntUnion::new_with(block);
let mut idx = 0;
for i in 0..4
{
self.block[i][0] = block_union.get_ubyte_(idx);
idx += 1;
}
}
}