frist
This commit is contained in:
190
src/gift256/interleave.rs
Normal file
190
src/gift256/interleave.rs
Normal file
@@ -0,0 +1,190 @@
|
||||
//! GIFT-256 fixsliced bit interleave/deinterleave
|
||||
//! Used to convert between standard and fixsliced representations
|
||||
//! Corresponds to gift256_encrypt_fixsliced State 0 (input) and State 3 (output)
|
||||
|
||||
/// Pack 8 u32 (standard) into 8 u32 (fixsliced) with initial round key XOR.
|
||||
/// Corresponds to gift256_encrypt_fixsliced State 0.
|
||||
///
|
||||
/// Input read order (from decompiled offsets):
|
||||
/// input[7]=@0x1c, input[3]=@0x0c, input[6]=@0x18, input[2]=@0x08
|
||||
/// input[5]=@0x14, input[1]=@0x04, input[4]=@0x10, input[0]=@0x00
|
||||
pub fn pack_input(input: &[u32; 8], initial_rk: &[u32; 8]) -> [u32; 8] {
|
||||
let (mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut h) =
|
||||
(input[7], input[3], input[6], input[2], input[5], input[1], input[4], input[0]);
|
||||
|
||||
// Phase 1: 0x55555555 interleave (odd/even bit separation)
|
||||
let t0 = (a ^ (b >> 1)) & 0x55555555;
|
||||
a ^= t0;
|
||||
b ^= t0 << 1;
|
||||
let t1 = (c ^ (d >> 1)) & 0x55555555;
|
||||
c ^= t1;
|
||||
d ^= t1 << 1;
|
||||
let t2 = (e ^ (f >> 1)) & 0x55555555;
|
||||
e ^= t2;
|
||||
f ^= t2 << 1;
|
||||
let t3 = (g ^ (h >> 1)) & 0x55555555;
|
||||
g ^= t3;
|
||||
h ^= t3 << 1;
|
||||
|
||||
// Phase 2: 0x33333333 interleave (2-bit group separation)
|
||||
let t4 = (a ^ (c >> 2)) & 0x33333333;
|
||||
a ^= t4;
|
||||
c ^= t4 << 2;
|
||||
let t5 = (e ^ (g >> 2)) & 0x33333333;
|
||||
e ^= t5;
|
||||
g ^= t5 << 2;
|
||||
let t6 = (b ^ (d >> 2)) & 0x33333333;
|
||||
b ^= t6;
|
||||
d ^= t6 << 2;
|
||||
let t7 = (f ^ (h >> 2)) & 0x33333333;
|
||||
f ^= t7;
|
||||
h ^= t7 << 2;
|
||||
|
||||
// Phase 3: 0x0F0F0F0F interleave (nibble separation) + initial round key XOR
|
||||
let t8 = (a ^ (e >> 4)) & 0x0F0F0F0F;
|
||||
let out7 = initial_rk[7] ^ (a ^ t8);
|
||||
let out3 = initial_rk[3] ^ ((t8 << 4) ^ e);
|
||||
|
||||
let t9 = (c ^ (g >> 4)) & 0x0F0F0F0F;
|
||||
let out5 = initial_rk[5] ^ (c ^ t9);
|
||||
let out1 = initial_rk[1] ^ ((t9 << 4) ^ g);
|
||||
|
||||
let t10 = (b ^ (f >> 4)) & 0x0F0F0F0F;
|
||||
let out6 = initial_rk[6] ^ (b ^ t10);
|
||||
let out2 = initial_rk[2] ^ ((t10 << 4) ^ f);
|
||||
|
||||
let t11 = (d ^ (h >> 4)) & 0x0F0F0F0F;
|
||||
let out4 = initial_rk[4] ^ (d ^ t11);
|
||||
let out0 = initial_rk[0] ^ ((t11 << 4) ^ h);
|
||||
|
||||
[out0, out1, out2, out3, out4, out5, out6, out7]
|
||||
}
|
||||
|
||||
/// Nibble deinterleave.
|
||||
/// Decompiled: ((uVar4 >> 4 ^ uVar4) & 0xf000f00) * 0x11 ^ uVar4
|
||||
pub fn nibble_deinterleave(x: u32) -> u32 {
|
||||
(((x >> 4) ^ x) & 0x0F000F00).wrapping_mul(0x11) ^ x
|
||||
}
|
||||
|
||||
/// Key schedule deinterleave type A (offsets 0x20..0x3C, 0x60..0x7C, 0x1A0..0x1BC)
|
||||
/// x = ((x ^ x>>4) & 0x030F0C00) * 0x11 ^ x;
|
||||
/// x = ((x>>2 ^ x) & 0x33003300) * 5 ^ x;
|
||||
pub fn key_deinterleave_a(x: u32) -> u32 {
|
||||
let x = (((x ^ (x >> 4)) & 0x030F0C00).wrapping_mul(0x11)) ^ x;
|
||||
((((x >> 2) ^ x) & 0x33003300).wrapping_mul(5)) ^ x
|
||||
}
|
||||
|
||||
/// Key schedule deinterleave type B (offsets 0x40..0x5C)
|
||||
/// x = ((x>>4 ^ x) & 0x0F000F00) * 0x11 ^ x;
|
||||
pub fn key_deinterleave_b(x: u32) -> u32 {
|
||||
((((x >> 4) ^ x) & 0x0F000F00).wrapping_mul(0x11)) ^ x
|
||||
}
|
||||
|
||||
/// Key schedule deinterleave type C (offsets 0x60..0x7C second group)
|
||||
/// x = ((x ^ x>>4) & 0x0C0F0300) * 0x11 ^ x;
|
||||
/// x = ((x>>2 ^ x) & 0x33003300) * 5 ^ x;
|
||||
pub fn key_deinterleave_c(x: u32) -> u32 {
|
||||
let x = (((x ^ (x >> 4)) & 0x0C0F0300).wrapping_mul(0x11)) ^ x;
|
||||
((((x >> 2) ^ x) & 0x33003300).wrapping_mul(5)) ^ x
|
||||
}
|
||||
|
||||
/// Interleave a half-key (4 u32 input -> 8 u32 output).
|
||||
/// Same 3-stage butterfly as pack_input but on 4 words.
|
||||
/// Used in key_schedule to interleave the two key halves.
|
||||
pub fn interleave_key_half(input: &[u32], output: &mut [u32]) {
|
||||
let (mut a, mut b) = (input[3], input[1]);
|
||||
let (mut c, mut d) = (input[2], input[0]);
|
||||
|
||||
// Phase 1: 0x55555555
|
||||
let t0 = (a ^ (b >> 1)) & 0x55555555;
|
||||
a ^= t0;
|
||||
b ^= t0 << 1;
|
||||
let t1 = (c ^ (d >> 1)) & 0x55555555;
|
||||
c ^= t1;
|
||||
d ^= t1 << 1;
|
||||
|
||||
// Phase 2: 0x33333333
|
||||
let t2 = (a ^ (c >> 2)) & 0x33333333;
|
||||
a ^= t2;
|
||||
c ^= t2 << 2;
|
||||
let t3 = (b ^ (d >> 2)) & 0x33333333;
|
||||
b ^= t3;
|
||||
d ^= t3 << 2;
|
||||
|
||||
// Phase 3: 0x0F0F0F0F
|
||||
let t4 = (a ^ (b >> 4)) & 0x0F0F0F0F;
|
||||
output[7] = a ^ t4;
|
||||
output[3] = (t4 << 4) ^ b;
|
||||
|
||||
let t5 = (c ^ (d >> 4)) & 0x0F0F0F0F;
|
||||
output[5] = c ^ t5;
|
||||
output[1] = (t5 << 4) ^ d;
|
||||
|
||||
// For the remaining outputs, use the already-interleaved values
|
||||
let t6 = (a ^ (c >> 4)) & 0x0F0F0F0F;
|
||||
output[6] = a ^ t6;
|
||||
output[2] = (t6 << 4) ^ c;
|
||||
|
||||
let t7 = (b ^ (d >> 4)) & 0x0F0F0F0F;
|
||||
output[4] = b ^ t7;
|
||||
output[0] = (t7 << 4) ^ d;
|
||||
}
|
||||
|
||||
/// Unpack output: reverse bit-interleave + final round key XOR.
|
||||
/// Reverse of pack_input: apply masks in reverse order (0x0F -> 0x33 -> 0x55).
|
||||
pub fn unpack_output(s: &[u32; 8], final_rk: &[u32; 8]) -> [u32; 8] {
|
||||
// XOR with final round keys first
|
||||
let mut a = s[7] ^ final_rk[7];
|
||||
let mut b = s[6] ^ final_rk[6];
|
||||
let mut c = s[5] ^ final_rk[5];
|
||||
let mut d = s[3] ^ final_rk[3];
|
||||
let mut e = s[4] ^ final_rk[4];
|
||||
let mut f = s[2] ^ final_rk[2];
|
||||
let mut g = s[1] ^ final_rk[1];
|
||||
let mut h = s[0] ^ final_rk[0];
|
||||
|
||||
// Reverse Phase 3: 0x0F0F0F0F
|
||||
let t8 = (a ^ (e >> 4)) & 0x0F0F0F0F;
|
||||
a ^= t8;
|
||||
e ^= t8 << 4;
|
||||
let t9 = (c ^ (g >> 4)) & 0x0F0F0F0F;
|
||||
c ^= t9;
|
||||
g ^= t9 << 4;
|
||||
let t10 = (b ^ (f >> 4)) & 0x0F0F0F0F;
|
||||
b ^= t10;
|
||||
f ^= t10 << 4;
|
||||
let t11 = (d ^ (h >> 4)) & 0x0F0F0F0F;
|
||||
d ^= t11;
|
||||
h ^= t11 << 4;
|
||||
|
||||
// Reverse Phase 2: 0x33333333
|
||||
let t4 = (a ^ (c >> 2)) & 0x33333333;
|
||||
a ^= t4;
|
||||
c ^= t4 << 2;
|
||||
let t5 = (e ^ (g >> 2)) & 0x33333333;
|
||||
e ^= t5;
|
||||
g ^= t5 << 2;
|
||||
let t6 = (b ^ (d >> 2)) & 0x33333333;
|
||||
b ^= t6;
|
||||
d ^= t6 << 2;
|
||||
let t7 = (f ^ (h >> 2)) & 0x33333333;
|
||||
f ^= t7;
|
||||
h ^= t7 << 2;
|
||||
|
||||
// Reverse Phase 1: 0x55555555
|
||||
let t0 = (a ^ (b >> 1)) & 0x55555555;
|
||||
a ^= t0;
|
||||
b ^= t0 << 1;
|
||||
let t1 = (c ^ (d >> 1)) & 0x55555555;
|
||||
c ^= t1;
|
||||
d ^= t1 << 1;
|
||||
let t2 = (e ^ (f >> 1)) & 0x55555555;
|
||||
e ^= t2;
|
||||
f ^= t2 << 1;
|
||||
let t3 = (g ^ (h >> 1)) & 0x55555555;
|
||||
g ^= t3;
|
||||
h ^= t3 << 1;
|
||||
|
||||
// Output in original order (reverse of input mapping)
|
||||
[h, f, d, b, g, e, c, a]
|
||||
}
|
||||
Reference in New Issue
Block a user