gift-cipher 0.1.0

Pure Rust implementation of the Gift block cipher
Documentation
#[inline]
pub(crate) fn u32big(x: &[u8]) -> u32 {
    ((x[0] as u32) << 24) | ((x[1] as u32) << 16) | ((x[2] as u32) << 8) | (x[3] as u32)
}

#[inline]
pub(crate) fn ror(x: &u32, y: &u32) -> u32 {
    (*x).rotate_right(*y)
}

#[inline]
pub(crate) fn byte_ror_2(x: &u32) -> u32 {
    (((x) >> 2) & 0x3f3f3f3f) | (((x) & 0x03030303) << 6)
}

#[inline]
pub(crate) fn byte_ror_4(x: &u32) -> u32 {
    (((x) >> 4) & 0x0f0f0f0f) | (((x) & 0x0f0f0f0f) << 4)
}

#[inline]
pub(crate) fn byte_ror_6(x: &u32) -> u32 {
    (((x) >> 6) & 0x03030303) | (((x) & 0x3f3f3f3f) << 2)
}

#[inline]
pub(crate) fn half_ror_4(&x: &u32) -> u32 {
    (((x) >> 4) & 0x0fff0fff) | (((x) & 0x000f000f) << 12)
}

#[inline]
pub(crate) fn half_ror_8(x: &u32) -> u32 {
    (((x) >> 8) & 0x00ff00ff) | (((x) & 0x00ff00ff) << 8)
}

#[inline]
pub(crate) fn half_ror_12(&x: &u32) -> u32 {
    (((x) >> 12) & 0x000f000f) | (((x) & 0x0fff0fff) << 4)
}

#[inline]
pub(crate) fn nibble_ror_1(x: &u32) -> u32 {
    (((x) >> 1) & 0x77777777) | (((x) & 0x11111111) << 3)
}

#[inline]
pub(crate) fn nibble_ror_2(x: &u32) -> u32 {
    (((x) >> 2) & 0x33333333) | (((x) & 0x33333333) << 2)
}

#[inline]
pub(crate) fn nibble_ror_3(&x: &u32) -> u32 {
    (((x) >> 3) & 0x11111111) | (((x) & 0x77777777) << 1)
}

#[inline]
pub(crate) fn swapmove(a: &mut u32, b: &mut u32, mask: u32, n: u8) {
    let tmp = (*b ^ (*a >> n)) & mask;
    *b ^= tmp;
    *a ^= tmp << n;
}

#[inline]
pub(crate) fn swapmovesingle(a: &mut u32, mask: u32, n: u8) {
    let tmp = (*a ^ (*a >> n)) & mask;
    *a ^= tmp;
    *a ^= tmp << n;
}

#[inline]
pub(crate) fn sbox(s0: &mut u32, s1: &mut u32, s2: &mut u32, s3: &mut u32) {
    *s1 ^= *s0 & *s2;
    *s0 ^= *s1 & *s3;
    *s2 ^= *s0 | *s1;
    *s3 ^= *s2;
    *s1 ^= *s3;
    *s3 ^= 0xffffffff;
    *s2 ^= *s0 & *s1;
}

#[inline]
pub(crate) fn inv_sbox(s0: &mut u32, s1: &mut u32, s2: &mut u32, s3: &mut u32) {
    *s2 ^= *s3 & *s1;
    *s0 ^= 0xffffffff;
    *s1 ^= *s0;
    *s0 ^= *s2;
    *s2 ^= *s3 | *s1;
    *s3 ^= *s1 & *s0;
    *s1 ^= *s3 & *s2;
}

#[inline]
pub(crate) fn packing(state: &mut [u32], input: &[u8; 16]) {
    let mut s0 = ((input[6] as u32) << 24)
        | ((input[7] as u32) << 16)
        | ((input[14] as u32) << 8)
        | input[15] as u32;
    let mut s1 = ((input[4] as u32) << 24)
        | ((input[5] as u32) << 16)
        | ((input[12] as u32) << 8)
        | input[13] as u32;
    let mut s2 = ((input[2] as u32) << 24)
        | ((input[3] as u32) << 16)
        | ((input[10] as u32) << 8)
        | input[11] as u32;
    let mut s3 = ((input[0] as u32) << 24)
        | ((input[1] as u32) << 16)
        | ((input[8] as u32) << 8)
        | input[9] as u32;
    swapmovesingle(&mut s0, 0x0a0a0a0a, 3);
    swapmovesingle(&mut s0, 0x00cc00cc, 6);
    swapmovesingle(&mut s1, 0x0a0a0a0a, 3);
    swapmovesingle(&mut s1, 0x00cc00cc, 6);
    swapmovesingle(&mut s2, 0x0a0a0a0a, 3);
    swapmovesingle(&mut s2, 0x00cc00cc, 6);
    swapmovesingle(&mut s3, 0x0a0a0a0a, 3);
    swapmovesingle(&mut s3, 0x00cc00cc, 6);
    swapmove(&mut s0, &mut s1, 0x000f000f, 4);
    swapmove(&mut s0, &mut s2, 0x000f000f, 8);
    swapmove(&mut s0, &mut s3, 0x000f000f, 12);
    swapmove(&mut s1, &mut s2, 0x00f000f0, 4);
    swapmove(&mut s1, &mut s3, 0x00f000f0, 8);
    swapmove(&mut s2, &mut s3, 0x0f000f00, 4);
    state[0] = s0;
    state[1] = s1;
    state[2] = s2;
    state[3] = s3;
}

#[inline]
pub(crate) fn unpacking(state: &[u32], output: &mut [u8; 16]) {
    let (mut s0, mut s1, mut s2, mut s3) = (state[0], state[1], state[2], state[3]);

    swapmove(&mut s2, &mut s3, 0x0f000f00, 4);
    swapmove(&mut s1, &mut s3, 0x00f000f0, 8);
    swapmove(&mut s1, &mut s2, 0x00f000f0, 4);
    swapmove(&mut s0, &mut s3, 0x000f000f, 12);
    swapmove(&mut s0, &mut s2, 0x000f000f, 8);
    swapmove(&mut s0, &mut s1, 0x000f000f, 4);
    swapmovesingle(&mut s3, 0x00cc00cc, 6);
    swapmovesingle(&mut s3, 0x0a0a0a0a, 3);
    swapmovesingle(&mut s2, 0x00cc00cc, 6);
    swapmovesingle(&mut s2, 0x0a0a0a0a, 3);
    swapmovesingle(&mut s1, 0x00cc00cc, 6);
    swapmovesingle(&mut s1, 0x0a0a0a0a, 3);
    swapmovesingle(&mut s0, 0x00cc00cc, 6);
    swapmovesingle(&mut s0, 0x0a0a0a0a, 3);
    output[0] = (s3 >> 24) as u8;
    output[1] = ((s3 >> 16) & 0xff) as u8;
    output[2] = (s2 >> 24) as u8;
    output[3] = ((s2 >> 16) & 0xff) as u8;
    output[4] = (s1 >> 24) as u8;
    output[5] = ((s1 >> 16) & 0xff) as u8;
    output[6] = (s0 >> 24) as u8;
    output[7] = ((s0 >> 16) & 0xff) as u8;
    output[8] = ((s3 >> 8) & 0xff) as u8;
    output[9] = (s3 & 0xff) as u8;
    output[10] = ((s2 >> 8) & 0xff) as u8;
    output[11] = (s2 & 0xff) as u8;
    output[12] = ((s1 >> 8) & 0xff) as u8;
    output[13] = (s1 & 0xff) as u8;
    output[14] = ((s0 >> 8) & 0xff) as u8;
    output[15] = (s0 & 0xff) as u8;
}

#[inline]
pub(crate) fn quintuple_round(state: &mut [u32; 4], rkey: &[u32], rconst: &[u32]) {
    let mut s0 = state[0];
    let mut s1 = state[1];
    let mut s2 = state[2];
    let mut s3 = state[3];
    sbox(&mut s0, &mut s1, &mut s2, &mut s3);
    s3 = nibble_ror_1(&s3);
    s1 = nibble_ror_2(&s1);
    s2 = nibble_ror_3(&s2);
    s1 ^= rkey[0];
    s2 ^= rkey[1];
    s0 ^= rconst[0];
    sbox(&mut s3, &mut s1, &mut s2, &mut s0);
    s0 = half_ror_4(&s0);
    s1 = half_ror_8(&s1);
    s2 = half_ror_12(&s2);
    s1 ^= rkey[2];
    s2 ^= rkey[3];
    s3 ^= rconst[1];
    sbox(&mut s0, &mut s1, &mut s2, &mut s3);
    s3 = ror(&s3, &16);
    s2 = ror(&s2, &16);
    swapmovesingle(&mut s1, 0x55555555, 1);
    swapmovesingle(&mut s2, 0x00005555, 1);
    swapmovesingle(&mut s3, 0x55550000, 1);
    s1 ^= rkey[4];
    s2 ^= rkey[5];
    s0 ^= rconst[2];
    sbox(&mut s3, &mut s1, &mut s2, &mut s0);
    s0 = byte_ror_6(&s0);
    s1 = byte_ror_4(&s1);
    s2 = byte_ror_2(&s2);
    s1 ^= rkey[6];
    s2 ^= rkey[7];
    s3 ^= rconst[3];
    sbox(&mut s0, &mut s1, &mut s2, &mut s3);
    s3 = ror(&s3, &24);
    s1 = ror(&s1, &16);
    s2 = ror(&s2, &8);
    s1 ^= rkey[8];
    s2 ^= rkey[9];
    s0 ^= rconst[4];
    core::mem::swap(&mut s0, &mut s3);
    state[0] = s0;
    state[1] = s1;
    state[2] = s2;
    state[3] = s3;
}

#[inline]
pub(crate) fn inv_quintuple_round(state: &mut [u32; 4], rkey: &[u32], rconst: &[u32]) {
    let mut s0 = state[0];
    let mut s1 = state[1];
    let mut s2 = state[2];
    let mut s3 = state[3];
    core::mem::swap(&mut s0, &mut s3);
    s1 ^= rkey[8];
    s2 ^= rkey[9];
    s0 ^= rconst[4];
    s3 = ror(&s3, &8);
    s1 = ror(&s1, &16);
    s2 = ror(&s2, &24);
    inv_sbox(&mut s3, &mut s1, &mut s2, &mut s0);
    s1 ^= rkey[6];
    s2 ^= rkey[7];
    s3 ^= rconst[3];
    s0 = byte_ror_2(&s0);
    s1 = byte_ror_4(&s1);
    s2 = byte_ror_6(&s2);
    inv_sbox(&mut s0, &mut s1, &mut s2, &mut s3);
    s1 ^= rkey[4];
    s2 ^= rkey[5];
    s0 ^= rconst[2];
    swapmovesingle(&mut s3, 0x55550000, 1);
    swapmovesingle(&mut s1, 0x55555555, 1);
    swapmovesingle(&mut s2, 0x00005555, 1);
    s3 = ror(&s3, &16);
    s2 = ror(&s2, &16);
    inv_sbox(&mut s3, &mut s1, &mut s2, &mut s0);
    s1 ^= rkey[2];
    s2 ^= rkey[3];
    s3 ^= rconst[1];
    s0 = half_ror_12(&s0);
    s1 = half_ror_8(&s1);
    s2 = half_ror_4(&s2);
    inv_sbox(&mut s0, &mut s1, &mut s2, &mut s3);
    s1 ^= rkey[0];
    s2 ^= rkey[1];
    s0 ^= rconst[0];
    s3 = nibble_ror_3(&s3);
    s1 = nibble_ror_2(&s1);
    s2 = nibble_ror_1(&s2);
    inv_sbox(&mut s3, &mut s1, &mut s2, &mut s0);
    state[0] = s0;
    state[1] = s1;
    state[2] = s2;
    state[3] = s3;
}