1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#![no_std]

extern crate byteorder;

use byteorder::{ ByteOrder, LittleEndian };


#[cfg(feature = "x64_128")]
pub mod params {
    pub const BLOCK_BYTES: usize = 64 / 8;
    pub const KEY_BYTES: usize = 128 / 8;
    pub type SubKey = [[u32; ROUNDS_PER_STEP]; BRANCHES * STEPS + 1];

    pub const BLOCK_SIZE: usize = BLOCK_BYTES / 4;
    pub const KEY_SIZE: usize = KEY_BYTES / 4;

    const ROUNDS: usize = 24;
    pub(crate) const ROUNDS_PER_STEP: usize = ROUNDS / STEPS;
    pub(crate) const STEPS: usize = 8;
    pub(crate) const BRANCHES: usize = 2;
}

#[cfg(feature = "x128_128")]
pub mod params {
    pub const BLOCK_BYTES: usize = 128 / 8;
    pub const KEY_BYTES: usize = 128 / 8;
    pub type SubKey = [[u32; ROUNDS_PER_STEP]; BRANCHES * STEPS + 1];

    pub const BLOCK_SIZE: usize = BLOCK_BYTES / 4;
    pub const KEY_SIZE: usize = KEY_BYTES / 4;

    const ROUNDS: usize = 32;
    pub(crate) const ROUNDS_PER_STEP: usize = ROUNDS / STEPS;
    pub(crate) const STEPS: usize = 8;
    pub(crate) const BRANCHES: usize = 4;
}

#[cfg(feature = "x128_256")]
pub mod params {
    pub const BLOCK_BYTES: usize = 128 / 8;
    pub const KEY_BYTES: usize = 256 / 8;
    pub type SubKey = [[u32; ROUNDS_PER_STEP]; BRANCHES * STEPS + 1];

    pub const BLOCK_SIZE: usize = BLOCK_BYTES / 4;
    pub const KEY_SIZE: usize = KEY_BYTES / 4;

    const ROUNDS: usize = 40;
    pub(crate) const ROUNDS_PER_STEP: usize = ROUNDS / STEPS;
    pub(crate) const STEPS: usize = 10;
    pub(crate) const BRANCHES: usize = 4;
}

pub mod block;

use params::*;
use block::{ key_schedule, encrypt_block, decrypt_block };


#[derive(Clone)]
pub struct Sparx(SubKey);

impl Sparx {
    pub fn new(key: &[u8; KEY_BYTES]) -> Self {
        let mut block = [0; KEY_SIZE];
        let mut subkey = [[0; ROUNDS_PER_STEP]; BRANCHES * STEPS + 1];
        LittleEndian::read_u32_into(key, &mut block);
        key_schedule(&mut block, &mut subkey);
        Sparx(subkey)
    }

    pub fn encrypt(&self, b: &mut [u8; BLOCK_BYTES]) {
        let mut nb = [0; BLOCK_SIZE];
        LittleEndian::read_u32_into(b, &mut nb);
        encrypt_block(&self.0, &mut nb);
        LittleEndian::write_u32_into(&nb, b);
    }

    pub fn decrypt(&self, b: &mut [u8; BLOCK_BYTES]) {
        let mut nb = [0; BLOCK_SIZE];
        LittleEndian::read_u32_into(b, &mut nb);
        decrypt_block(&self.0, &mut nb);
        LittleEndian::write_u32_into(&nb, b);
    }
}