• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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