1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License..
14 * Description: sha256 functions
15 */
16
17 #include "securec.h"
18 #include "sha256/sha256.h"
19
20 #ifdef __cplusplus
21 #if __cplusplus
22 extern "C" {
23 #endif
24 #endif
25
26 #define rotl(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
27 #define rotr(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
28
29 #define ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
30 #define maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
31 #define sigma_0(x) (rotr((x), 2) ^ rotr((x), 13) ^ rotr((x), 22))
32 #define sigma_1(x) (rotr((x), 6) ^ rotr((x), 11) ^ rotr((x), 25))
33 #define sigma0(x) (rotr((x), 7) ^ rotr((x), 18) ^ ((x) >> 3))
34 #define sigma1(x) (rotr((x), 17) ^ rotr((x), 19) ^ ((x) >> 10))
35
36 #define K_ARRAY_LEN 64
37 #define PADDING_ARRAY_LEN 64
38 #define H_SWAP_L_SHIFT 32
39 #define SHA256GUTS_BUF_LEN 64
40 #define BURNSTACK_BUF_LEN 128
41 #define SHIFT_15_8_WORD 8
42 #define SHIFT_23_16_WORD 16
43 #define SHIFT_31_24_WORD 24
44 #define SHA256_UNROLL_1 1
45 #define SHA256_UNROLL_2 2
46 #define SHA256_UNROLL_4 4
47 #define SHA256_UNROLL_8 8
48 #define SHA256_UNROLL_16 16
49 #define SHA256_UNROLL_32 32
50 #define SHA256_UNROLL_64 64
51
52 #define SC_HASH_INDEX2 2
53 #define SC_HASH_INDEX3 3
54 #define SC_HASH_INDEX4 4
55 #define SC_HASH_INDEX5 5
56 #define SC_HASH_INDEX6 6
57 #define SC_HASH_INDEX7 7
58
59 #define BUF_INDEX1 9
60 #define BUF_INDEX2 14
61
62 #define BURN_PARAMETER_INDEX1 74
63 #define BURN_PARAMETER_INDEX2 6
64
65
66 #define do_round() do { \
67 t1 = h + sigma_1(e) + ch(e, f, g) + *(kp++) + *(w++); \
68 t2 = sigma_0(a) + maj(a, b, c); \
69 h = g, g = f, f = e; \
70 e = d + t1; \
71 d = c; \
72 c = b; \
73 b = a; \
74 a = t1 + t2; \
75 } while (0)
76
77 static const uint32_t g_k[K_ARRAY_LEN] = {
78 0x428a2f98L, 0x71374491L, 0xb5c0fbcfL, 0xe9b5dba5L,
79 0x3956c25bL, 0x59f111f1L, 0x923f82a4L, 0xab1c5ed5L,
80 0xd807aa98L, 0x12835b01L, 0x243185beL, 0x550c7dc3L,
81 0x72be5d74L, 0x80deb1feL, 0x9bdc06a7L, 0xc19bf174L,
82 0xe49b69c1L, 0xefbe4786L, 0x0fc19dc6L, 0x240ca1ccL,
83 0x2de92c6fL, 0x4a7484aaL, 0x5cb0a9dcL, 0x76f988daL,
84 0x983e5152L, 0xa831c66dL, 0xb00327c8L, 0xbf597fc7L,
85 0xc6e00bf3L, 0xd5a79147L, 0x06ca6351L, 0x14292967L,
86 0x27b70a85L, 0x2e1b2138L, 0x4d2c6dfcL, 0x53380d13L,
87 0x650a7354L, 0x766a0abbL, 0x81c2c92eL, 0x92722c85L,
88 0xa2bfe8a1L, 0xa81a664bL, 0xc24b8b70L, 0xc76c51a3L,
89 0xd192e819L, 0xd6990624L, 0xf40e3585L, 0x106aa070L,
90 0x19a4c116L, 0x1e376c08L, 0x2748774cL, 0x34b0bcb5L,
91 0x391c0cb3L, 0x4ed8aa4aL, 0x5b9cca4fL, 0x682e6ff3L,
92 0x748f82eeL, 0x78a5636fL, 0x84c87814L, 0x8cc70208L,
93 0x90befffaL, 0xa4506cebL, 0xbef9a3f7L, 0xc67178f2L
94 };
95
96 #ifndef RUNTIME_ENDIAN
97
98 #ifdef WORDS_BIGENDIAN
99
100 #define byte_swap(x) (x)
101 #define byte_swap_64(x) (x)
102
103 #else /* WORDS_BIGENDIAN */
104
105 #define byte_swap(x) ((rotr((x), 8) & 0xff00ff00L) | (rotl((x), 8) & 0x00ff00ffL))
106 #define byte_swap_64(x) _byteswap64(x)
107
_byteswap64(uint64_t x)108 static uint64_t _byteswap64(uint64_t x)
109 {
110 uint32_t a = (uint32_t)(x >> H_SWAP_L_SHIFT);
111 uint32_t b = (uint32_t)x;
112
113 return ((uint64_t)byte_swap(b) << H_SWAP_L_SHIFT) | (uint64_t)byte_swap(a);
114 }
115 #endif /* WORDS_BIGENDIAN */
116
117 #else /* !RUNTIME_ENDIAN */
118
119 #define byte_swap(x) _byteswap(sc->little_endian, x)
120 #define byte_swap_64(x) _byteswap64(sc->little_endian, x)
121
122 #define _byte_swap(x) ((rotr((x), 8) & 0xff00ff00L) | \
123 (rotl((x), 8) & 0x00ff00ffL))
124 #define _byte_swap64(x) __byteswap64(x)
125
__byteswap64(uint64_t x)126 static inline uint64_t __byteswap64(uint64_t x)
127 {
128 uint32_t a = x >> H_SWAP_L_SHIFT;
129 uint32_t b = (uint32_t)x;
130
131 return ((uint64_t)_byte_swap(b) << H_SWAP_L_SHIFT) | (uint64_t)_byte_swap(a);
132 }
133
_byteswap(int little_endian,uint32_t x)134 static inline uint32_t _byteswap(int little_endian, uint32_t x)
135 {
136 if (!little_endian) {
137 return x;
138 } else {
139 return _byte_swap(x);
140 }
141 }
142
_byte_swap_64(int little_endian,uint64_t x)143 static inline uint64_t _byte_swap_64(int little_endian, uint64_t x)
144 {
145 if (!little_endian) {
146 return x;
147 } else {
148 return _byte_swap_64(x);
149 }
150 }
151
set_endian(int * little_endianp)152 static inline void set_endian(int *little_endianp)
153 {
154 const uint8_t endian_bites_len = 4;
155 union {
156 uint32_t w;
157 uint8_t b[endian_bites_len];
158 } endian;
159
160 endian.w = 1L;
161 *little_endianp = endian.b[0] != 0;
162 }
163 #endif /* !RUNTIME_ENDIAN */
164
165 static const uint8_t g_padding[PADDING_ARRAY_LEN] = {
166 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
174 };
175
sha256_init(sha256_context_t * sc)176 void sha256_init(sha256_context_t *sc)
177 {
178 #ifdef RUNTIME_ENDIAN
179 set_endian(&sc->little_endian);
180 #endif /* RUNTIME_ENDIAN */
181
182 sc->total_length = 0LL;
183 sc->hash[0] = 0x6a09e667L;
184 sc->hash[1] = 0xbb67ae85L;
185 sc->hash[SC_HASH_INDEX2] = 0x3c6ef372L;
186 sc->hash[SC_HASH_INDEX3] = 0xa54ff53aL;
187 sc->hash[SC_HASH_INDEX4] = 0x510e527fL;
188 sc->hash[SC_HASH_INDEX5] = 0x9b05688cL;
189 sc->hash[SC_HASH_INDEX6] = 0x1f83d9abL;
190 sc->hash[SC_HASH_INDEX7] = 0x5be0cd19L;
191 sc->buffer_length = 0L;
192 }
193
burn_stack(int size)194 static void burn_stack(int size)
195 {
196 char buf[BURNSTACK_BUF_LEN];
197
198 (void)memset_s(buf, sizeof(buf), 0, sizeof(buf));
199 size -= (int)sizeof(buf);
200 if (size > 0) {
201 burn_stack(size);
202 }
203 }
204
SHA256Guts(sha256_context_t * sc,const uint32_t * cbuf)205 static void SHA256Guts(sha256_context_t *sc, const uint32_t *cbuf)
206 {
207 uint32_t buf[SHA256GUTS_BUF_LEN] = { 0 };
208 uint32_t *w = NULL;
209 uint32_t *w2 = NULL;
210 uint32_t *w7 = NULL;
211 uint32_t *w15 = NULL;
212 uint32_t *w16 = NULL;
213 uint32_t a, b, c, d, e, f, g, h;
214 uint32_t t1, t2;
215 const uint32_t *kp = NULL;
216 int i;
217
218 w = buf;
219
220 for (i = 0xF; i >= 0; i--) {
221 *(w++) = byte_swap(*cbuf);
222 cbuf++;
223 }
224
225 w16 = &buf[0];
226 w15 = &buf[1];
227 w7 = &buf[BUF_INDEX1];
228 w2 = &buf[BUF_INDEX2];
229
230 for (i = 0x2F; i >= 0; i--) {
231 *(w++) = sigma1(*w2) + *(w7++) + sigma0(*w15) + *(w16++);
232 w2++;
233 w15++;
234 }
235
236 a = sc->hash[0];
237 b = sc->hash[1];
238 c = sc->hash[SC_HASH_INDEX2];
239 d = sc->hash[SC_HASH_INDEX3];
240 e = sc->hash[SC_HASH_INDEX4];
241 f = sc->hash[SC_HASH_INDEX5];
242 g = sc->hash[SC_HASH_INDEX6];
243 h = sc->hash[SC_HASH_INDEX7];
244
245 kp = g_k;
246 w = buf;
247
248 #ifndef SHA256_UNROLL
249 #define SHA256_UNROLL 1
250 #endif /* !SHA256_UNROLL */
251
252 #if SHA256_UNROLL == SHA256_UNROLL_1
253 for (i = 0x3F; i >= 0; i--) {
254 do_round();
255 }
256
257 #elif SHA256_UNROLL == SHA256_UNROLL_2
258 for (i = 0x1F; i >= 0; i--) {
259 do_round();
260 do_round();
261 }
262
263 #elif SHA256_UNROLL == SHA256_UNROLL_4
264 for (i = 0xF; i >= 0; i--) {
265 do_round();
266 do_round();
267 do_round();
268 do_round();
269 }
270
271 #elif SHA256_UNROLL == SHA256_UNROLL_8
272 for (i = 0x7; i >= 0; i--) {
273 do_round();
274 do_round();
275 do_round();
276 do_round();
277 do_round();
278 do_round();
279 do_round();
280 do_round();
281 }
282
283 #elif SHA256_UNROLL == SHA256_UNROLL_16
284 for (i = 0x3; i >= 0; i--) {
285 do_round();
286 do_round();
287 do_round();
288 do_round();
289 do_round();
290 do_round();
291 do_round();
292 do_round();
293 do_round();
294 do_round();
295 do_round();
296 do_round();
297 do_round();
298 do_round();
299 do_round();
300 do_round();
301 }
302 #else
303 #error "SHA256_UNROLL must be 1, 2, 4, 8 or 16!"
304 #endif
305
306 sc->hash[0] += a;
307 sc->hash[1] += b;
308 sc->hash[SC_HASH_INDEX2] += c;
309 sc->hash[SC_HASH_INDEX3] += d;
310 sc->hash[SC_HASH_INDEX4] += e;
311 sc->hash[SC_HASH_INDEX5] += f;
312 sc->hash[SC_HASH_INDEX6] += g;
313 sc->hash[SC_HASH_INDEX7] += h;
314 }
315
SHA256Update(sha256_context_t * sc,const void * vdata,uint32_t len)316 void SHA256Update(sha256_context_t *sc, const void *vdata, uint32_t len)
317 {
318 const uint8_t *data = vdata;
319 uint32_t buffer_bytes_left, bytes_to_copy;
320 int need_burn = 0;
321
322 #ifdef SHA256_FAST_COPY
323 if (sc->buffer_length) {
324 buffer_bytes_left = 64L - sc->buffer_length;
325
326 bytes_to_copy = buffer_bytes_left;
327 if (bytes_to_copy > len) {
328 bytes_to_copy = len;
329 }
330
331 if (memcpy_s(&sc->buffer.bytes[sc->buffer_length], (64L - sc->buffer_length), data, bytes_to_copy) != EOK) {
332 return;
333 }
334 sc->total_length += bytes_to_copy * 8L;
335
336 sc->buffer_length += bytes_to_copy;
337 data += bytes_to_copy;
338 len -= bytes_to_copy;
339
340 if (sc->buffer_length == 64L) {
341 SHA256Guts(sc, sc->buffer.words);
342 need_burn = 1;
343 sc->buffer_length = 0L;
344 }
345 }
346
347 while (len > 63L) {
348 sc->total_length += 512L;
349
350 SHA256Guts(sc, data);
351 need_burn = 1;
352
353 data += 64L;
354 len -= 64L;
355 }
356
357 if (len) {
358 if (memcpy_s(&sc->buffer.bytes[sc->buffer_length], (64L - sc->buffer_length), data, len) != EOK) {
359 return;
360 }
361
362 sc->total_length += len * 8L;
363
364 sc->buffer_length += len;
365 }
366
367 #else /* SHA256_FAST_COPY */
368 while (len != 0) {
369 buffer_bytes_left = 64L - sc->buffer_length;
370
371 bytes_to_copy = buffer_bytes_left;
372 if (bytes_to_copy > len) {
373 bytes_to_copy = len;
374 }
375
376 if (memcpy_s(&sc->buffer.bytes[sc->buffer_length], (64L - sc->buffer_length), data, bytes_to_copy) != EOK) {
377 return;
378 }
379 sc->total_length += (uint64_t)(unsigned)(bytes_to_copy * 8L);
380
381 sc->buffer_length += bytes_to_copy;
382 data += bytes_to_copy;
383 len -= bytes_to_copy;
384
385 if (sc->buffer_length == 64L) {
386 SHA256Guts(sc, sc->buffer.words);
387 need_burn = 1;
388 sc->buffer_length = 0L;
389 }
390 }
391 #endif /* SHA256_FAST_COPY */
392
393 if (need_burn != 0) {
394 burn_stack(sizeof(uint32_t[BURN_PARAMETER_INDEX1]) +
395 sizeof(uint32_t *[BURN_PARAMETER_INDEX2]) + sizeof(int));
396 }
397 }
398
sha256_final(sha256_context_t * sc,uint8_t hash[SHA256_HASH_SIZE],uint32_t hash_len)399 void sha256_final(sha256_context_t *sc, uint8_t hash[SHA256_HASH_SIZE], uint32_t hash_len)
400 {
401 uint32_t bytes_to_pad;
402 uint64_t length_pad;
403 int i;
404 if (hash_len == 0) {
405 return;
406 }
407 bytes_to_pad = 120L - sc->buffer_length;
408 if (bytes_to_pad > 64L) {
409 bytes_to_pad -= 64L;
410 }
411
412 length_pad = byte_swap_64(sc->total_length);
413
414 SHA256Update(sc, g_padding, bytes_to_pad);
415 SHA256Update(sc, &length_pad, 8L);
416
417 if (hash) {
418 for (i = 0; i < SHA256_HASH_WORDS; i++) {
419 #ifdef SHA256_FAST_COPY
420 *((uint32_t *)hash) = byte_swap(sc->hash[i]);
421 #else /* SHA256_FAST_COPY */
422 hash[0] = (uint8_t)(sc->hash[i] >> SHIFT_31_24_WORD);
423 hash[1] = (uint8_t)(sc->hash[i] >> SHIFT_23_16_WORD);
424 hash[SC_HASH_INDEX2] = (uint8_t)(sc->hash[i] >> SHIFT_15_8_WORD);
425 hash[SC_HASH_INDEX3] = (uint8_t)sc->hash[i];
426 #endif /* SHA256_FAST_COPY */
427 hash += 4; // Pointer offset 4 bites per cycle
428 }
429 }
430 }
431
sha256_hash(const uint8_t * in_buff,uint32_t in_buff_len,uint8_t * out_buff,uint32_t out_buff_len)432 void sha256_hash(const uint8_t *in_buff, uint32_t in_buff_len, uint8_t *out_buff, uint32_t out_buff_len)
433 {
434 sha256_context_t foo;
435
436 sha256_init(&foo);
437 SHA256Update(&foo, in_buff, in_buff_len);
438 sha256_final(&foo, out_buff, out_buff_len);
439 }
440
441 #ifdef __cplusplus
442 #if __cplusplus
443 }
444 #endif
445 #endif
446