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