eva_crypto/
led.rs

1use super::generic::{create_u8x4x4, u8x4x4, Ops, Permutation};
2
3/// LED block cipher's block length is 64 bits, and it supports 3 key lengths of 64, 80 and 128 bits in the [paper](https://link.springer.com/chapter/10.1007/978-3-642-23951-9_22).
4pub struct LED {
5    /// Each element in the key vector should be 4-bit(ranges from 0x0 to 0xf).
6    pub key: Vec<u8>,
7    /// `ns` represents the number of steps.
8    ns: u8,
9    /// `keysize` can be 64, 80 and 128.
10    keysize: u8,
11    sbox: [u8; 16],
12    rsbox: [u8; 16],
13}
14
15type LEDstate = u8x4x4;
16
17impl LED {
18    /// Initialize a LED cipher.
19    pub fn new(key: &[u8]) -> Self {
20        let keysize = key.len() * 4;
21        let ns = match keysize {
22            64 => 8,
23            80 => 10,
24            128 => 12,
25            _ => unimplemented!(),
26        };
27        LED {
28            key: key.to_vec(),
29            ns,
30            keysize: keysize as u8,
31            sbox: SBOX,
32            rsbox: RSBOX,
33        }
34    }
35
36    /// Encrypt a block.
37    pub fn encrypt(&self, data: &[u8]) -> Vec<u8> {
38        let mut state = create_u8x4x4(data);
39        for i in 0..self.ns {
40            state = add_round_key(&state, &self.key, self.keysize, i);
41            state = step(&state, self.keysize, i, &self.sbox);
42        }
43        state = add_round_key(&state, &self.key, self.keysize, self.ns);
44        state.concat()
45    }
46
47    /// Decrypt a block.
48    pub fn decrypt(&self, data: &[u8]) -> Vec<u8> {
49        let mut state = create_u8x4x4(data);
50        for i in (0..self.ns).rev() {
51            state = add_round_key(&state, &self.key, self.keysize, i);
52            state = inv_step(&state, self.keysize, i, &self.rsbox);
53        }
54        state = add_round_key(&state, &self.key, self.keysize, 0);
55        state.concat()
56    }
57
58    // Fault injection
59    pub fn with_sbox_byte(mut self, faulty_idx: usize, faulty_val: u8) -> Self {
60        let mut sbox = SBOX;
61        sbox[faulty_idx] = faulty_val;
62        self.sbox = sbox;
63        self
64    }
65
66    pub fn with_rsbox_byte(mut self, faulty_idx: usize, faulty_val: u8) -> Self {
67        let mut rsbox = RSBOX;
68        rsbox[faulty_idx] = faulty_val;
69        self.rsbox = rsbox;
70        self
71    }
72}
73
74fn step(state: &LEDstate, keysize: u8, round: u8, sbox: &[u8]) -> LEDstate {
75    let mut out = *state;
76    for i in 0..4 {
77        out = add_constants(&out, round * 4 + i, keysize);
78        out = sub_cells(&out, sbox);
79        out = shift_rows(&out);
80        out = mix_columns_serial(&out);
81    }
82    out
83}
84fn inv_step(state: &LEDstate, keysize: u8, round: u8, rsbox: &[u8]) -> LEDstate {
85    let mut out = *state;
86    for i in (0..4).rev() {
87        out = inv_mix_columns_serial(&out);
88        out = inv_shift_rows(&out);
89        out = inv_sub_cells(&out, rsbox);
90        out = add_constants(&out, round * 4 + i, keysize);
91    }
92    out
93}
94fn add_round_key(state: &LEDstate, key: &[u8], keysize: u8, round: u8) -> LEDstate {
95    let mut rkey: [u8; 16] = [0; 16];
96    for i in 0..16 {
97        rkey[i] = key[((round * 16 + i as u8) % (keysize / 4)) as usize];
98    }
99    state.xor(&create_u8x4x4(&rkey))
100}
101fn add_constants(state: &LEDstate, r: u8, keysize: u8) -> LEDstate {
102    state.xor(&[
103        [keysize >> 4, (RCON[r as usize] >> 3) & 0x7, 0, 0],
104        [1 ^ ((keysize >> 4) & 0xf), RCON[r as usize] & 0x7, 0, 0],
105        [2 ^ (keysize & 0xf), (RCON[r as usize] >> 3) & 0x7, 0, 0],
106        [3 ^ (keysize & 0xf), RCON[r as usize] & 0x7, 0, 0],
107    ])
108}
109fn sub_cells(state: &LEDstate, sbox: &[u8]) -> LEDstate {
110    state.sub_sbox(sbox)
111}
112fn inv_sub_cells(state: &LEDstate, rsbox: &[u8]) -> LEDstate {
113    state.sub_sbox(rsbox)
114}
115fn shift_rows(state: &LEDstate) -> LEDstate {
116    state.lrot()
117}
118fn inv_shift_rows(state: &LEDstate) -> LEDstate {
119    state.rrot()
120}
121fn mix_columns_serial(state: &LEDstate) -> LEDstate {
122    state.gmul(&MDS, 4)
123}
124fn inv_mix_columns_serial(state: &LEDstate) -> LEDstate {
125    state.gmul(&RMDS, 4)
126}
127
128pub static RCON: [u8; 48] = [
129    0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3E, 0x3D, 0x3B, 0x37, 0x2F, 0x1E, 0x3C, 0x39, 0x33, 0x27, 0x0E,
130    0x1D, 0x3A, 0x35, 0x2B, 0x16, 0x2C, 0x18, 0x30, 0x21, 0x02, 0x05, 0x0B, 0x17, 0x2E, 0x1C, 0x38,
131    0x31, 0x23, 0x06, 0x0D, 0x1B, 0x36, 0x2D, 0x1A, 0x34, 0x29, 0x12, 0x24, 0x08, 0x11, 0x22, 0x04,
132];
133
134pub static SBOX: [u8; 16] = [
135    0xC, 0x5, 0x6, 0xB, 0x9, 0x0, 0xA, 0xD, 0x3, 0xE, 0xF, 0x8, 0x4, 0x7, 0x1, 0x2,
136];
137
138pub static RSBOX: [u8; 16] = [
139    0x5, 0xe, 0xF, 0x8, 0xC, 0x1, 0x2, 0xD, 0xB, 0x4, 0x6, 0x3, 0x0, 0x7, 0x9, 0xA,
140];
141
142pub static MDS: [[u8; 4]; 4] = [
143    [0x4, 0x1, 0x2, 0x2],
144    [0x8, 0x6, 0x5, 0x6],
145    [0xB, 0xE, 0xA, 0x9],
146    [0x2, 0x2, 0xF, 0xB],
147];
148
149pub static RMDS: [[u8; 4]; 4] = [
150    [0xc, 0xc, 0xd, 0x4],
151    [0x3, 0x8, 0x4, 0x5],
152    [0x7, 0x6, 0x2, 0xe],
153    [0xd, 0x9, 0x9, 0xd],
154];