gift-cipher 0.1.0

Pure Rust implementation of the Gift block cipher
Documentation
use crate::primitives::{ror, swapmovesingle, u32big};

fn rearrange_rkey_0(x: &u32) -> u32 {
    let mut tmp = *x;
    swapmovesingle(&mut tmp, 0x00550055, 9);
    swapmovesingle(&mut tmp, 0x000f000f, 12);
    swapmovesingle(&mut tmp, 0x00003333, 18);
    swapmovesingle(&mut tmp, 0x000000ff, 24);
    tmp
}

fn rearrange_rkey_1(x: &u32) -> u32 {
    let mut tmp = *x;
    swapmovesingle(&mut tmp, 0x11111111, 3);
    swapmovesingle(&mut tmp, 0x03030303, 6);
    swapmovesingle(&mut tmp, 0x000f000f, 12);
    swapmovesingle(&mut tmp, 0x000000ff, 24);
    tmp
}

fn rearrange_rkey_2(x: &u32) -> u32 {
    let mut tmp = *x;
    swapmovesingle(&mut tmp, 0x0000aaaa, 15);
    swapmovesingle(&mut tmp, 0x00003333, 18);
    swapmovesingle(&mut tmp, 0x0000f0f0, 12);
    swapmovesingle(&mut tmp, 0x000000ff, 24);
    tmp
}

fn rearrange_rkey_3(x: &u32) -> u32 {
    let mut tmp = *x;
    swapmovesingle(&mut tmp, 0x0a0a0a0a, 3);
    swapmovesingle(&mut tmp, 0x00cc00cc, 6);
    swapmovesingle(&mut tmp, 0x0000f0f0, 12);
    swapmovesingle(&mut tmp, 0x000000ff, 24);
    tmp
}

fn key_update(x: &u32) -> u32 {
    (((*x) >> 12) & 0x0000000f)
        | (((*x) & 0x00000fff) << 4)
        | (((*x) >> 2) & 0x3fff0000)
        | (((*x) & 0x00030000) << 14)
}

fn key_triple_update_0(x: &u32) -> u32 {
    ror(&(*x & 0x33333333), &24) | ror(&(*x & 0xcccccccc), &16)
}

fn key_double_update_1(x: &u32) -> u32 {
    (((x) >> 4) & 0x0f000f00)
        | (((x) & 0x0f000f00) << 4)
        | (((x) >> 6) & 0x00030003)
        | (((x) & 0x003f003f) << 2)
}

fn key_triple_update_1(x: &u32) -> u32 {
    (((x) >> 6) & 0x03000300)
        | (((x) & 0x3f003f00) << 2)
        | (((x) >> 5) & 0x00070007)
        | (((x) & 0x001f001f) << 3)
}

fn key_double_update_2(x: &u32) -> u32 {
    ror(&(*x & 0xaaaaaaaa), &24) | ror(&(*x & 0x55555555), &16)
}

fn key_triple_update_2(x: &u32) -> u32 {
    ror(&(*x & 0x55555555), &24) | ror(&(*x & 0xaaaaaaaa), &20)
}

fn key_double_update_3(x: &u32) -> u32 {
    (((x) >> 2) & 0x03030303)
        | (((x) & 0x03030303) << 2)
        | (((x) >> 1) & 0x70707070)
        | (((x) & 0x10101010) << 3)
}

fn key_triple_update_3(x: &u32) -> u32 {
    (((x) >> 18) & 0x00003030)
        | (((x) & 0x01010101) << 3)
        | (((x) >> 14) & 0x0000c0c0)
        | (((x) & 0x0000e0e0) << 15)
        | (((x) >> 1) & 0x07070707)
        | (((x) & 0x00001010) << 19)
}

fn key_double_update_4(x: &u32) -> u32 {
    (((x) >> 4) & 0x0fff0000)
        | (((x) & 0x000f0000) << 12)
        | (((x) >> 8) & 0x000000ff)
        | (((x) & 0x000000ff) << 8)
}

fn key_triple_update_4(x: &u32) -> u32 {
    (((x) >> 6) & 0x03ff0000)
        | (((x) & 0x003f0000) << 10)
        | (((x) >> 4) & 0x00000fff)
        | (((x) & 0x0000000f) << 12)
}

pub fn precompute_rkeys(key: &[u8; 16]) -> [u32; 80] {
    let mut rkey = [0u32; 80];
    rkey[0] = u32big(&(key[12..16]));
    rkey[1] = u32big(&(key[4..8]));
    rkey[2] = u32big(&(key[8..12]));
    rkey[3] = u32big(&(key[0..4]));

    for i in (0..16).step_by(2) {
        rkey[i + 4] = rkey[i + 1];
        rkey[i + 5] = key_update(&rkey[i]);
    }

    for i in (0..20).step_by(10) {
        rkey[i] = rearrange_rkey_0(&rkey[i]);
        rkey[i + 1] = rearrange_rkey_0(&rkey[i + 1]);
        rkey[i + 2] = rearrange_rkey_1(&rkey[i + 2]);
        rkey[i + 3] = rearrange_rkey_1(&rkey[i + 3]);
        rkey[i + 4] = rearrange_rkey_2(&rkey[i + 4]);
        rkey[i + 5] = rearrange_rkey_2(&rkey[i + 5]);
        rkey[i + 6] = rearrange_rkey_3(&rkey[i + 6]);
        rkey[i + 7] = rearrange_rkey_3(&rkey[i + 7]);
    }

    for i in (20..80).step_by(10) {
        rkey[i] = rkey[i - 19];
        rkey[i + 1] = key_triple_update_0(&rkey[i - 20]);
        rkey[i + 2] = key_double_update_1(&rkey[i - 17]);
        rkey[i + 3] = key_triple_update_1(&rkey[i - 18]);
        rkey[i + 4] = key_double_update_2(&rkey[i - 15]);
        rkey[i + 5] = key_triple_update_2(&rkey[i - 16]);
        rkey[i + 6] = key_double_update_3(&rkey[i - 13]);
        rkey[i + 7] = key_triple_update_3(&rkey[i - 14]);
        rkey[i + 8] = key_double_update_4(&rkey[i - 11]);
        rkey[i + 9] = key_triple_update_4(&rkey[i - 12]);
        swapmovesingle(&mut rkey[i], 0x00003333, 16);
        swapmovesingle(&mut rkey[i], 0x55554444, 1);
        swapmovesingle(&mut rkey[i + 1], 0x55551100, 1);
    }

    rkey
}