v2 / vlib / x / crypto / ascon / ascon.v
133 lines · 121 sloc · 4.32 KB · 50d03eb7b93bcdcfa90a43fc6cfa68916f38d28e
Raw
1// Copyright ©2025 blackshirt.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4//
5module ascon
6
7// max_nr_perm is the maximum number of permutations round supported on this module.
8// The previous Ascon submission defined three Ascon permutations with 6, 8, and 12 rounds.
9// The NIST SP 800-232 standard specifies additional Ascon permutations by providing round
10// constants for up to 16 rounds to accommodate potential functionality extensions in the future.
11const max_nr_perm = 16
12
13// The number how many round(s) for the Ascon permutation routine called.
14enum PrndEnum {
15 ascon_prnd_6 = 6
16 ascon_prnd_8 = 8
17 ascon_prnd_12 = 12
18}
19
20// The constants to derive round constants of the Ascon permutations
21// See Table 5. of NIST SP 800-232 docs
22//
23// 0 0x000000000000003c 8 0x00000000000000b4
24// 1 0x000000000000002d 9 0x00000000000000a5
25// 2 0x000000000000001e 10 0x0000000000000096
26// 3 0x000000000000000f 11 0x0000000000000087
27// 4 0x00000000000000f0 12 0x0000000000000078
28// 5 0x00000000000000e1 13 0x0000000000000069
29// 6 0x00000000000000d2 14 0x000000000000005a
30// 7 0x00000000000000c3 15 0x000000000000004b
31//
32// We use u8 instead, since the first 56 bits of the constants are zero
33const rnc = [u8(0x3c), 0x2d, 0x1e, 0x0f, 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, 0x78,
34 0x69, 0x5a, 0x4b]
35
36// ascon_pnr is the core of Ascon family permutation routine with specified numbers of round nr, where 1 ≤ nr ≤ 16
37// Its consist of iterations of the round function that is defined as the composition of three steps, ie:
38// 1. the constant-addition layer (see Sec. 3.2),
39// 2. the substitution layer (see Sec.3.3), and,
40// 3. the linear diffusion layer (Sec 3.4)
41@[direct_array_access]
42fn ascon_pnr(mut s State, nr PrndEnum) {
43 // Allocate temporary vars to reduce allocation within loop
44 mut x0 := u64(0)
45 mut y0 := u64(0)
46 // Ascon permutation routine
47 for i := max_nr_perm - int(nr); i < max_nr_perm; i++ {
48 // 3.2 Constant-Addition Layer step
49 //
50 // The constant-addition layer adds a 64-bit round constant 𝑐𝑖
51 // to 𝑆₂ in round 𝑖, for 𝑖 ≥ 0, ie, this is equivalent to applying
52 // the constant to only the least significant eight bits of 𝑆₂
53 s.e2 ^= rnc[i]
54
55 // 3.3. Substitution Layer
56 // The substitution layer updates the state S with 64 parallel applications of the 5-bit
57 // substitution box SBOX
58 s.e0 ^= s.e4
59 s.e4 ^= s.e3
60 s.e2 ^= s.e1
61
62 // Set temp vars to values
63 x0 = s.e0
64 y0 = s.e4 ^ (~s.e0 & s.e1)
65
66 s.e0 = s.e0 ^ (~s.e1 & s.e2) // t1
67 s.e1 = s.e1 ^ (~s.e2 & s.e3) // t2
68 s.e2 = s.e2 ^ (~s.e3 & s.e4) // t3
69 s.e3 = s.e3 ^ (~s.e4 & x0) // t4, change s.e0 to x0
70 s.e4 = y0
71
72 s.e1 ^= s.e0
73 s.e0 ^= s.e4
74 s.e3 ^= s.e2
75 s.e2 = ~(s.e2)
76
77 // 3.4. Linear Diffusion Layer
78 //
79 // The linear diffusion layer provides diffusion within each 64-bit word S,
80 // defined as :
81 // Σ0(𝑆0) = 𝑆0 ⊕ (𝑆0 ⋙ 19) ⊕ (𝑆0 ⋙ 28)
82 // Σ1(𝑆1) = 𝑆1 ⊕ (𝑆1 ⋙ 61) ⊕ (𝑆1 ⋙ 39)
83 // Σ2(𝑆2) = 𝑆2 ⊕ (𝑆2 ⋙ 1) ⊕ (𝑆2 ⋙ 6)
84 // Σ3(𝑆3) = 𝑆3 ⊕ (𝑆3 ⋙ 10) ⊕ (𝑆3 ⋙ 17)
85 // Σ4(𝑆4) = 𝑆4 ⊕ (𝑆4 ⋙ 7) ⊕ (𝑆4 ⋙ 41)
86 //
87 // This diffusion layer, especially on the bits right rotation part is a most widely called
88 // for Ascon permutation routine. So, even bits rotation almost efficient on most platform,
89 // to reduce overhead on function call, we work on the raw bits right rotation here.
90 // Bits right rotation, basically can be defined as:
91 // ror = (x >> n) | x << (64 - n) for some u64 x
92 //
93 s.e0 ^= (s.e0 >> 19 | s.e0 << 45) ^ (s.e0 >> 28 | s.e0 << 36)
94 s.e1 ^= (s.e1 >> 61 | s.e1 << 3) ^ (s.e1 >> 39 | s.e1 << 25)
95 s.e2 ^= (s.e2 >> 1 | s.e2 << 63) ^ (s.e2 >> 6 | s.e2 << 58)
96 s.e3 ^= (s.e3 >> 10 | s.e3 << 54) ^ (s.e3 >> 17 | s.e3 << 47)
97 s.e4 ^= (s.e4 >> 7 | s.e4 << 57) ^ (s.e4 >> 41 | s.e4 << 23)
98 }
99}
100
101// State is structure represents Ascon state. Its operates on the 320-bit opaque,
102// which is represented as five of 64-bit words.
103@[noinit]
104struct State {
105mut:
106 e0 u64
107 e1 u64
108 e2 u64
109 e3 u64
110 e4 u64
111}
112
113// clone returns a clone of current state.
114@[inline]
115fn clone_state(s State) State {
116 return State{
117 e0: s.e0
118 e1: s.e1
119 e2: s.e2
120 e3: s.e3
121 e4: s.e4
122 }
123}
124
125// reset this state with default value
126@[inline]
127fn reset_state(mut s State) {
128 s.e0 = 0
129 s.e1 = 0
130 s.e2 = 0
131 s.e3 = 0
132 s.e4 = 0
133}
134