diff --git a/kuznyechik/Cargo.toml b/kuznyechik/Cargo.toml index 17c2fbe6..6d02e826 100644 --- a/kuznyechik/Cargo.toml +++ b/kuznyechik/Cargo.toml @@ -25,7 +25,7 @@ zeroize = ["cipher/zeroize"] [lints.rust.unexpected_cfgs] level = "warn" -check-cfg = ["cfg(kuznyechik_force_soft)", "cfg(kuznyechik_compact_soft)"] +check-cfg = ['cfg(kuznyechik_backend, values("soft", "compact_soft"))'] [package.metadata.docs.rs] all-features = true diff --git a/kuznyechik/src/big_soft/backends.rs b/kuznyechik/src/big_soft/backends.rs index d4d8a46c..578f0afb 100644 --- a/kuznyechik/src/big_soft/backends.rs +++ b/kuznyechik/src/big_soft/backends.rs @@ -1,6 +1,7 @@ -use super::consts::{Table, DEC_TABLE, ENC_TABLE, RKEY_GEN}; use crate::{ consts::{P, P_INV}, + fused_tables::{Table, DEC_TABLE, ENC_TABLE}, + utils::KEYGEN, Block, Key, }; use cipher::{ @@ -27,7 +28,7 @@ fn sub_bytes(block: u128, sbox: &[u8; 256]) -> u128 { #[inline(always)] fn transform(block: u128, table: &Table) -> u128 { - let table: &[[u128; 256]; 16] = unsafe { &*(table.as_ptr().cast()) }; + let table: &[[u128; 256]; 16] = unsafe { &*(table.0.as_ptr().cast()) }; let block = block.to_le_bytes(); let mut res = 0u128; for i in 0..16 { @@ -41,12 +42,7 @@ fn transform(block: u128, table: &Table) -> u128 { pub(super) fn expand_enc_keys(key: &Key) -> RoundKeys { #[inline(always)] fn next_const(i: usize) -> u128 { - // correct alignment of `p` is guaranteed since the table is aligned to 16 bytes - let t: &[u128; 32] = unsafe { &*(RKEY_GEN.as_ptr().cast()) }; - let val = t[i]; - #[cfg(target_endian = "big")] - let val = val.swap_bytes(); - val + u128::from_le_bytes(KEYGEN[i].0) } let mut enc_keys = [0; 10]; diff --git a/kuznyechik/src/big_soft/mod.rs b/kuznyechik/src/big_soft/mod.rs index 51f45036..d3c0833c 100644 --- a/kuznyechik/src/big_soft/mod.rs +++ b/kuznyechik/src/big_soft/mod.rs @@ -4,8 +4,6 @@ use cipher::{ }; mod backends; -#[path = "../fused_tables/consts.rs"] -mod consts; use backends::{expand_enc_keys, inv_enc_keys, DecBackend, EncBackend, RoundKeys}; diff --git a/kuznyechik/src/compact_soft/backends.rs b/kuznyechik/src/compact_soft/backends.rs index 4f97499d..a2d7aaa3 100644 --- a/kuznyechik/src/compact_soft/backends.rs +++ b/kuznyechik/src/compact_soft/backends.rs @@ -1,6 +1,8 @@ -use super::consts::GF; -use crate::consts::{P, P_INV}; -use crate::{Block, Key}; +use crate::{ + consts::{P, P_INV}, + utils::{l_step, KEYGEN}, + Block, Key, +}; use cipher::{ consts, BlockCipherDecBackend, BlockCipherEncBackend, BlockSizeUser, InOut, ParBlocksSizeUser, }; @@ -14,35 +16,6 @@ fn x(a: &mut Block, b: &Block) { } } -fn l_step(msg: &mut Block, i: usize) { - #[inline(always)] - fn get_idx(b: usize, i: usize) -> usize { - b.wrapping_sub(i) & 0x0F - } - #[inline(always)] - fn get_m(msg: &Block, b: usize, i: usize) -> usize { - msg[get_idx(b, i)] as usize - } - - let mut x = msg[get_idx(15, i)]; - x ^= GF[3][get_m(msg, 14, i)]; - x ^= GF[1][get_m(msg, 13, i)]; - x ^= GF[2][get_m(msg, 12, i)]; - x ^= GF[0][get_m(msg, 11, i)]; - x ^= GF[5][get_m(msg, 10, i)]; - x ^= GF[4][get_m(msg, 9, i)]; - x ^= msg[get_idx(8, i)]; - x ^= GF[6][get_m(msg, 7, i)]; - x ^= msg[get_idx(6, i)]; - x ^= GF[4][get_m(msg, 5, i)]; - x ^= GF[5][get_m(msg, 4, i)]; - x ^= GF[0][get_m(msg, 3, i)]; - x ^= GF[2][get_m(msg, 2, i)]; - x ^= GF[1][get_m(msg, 1, i)]; - x ^= GF[3][get_m(msg, 0, i)]; - msg[get_idx(15, i)] = x; -} - #[inline(always)] fn lsx(block: &mut Block, key: &Block) { x(block, key); @@ -52,7 +25,7 @@ fn lsx(block: &mut Block, key: &Block) { } // l for i in 0..16 { - l_step(block, i); + l_step(&mut block.0, i); } } @@ -61,7 +34,7 @@ fn lsx_inv(block: &mut Block, key: &Block) { x(block, key); // l_inv for i in 0..16 { - l_step(block, 15 - i); + l_step(&mut block.0, 15 - i); } // s_inv for i in 0..16 { @@ -70,22 +43,17 @@ fn lsx_inv(block: &mut Block, key: &Block) { } fn get_c(n: usize) -> Block { - let mut v = Block::default(); - v[15] = n as u8; - for i in 0..16 { - l_step(&mut v, i); - } - v + KEYGEN[n].0.into() } fn f(k1: &mut Block, k2: &mut Block, n: usize) { for i in 0..4 { let mut k1_cpy = *k1; - lsx(&mut k1_cpy, &get_c(8 * n + 2 * i + 1)); + lsx(&mut k1_cpy, &get_c(8 * n + 2 * i)); x(k2, &k1_cpy); let mut k2_cpy = *k2; - lsx(&mut k2_cpy, &get_c(8 * n + 2 * i + 2)); + lsx(&mut k2_cpy, &get_c(8 * n + 2 * i + 1)); x(k1, &k2_cpy); } } diff --git a/kuznyechik/src/compact_soft/consts.rs b/kuznyechik/src/compact_soft/consts.rs deleted file mode 100644 index fcf92921..00000000 --- a/kuznyechik/src/compact_soft/consts.rs +++ /dev/null @@ -1,143 +0,0 @@ -// Precomputed values for Galois field multiplication -pub const GF: [[u8; 256]; 7] = [ - [ - 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, - 0xF0, 0xC3, 0xD3, 0xE3, 0xF3, 0x83, 0x93, 0xA3, 0xB3, 0x43, 0x53, 0x63, 0x73, 0x03, 0x13, - 0x23, 0x33, 0x45, 0x55, 0x65, 0x75, 0x05, 0x15, 0x25, 0x35, 0xC5, 0xD5, 0xE5, 0xF5, 0x85, - 0x95, 0xA5, 0xB5, 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, 0x06, 0x16, 0x26, 0x36, - 0x46, 0x56, 0x66, 0x76, 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, 0x0A, 0x1A, 0x2A, - 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, 0x49, 0x59, 0x69, 0x79, 0x09, 0x19, 0x29, 0x39, 0xC9, 0xD9, - 0xE9, 0xF9, 0x89, 0x99, 0xA9, 0xB9, 0xCF, 0xDF, 0xEF, 0xFF, 0x8F, 0x9F, 0xAF, 0xBF, 0x4F, - 0x5F, 0x6F, 0x7F, 0x0F, 0x1F, 0x2F, 0x3F, 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, - 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, 0xD7, 0xC7, 0xF7, 0xE7, 0x97, 0x87, 0xB7, - 0xA7, 0x57, 0x47, 0x77, 0x67, 0x17, 0x07, 0x37, 0x27, 0x14, 0x04, 0x34, 0x24, 0x54, 0x44, - 0x74, 0x64, 0x94, 0x84, 0xB4, 0xA4, 0xD4, 0xC4, 0xF4, 0xE4, 0x92, 0x82, 0xB2, 0xA2, 0xD2, - 0xC2, 0xF2, 0xE2, 0x12, 0x02, 0x32, 0x22, 0x52, 0x42, 0x72, 0x62, 0x51, 0x41, 0x71, 0x61, - 0x11, 0x01, 0x31, 0x21, 0xD1, 0xC1, 0xF1, 0xE1, 0x91, 0x81, 0xB1, 0xA1, 0x5D, 0x4D, 0x7D, - 0x6D, 0x1D, 0x0D, 0x3D, 0x2D, 0xDD, 0xCD, 0xFD, 0xED, 0x9D, 0x8D, 0xBD, 0xAD, 0x9E, 0x8E, - 0xBE, 0xAE, 0xDE, 0xCE, 0xFE, 0xEE, 0x1E, 0x0E, 0x3E, 0x2E, 0x5E, 0x4E, 0x7E, 0x6E, 0x18, - 0x08, 0x38, 0x28, 0x58, 0x48, 0x78, 0x68, 0x98, 0x88, 0xB8, 0xA8, 0xD8, 0xC8, 0xF8, 0xE8, - 0xDB, 0xCB, 0xFB, 0xEB, 0x9B, 0x8B, 0xBB, 0xAB, 0x5B, 0x4B, 0x7B, 0x6B, 0x1B, 0x0B, 0x3B, - 0x2B, - ], - [ - 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0, 0xC3, 0xE3, 0x83, 0xA3, 0x43, 0x63, 0x03, - 0x23, 0x45, 0x65, 0x05, 0x25, 0xC5, 0xE5, 0x85, 0xA5, 0x86, 0xA6, 0xC6, 0xE6, 0x06, 0x26, - 0x46, 0x66, 0x8A, 0xAA, 0xCA, 0xEA, 0x0A, 0x2A, 0x4A, 0x6A, 0x49, 0x69, 0x09, 0x29, 0xC9, - 0xE9, 0x89, 0xA9, 0xCF, 0xEF, 0x8F, 0xAF, 0x4F, 0x6F, 0x0F, 0x2F, 0x0C, 0x2C, 0x4C, 0x6C, - 0x8C, 0xAC, 0xCC, 0xEC, 0xD7, 0xF7, 0x97, 0xB7, 0x57, 0x77, 0x17, 0x37, 0x14, 0x34, 0x54, - 0x74, 0x94, 0xB4, 0xD4, 0xF4, 0x92, 0xB2, 0xD2, 0xF2, 0x12, 0x32, 0x52, 0x72, 0x51, 0x71, - 0x11, 0x31, 0xD1, 0xF1, 0x91, 0xB1, 0x5D, 0x7D, 0x1D, 0x3D, 0xDD, 0xFD, 0x9D, 0xBD, 0x9E, - 0xBE, 0xDE, 0xFE, 0x1E, 0x3E, 0x5E, 0x7E, 0x18, 0x38, 0x58, 0x78, 0x98, 0xB8, 0xD8, 0xF8, - 0xDB, 0xFB, 0x9B, 0xBB, 0x5B, 0x7B, 0x1B, 0x3B, 0x6D, 0x4D, 0x2D, 0x0D, 0xED, 0xCD, 0xAD, - 0x8D, 0xAE, 0x8E, 0xEE, 0xCE, 0x2E, 0x0E, 0x6E, 0x4E, 0x28, 0x08, 0x68, 0x48, 0xA8, 0x88, - 0xE8, 0xC8, 0xEB, 0xCB, 0xAB, 0x8B, 0x6B, 0x4B, 0x2B, 0x0B, 0xE7, 0xC7, 0xA7, 0x87, 0x67, - 0x47, 0x27, 0x07, 0x24, 0x04, 0x64, 0x44, 0xA4, 0x84, 0xE4, 0xC4, 0xA2, 0x82, 0xE2, 0xC2, - 0x22, 0x02, 0x62, 0x42, 0x61, 0x41, 0x21, 0x01, 0xE1, 0xC1, 0xA1, 0x81, 0xBA, 0x9A, 0xFA, - 0xDA, 0x3A, 0x1A, 0x7A, 0x5A, 0x79, 0x59, 0x39, 0x19, 0xF9, 0xD9, 0xB9, 0x99, 0xFF, 0xDF, - 0xBF, 0x9F, 0x7F, 0x5F, 0x3F, 0x1F, 0x3C, 0x1C, 0x7C, 0x5C, 0xBC, 0x9C, 0xFC, 0xDC, 0x30, - 0x10, 0x70, 0x50, 0xB0, 0x90, 0xF0, 0xD0, 0xF3, 0xD3, 0xB3, 0x93, 0x73, 0x53, 0x33, 0x13, - 0x75, 0x55, 0x35, 0x15, 0xF5, 0xD5, 0xB5, 0x95, 0xB6, 0x96, 0xF6, 0xD6, 0x36, 0x16, 0x76, - 0x56, - ], - [ - 0x00, 0x85, 0xC9, 0x4C, 0x51, 0xD4, 0x98, 0x1D, 0xA2, 0x27, 0x6B, 0xEE, 0xF3, 0x76, 0x3A, - 0xBF, 0x87, 0x02, 0x4E, 0xCB, 0xD6, 0x53, 0x1F, 0x9A, 0x25, 0xA0, 0xEC, 0x69, 0x74, 0xF1, - 0xBD, 0x38, 0xCD, 0x48, 0x04, 0x81, 0x9C, 0x19, 0x55, 0xD0, 0x6F, 0xEA, 0xA6, 0x23, 0x3E, - 0xBB, 0xF7, 0x72, 0x4A, 0xCF, 0x83, 0x06, 0x1B, 0x9E, 0xD2, 0x57, 0xE8, 0x6D, 0x21, 0xA4, - 0xB9, 0x3C, 0x70, 0xF5, 0x59, 0xDC, 0x90, 0x15, 0x08, 0x8D, 0xC1, 0x44, 0xFB, 0x7E, 0x32, - 0xB7, 0xAA, 0x2F, 0x63, 0xE6, 0xDE, 0x5B, 0x17, 0x92, 0x8F, 0x0A, 0x46, 0xC3, 0x7C, 0xF9, - 0xB5, 0x30, 0x2D, 0xA8, 0xE4, 0x61, 0x94, 0x11, 0x5D, 0xD8, 0xC5, 0x40, 0x0C, 0x89, 0x36, - 0xB3, 0xFF, 0x7A, 0x67, 0xE2, 0xAE, 0x2B, 0x13, 0x96, 0xDA, 0x5F, 0x42, 0xC7, 0x8B, 0x0E, - 0xB1, 0x34, 0x78, 0xFD, 0xE0, 0x65, 0x29, 0xAC, 0xB2, 0x37, 0x7B, 0xFE, 0xE3, 0x66, 0x2A, - 0xAF, 0x10, 0x95, 0xD9, 0x5C, 0x41, 0xC4, 0x88, 0x0D, 0x35, 0xB0, 0xFC, 0x79, 0x64, 0xE1, - 0xAD, 0x28, 0x97, 0x12, 0x5E, 0xDB, 0xC6, 0x43, 0x0F, 0x8A, 0x7F, 0xFA, 0xB6, 0x33, 0x2E, - 0xAB, 0xE7, 0x62, 0xDD, 0x58, 0x14, 0x91, 0x8C, 0x09, 0x45, 0xC0, 0xF8, 0x7D, 0x31, 0xB4, - 0xA9, 0x2C, 0x60, 0xE5, 0x5A, 0xDF, 0x93, 0x16, 0x0B, 0x8E, 0xC2, 0x47, 0xEB, 0x6E, 0x22, - 0xA7, 0xBA, 0x3F, 0x73, 0xF6, 0x49, 0xCC, 0x80, 0x05, 0x18, 0x9D, 0xD1, 0x54, 0x6C, 0xE9, - 0xA5, 0x20, 0x3D, 0xB8, 0xF4, 0x71, 0xCE, 0x4B, 0x07, 0x82, 0x9F, 0x1A, 0x56, 0xD3, 0x26, - 0xA3, 0xEF, 0x6A, 0x77, 0xF2, 0xBE, 0x3B, 0x84, 0x01, 0x4D, 0xC8, 0xD5, 0x50, 0x1C, 0x99, - 0xA1, 0x24, 0x68, 0xED, 0xF0, 0x75, 0x39, 0xBC, 0x03, 0x86, 0xCA, 0x4F, 0x52, 0xD7, 0x9B, - 0x1E, - ], - [ - 0x00, 0x94, 0xEB, 0x7F, 0x15, 0x81, 0xFE, 0x6A, 0x2A, 0xBE, 0xC1, 0x55, 0x3F, 0xAB, 0xD4, - 0x40, 0x54, 0xC0, 0xBF, 0x2B, 0x41, 0xD5, 0xAA, 0x3E, 0x7E, 0xEA, 0x95, 0x01, 0x6B, 0xFF, - 0x80, 0x14, 0xA8, 0x3C, 0x43, 0xD7, 0xBD, 0x29, 0x56, 0xC2, 0x82, 0x16, 0x69, 0xFD, 0x97, - 0x03, 0x7C, 0xE8, 0xFC, 0x68, 0x17, 0x83, 0xE9, 0x7D, 0x02, 0x96, 0xD6, 0x42, 0x3D, 0xA9, - 0xC3, 0x57, 0x28, 0xBC, 0x93, 0x07, 0x78, 0xEC, 0x86, 0x12, 0x6D, 0xF9, 0xB9, 0x2D, 0x52, - 0xC6, 0xAC, 0x38, 0x47, 0xD3, 0xC7, 0x53, 0x2C, 0xB8, 0xD2, 0x46, 0x39, 0xAD, 0xED, 0x79, - 0x06, 0x92, 0xF8, 0x6C, 0x13, 0x87, 0x3B, 0xAF, 0xD0, 0x44, 0x2E, 0xBA, 0xC5, 0x51, 0x11, - 0x85, 0xFA, 0x6E, 0x04, 0x90, 0xEF, 0x7B, 0x6F, 0xFB, 0x84, 0x10, 0x7A, 0xEE, 0x91, 0x05, - 0x45, 0xD1, 0xAE, 0x3A, 0x50, 0xC4, 0xBB, 0x2F, 0xE5, 0x71, 0x0E, 0x9A, 0xF0, 0x64, 0x1B, - 0x8F, 0xCF, 0x5B, 0x24, 0xB0, 0xDA, 0x4E, 0x31, 0xA5, 0xB1, 0x25, 0x5A, 0xCE, 0xA4, 0x30, - 0x4F, 0xDB, 0x9B, 0x0F, 0x70, 0xE4, 0x8E, 0x1A, 0x65, 0xF1, 0x4D, 0xD9, 0xA6, 0x32, 0x58, - 0xCC, 0xB3, 0x27, 0x67, 0xF3, 0x8C, 0x18, 0x72, 0xE6, 0x99, 0x0D, 0x19, 0x8D, 0xF2, 0x66, - 0x0C, 0x98, 0xE7, 0x73, 0x33, 0xA7, 0xD8, 0x4C, 0x26, 0xB2, 0xCD, 0x59, 0x76, 0xE2, 0x9D, - 0x09, 0x63, 0xF7, 0x88, 0x1C, 0x5C, 0xC8, 0xB7, 0x23, 0x49, 0xDD, 0xA2, 0x36, 0x22, 0xB6, - 0xC9, 0x5D, 0x37, 0xA3, 0xDC, 0x48, 0x08, 0x9C, 0xE3, 0x77, 0x1D, 0x89, 0xF6, 0x62, 0xDE, - 0x4A, 0x35, 0xA1, 0xCB, 0x5F, 0x20, 0xB4, 0xF4, 0x60, 0x1F, 0x8B, 0xE1, 0x75, 0x0A, 0x9E, - 0x8A, 0x1E, 0x61, 0xF5, 0x9F, 0x0B, 0x74, 0xE0, 0xA0, 0x34, 0x4B, 0xDF, 0xB5, 0x21, 0x5E, - 0xCA, - ], - [ - 0x00, 0xC0, 0x43, 0x83, 0x86, 0x46, 0xC5, 0x05, 0xCF, 0x0F, 0x8C, 0x4C, 0x49, 0x89, 0x0A, - 0xCA, 0x5D, 0x9D, 0x1E, 0xDE, 0xDB, 0x1B, 0x98, 0x58, 0x92, 0x52, 0xD1, 0x11, 0x14, 0xD4, - 0x57, 0x97, 0xBA, 0x7A, 0xF9, 0x39, 0x3C, 0xFC, 0x7F, 0xBF, 0x75, 0xB5, 0x36, 0xF6, 0xF3, - 0x33, 0xB0, 0x70, 0xE7, 0x27, 0xA4, 0x64, 0x61, 0xA1, 0x22, 0xE2, 0x28, 0xE8, 0x6B, 0xAB, - 0xAE, 0x6E, 0xED, 0x2D, 0xB7, 0x77, 0xF4, 0x34, 0x31, 0xF1, 0x72, 0xB2, 0x78, 0xB8, 0x3B, - 0xFB, 0xFE, 0x3E, 0xBD, 0x7D, 0xEA, 0x2A, 0xA9, 0x69, 0x6C, 0xAC, 0x2F, 0xEF, 0x25, 0xE5, - 0x66, 0xA6, 0xA3, 0x63, 0xE0, 0x20, 0x0D, 0xCD, 0x4E, 0x8E, 0x8B, 0x4B, 0xC8, 0x08, 0xC2, - 0x02, 0x81, 0x41, 0x44, 0x84, 0x07, 0xC7, 0x50, 0x90, 0x13, 0xD3, 0xD6, 0x16, 0x95, 0x55, - 0x9F, 0x5F, 0xDC, 0x1C, 0x19, 0xD9, 0x5A, 0x9A, 0xAD, 0x6D, 0xEE, 0x2E, 0x2B, 0xEB, 0x68, - 0xA8, 0x62, 0xA2, 0x21, 0xE1, 0xE4, 0x24, 0xA7, 0x67, 0xF0, 0x30, 0xB3, 0x73, 0x76, 0xB6, - 0x35, 0xF5, 0x3F, 0xFF, 0x7C, 0xBC, 0xB9, 0x79, 0xFA, 0x3A, 0x17, 0xD7, 0x54, 0x94, 0x91, - 0x51, 0xD2, 0x12, 0xD8, 0x18, 0x9B, 0x5B, 0x5E, 0x9E, 0x1D, 0xDD, 0x4A, 0x8A, 0x09, 0xC9, - 0xCC, 0x0C, 0x8F, 0x4F, 0x85, 0x45, 0xC6, 0x06, 0x03, 0xC3, 0x40, 0x80, 0x1A, 0xDA, 0x59, - 0x99, 0x9C, 0x5C, 0xDF, 0x1F, 0xD5, 0x15, 0x96, 0x56, 0x53, 0x93, 0x10, 0xD0, 0x47, 0x87, - 0x04, 0xC4, 0xC1, 0x01, 0x82, 0x42, 0x88, 0x48, 0xCB, 0x0B, 0x0E, 0xCE, 0x4D, 0x8D, 0xA0, - 0x60, 0xE3, 0x23, 0x26, 0xE6, 0x65, 0xA5, 0x6F, 0xAF, 0x2C, 0xEC, 0xE9, 0x29, 0xAA, 0x6A, - 0xFD, 0x3D, 0xBE, 0x7E, 0x7B, 0xBB, 0x38, 0xF8, 0x32, 0xF2, 0x71, 0xB1, 0xB4, 0x74, 0xF7, - 0x37, - ], - [ - 0x00, 0xC2, 0x47, 0x85, 0x8E, 0x4C, 0xC9, 0x0B, 0xDF, 0x1D, 0x98, 0x5A, 0x51, 0x93, 0x16, - 0xD4, 0x7D, 0xBF, 0x3A, 0xF8, 0xF3, 0x31, 0xB4, 0x76, 0xA2, 0x60, 0xE5, 0x27, 0x2C, 0xEE, - 0x6B, 0xA9, 0xFA, 0x38, 0xBD, 0x7F, 0x74, 0xB6, 0x33, 0xF1, 0x25, 0xE7, 0x62, 0xA0, 0xAB, - 0x69, 0xEC, 0x2E, 0x87, 0x45, 0xC0, 0x02, 0x09, 0xCB, 0x4E, 0x8C, 0x58, 0x9A, 0x1F, 0xDD, - 0xD6, 0x14, 0x91, 0x53, 0x37, 0xF5, 0x70, 0xB2, 0xB9, 0x7B, 0xFE, 0x3C, 0xE8, 0x2A, 0xAF, - 0x6D, 0x66, 0xA4, 0x21, 0xE3, 0x4A, 0x88, 0x0D, 0xCF, 0xC4, 0x06, 0x83, 0x41, 0x95, 0x57, - 0xD2, 0x10, 0x1B, 0xD9, 0x5C, 0x9E, 0xCD, 0x0F, 0x8A, 0x48, 0x43, 0x81, 0x04, 0xC6, 0x12, - 0xD0, 0x55, 0x97, 0x9C, 0x5E, 0xDB, 0x19, 0xB0, 0x72, 0xF7, 0x35, 0x3E, 0xFC, 0x79, 0xBB, - 0x6F, 0xAD, 0x28, 0xEA, 0xE1, 0x23, 0xA6, 0x64, 0x6E, 0xAC, 0x29, 0xEB, 0xE0, 0x22, 0xA7, - 0x65, 0xB1, 0x73, 0xF6, 0x34, 0x3F, 0xFD, 0x78, 0xBA, 0x13, 0xD1, 0x54, 0x96, 0x9D, 0x5F, - 0xDA, 0x18, 0xCC, 0x0E, 0x8B, 0x49, 0x42, 0x80, 0x05, 0xC7, 0x94, 0x56, 0xD3, 0x11, 0x1A, - 0xD8, 0x5D, 0x9F, 0x4B, 0x89, 0x0C, 0xCE, 0xC5, 0x07, 0x82, 0x40, 0xE9, 0x2B, 0xAE, 0x6C, - 0x67, 0xA5, 0x20, 0xE2, 0x36, 0xF4, 0x71, 0xB3, 0xB8, 0x7A, 0xFF, 0x3D, 0x59, 0x9B, 0x1E, - 0xDC, 0xD7, 0x15, 0x90, 0x52, 0x86, 0x44, 0xC1, 0x03, 0x08, 0xCA, 0x4F, 0x8D, 0x24, 0xE6, - 0x63, 0xA1, 0xAA, 0x68, 0xED, 0x2F, 0xFB, 0x39, 0xBC, 0x7E, 0x75, 0xB7, 0x32, 0xF0, 0xA3, - 0x61, 0xE4, 0x26, 0x2D, 0xEF, 0x6A, 0xA8, 0x7C, 0xBE, 0x3B, 0xF9, 0xF2, 0x30, 0xB5, 0x77, - 0xDE, 0x1C, 0x99, 0x5B, 0x50, 0x92, 0x17, 0xD5, 0x01, 0xC3, 0x46, 0x84, 0x8F, 0x4D, 0xC8, - 0x0A, - ], - [ - 0x00, 0xFB, 0x35, 0xCE, 0x6A, 0x91, 0x5F, 0xA4, 0xD4, 0x2F, 0xE1, 0x1A, 0xBE, 0x45, 0x8B, - 0x70, 0x6B, 0x90, 0x5E, 0xA5, 0x01, 0xFA, 0x34, 0xCF, 0xBF, 0x44, 0x8A, 0x71, 0xD5, 0x2E, - 0xE0, 0x1B, 0xD6, 0x2D, 0xE3, 0x18, 0xBC, 0x47, 0x89, 0x72, 0x02, 0xF9, 0x37, 0xCC, 0x68, - 0x93, 0x5D, 0xA6, 0xBD, 0x46, 0x88, 0x73, 0xD7, 0x2C, 0xE2, 0x19, 0x69, 0x92, 0x5C, 0xA7, - 0x03, 0xF8, 0x36, 0xCD, 0x6F, 0x94, 0x5A, 0xA1, 0x05, 0xFE, 0x30, 0xCB, 0xBB, 0x40, 0x8E, - 0x75, 0xD1, 0x2A, 0xE4, 0x1F, 0x04, 0xFF, 0x31, 0xCA, 0x6E, 0x95, 0x5B, 0xA0, 0xD0, 0x2B, - 0xE5, 0x1E, 0xBA, 0x41, 0x8F, 0x74, 0xB9, 0x42, 0x8C, 0x77, 0xD3, 0x28, 0xE6, 0x1D, 0x6D, - 0x96, 0x58, 0xA3, 0x07, 0xFC, 0x32, 0xC9, 0xD2, 0x29, 0xE7, 0x1C, 0xB8, 0x43, 0x8D, 0x76, - 0x06, 0xFD, 0x33, 0xC8, 0x6C, 0x97, 0x59, 0xA2, 0xDE, 0x25, 0xEB, 0x10, 0xB4, 0x4F, 0x81, - 0x7A, 0x0A, 0xF1, 0x3F, 0xC4, 0x60, 0x9B, 0x55, 0xAE, 0xB5, 0x4E, 0x80, 0x7B, 0xDF, 0x24, - 0xEA, 0x11, 0x61, 0x9A, 0x54, 0xAF, 0x0B, 0xF0, 0x3E, 0xC5, 0x08, 0xF3, 0x3D, 0xC6, 0x62, - 0x99, 0x57, 0xAC, 0xDC, 0x27, 0xE9, 0x12, 0xB6, 0x4D, 0x83, 0x78, 0x63, 0x98, 0x56, 0xAD, - 0x09, 0xF2, 0x3C, 0xC7, 0xB7, 0x4C, 0x82, 0x79, 0xDD, 0x26, 0xE8, 0x13, 0xB1, 0x4A, 0x84, - 0x7F, 0xDB, 0x20, 0xEE, 0x15, 0x65, 0x9E, 0x50, 0xAB, 0x0F, 0xF4, 0x3A, 0xC1, 0xDA, 0x21, - 0xEF, 0x14, 0xB0, 0x4B, 0x85, 0x7E, 0x0E, 0xF5, 0x3B, 0xC0, 0x64, 0x9F, 0x51, 0xAA, 0x67, - 0x9C, 0x52, 0xA9, 0x0D, 0xF6, 0x38, 0xC3, 0xB3, 0x48, 0x86, 0x7D, 0xD9, 0x22, 0xEC, 0x17, - 0x0C, 0xF7, 0x39, 0xC2, 0x66, 0x9D, 0x53, 0xA8, 0xD8, 0x23, 0xED, 0x16, 0xB2, 0x49, 0x87, - 0x7C, - ], -]; diff --git a/kuznyechik/src/compact_soft/mod.rs b/kuznyechik/src/compact_soft/mod.rs index 0561c265..9fe6b724 100644 --- a/kuznyechik/src/compact_soft/mod.rs +++ b/kuznyechik/src/compact_soft/mod.rs @@ -4,7 +4,6 @@ use cipher::{ }; mod backends; -mod consts; use backends::{expand, DecBackend, EncBackend, RoundKeys}; diff --git a/kuznyechik/src/consts.rs b/kuznyechik/src/consts.rs index b87818e1..b9231243 100644 --- a/kuznyechik/src/consts.rs +++ b/kuznyechik/src/consts.rs @@ -1,46 +1,49 @@ -/// Substitution table -pub const P: [u8; 256] = [ - 0xFC, 0xEE, 0xDD, 0x11, 0xCF, 0x6E, 0x31, 0x16, 0xFB, 0xC4, 0xFA, 0xDA, 0x23, 0xC5, 0x04, 0x4D, - 0xE9, 0x77, 0xF0, 0xDB, 0x93, 0x2E, 0x99, 0xBA, 0x17, 0x36, 0xF1, 0xBB, 0x14, 0xCD, 0x5F, 0xC1, - 0xF9, 0x18, 0x65, 0x5A, 0xE2, 0x5C, 0xEF, 0x21, 0x81, 0x1C, 0x3C, 0x42, 0x8B, 0x01, 0x8E, 0x4F, - 0x05, 0x84, 0x02, 0xAE, 0xE3, 0x6A, 0x8F, 0xA0, 0x06, 0x0B, 0xED, 0x98, 0x7F, 0xD4, 0xD3, 0x1F, - 0xEB, 0x34, 0x2C, 0x51, 0xEA, 0xC8, 0x48, 0xAB, 0xF2, 0x2A, 0x68, 0xA2, 0xFD, 0x3A, 0xCE, 0xCC, - 0xB5, 0x70, 0x0E, 0x56, 0x08, 0x0C, 0x76, 0x12, 0xBF, 0x72, 0x13, 0x47, 0x9C, 0xB7, 0x5D, 0x87, - 0x15, 0xA1, 0x96, 0x29, 0x10, 0x7B, 0x9A, 0xC7, 0xF3, 0x91, 0x78, 0x6F, 0x9D, 0x9E, 0xB2, 0xB1, - 0x32, 0x75, 0x19, 0x3D, 0xFF, 0x35, 0x8A, 0x7E, 0x6D, 0x54, 0xC6, 0x80, 0xC3, 0xBD, 0x0D, 0x57, - 0xDF, 0xF5, 0x24, 0xA9, 0x3E, 0xA8, 0x43, 0xC9, 0xD7, 0x79, 0xD6, 0xF6, 0x7C, 0x22, 0xB9, 0x03, - 0xE0, 0x0F, 0xEC, 0xDE, 0x7A, 0x94, 0xB0, 0xBC, 0xDC, 0xE8, 0x28, 0x50, 0x4E, 0x33, 0x0A, 0x4A, - 0xA7, 0x97, 0x60, 0x73, 0x1E, 0x00, 0x62, 0x44, 0x1A, 0xB8, 0x38, 0x82, 0x64, 0x9F, 0x26, 0x41, - 0xAD, 0x45, 0x46, 0x92, 0x27, 0x5E, 0x55, 0x2F, 0x8C, 0xA3, 0xA5, 0x7D, 0x69, 0xD5, 0x95, 0x3B, - 0x07, 0x58, 0xB3, 0x40, 0x86, 0xAC, 0x1D, 0xF7, 0x30, 0x37, 0x6B, 0xE4, 0x88, 0xD9, 0xE7, 0x89, - 0xE1, 0x1B, 0x83, 0x49, 0x4C, 0x3F, 0xF8, 0xFE, 0x8D, 0x53, 0xAA, 0x90, 0xCA, 0xD8, 0x85, 0x61, - 0x20, 0x71, 0x67, 0xA4, 0x2D, 0x2B, 0x09, 0x5B, 0xCB, 0x9B, 0x25, 0xD0, 0xBE, 0xE5, 0x6C, 0x52, - 0x59, 0xA6, 0x74, 0xD2, 0xE6, 0xF4, 0xB4, 0xC0, 0xD1, 0x66, 0xAF, 0xC2, 0x39, 0x4B, 0x63, 0xB6, +/// Non-linear bijective transformation defined in the section 4.1.1. +pub(crate) const P: [u8; 256] = [ + 252, 238, 221, 17, 207, 110, 49, 22, 251, 196, 250, 218, 35, 197, 4, 77, 233, 119, 240, 219, + 147, 46, 153, 186, 23, 54, 241, 187, 20, 205, 95, 193, 249, 24, 101, 90, 226, 92, 239, 33, 129, + 28, 60, 66, 139, 1, 142, 79, 5, 132, 2, 174, 227, 106, 143, 160, 6, 11, 237, 152, 127, 212, + 211, 31, 235, 52, 44, 81, 234, 200, 72, 171, 242, 42, 104, 162, 253, 58, 206, 204, 181, 112, + 14, 86, 8, 12, 118, 18, 191, 114, 19, 71, 156, 183, 93, 135, 21, 161, 150, 41, 16, 123, 154, + 199, 243, 145, 120, 111, 157, 158, 178, 177, 50, 117, 25, 61, 255, 53, 138, 126, 109, 84, 198, + 128, 195, 189, 13, 87, 223, 245, 36, 169, 62, 168, 67, 201, 215, 121, 214, 246, 124, 34, 185, + 3, 224, 15, 236, 222, 122, 148, 176, 188, 220, 232, 40, 80, 78, 51, 10, 74, 167, 151, 96, 115, + 30, 0, 98, 68, 26, 184, 56, 130, 100, 159, 38, 65, 173, 69, 70, 146, 39, 94, 85, 47, 140, 163, + 165, 125, 105, 213, 149, 59, 7, 88, 179, 64, 134, 172, 29, 247, 48, 55, 107, 228, 136, 217, + 231, 137, 225, 27, 131, 73, 76, 63, 248, 254, 141, 83, 170, 144, 202, 216, 133, 97, 32, 113, + 103, 164, 45, 43, 9, 91, 203, 155, 37, 208, 190, 229, 108, 82, 89, 166, 116, 210, 230, 244, + 180, 192, 209, 102, 175, 194, 57, 75, 99, 182, ]; -/// Inverse ubstitution table -pub const P_INV: [u8; 256] = [ - 0xA5, 0x2D, 0x32, 0x8F, 0x0E, 0x30, 0x38, 0xC0, 0x54, 0xE6, 0x9E, 0x39, 0x55, 0x7E, 0x52, 0x91, - 0x64, 0x03, 0x57, 0x5A, 0x1C, 0x60, 0x07, 0x18, 0x21, 0x72, 0xA8, 0xD1, 0x29, 0xC6, 0xA4, 0x3F, - 0xE0, 0x27, 0x8D, 0x0C, 0x82, 0xEA, 0xAE, 0xB4, 0x9A, 0x63, 0x49, 0xE5, 0x42, 0xE4, 0x15, 0xB7, - 0xC8, 0x06, 0x70, 0x9D, 0x41, 0x75, 0x19, 0xC9, 0xAA, 0xFC, 0x4D, 0xBF, 0x2A, 0x73, 0x84, 0xD5, - 0xC3, 0xAF, 0x2B, 0x86, 0xA7, 0xB1, 0xB2, 0x5B, 0x46, 0xD3, 0x9F, 0xFD, 0xD4, 0x0F, 0x9C, 0x2F, - 0x9B, 0x43, 0xEF, 0xD9, 0x79, 0xB6, 0x53, 0x7F, 0xC1, 0xF0, 0x23, 0xE7, 0x25, 0x5E, 0xB5, 0x1E, - 0xA2, 0xDF, 0xA6, 0xFE, 0xAC, 0x22, 0xF9, 0xE2, 0x4A, 0xBC, 0x35, 0xCA, 0xEE, 0x78, 0x05, 0x6B, - 0x51, 0xE1, 0x59, 0xA3, 0xF2, 0x71, 0x56, 0x11, 0x6A, 0x89, 0x94, 0x65, 0x8C, 0xBB, 0x77, 0x3C, - 0x7B, 0x28, 0xAB, 0xD2, 0x31, 0xDE, 0xC4, 0x5F, 0xCC, 0xCF, 0x76, 0x2C, 0xB8, 0xD8, 0x2E, 0x36, - 0xDB, 0x69, 0xB3, 0x14, 0x95, 0xBE, 0x62, 0xA1, 0x3B, 0x16, 0x66, 0xE9, 0x5C, 0x6C, 0x6D, 0xAD, - 0x37, 0x61, 0x4B, 0xB9, 0xE3, 0xBA, 0xF1, 0xA0, 0x85, 0x83, 0xDA, 0x47, 0xC5, 0xB0, 0x33, 0xFA, - 0x96, 0x6F, 0x6E, 0xC2, 0xF6, 0x50, 0xFF, 0x5D, 0xA9, 0x8E, 0x17, 0x1B, 0x97, 0x7D, 0xEC, 0x58, - 0xF7, 0x1F, 0xFB, 0x7C, 0x09, 0x0D, 0x7A, 0x67, 0x45, 0x87, 0xDC, 0xE8, 0x4F, 0x1D, 0x4E, 0x04, - 0xEB, 0xF8, 0xF3, 0x3E, 0x3D, 0xBD, 0x8A, 0x88, 0xDD, 0xCD, 0x0B, 0x13, 0x98, 0x02, 0x93, 0x80, - 0x90, 0xD0, 0x24, 0x34, 0xCB, 0xED, 0xF4, 0xCE, 0x99, 0x10, 0x44, 0x40, 0x92, 0x3A, 0x01, 0x26, - 0x12, 0x1A, 0x48, 0x68, 0xF5, 0x81, 0x8B, 0xC7, 0xD6, 0x20, 0x0A, 0x08, 0x00, 0x4C, 0xD7, 0x74, -]; +/// Inverse of the non-linear bijective transformation [`P`]. +pub(crate) const P_INV: [u8; 256] = { + let mut i = 0; + let mut t = [0u8; 256]; + while i < 256 { + t[P[i] as usize] = i as u8; + i += 1; + } + t +}; + +#[cfg(test)] +mod tests { + use super::{P, P_INV}; + + #[test] + fn test_p_inv() { + for i in 0..256 { + assert_eq!(P_INV[P[i] as usize], i as u8); + } + } -#[test] -fn test_subst_tables() { - for i in 0..256 { - assert_eq!(P_INV[P[i] as usize], i as u8); + #[test] + fn test_p_bijectivity() { + let mut flags = [true; 256]; + for i in 0..256 { + let old_flag = core::mem::take(&mut flags[P[i] as usize]); + assert!(old_flag); + } + assert_eq!(flags, [false; 256]); } } diff --git a/kuznyechik/src/fused_tables.rs b/kuznyechik/src/fused_tables.rs new file mode 100644 index 00000000..34666557 --- /dev/null +++ b/kuznyechik/src/fused_tables.rs @@ -0,0 +1,104 @@ +use crate::{ + consts, + gft::{GFT_133, GFT_148, GFT_16, GFT_192, GFT_194, GFT_251, GFT_32}, + utils::Align16, +}; + +pub(crate) type Table = Align16<[u8; 16 * 4096]>; +pub(crate) static ENC_TABLE: Table = Align16(fused_enc_table()); +pub(crate) static DEC_TABLE: Table = Align16(fused_dec_table()); + +const fn fused_enc_table() -> [u8; 16 * 4096] { + let mut table = [0u8; 16 * 4096]; + + let mut i = 0; + let mut pos = 0; + while i < 16 { + let mut j = 0; + while j < 256 { + table[pos + i] = consts::P[j]; + + let mut n = 0; + while n < 16 { + let mut x = table[pos + 15]; + x ^= GFT_148[table[pos + 14] as usize]; + x ^= GFT_32[table[pos + 13] as usize]; + x ^= GFT_133[table[pos + 12] as usize]; + x ^= GFT_16[table[pos + 11] as usize]; + x ^= GFT_194[table[pos + 10] as usize]; + x ^= GFT_192[table[pos + 9] as usize]; + x ^= table[pos + 8]; + x ^= GFT_251[table[pos + 7] as usize]; + x ^= table[pos + 6]; + x ^= GFT_192[table[pos + 5] as usize]; + x ^= GFT_194[table[pos + 4] as usize]; + x ^= GFT_16[table[pos + 3] as usize]; + x ^= GFT_133[table[pos + 2] as usize]; + x ^= GFT_32[table[pos + 1] as usize]; + x ^= GFT_148[table[pos] as usize]; + + let mut k = 15; + while k > 0 { + k -= 1; + table[pos + k + 1] = table[pos + k]; + } + table[pos] = x; + + n += 1; + } + + j += 1; + pos += 16; + } + i += 1; + } + + table +} + +const fn fused_dec_table() -> [u8; 16 * 4096] { + let mut table = [0u8; 16 * 4096]; + + let mut i = 0; + let mut pos = 0; + while i < 16 { + let mut j = 0; + while j < 256 { + table[pos + i] = consts::P_INV[j]; + + let mut n = 0; + while n < 16 { + let mut x = table[pos]; + x ^= GFT_148[table[pos + 1] as usize]; + x ^= GFT_32[table[pos + 2] as usize]; + x ^= GFT_133[table[pos + 3] as usize]; + x ^= GFT_16[table[pos + 4] as usize]; + x ^= GFT_194[table[pos + 5] as usize]; + x ^= GFT_192[table[pos + 6] as usize]; + x ^= table[pos + 7]; + x ^= GFT_251[table[pos + 8] as usize]; + x ^= table[pos + 9]; + x ^= GFT_192[table[pos + 10] as usize]; + x ^= GFT_194[table[pos + 11] as usize]; + x ^= GFT_16[table[pos + 12] as usize]; + x ^= GFT_133[table[pos + 13] as usize]; + x ^= GFT_32[table[pos + 14] as usize]; + x ^= GFT_148[table[pos + 15] as usize]; + + let mut k = 0; + while k < 15 { + table[pos + k] = table[pos + k + 1]; + k += 1; + } + table[pos + 15] = x; + + n += 1; + } + + j += 1; + pos += 16; + } + i += 1; + } + table +} diff --git a/kuznyechik/src/fused_tables/consts.rs b/kuznyechik/src/fused_tables/consts.rs deleted file mode 100644 index 1ea53d72..00000000 --- a/kuznyechik/src/fused_tables/consts.rs +++ /dev/null @@ -1,18 +0,0 @@ -// TODO: use u128 tables after MSRV is bumped to 1.77 or higher -#[repr(align(16))] -pub(crate) struct Align16(pub T); - -impl Align16 { - #[allow(dead_code)] - pub fn as_ptr(&self) -> *const u128 { - self as *const Self as *const u128 - } -} - -pub(crate) type Table = Align16<[u8; 16 * 4096]>; - -pub(crate) static ENC_TABLE: Table = Align16(*include_bytes!("enc_table.bin")); - -pub(crate) static DEC_TABLE: Table = Align16(*include_bytes!("dec_table.bin")); - -pub(crate) static RKEY_GEN: Align16<[u8; 16 * 32]> = Align16(*include_bytes!("rkey_gen.bin")); diff --git a/kuznyechik/src/fused_tables/dec_table.bin b/kuznyechik/src/fused_tables/dec_table.bin deleted file mode 100644 index 0dd6990d..00000000 Binary files a/kuznyechik/src/fused_tables/dec_table.bin and /dev/null differ diff --git a/kuznyechik/src/fused_tables/enc_table.bin b/kuznyechik/src/fused_tables/enc_table.bin deleted file mode 100644 index ee4bf1b9..00000000 Binary files a/kuznyechik/src/fused_tables/enc_table.bin and /dev/null differ diff --git a/kuznyechik/src/fused_tables/rkey_gen.bin b/kuznyechik/src/fused_tables/rkey_gen.bin deleted file mode 100644 index af195422..00000000 --- a/kuznyechik/src/fused_tables/rkey_gen.bin +++ /dev/null @@ -1,3 +0,0 @@ -nvrlHz]'݄܇ؐN y%؎ i0O{ s+@UomyQ P/сJs `聝;PpVjY6V'*@dM,1. *>:^a -D|R؂JU -},g? 6[oG@{ QMv)4?!>'q@/l, -љ5NTA^cBi<ӓ5ךXb#{87\"~\+Tw'|t.0A:UsaFäysǔ牣 Z1 4>Z:X4 Ci=~I,HGiSl1뎀ck]tSӧ$sr&A1Rhk̄7CEu,F~B|%N9(#⣀ۧ.4_d;3?'^XajE \ No newline at end of file diff --git a/kuznyechik/src/gft.rs b/kuznyechik/src/gft.rs new file mode 100644 index 00000000..ea05bd46 --- /dev/null +++ b/kuznyechik/src/gft.rs @@ -0,0 +1,31 @@ +//! Pre-computed mutliplication tables for coefficients of the linear transform + +pub(crate) const GFT_16: [u8; 256] = mul_table_gf256(16); +pub(crate) const GFT_32: [u8; 256] = mul_table_gf256(32); +pub(crate) const GFT_133: [u8; 256] = mul_table_gf256(133); +pub(crate) const GFT_148: [u8; 256] = mul_table_gf256(148); +pub(crate) const GFT_192: [u8; 256] = mul_table_gf256(192); +pub(crate) const GFT_194: [u8; 256] = mul_table_gf256(194); +pub(crate) const GFT_251: [u8; 256] = mul_table_gf256(251); + +const fn mul_gf256(mut a: u8, mut b: u8) -> u8 { + let mut c = 0; + while b != 0 { + if b & 1 != 0 { + c ^= a; + } + a = (a << 1) ^ if a & 0x80 != 0 { 0xC3 } else { 0x00 }; + b >>= 1; + } + c +} + +const fn mul_table_gf256(a: u8) -> [u8; 256] { + let mut table = [0u8; 256]; + let mut i = 0; + while i < table.len() { + table[i] = mul_gf256(a, i as u8); + i += 1; + } + table +} diff --git a/kuznyechik/src/lib.rs b/kuznyechik/src/lib.rs index 7b9b7fe2..27280153 100644 --- a/kuznyechik/src/lib.rs +++ b/kuznyechik/src/lib.rs @@ -10,13 +10,14 @@ //! //! # Configuration Flags //! -//! You can modify crate using the following configuration flag: +//! You can modify crate using the `kuznyechik_backend` configuration flag. +//! It accepts the following values //! -//! - `kuznyechik_force_soft`: force software implementation. -//! - `kuznyechik_compact_soft`: use compact software implementation. +//! - `soft`: use software backend with big fused tables. +//! - `compact_soft`: use software backend with small tables and slower performance. //! -//! It can be enabled using `RUSTFLAGS` environmental variable -//! (e.g. `RUSTFLAGS="--cfg kuznyechik_force_soft"`) or by modifying +//! The flag can be enabled using `RUSTFLAGS` environmental variable +//! (e.g. `RUSTFLAGS='--cfg kuznyechik_backend="soft"'`) or by modifying //! `.cargo/config`. //! //! [Kuznyechik]: https://en.wikipedia.org/wiki/Kuznyechik @@ -42,26 +43,31 @@ use core::fmt; use cipher::zeroize::{zeroize_flat_type, ZeroizeOnDrop}; mod consts; +pub(crate) mod gft; +pub(crate) mod utils; cfg_if::cfg_if!( if #[cfg(all( any(target_arch = "x86_64", target_arch = "x86"), target_feature = "sse2", - not(kuznyechik_force_soft), + not(any(kuznyechik_backend = "soft", kuznyechik_backend = "compact_soft")), ))] { + mod fused_tables; mod sse2; use sse2 as imp; } else if #[cfg(all( target_arch = "aarch64", target_feature = "neon", - not(kuznyechik_force_soft), + not(any(kuznyechik_backend = "soft", kuznyechik_backend = "compact_soft")), ))] { + mod fused_tables; mod neon; use neon as imp; - } else if #[cfg(kuznyechik_compact_soft)] { + } else if #[cfg(kuznyechik_backend = "compact_soft")] { mod compact_soft; use compact_soft as imp; } else { + mod fused_tables; mod big_soft; use big_soft as imp; } diff --git a/kuznyechik/src/neon/backends.rs b/kuznyechik/src/neon/backends.rs index 30fd2c0f..79539cc7 100644 --- a/kuznyechik/src/neon/backends.rs +++ b/kuznyechik/src/neon/backends.rs @@ -1,6 +1,7 @@ -use super::consts::{Table, DEC_TABLE, ENC_TABLE, RKEY_GEN}; use crate::{ consts::{P, P_INV}, + fused_tables::{Table, DEC_TABLE, ENC_TABLE}, + utils::KEYGEN, Block, Key, }; use cipher::{ @@ -81,11 +82,11 @@ unsafe fn transform(block: uint8x16_t, table: &Table) -> uint8x16_t { macro_rules! get { ($table:expr, $ind:expr, $i:expr) => {{ let idx = vgetq_lane_u16($ind, $i) as usize; - let p = &($table.0[idx]) as *const u8 as *const uint8x16_t; + let p = $table.0.as_ptr().add(idx); // correct alignment of `p` is guaranteed since offset values // are shifted by 4 bits left and the table is aligned to 16 bytes debug_assert_eq!(p as usize % 16, 0); - vld1q_u8(p as *const u8) + vld1q_u8(p) }}; } @@ -130,7 +131,7 @@ unsafe fn transform(block: uint8x16_t, table: &Table) -> uint8x16_t { pub fn expand_enc_keys(key: &Key) -> RoundKeys { macro_rules! next_const { ($i:expr) => {{ - let p = RKEY_GEN.0.as_ptr() as *const uint8x16_t; + let p = KEYGEN.as_ptr() as *const uint8x16_t; // correct alignment of `p` is guaranteed since the table // is aligned to 16 bytes let p = p.add($i); diff --git a/kuznyechik/src/neon/mod.rs b/kuznyechik/src/neon/mod.rs index 0742ad82..413258f1 100644 --- a/kuznyechik/src/neon/mod.rs +++ b/kuznyechik/src/neon/mod.rs @@ -4,8 +4,6 @@ use cipher::{ }; mod backends; -#[path = "../fused_tables/consts.rs"] -mod consts; use backends::{expand_enc_keys, inv_enc_keys, DecBackend, EncBackend, RoundKeys}; diff --git a/kuznyechik/src/sse2/backends.rs b/kuznyechik/src/sse2/backends.rs index b9bc4840..bfa4a752 100644 --- a/kuznyechik/src/sse2/backends.rs +++ b/kuznyechik/src/sse2/backends.rs @@ -1,6 +1,7 @@ -use super::consts::{Table, DEC_TABLE, ENC_TABLE, RKEY_GEN}; use crate::{ consts::{P, P_INV}, + fused_tables::{Table, DEC_TABLE, ENC_TABLE}, + utils::KEYGEN, Block, Key, }; use cipher::{ @@ -65,7 +66,7 @@ unsafe fn transform(block: __m128i, table: &Table) -> __m128i { macro_rules! get { ($table:expr, $ind:expr, $i:expr) => {{ let idx = _mm_extract_epi16($ind, $i) as u16 as usize; - let p = &($table.0[idx]) as *const u8 as *const __m128i; + let p = $table.0.as_ptr().add(idx).cast(); // correct alignment of `p` is guaranteed since offset values // are shifted by 4 bits left and the table is aligned to 16 bytes debug_assert_eq!(p as usize % 16, 0); @@ -109,7 +110,7 @@ unsafe fn transform(block: __m128i, table: &Table) -> __m128i { pub(super) fn expand_enc_keys(key: &Key) -> RoundKeys { macro_rules! next_const { ($i:expr) => {{ - let p = RKEY_GEN.0.as_ptr() as *const __m128i; + let p = KEYGEN.as_ptr() as *const __m128i; // correct alignment of `p` is guaranteed since the table // is aligned to 16 bytes let p = p.add($i); diff --git a/kuznyechik/src/sse2/mod.rs b/kuznyechik/src/sse2/mod.rs index 61fc0c45..566ddcf1 100644 --- a/kuznyechik/src/sse2/mod.rs +++ b/kuznyechik/src/sse2/mod.rs @@ -6,8 +6,6 @@ use cipher::{ }; mod backends; -#[path = "../fused_tables/consts.rs"] -mod consts; use backends::{expand_enc_keys, inv_enc_keys, DecBackend, EncBackend, RoundKeys}; diff --git a/kuznyechik/src/utils.rs b/kuznyechik/src/utils.rs new file mode 100644 index 00000000..24d18c29 --- /dev/null +++ b/kuznyechik/src/utils.rs @@ -0,0 +1,53 @@ +use crate::gft::{GFT_133, GFT_148, GFT_16, GFT_192, GFT_194, GFT_251, GFT_32}; + +#[inline(always)] +const fn get_idx(b: usize, i: usize) -> usize { + b.wrapping_sub(i) & 0x0F +} + +#[inline(always)] +const fn get_m(msg: &[u8; 16], b: usize, i: usize) -> usize { + msg[get_idx(b, i)] as usize +} + +pub(crate) const fn l_step(msg: &mut [u8; 16], i: usize) { + let mut x = msg[get_idx(15, i)]; + x ^= GFT_148[get_m(msg, 14, i)]; + x ^= GFT_32[get_m(msg, 13, i)]; + x ^= GFT_133[get_m(msg, 12, i)]; + x ^= GFT_16[get_m(msg, 11, i)]; + x ^= GFT_194[get_m(msg, 10, i)]; + x ^= GFT_192[get_m(msg, 9, i)]; + x ^= msg[get_idx(8, i)]; + x ^= GFT_251[get_m(msg, 7, i)]; + x ^= msg[get_idx(6, i)]; + x ^= GFT_192[get_m(msg, 5, i)]; + x ^= GFT_194[get_m(msg, 4, i)]; + x ^= GFT_16[get_m(msg, 3, i)]; + x ^= GFT_133[get_m(msg, 2, i)]; + x ^= GFT_32[get_m(msg, 1, i)]; + x ^= GFT_148[get_m(msg, 0, i)]; + msg[get_idx(15, i)] = x; +} + +#[repr(align(16))] +#[derive(Clone, Copy)] +pub(crate) struct Align16(pub T); + +/// Constants used to generate round keys +pub(crate) static KEYGEN: [Align16<[u8; 16]>; 32] = { + let mut res = [Align16([0u8; 16]); 32]; + let mut n = 0; + while n < res.len() { + let block = &mut res[n].0; + block[15] = (n + 1) as u8; + + let mut i = 0; + while i < 16 { + l_step(block, i); + i += 1; + } + n += 1; + } + res +}; diff --git a/kuznyechik/tests/mod.rs b/kuznyechik/tests/mod.rs index bd080b31..e74a0855 100644 --- a/kuznyechik/tests/mod.rs +++ b/kuznyechik/tests/mod.rs @@ -1,4 +1,4 @@ -use cipher::{Block, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; +use cipher::{Array, Block, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; use hex_literal::hex; use kuznyechik::{Kuznyechik, KuznyechikDec, KuznyechikEnc}; @@ -68,3 +68,109 @@ fn kuznyechik() { } assert_eq!(blocks2[..], blocks_cpy[..]); } + +#[test] +fn kuznyechik_chain() { + type Blocks = [[u8; 16]; 32]; + const N: usize = 1 << 16; + const INIT_BLOCKS: Blocks = { + let mut i = 0; + let mut blocks: Blocks = [[0u8; 16]; 32]; + while i < blocks.len() { + blocks[i][0] = i as u8; + i += 1; + } + blocks + }; + + let key = [42; 32]; + let mut blocks: Blocks = INIT_BLOCKS; + + let expected: Blocks = [ + hex!("11D15674379CD494AD88593829490D88"), + hex!("CD6FADA332F2A0DA822104CC1504AC25"), + hex!("42E01F93BA3A32B63BFD510422C3C63E"), + hex!("98CF3C6A666C615E2E30AEA728AE5F99"), + hex!("48D0A38142D67888B655AAB30F6A272C"), + hex!("AAC6FB321587253415ADEC32781125B6"), + hex!("73511E76309D5828E5B101E41A905F8B"), + hex!("6411E97F18C3880877993C6D89320923"), + hex!("8DFA86AAAB005B656B4DEC969C12D920"), + hex!("62B1EC7E54B2F2AC4CD2A4CC35A667DF"), + hex!("FB28F70F8F7E57AADBFE16914BFA182E"), + hex!("DA549C44F5B67C35BB36B482B0D1395B"), + hex!("B54A552F1EF9F42B9EA807573202F67D"), + hex!("625A9CD84D0B1FFDD194ECD2967AE637"), + hex!("8D289AFB65774FC553090FBBC4869990"), + hex!("8CDE9FCF9BDBFCC7465481F4D305EFC3"), + hex!("60A8836A71692E2975935E6AD357C22F"), + hex!("90CB51859D95A03D472EAD2FE8001A73"), + hex!("32CD8B2FBD2826646EC05400A9FD2026"), + hex!("426B92425A2C36A1F78A6D548EE092A1"), + hex!("7CE00E51E8BA451EE3117B3655736200"), + hex!("A5A8D7ADA61A55E632DC18A40E11A536"), + hex!("5506E07D1CDF1E9CBB976FE5C06F65B6"), + hex!("968DBF83021137C4E28FBB5E045A9806"), + hex!("2B5D4D11ED27B9F3AFDACEF63099FE8F"), + hex!("960D76DBA4B3019AD7ABA1F2B62C195A"), + hex!("D9CCB67B70E3EBEC9729234B57D389BE"), + hex!("42E01DCBF710D24BB95D62BCD6D980B4"), + hex!("4346E56B5CDE431ABD256812AF44B862"), + hex!("5B20A5A85A484758470B102D4D8B4B5A"), + hex!("547DBA406B244657CAC3052E4CC93616"), + hex!("E350A265B6E2F43910C26F875CB8ADD6"), + ]; + + let cipher = Kuznyechik::new(&key.into()); + + for _ in 0..N { + for block in blocks.iter_mut() { + cipher.encrypt_block(block.into()); + } + } + assert_eq!(blocks, expected); + + for _ in 0..N { + for block in blocks.iter_mut() { + cipher.decrypt_block(block.into()); + } + } + assert_eq!(blocks, INIT_BLOCKS); + + for _ in 0..N { + cipher.encrypt_blocks(Array::cast_slice_from_core_mut(&mut blocks[..])); + } + assert_eq!(blocks, expected); + + for _ in 0..N { + cipher.decrypt_blocks(Array::cast_slice_from_core_mut(&mut blocks[..])); + } + assert_eq!(blocks, INIT_BLOCKS); + + let cipher_enc = KuznyechikEnc::new(&key.into()); + let cipher_dec = KuznyechikDec::new(&key.into()); + + for _ in 0..N { + for block in blocks.iter_mut() { + cipher_enc.encrypt_block(block.into()); + } + } + assert_eq!(blocks, expected); + + for _ in 0..N { + for block in blocks.iter_mut() { + cipher_dec.decrypt_block(block.into()); + } + } + assert_eq!(blocks, INIT_BLOCKS); + + for _ in 0..N { + cipher_enc.encrypt_blocks(Array::cast_slice_from_core_mut(&mut blocks[..])); + } + assert_eq!(blocks, expected); + + for _ in 0..N { + cipher_dec.decrypt_blocks(Array::cast_slice_from_core_mut(&mut blocks[..])); + } + assert_eq!(blocks, INIT_BLOCKS); +}