vaz256/
fips202.rs

1// This module was originally derived from CRYSTALS-Dilithium
2// Source: https://github.com/Quantum-Blockchains/dilithium
3// Which itself was ported from: https://github.com/pq-crystals/dilithium
4// Original implementation by: Quantum Blockchains (https://www.quantumblockchains.io/)
5// 
6// Modified for use in VAZ256™
7// Copyright (C) 2025 Fran Luis Vazquez Alonso
8//
9// This program is free software: you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation, either version 3 of the License, or
12// (at your option) any later version.
13
14
15pub const SHAKE128_RATE: usize = 168;
16pub const SHAKE256_RATE: usize = 136;
17
18const NROUNDS: usize = 24;
19
20/// 1600-bit state of the algorithm, with an index of curent position.
21#[derive(Copy, Clone)]
22pub struct KeccakState {
23    pub s: [u64; 25],
24    pub pos: usize,
25}
26
27impl Default for KeccakState {
28    fn default() -> Self {
29        KeccakState {
30            s: [0u64; 25],
31            pos: 0,
32        }
33    }
34}
35
36impl KeccakState {
37    /// Set the state to the initial form.
38    pub fn init(&mut self) {
39        self.s.fill(0);
40        self.pos = 0;
41    }
42}
43
44/// No rolling defined in the language so got to do it ourselfs :(
45/// 
46/// # Arguments
47/// 
48/// * 'a' - number to rotate right
49/// * 'offset' - how many places to rotate
50/// 
51/// Returns the rotated number
52fn rol(a: u64, offset: u64) -> u64 {
53    (a << offset) ^ (a >> (64 - offset))
54}
55
56/// Load 8 bytes into uint64_t in little-endian order
57pub fn load64(x: &[u8]) -> u64 {
58    let mut r = 0u64;
59    for i in 0..8 {
60        r |= (x[i] as u64) << (8 * i);
61    }
62    r
63}
64
65/// Store a 64-bit integer to array of 8 bytes in little-endian order
66pub fn store64(x: &mut [u8], u: u64) {
67    for i in 0..8 {
68        x[i] = (u >> 8 * i) as u8;
69    }
70}
71
72/// Keccak round constants
73const KECCAKF_ROUNDCONSTANTS: [u64; NROUNDS] = [
74    0x0000000000000001u64,
75    0x0000000000008082u64,
76    0x800000000000808au64,
77    0x8000000080008000u64,
78    0x000000000000808bu64,
79    0x0000000080000001u64,
80    0x8000000080008081u64,
81    0x8000000000008009u64,
82    0x000000000000008au64,
83    0x0000000000000088u64,
84    0x0000000080008009u64,
85    0x000000008000000au64,
86    0x000000008000808bu64,
87    0x800000000000008bu64,
88    0x8000000000008089u64,
89    0x8000000000008003u64,
90    0x8000000000008002u64,
91    0x8000000000000080u64,
92    0x000000000000800au64,
93    0x800000008000000au64,
94    0x8000000080008081u64,
95    0x8000000000008080u64,
96    0x0000000080000001u64,
97    0x8000000080008008u64,
98];
99
100/// The Keccak F1600 Permutation
101pub fn keccakf1600_statepermute(state: &mut [u64]) {
102    let mut aba = state[0];
103    let mut abe = state[1];
104    let mut abi = state[2];
105    let mut abo = state[3];
106    let mut abu = state[4];
107    let mut aga = state[5];
108    let mut age = state[6];
109    let mut agi = state[7];
110    let mut ago = state[8];
111    let mut agu = state[9];
112    let mut aka = state[10];
113    let mut ake = state[11];
114    let mut aki = state[12];
115    let mut ako = state[13];
116    let mut aku = state[14];
117    let mut ama = state[15];
118    let mut ame = state[16];
119    let mut ami = state[17];
120    let mut amo = state[18];
121    let mut amu = state[19];
122    let mut asa = state[20];
123    let mut ase = state[21];
124    let mut asi = state[22];
125    let mut aso = state[23];
126    let mut asu = state[24];
127
128    for round in (0..NROUNDS).step_by(2) {
129        let mut bca = aba ^ aga ^ aka ^ ama ^ asa;
130        let mut bce = abe ^ age ^ ake ^ ame ^ ase;
131        let mut bci = abi ^ agi ^ aki ^ ami ^ asi;
132        let mut bco = abo ^ ago ^ ako ^ amo ^ aso;
133        let mut bcu = abu ^ agu ^ aku ^ amu ^ asu;
134
135        let mut da = bcu ^ rol(bce, 1);
136        let mut de = bca ^ rol(bci, 1);
137        let mut di = bce ^ rol(bco, 1);
138        let mut d_o = bci ^ rol(bcu, 1);
139        let mut du = bco ^ rol(bca, 1);
140
141        aba ^= da;
142        bca = aba;
143        age ^= de;
144        bce = rol(age, 44);
145        aki ^= di;
146        bci = rol(aki, 43);
147        amo ^= d_o;
148        bco = rol(amo, 21);
149        asu ^= du;
150        bcu = rol(asu, 14);
151        let mut eba = bca ^ ((!bce) & bci);
152        eba ^= KECCAKF_ROUNDCONSTANTS[round];
153        let mut ebe = bce ^ ((!bci) & bco);
154        let mut ebi = bci ^ ((!bco) & bcu);
155        let mut ebo = bco ^ ((!bcu) & bca);
156        let mut ebu = bcu ^ ((!bca) & bce);
157
158        abo ^= d_o;
159        bca = rol(abo, 28);
160        agu ^= du;
161        bce = rol(agu, 20);
162        aka ^= da;
163        bci = rol(aka, 3);
164        ame ^= de;
165        bco = rol(ame, 45);
166        asi ^= di;
167        bcu = rol(asi, 61);
168        let mut ega = bca ^ ((!bce) & bci);
169        let mut ege = bce ^ ((!bci) & bco);
170        let mut egi = bci ^ ((!bco) & bcu);
171        let mut ego = bco ^ ((!bcu) & bca);
172        let mut egu = bcu ^ ((!bca) & bce);
173
174        abe ^= de;
175        bca = rol(abe, 1);
176        agi ^= di;
177        bce = rol(agi, 6);
178        ako ^= d_o;
179        bci = rol(ako, 25);
180        amu ^= du;
181        bco = rol(amu, 8);
182        asa ^= da;
183        bcu = rol(asa, 18);
184        let mut eka = bca ^ ((!bce) & bci);
185        let mut eke = bce ^ ((!bci) & bco);
186        let mut eki = bci ^ ((!bco) & bcu);
187        let mut eko = bco ^ ((!bcu) & bca);
188        let mut eku = bcu ^ ((!bca) & bce);
189
190        abu ^= du;
191        bca = rol(abu, 27);
192        aga ^= da;
193        bce = rol(aga, 36);
194        ake ^= de;
195        bci = rol(ake, 10);
196        ami ^= di;
197        bco = rol(ami, 15);
198        aso ^= d_o;
199        bcu = rol(aso, 56);
200        let mut ema = bca ^ ((!bce) & bci);
201        let mut eme = bce ^ ((!bci) & bco);
202        let mut emi = bci ^ ((!bco) & bcu);
203        let mut emo = bco ^ ((!bcu) & bca);
204        let mut emu = bcu ^ ((!bca) & bce);
205
206        abi ^= di;
207        bca = rol(abi, 62);
208        ago ^= d_o;
209        bce = rol(ago, 55);
210        aku ^= du;
211        bci = rol(aku, 39);
212        ama ^= da;
213        bco = rol(ama, 41);
214        ase ^= de;
215        bcu = rol(ase, 2);
216        let mut esa = bca ^ ((!bce) & bci);
217        let mut ese = bce ^ ((!bci) & bco);
218        let mut esi = bci ^ ((!bco) & bcu);
219        let mut eso = bco ^ ((!bcu) & bca);
220        let mut esu = bcu ^ ((!bca) & bce);
221
222        bca = eba ^ ega ^ eka ^ ema ^ esa;
223        bce = ebe ^ ege ^ eke ^ eme ^ ese;
224        bci = ebi ^ egi ^ eki ^ emi ^ esi;
225        bco = ebo ^ ego ^ eko ^ emo ^ eso;
226        bcu = ebu ^ egu ^ eku ^ emu ^ esu;
227
228        da = bcu ^ rol(bce, 1);
229        de = bca ^ rol(bci, 1);
230        di = bce ^ rol(bco, 1);
231        d_o = bci ^ rol(bcu, 1);
232        du = bco ^ rol(bca, 1);
233
234        eba ^= da;
235        bca = eba;
236        ege ^= de;
237        bce = rol(ege, 44);
238        eki ^= di;
239        bci = rol(eki, 43);
240        emo ^= d_o;
241        bco = rol(emo, 21);
242        esu ^= du;
243        bcu = rol(esu, 14);
244        aba = bca ^ ((!bce) & bci);
245        aba ^= KECCAKF_ROUNDCONSTANTS[round + 1];
246        abe = bce ^ ((!bci) & bco);
247        abi = bci ^ ((!bco) & bcu);
248        abo = bco ^ ((!bcu) & bca);
249        abu = bcu ^ ((!bca) & bce);
250
251        ebo ^= d_o;
252        bca = rol(ebo, 28);
253        egu ^= du;
254        bce = rol(egu, 20);
255        eka ^= da;
256        bci = rol(eka, 3);
257        eme ^= de;
258        bco = rol(eme, 45);
259        esi ^= di;
260        bcu = rol(esi, 61);
261        aga = bca ^ ((!bce) & bci);
262        age = bce ^ ((!bci) & bco);
263        agi = bci ^ ((!bco) & bcu);
264        ago = bco ^ ((!bcu) & bca);
265        agu = bcu ^ ((!bca) & bce);
266
267        ebe ^= de;
268        bca = rol(ebe, 1);
269        egi ^= di;
270        bce = rol(egi, 6);
271        eko ^= d_o;
272        bci = rol(eko, 25);
273        emu ^= du;
274        bco = rol(emu, 8);
275        esa ^= da;
276        bcu = rol(esa, 18);
277        aka = bca ^ ((!bce) & bci);
278        ake = bce ^ ((!bci) & bco);
279        aki = bci ^ ((!bco) & bcu);
280        ako = bco ^ ((!bcu) & bca);
281        aku = bcu ^ ((!bca) & bce);
282
283        ebu ^= du;
284        bca = rol(ebu, 27);
285        ega ^= da;
286        bce = rol(ega, 36);
287        eke ^= de;
288        bci = rol(eke, 10);
289        emi ^= di;
290        bco = rol(emi, 15);
291        eso ^= d_o;
292        bcu = rol(eso, 56);
293        ama = bca ^ ((!bce) & bci);
294        ame = bce ^ ((!bci) & bco);
295        ami = bci ^ ((!bco) & bcu);
296        amo = bco ^ ((!bcu) & bca);
297        amu = bcu ^ ((!bca) & bce);
298
299        ebi ^= di;
300        bca = rol(ebi, 62);
301        ego ^= d_o;
302        bce = rol(ego, 55);
303        eku ^= du;
304        bci = rol(eku, 39);
305        ema ^= da;
306        bco = rol(ema, 41);
307        ese ^= de;
308        bcu = rol(ese, 2);
309        asa = bca ^ ((!bce) & bci);
310        ase = bce ^ ((!bci) & bco);
311        asi = bci ^ ((!bco) & bcu);
312        aso = bco ^ ((!bcu) & bca);
313        asu = bcu ^ ((!bca) & bce);
314    }
315
316    state[0] = aba;
317    state[1] = abe;
318    state[2] = abi;
319    state[3] = abo;
320    state[4] = abu;
321    state[5] = aga;
322    state[6] = age;
323    state[7] = agi;
324    state[8] = ago;
325    state[9] = agu;
326    state[10] = aka;
327    state[11] = ake;
328    state[12] = aki;
329    state[13] = ako;
330    state[14] = aku;
331    state[15] = ama;
332    state[16] = ame;
333    state[17] = ami;
334    state[18] = amo;
335    state[19] = amu;
336    state[20] = asa;
337    state[21] = ase;
338    state[22] = asi;
339    state[23] = aso;
340    state[24] = asu;
341}
342
343/// Absorb step of Keccak; incremental.
344fn keccak_absorb(state: &mut KeccakState, r: usize, input: &[u8], mut inlen: usize) {
345    let mut idx = 0;
346    let mut pos = state.pos;
347    while pos + inlen >= r {
348        for i in pos..r {
349            state.s[i / 8] ^= (input[idx] as u64) << 8 * (i % 8);
350            idx += 1;
351        }
352        inlen -= r - pos;
353        keccakf1600_statepermute(&mut state.s);
354        pos = 0;
355    }
356    let mut i = pos;
357    while i < pos + inlen {
358        state.s[i / 8] ^= (input[idx] as u64) << 8 * (i % 8);
359        idx += 1;
360        i += 1
361    }
362    state.pos = i;
363}
364
365/// Finalize absorb step.
366fn keccak_finalize(s: &mut [u64; 25], pos: usize, r: usize, p: u8) {
367    s[pos / 8] ^= (p as u64) << 8 * (pos % 8);
368    s[r / 8 - 1] ^= 1u64 << 63;
369}
370
371/// Squeeze step of Keccak. Squeezes arbitratrily many bytes.
372/// Modifies the state. Can be called multiple times to keep squeezing, i.e., is incremental.
373///
374/// Returns new position pos in current block
375fn keccak_squeeze(
376    out: &mut [u8],
377    mut outlen: usize,
378    s: &mut [u64; 25],
379    mut pos: usize,
380    r: usize,
381) -> usize {
382    while outlen != 0 {
383        if pos == r {
384            keccakf1600_statepermute(s);
385            pos = 0;
386        }
387        let mut i = pos;
388        let mut idx = 0;
389        while i < r && i < pos + outlen {
390            // println!("i = {}", i);
391            // println!("out[idx] przed przypisaniem: {}", out[idx]);
392            out[idx] = (s[i / 8] >> 8 * (i % 8)) as u8;
393            // println!("out[idx] po przypisaniu: {}", out[idx]);
394            idx += 1;
395            i += 1;
396        }
397        outlen -= i - pos;
398        pos = i;
399    }
400
401    return pos;
402}
403
404/// Absorb step of Keccak; non-incremental, starts by zeroeing the state.
405fn keccak_absorb_once(s: &mut [u64; 25], r: usize, input: &[u8], mut inlen: usize, p: u8) {
406    s.fill(0);
407    let mut idx = 0;
408    while inlen >= r {
409        for i in 0..r / 8 {
410            s[i] ^= load64(&input[idx + 8 * i..]);
411        }
412        idx += r;
413        inlen -= r;
414        keccakf1600_statepermute(s);
415    }
416
417    for i in 0..inlen {
418        s[i / 8] ^= (input[idx + i] as u64) << 8 * (i % 8);
419    }
420
421    s[inlen / 8] ^= (p as u64) << 8 * (inlen % 8);
422    s[(r - 1) / 8] ^= 1u64 << 63;
423}
424
425/// Squeeze step of Keccak. Squeezes full blocks of r bytes each.
426/// Modifies the state. Can be called multiple times to keep squeezing, i.e., is incremental.
427/// Assumes zero bytes of current block have already been squeezed.
428fn keccak_squeezeblocks(out: &mut [u8], mut nblocks: usize, s: &mut [u64], r: usize) {
429    let mut idx = 0usize;
430    while nblocks > 0 {
431        keccakf1600_statepermute(s);
432        for i in 0..(r >> 3) {
433            store64(&mut out[idx + 8 * i..], s[i])
434        }
435        idx += r;
436        nblocks -= 1;
437    }
438}
439
440/// Absorb step of the SHAKE128 XOF; incremental.
441pub fn shake128_absorb(state: &mut KeccakState, input: &[u8], inlen: usize) {
442    keccak_absorb(state, SHAKE128_RATE, input, inlen);
443}
444
445/// Finalize absorb step of the SHAKE128 XOF.
446pub fn shake128_finalize(state: &mut KeccakState) {
447    keccak_finalize(&mut state.s, state.pos as usize, SHAKE128_RATE, 0x1F);
448    state.pos = SHAKE128_RATE;
449}
450
451/// Squeeze step of SHAKE128 XOF. Squeezes full blocks of SHAKE128_RATE bytes each.
452/// Can be called multiple times to keep squeezing.
453/// Assumes new block has not yet been started (state->pos = SHAKE128_RATE).
454pub fn shake128_squeezeblocks(output: &mut [u8], nblocks: usize, s: &mut KeccakState) {
455    keccak_squeezeblocks(output, nblocks, &mut s.s, SHAKE128_RATE);
456}
457
458/// Absorb step of the SHAKE256 XOF; incremental.
459pub fn shake256_absorb(state: &mut KeccakState, input: &[u8], inlen: usize) {
460    keccak_absorb(state, SHAKE256_RATE, input, inlen);
461}
462
463/// Finalize absorb step of the SHAKE256 XOF.
464pub fn shake256_finalize(state: &mut KeccakState) {
465    keccak_finalize(&mut state.s, state.pos, SHAKE256_RATE, 0x1F);
466    state.pos = SHAKE256_RATE;
467}
468
469/// Squeeze step of SHAKE256 XOF. Squeezes arbitraily many bytes.
470/// Can be called multiple times to keep squeezing.
471pub fn shake256_squeeze(out: &mut [u8], outlen: usize, state: &mut KeccakState) {
472    state.pos = keccak_squeeze(out, outlen, &mut state.s, state.pos, SHAKE256_RATE);
473}
474
475/// Initialize, absorb into and finalize SHAKE256 XOF; non-incremental.
476pub fn shake256_absorb_once(state: &mut KeccakState, input: &[u8], inlen: usize) {
477    keccak_absorb_once(&mut state.s, SHAKE256_RATE, input, inlen, 0x1F);
478    state.pos = SHAKE256_RATE;
479}
480
481/// Squeeze step of SHAKE256 XOF. Squeezes full blocks of SHAKE256_RATE bytes each.
482/// Can be called multiple times to keep squeezing.
483/// Assumes next block has not yet been started (state.pos = SHAKE256_RATE).
484pub fn shake256_squeezeblocks(out: &mut [u8], nblocks: usize, state: &mut KeccakState) {
485    keccak_squeezeblocks(out, nblocks, &mut state.s, SHAKE256_RATE);
486}
487
488/// SHAKE256 XOF with non-incremental API
489pub fn shake256(output: &mut [u8], mut outlen: usize, input: &[u8], inlen: usize) {
490    let mut state = KeccakState::default();
491
492    shake256_absorb_once(&mut state, input, inlen);
493    let nblocks = outlen / SHAKE256_RATE;
494    shake256_squeezeblocks(output, nblocks, &mut state);
495    outlen -= nblocks * SHAKE256_RATE;
496    let idx = nblocks * SHAKE256_RATE;
497    shake256_squeeze(&mut output[idx..], outlen, &mut state);
498}
499
500pub fn shake128_stream_init(state: &mut KeccakState, seed: &[u8], nonce: u16) {
501    let t = [nonce as u8, (nonce >> 8) as u8];
502    state.init();
503    shake128_absorb(state, seed, crate::params_dilithium5::SEEDBYTES);
504    shake128_absorb(state, &t, 2);
505    shake128_finalize(state);
506}
507
508pub fn shake256_stream_init(state: &mut KeccakState, seed: &[u8], nonce: u16) {
509    let t = [nonce as u8, (nonce >> 8) as u8];
510    state.init();
511    shake256_absorb(state, seed, crate::params_dilithium5::CRHBYTES);
512    shake256_absorb(state, &t, 2);
513    shake256_finalize(state);
514}