91 lines
4.2 KiB
Rust
91 lines
4.2 KiB
Rust
//! GIFT-256 bitsliced S-Box
|
|
//! Corresponds to gift256_sbox_bitsliced @ 0x8000394c
|
|
//! Pure AND/XOR Boolean network, 32 S-Box instances in parallel
|
|
//!
|
|
//! Directly transcribed from Ghidra decompilation.
|
|
//! WARNING: Variables are reassigned multiple times. Do NOT optimize or merge.
|
|
|
|
/// Bitsliced S-Box: 8 u32 words processed in parallel.
|
|
/// Each bit position across s[0]..s[7] forms one 8-bit S-Box input/output.
|
|
///
|
|
/// Register mapping (encrypted_mem_read_u32 offsets):
|
|
/// s[0]=@0x00, s[1]=@0x04, s[2]=@0x08, s[3]=@0x0c
|
|
/// s[4]=@0x10, s[5]=@0x14, s[6]=@0x18, s[7]=@0x1c
|
|
pub fn sbox_bitsliced(s: &mut [u32; 8]) {
|
|
// Direct mapping from decompilation variable names:
|
|
// uVar1=@0x1c=s[7], uVar2=@0x04=s[1], uVar3=@0x10=s[4], uVar4=@0x08=s[2]
|
|
// uVar5=@0x0c=s[3], uVar6=@0x18=s[6], uVar7=@0x14=s[5], uVar(last)=@0x00=s[0]
|
|
let (a, b, c, d, e, f, g, h) = (s[7], s[1], s[2], s[3], s[4], s[5], s[6], s[0]);
|
|
|
|
let t1 = a ^ b; // uVar8 = uVar1 ^ uVar2
|
|
let t2 = e ^ c; // uVar14 = uVar3 ^ uVar4
|
|
let t3 = t1 ^ t2; // uVar9
|
|
let t4 = d ^ t3 ^ g; // uVar10
|
|
let t5 = e ^ a; // uVar15 = uVar3 ^ uVar1
|
|
let t6 = t4 ^ t5; // uVar11
|
|
let fg = f ^ g; // uVar7 = s[5] ^ s[6]
|
|
let t7 = t6 ^ fg; // uVar12
|
|
|
|
let ag = h ^ fg; // uVar25 = s[0] ^ (f^g)
|
|
let bx = b ^ ag; // uVar2 updated
|
|
let cd_mix = c ^ d ^ t3; // uVar26
|
|
let fg_cd = fg ^ cd_mix; // uVar7 subsequent
|
|
|
|
// Nonlinear core
|
|
let n1 = (t6 & t5) ^ (t2 & (fg_cd ^ t6)); // uVar16
|
|
let n2 = (t7 & t1) ^ t7 ^ (bx & ag) ^ t1 ^ n1; // uVar5
|
|
|
|
let ac = a ^ c; // uVar4 updated
|
|
let n1_ext = n1 ^ (cd_mix & t3) ^ t4 ^ ((h ^ cd_mix) & (ac ^ bx)); // uVar16 updated
|
|
|
|
let p = n2 & n1_ext; // uVar10
|
|
let q = (ac & fg_cd) ^ (t6 & t5); // uVar22
|
|
let r = (h & (e ^ ag)) ^ ac ^ fg_cd ^ (cd_mix & t3) ^ q; // uVar17
|
|
let qx = q ^ t7 ^ ((a ^ ag) & (h ^ t6)) ^ (t7 & t1) ^ a; // uVar22 updated
|
|
|
|
let m = (p ^ r) & (qx ^ n2); // uVar13
|
|
let n1x = r ^ n1_ext; // uVar16 = r ^ n1_ext
|
|
let rx = r ^ ((qx ^ p) & n1x); // uVar17 updated
|
|
let sx = (p ^ m) & qx; // uVar18
|
|
let n1x = (rx & (sx ^ qx ^ p)) ^ n1x; // uVar16 final
|
|
let sx = sx ^ n2; // uVar18 ^= uVar5
|
|
let qx = qx ^ m; // uVar22 ^= uVar13
|
|
|
|
let u = sx ^ qx; // uVar19
|
|
let v = n1x ^ u; // uVar5(final) = uVar16 ^ uVar19
|
|
let w = qx ^ rx; // uVar20
|
|
|
|
// Diffusion outputs
|
|
let o1 = ((v ^ w) & t2) ^ (w & t5); // uVar10
|
|
let o2 = o1 ^ (u & (ac ^ bx)); // uVar13
|
|
let o3 = o2 ^ (t3 & sx); // uVar9
|
|
|
|
let o4 = t7 & (rx ^ n1x); // uVar12
|
|
let o5 = o4 ^ (n1x & ag); // uVar23
|
|
let o6 = ((v ^ w) & (fg_cd ^ t6)) ^ o5; // uVar21
|
|
let o7 = o6 ^ (w & t6); // uVar14
|
|
|
|
// Output assignments (encrypted_mem_write_u32):
|
|
s[7] = o3 ^ o7; // @0x1c = uVar9 ^ uVar14
|
|
|
|
let o8 = (rx ^ n1x) & t1; // uVar8
|
|
let o9 = (qx & h) ^ (cd_mix & sx); // uVar24
|
|
let o6 = o8 ^ o9 ^ (fg_cd & v) ^ o6; // uVar21 updated
|
|
let o10 = o6 ^ (rx & (a ^ ag)); // uVar1
|
|
|
|
s[5] = (ac & v) ^ (w & t5) ^ o7 ^ o10; // @0x14
|
|
s[6] = o3 ^ o7; // @0x18 (same as s[7])
|
|
|
|
let o3x = (u & (h ^ cd_mix)) ^ (cd_mix & sx) ^ o5 ^ o3; // uVar9 updated
|
|
s[4] = o3x; // @0x10
|
|
|
|
s[2] = o2 ^ (qx & (e ^ ag)) ^ o10; // @0x08
|
|
|
|
let o4x = o9 ^ (rx & (h ^ t6)) ^ o4; // uVar12 updated
|
|
let o11 = o4x ^ o1 ^ (n1x & bx); // uVar1
|
|
|
|
s[1] = o11 ^ o6; // @0x04
|
|
s[0] = o11 ^ o8; // @0x00
|
|
s[3] = o4x ^ o3x; // @0x0c
|
|
}
|