v / vlib / crypto / sha3 / sha3_state_generic.v
197 lines · 173 sloc · 6.28 KB · 4b7955afe528e233a43f8586b923529e6d28c391
Raw
1// Copyright (c) 2023 Kim Shrier. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4// Package sha3 implements the 512, 384, 256, and 224
5// bit hash algorithms and the 128 and 256 bit
6// extended output functions as defined in
7// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf.
8// Last updated: August 2015
9module sha3
10
11import math.bits
12
13// when the state is 1600 bits, a lane is 64 bits
14type Lane = u64
15
16// the state is a 5 x 5 array of lanes
17struct State {
18mut:
19 a [5][5]Lane
20}
21
22@[direct_array_access; inline]
23fn read_u64_le_at(b []u8, offset int) u64 {
24 _ = b[offset]
25 _ = b[offset + 7]
26 return u64(b[offset]) | (u64(b[offset + 1]) << 8) | (u64(b[offset + 2]) << 16) | (u64(b[
27 offset + 3]) << 24) | (u64(b[offset + 4]) << 32) | (u64(b[offset + 5]) << 40) | (u64(b[
28 offset + 6]) << 48) | (u64(b[offset + 7]) << 56)
29}
30
31@[direct_array_access; inline]
32fn put_u64_le_at(mut b []u8, value u64, offset int) {
33 _ = b[offset]
34 _ = b[offset + 7]
35 b[offset] = u8(value)
36 b[offset + 1] = u8(value >> 8)
37 b[offset + 2] = u8(value >> 16)
38 b[offset + 3] = u8(value >> 24)
39 b[offset + 4] = u8(value >> 32)
40 b[offset + 5] = u8(value >> 40)
41 b[offset + 6] = u8(value >> 48)
42 b[offset + 7] = u8(value >> 56)
43}
44
45// to_bytes converts the state into a byte array
46//
47// A 1600 bit state fits into 200 bytes.
48//
49// The state consists of 25 u64 values arranged in a
50// 5 x 5 array.
51//
52// The state is not modified by this method.
53@[direct_array_access]
54fn (s State) to_bytes() []u8 {
55 mut byte_array := []u8{len: 200}
56 mut index := 0
57
58 for y in 0 .. 5 {
59 for x in 0 .. 5 {
60 put_u64_le_at(mut byte_array, s.a[x][y], index)
61 index += 8
62 }
63 }
64
65 return byte_array
66}
67
68// from_bytes sets the state from an array of bytes
69//
70// A 1600 bit state fits into 200 bytes. It is expected
71// that the input byte array is 200 bytes long.
72//
73// All 25 u64 values are set from the input byte array.
74@[direct_array_access]
75fn (mut s State) from_bytes(byte_array []u8) {
76 mut index := 0
77
78 for y in 0 .. 5 {
79 for x in 0 .. 5 {
80 s.a[x][y] = read_u64_le_at(byte_array, index)
81 index += 8
82 }
83 }
84}
85
86// xor_bytes xor's an array of bytes into the state
87//
88// This is how new data gets absorbed into the sponge.
89//
90// It is expected that the length of the byte array is
91// the same as the rate. The rate is how many bytes
92// can be absorbed at one permutation of the state.
93//
94// The rate must be less than the size of the state
95// in bytes.
96@[direct_array_access]
97fn (mut s State) xor_bytes(byte_array []u8, rate int) {
98 mut index := 0
99
100 for y in 0 .. 5 {
101 for x in 0 .. 5 {
102 s.a[x][y] ^= read_u64_le_at(byte_array, index)
103 index += 8
104
105 if index >= rate {
106 return
107 }
108 }
109 }
110}
111
112// kaccak_p_1600_24 performs 24 rounnds on a 1600 bit state.
113//
114@[direct_array_access]
115fn (mut s State) kaccak_p_1600_24() {
116 mut b := [5][5]Lane{}
117 for round_index in 0 .. 24 {
118 // theta
119 // C[x] = A[x,0] xor A[x,1] xor A[x,2] xor A[x,3] xor A[x,4], for x in 0…4
120 // D[x] = C[x-1] xor rot(C[x+1],1), for x in 0…4
121 // A[x,y] = A[x,y] xor D[x], for (x,y) in (0…4,0…4)
122 c0 := s.a[0][0] ^ s.a[0][1] ^ s.a[0][2] ^ s.a[0][3] ^ s.a[0][4]
123 c1 := s.a[1][0] ^ s.a[1][1] ^ s.a[1][2] ^ s.a[1][3] ^ s.a[1][4]
124 c2 := s.a[2][0] ^ s.a[2][1] ^ s.a[2][2] ^ s.a[2][3] ^ s.a[2][4]
125 c3 := s.a[3][0] ^ s.a[3][1] ^ s.a[3][2] ^ s.a[3][3] ^ s.a[3][4]
126 c4 := s.a[4][0] ^ s.a[4][1] ^ s.a[4][2] ^ s.a[4][3] ^ s.a[4][4]
127
128 d0 := c4 ^ bits.rotate_left_64(c1, 1)
129 d1 := c0 ^ bits.rotate_left_64(c2, 1)
130 d2 := c1 ^ bits.rotate_left_64(c3, 1)
131 d3 := c2 ^ bits.rotate_left_64(c4, 1)
132 d4 := c3 ^ bits.rotate_left_64(c0, 1)
133
134 // vfmt off
135 s.a[0][0] ^= d0 s.a[0][1] ^= d0 s.a[0][2] ^= d0 s.a[0][3] ^= d0 s.a[0][4] ^= d0
136 s.a[1][0] ^= d1 s.a[1][1] ^= d1 s.a[1][2] ^= d1 s.a[1][3] ^= d1 s.a[1][4] ^= d1
137 s.a[2][0] ^= d2 s.a[2][1] ^= d2 s.a[2][2] ^= d2 s.a[2][3] ^= d2 s.a[2][4] ^= d2
138 s.a[3][0] ^= d3 s.a[3][1] ^= d3 s.a[3][2] ^= d3 s.a[3][3] ^= d3 s.a[3][4] ^= d3
139 s.a[4][0] ^= d4 s.a[4][1] ^= d4 s.a[4][2] ^= d4 s.a[4][3] ^= d4 s.a[4][4] ^= d4
140 // vfmt on
141
142 // rho and pi
143 // B[y,2*x+3*y] = rot(A[x,y], r[x,y]), for (x,y) in (0…4,0…4)
144 b[0][0] = s.a[0][0]
145 b[0][1] = bits.rotate_left_64(s.a[3][0], 28)
146 b[0][2] = bits.rotate_left_64(s.a[1][0], 1)
147 b[0][3] = bits.rotate_left_64(s.a[4][0], 27)
148 b[0][4] = bits.rotate_left_64(s.a[2][0], 62)
149
150 b[1][0] = bits.rotate_left_64(s.a[1][1], 44)
151 b[1][1] = bits.rotate_left_64(s.a[4][1], 20)
152 b[1][2] = bits.rotate_left_64(s.a[2][1], 6)
153 b[1][3] = bits.rotate_left_64(s.a[0][1], 36)
154 b[1][4] = bits.rotate_left_64(s.a[3][1], 55)
155
156 b[2][0] = bits.rotate_left_64(s.a[2][2], 43)
157 b[2][1] = bits.rotate_left_64(s.a[0][2], 3)
158 b[2][2] = bits.rotate_left_64(s.a[3][2], 25)
159 b[2][3] = bits.rotate_left_64(s.a[1][2], 10)
160 b[2][4] = bits.rotate_left_64(s.a[4][2], 39)
161
162 b[3][0] = bits.rotate_left_64(s.a[3][3], 21)
163 b[3][1] = bits.rotate_left_64(s.a[1][3], 45)
164 b[3][2] = bits.rotate_left_64(s.a[4][3], 8)
165 b[3][3] = bits.rotate_left_64(s.a[2][3], 15)
166 b[3][4] = bits.rotate_left_64(s.a[0][3], 41)
167
168 b[4][0] = bits.rotate_left_64(s.a[4][4], 14)
169 b[4][1] = bits.rotate_left_64(s.a[2][4], 61)
170 b[4][2] = bits.rotate_left_64(s.a[0][4], 18)
171 b[4][3] = bits.rotate_left_64(s.a[3][4], 56)
172 b[4][4] = bits.rotate_left_64(s.a[1][4], 2)
173
174 // chi
175 // A[x,y] = B[x,y] xor ((not B[x+1,y]) and B[x+2,y]), for (x,y) in (0…4,0…4)
176 for y in 0 .. 5 {
177 s.a[0][y] = b[0][y] ^ (~b[1][y] & b[2][y])
178 s.a[1][y] = b[1][y] ^ (~b[2][y] & b[3][y])
179 s.a[2][y] = b[2][y] ^ (~b[3][y] & b[4][y])
180 s.a[3][y] = b[3][y] ^ (~b[4][y] & b[0][y])
181 s.a[4][y] = b[4][y] ^ (~b[0][y] & b[1][y])
182 }
183
184 // iota
185 // A[0,0] = A[0,0] xor RC
186 s.a[0][0] ^= iota_round_constants[round_index]
187 }
188}
189
190// iota_round_constants are precomputed xor masks for the iota function
191const iota_round_constants = [u64(0x0000000000000001), 0x0000000000008082, 0x800000000000808a,
192 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, 0x8000000080008081,
193 0x8000000000008009, 0x000000000000008a, 0x0000000000000088, 0x0000000080008009,
194 0x000000008000000a, 0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
195 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, 0x000000000000800a,
196 0x800000008000000a, 0x8000000080008081, 0x8000000000008080, 0x0000000080000001,
197 0x8000000080008008]
198