1 /*
2 * This file is part of the openHiTLS project.
3 *
4 * openHiTLS is licensed under the Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *
8 * http://license.coscl.org.cn/MulanPSL2
9 *
10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13 * See the Mulan PSL v2 for more details.
14 */
15
16 #include "hitls_build.h"
17 #ifdef HITLS_CRYPTO_SHA3
18
19 #include <stdlib.h>
20 #include "securec.h"
21 #include "crypt_errno.h"
22 #include "crypt_utils.h"
23 #include "bsl_err_internal.h"
24 #include "crypt_sha3.h"
25
26 #ifdef __cplusplus
27 extern "C" {
28 #endif /* __cpluscplus */
29
30 static void SHA3_Keccak(uint8_t *state);
31 static void Round(const uint64_t *a, uint64_t *e, uint32_t i);
32
33 #define ROL64(a, offset) ((((uint64_t)(a)) << (offset)) ^ (((uint64_t)(a)) >> (64 - (offset))))
34
35 // the rotation offsets, see https://keccak.team/keccak_specs_summary.html
36 static const uint8_t g_rotationOffset[5][5] = {
37 { 0, 1, 62, 28, 27 },
38 { 36, 44, 6, 55, 20 },
39 { 3, 10, 43, 25, 39 },
40 { 41, 45, 15, 21, 8 },
41 { 18, 2, 61, 56, 14 }
42 };
43
44 // the round constants, see https://keccak.team/keccak_specs_summary.html
45 static const uint64_t g_roundConstant[24] = {
46 (uint64_t)0x0000000000000001, (uint64_t)0x0000000000008082,
47 (uint64_t)0x800000000000808a, (uint64_t)0x8000000080008000,
48 (uint64_t)0x000000000000808b, (uint64_t)0x0000000080000001,
49 (uint64_t)0x8000000080008081, (uint64_t)0x8000000000008009,
50 (uint64_t)0x000000000000008a, (uint64_t)0x0000000000000088,
51 (uint64_t)0x0000000080008009, (uint64_t)0x000000008000000a,
52 (uint64_t)0x000000008000808b, (uint64_t)0x800000000000008b,
53 (uint64_t)0x8000000000008089, (uint64_t)0x8000000000008003,
54 (uint64_t)0x8000000000008002, (uint64_t)0x8000000000000080,
55 (uint64_t)0x000000000000800a, (uint64_t)0x800000008000000a,
56 (uint64_t)0x8000000080008081, (uint64_t)0x8000000000008080,
57 (uint64_t)0x0000000080000001, (uint64_t)0x8000000080008008
58 };
59
60 // Absorbing function of the sponge structure
SHA3_Absorb(uint8_t * state,const uint8_t * in,uint32_t inLen,uint32_t r)61 const uint8_t *SHA3_Absorb(uint8_t *state, const uint8_t *in, uint32_t inLen, uint32_t r)
62 {
63 const uint8_t *data = (const uint8_t *)in;
64 uint64_t *pSt = (uint64_t *)state;
65 uint32_t dataLen = inLen;
66 // Divide one block data into some uint64_t data (8 bytes) and perform XOR with the status variable.
67 uint32_t blockInWord = r / 8;
68
69 while (dataLen >= r) {
70 for (uint32_t i = 0; i < blockInWord; i++) {
71 uint64_t oneLane = GET_UINT64_LE(data, i << 3);
72 pSt[i] ^= oneLane;
73 }
74
75 // Process one block data.
76 SHA3_Keccak(state);
77 dataLen -= r;
78 data += r;
79 }
80
81 return (const uint8_t *)data;
82 }
83
84 // Squeezing function of the sponge structure
SHA3_Squeeze(uint8_t * state,uint8_t * out,uint32_t outLen,uint32_t r,bool isNeedKeccak)85 void SHA3_Squeeze(uint8_t *state, uint8_t *out, uint32_t outLen, uint32_t r, bool isNeedKeccak)
86 {
87 uint32_t dataLen = outLen;
88 uint32_t copyLen;
89 // Divide one block data into some uint64_t data (8 bytes) and perform XOR with the status variable.
90 uint32_t blockInWord = r / 8;
91 uint64_t *oneLane = (uint64_t *)state;
92 uint8_t outTmp[168];
93
94 while (dataLen > 0) {
95 copyLen = (dataLen > r) ? r : dataLen;
96
97 for (uint32_t i = 0; i < blockInWord; i++) {
98 PUT_UINT64_LE(oneLane[i], outTmp, i << 3); // left shift by 3 bits equals i * 8.
99 }
100 (void)memcpy_s(out + outLen - dataLen, dataLen, outTmp, copyLen);
101 dataLen -= copyLen;
102 if (dataLen > 0 || isNeedKeccak) {
103 SHA3_Keccak(state);
104 }
105 }
106 }
107
SHA3_Keccak(uint8_t * state)108 static void SHA3_Keccak(uint8_t *state)
109 {
110 uint8_t stTmp[200] = {0};
111
112 // See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
113 // SHA3 depends on keccak-p[1600,24] for 24 rounds of cyclic calculation.
114 for (uint32_t i = 0; i < 24; i += 2) {
115 Round((uint64_t *)state, (uint64_t *)stTmp, i);
116 Round((uint64_t *)stTmp, (uint64_t *)state, i + 1);
117 }
118 }
119
120 // see section 2.4 Algorithm 1 in https://keccak.team/files/Keccak-implementation-3.2.pdf
Round(const uint64_t * a,uint64_t * e,uint32_t i)121 static void Round(const uint64_t *a, uint64_t *e, uint32_t i)
122 {
123 uint64_t c[5], d[5];
124
125 // The corresponding formula for calculating the indexes of array A and array E is (5 * x) + y,
126 // the value of x is in [0, 4] and the value of y is [0, 4].
127 // The row coordinates of the array index correspond to y in the algorithm principle,
128 // and the column coordinates correspond to x in the algorithm principle, for example, A[1, 1] = A[5 * 1 + 1] = A[6]
129 // THETA operation
130 c[0] = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20];
131 c[1] = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21];
132 c[2] = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22];
133 c[3] = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23];
134 c[4] = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24];
135
136 d[0] = ROL64(c[1], 1) ^ c[4];
137 d[1] = ROL64(c[2], 1) ^ c[0];
138 d[2] = ROL64(c[3], 1) ^ c[1];
139 d[3] = ROL64(c[4], 1) ^ c[2];
140 d[4] = ROL64(c[0], 1) ^ c[3];
141
142 // THETA RHP Pi operation
143 c[0] = a[0] ^ d[0];
144 c[1] = ROL64(a[6] ^ d[1], g_rotationOffset[1][1]);
145 c[2] = ROL64(a[12] ^ d[2], g_rotationOffset[2][2]);
146 c[3] = ROL64(a[18] ^ d[3], g_rotationOffset[3][3]);
147 c[4] = ROL64(a[24] ^ d[4], g_rotationOffset[4][4]);
148
149 // CHI IOTA operation,
150 e[0] = c[0] ^ (~c[1] & c[2]) ^ g_roundConstant[i];
151 // CHI operation
152 e[1] = c[1] ^ (~c[2] & c[3]);
153 e[2] = c[2] ^ (~c[3] & c[4]);
154 e[3] = c[3] ^ (~c[4] & c[0]);
155 e[4] = c[4] ^ (~c[0] & c[1]);
156
157 // THETA RHP Pi operation
158 c[0] = ROL64(a[3] ^ d[3], g_rotationOffset[0][3]);
159 c[1] = ROL64(a[9] ^ d[4], g_rotationOffset[1][4]);
160 c[2] = ROL64(a[10] ^ d[0], g_rotationOffset[2][0]);
161 c[3] = ROL64(a[16] ^ d[1], g_rotationOffset[3][1]);
162 c[4] = ROL64(a[22] ^ d[2], g_rotationOffset[4][2]);
163
164 // CHI operation
165 e[5] = c[0] ^ (~c[1] & c[2]);
166 e[6] = c[1] ^ (~c[2] & c[3]);
167 e[7] = c[2] ^ (~c[3] & c[4]);
168 e[8] = c[3] ^ (~c[4] & c[0]);
169 e[9] = c[4] ^ (~c[0] & c[1]);
170
171 // THETA RHP Pi operation
172 c[0] = ROL64(a[1] ^ d[1], g_rotationOffset[0][1]);
173 c[1] = ROL64(a[7] ^ d[2], g_rotationOffset[1][2]);
174 c[2] = ROL64(a[13] ^ d[3], g_rotationOffset[2][3]);
175 c[3] = ROL64(a[19] ^ d[4], g_rotationOffset[3][4]);
176 c[4] = ROL64(a[20] ^ d[0], g_rotationOffset[4][0]);
177
178 // CHI operation
179 e[10] = c[0] ^ (~c[1] & c[2]);
180 e[11] = c[1] ^ (~c[2] & c[3]);
181 e[12] = c[2] ^ (~c[3] & c[4]);
182 e[13] = c[3] ^ (~c[4] & c[0]);
183 e[14] = c[4] ^ (~c[0] & c[1]);
184
185 // THETA RHP Pi operation
186 c[0] = ROL64(a[4] ^ d[4], g_rotationOffset[0][4]);
187 c[1] = ROL64(a[5] ^ d[0], g_rotationOffset[1][0]);
188 c[2] = ROL64(a[11] ^ d[1], g_rotationOffset[2][1]);
189 c[3] = ROL64(a[17] ^ d[2], g_rotationOffset[3][2]);
190 c[4] = ROL64(a[23] ^ d[3], g_rotationOffset[4][3]);
191
192 // CHI operation
193 e[15] = c[0] ^ (~c[1] & c[2]);
194 e[16] = c[1] ^ (~c[2] & c[3]);
195 e[17] = c[2] ^ (~c[3] & c[4]);
196 e[18] = c[3] ^ (~c[4] & c[0]);
197 e[19] = c[4] ^ (~c[0] & c[1]);
198
199 // THETA RHP Pi operation
200 c[0] = ROL64(a[2] ^ d[2], g_rotationOffset[0][2]);
201 c[1] = ROL64(a[8] ^ d[3], g_rotationOffset[1][3]);
202 c[2] = ROL64(a[14] ^ d[4], g_rotationOffset[2][4]);
203 c[3] = ROL64(a[15] ^ d[0], g_rotationOffset[3][0]);
204 c[4] = ROL64(a[21] ^ d[1], g_rotationOffset[4][1]);
205
206 // CHI operation
207 e[20] = c[0] ^ (~c[1] & c[2]);
208 e[21] = c[1] ^ (~c[2] & c[3]);
209 e[22] = c[2] ^ (~c[3] & c[4]);
210 e[23] = c[3] ^ (~c[4] & c[0]);
211 e[24] = c[4] ^ (~c[0] & c[1]);
212 }
213
214 #ifdef __cplusplus
215 }
216 #endif
217
218 #endif // HITLS_CRYPTO_SHA3
219