1 /* SHA-256 and SHA-512 implementation based on code by Oliver Gay
2 * <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
3 */
4
5 /*
6 * FIPS 180-2 SHA-224/256/384/512 implementation
7 * Last update: 02/02/2007
8 * Issue date: 04/30/2005
9 *
10 * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the project nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37
38 #include "sysincludes.h"
39
40 #include "cryptolib.h"
41 #include "utility.h"
42
43 #define SHFR(x, n) (x >> n)
44 #define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
45 #define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
46 #define CH(x, y, z) ((x & y) ^ (~x & z))
47 #define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
48
49 #define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
50 #define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
51 #define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7))
52 #define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6))
53
54 #define UNPACK32(x, str) \
55 { \
56 *((str) + 3) = (uint8_t) ((x) ); \
57 *((str) + 2) = (uint8_t) ((x) >> 8); \
58 *((str) + 1) = (uint8_t) ((x) >> 16); \
59 *((str) + 0) = (uint8_t) ((x) >> 24); \
60 }
61
62 #define UNPACK64(x, str) \
63 { \
64 *((str) + 7) = (uint8_t) x; \
65 *((str) + 6) = (uint8_t) ((uint64_t)x >> 8); \
66 *((str) + 5) = (uint8_t) ((uint64_t)x >> 16); \
67 *((str) + 4) = (uint8_t) ((uint64_t)x >> 24); \
68 *((str) + 3) = (uint8_t) ((uint64_t)x >> 32); \
69 *((str) + 2) = (uint8_t) ((uint64_t)x >> 40); \
70 *((str) + 1) = (uint8_t) ((uint64_t)x >> 48); \
71 *((str) + 0) = (uint8_t) ((uint64_t)x >> 56); \
72 }
73
74 #define PACK64(str, x) \
75 { \
76 *(x) = ((uint64_t) *((str) + 7) ) \
77 | ((uint64_t) *((str) + 6) << 8) \
78 | ((uint64_t) *((str) + 5) << 16) \
79 | ((uint64_t) *((str) + 4) << 24) \
80 | ((uint64_t) *((str) + 3) << 32) \
81 | ((uint64_t) *((str) + 2) << 40) \
82 | ((uint64_t) *((str) + 1) << 48) \
83 | ((uint64_t) *((str) + 0) << 56); \
84 }
85
86 /* Macros used for loops unrolling */
87
88 #define SHA512_SCR(i) \
89 { \
90 w[i] = SHA512_F4(w[i - 2]) + w[i - 7] \
91 + SHA512_F3(w[i - 15]) + w[i - 16]; \
92 }
93
94 #define SHA512_EXP(a, b, c, d, e, f, g ,h, j) \
95 { \
96 t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
97 + sha512_k[j] + w[j]; \
98 t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
99 wv[d] += t1; \
100 wv[h] = t1 + t2; \
101 }
102
103 static const uint64_t sha512_h0[8] = {
104 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
105 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
106 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
107 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL};
108
109 static const uint64_t sha512_k[80] = {
110 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
111 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
112 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
113 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
114 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
115 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
116 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
117 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
118 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
119 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
120 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
121 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
122 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
123 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
124 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
125 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
126 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
127 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
128 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
129 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
130 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
131 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
132 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
133 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
134 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
135 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
136 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
137 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
138 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
139 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
140 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
141 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
142 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
143 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
144 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
145 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
146 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
147 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
148 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
149 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
150
151
152 /* SHA-512 implementation */
153
SHA512_init(VB_SHA512_CTX * ctx)154 void SHA512_init(VB_SHA512_CTX *ctx) {
155 #ifdef UNROLL_LOOPS_SHA512
156 ctx->h[0] = sha512_h0[0]; ctx->h[1] = sha512_h0[1];
157 ctx->h[2] = sha512_h0[2]; ctx->h[3] = sha512_h0[3];
158 ctx->h[4] = sha512_h0[4]; ctx->h[5] = sha512_h0[5];
159 ctx->h[6] = sha512_h0[6]; ctx->h[7] = sha512_h0[7];
160 #else
161 int i;
162
163 for (i = 0; i < 8; i++)
164 ctx->h[i] = sha512_h0[i];
165 #endif /* UNROLL_LOOPS_SHA512 */
166
167 ctx->len = 0;
168 ctx->tot_len = 0;
169 }
170
171
SHA512_transform(VB_SHA512_CTX * ctx,const uint8_t * message,unsigned int block_nb)172 static void SHA512_transform(VB_SHA512_CTX* ctx, const uint8_t* message,
173 unsigned int block_nb) {
174 uint64_t w[80];
175 uint64_t wv[8];
176 uint64_t t1, t2;
177 const uint8_t *sub_block;
178 int i, j;
179
180 for (i = 0; i < (int) block_nb; i++) {
181 sub_block = message + (i << 7);
182
183 #ifdef UNROLL_LOOPS_SHA512
184 PACK64(&sub_block[ 0], &w[ 0]); PACK64(&sub_block[ 8], &w[ 1]);
185 PACK64(&sub_block[ 16], &w[ 2]); PACK64(&sub_block[ 24], &w[ 3]);
186 PACK64(&sub_block[ 32], &w[ 4]); PACK64(&sub_block[ 40], &w[ 5]);
187 PACK64(&sub_block[ 48], &w[ 6]); PACK64(&sub_block[ 56], &w[ 7]);
188 PACK64(&sub_block[ 64], &w[ 8]); PACK64(&sub_block[ 72], &w[ 9]);
189 PACK64(&sub_block[ 80], &w[10]); PACK64(&sub_block[ 88], &w[11]);
190 PACK64(&sub_block[ 96], &w[12]); PACK64(&sub_block[104], &w[13]);
191 PACK64(&sub_block[112], &w[14]); PACK64(&sub_block[120], &w[15]);
192
193 SHA512_SCR(16); SHA512_SCR(17); SHA512_SCR(18); SHA512_SCR(19);
194 SHA512_SCR(20); SHA512_SCR(21); SHA512_SCR(22); SHA512_SCR(23);
195 SHA512_SCR(24); SHA512_SCR(25); SHA512_SCR(26); SHA512_SCR(27);
196 SHA512_SCR(28); SHA512_SCR(29); SHA512_SCR(30); SHA512_SCR(31);
197 SHA512_SCR(32); SHA512_SCR(33); SHA512_SCR(34); SHA512_SCR(35);
198 SHA512_SCR(36); SHA512_SCR(37); SHA512_SCR(38); SHA512_SCR(39);
199 SHA512_SCR(40); SHA512_SCR(41); SHA512_SCR(42); SHA512_SCR(43);
200 SHA512_SCR(44); SHA512_SCR(45); SHA512_SCR(46); SHA512_SCR(47);
201 SHA512_SCR(48); SHA512_SCR(49); SHA512_SCR(50); SHA512_SCR(51);
202 SHA512_SCR(52); SHA512_SCR(53); SHA512_SCR(54); SHA512_SCR(55);
203 SHA512_SCR(56); SHA512_SCR(57); SHA512_SCR(58); SHA512_SCR(59);
204 SHA512_SCR(60); SHA512_SCR(61); SHA512_SCR(62); SHA512_SCR(63);
205 SHA512_SCR(64); SHA512_SCR(65); SHA512_SCR(66); SHA512_SCR(67);
206 SHA512_SCR(68); SHA512_SCR(69); SHA512_SCR(70); SHA512_SCR(71);
207 SHA512_SCR(72); SHA512_SCR(73); SHA512_SCR(74); SHA512_SCR(75);
208 SHA512_SCR(76); SHA512_SCR(77); SHA512_SCR(78); SHA512_SCR(79);
209
210 wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
211 wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
212 wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
213 wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
214
215 j = 0;
216
217 do {
218 SHA512_EXP(0,1,2,3,4,5,6,7,j); j++;
219 SHA512_EXP(7,0,1,2,3,4,5,6,j); j++;
220 SHA512_EXP(6,7,0,1,2,3,4,5,j); j++;
221 SHA512_EXP(5,6,7,0,1,2,3,4,j); j++;
222 SHA512_EXP(4,5,6,7,0,1,2,3,j); j++;
223 SHA512_EXP(3,4,5,6,7,0,1,2,j); j++;
224 SHA512_EXP(2,3,4,5,6,7,0,1,j); j++;
225 SHA512_EXP(1,2,3,4,5,6,7,0,j); j++;
226 } while (j < 80);
227
228 ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
229 ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
230 ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
231 ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
232 #else
233 for (j = 0; j < 16; j++) {
234 PACK64(&sub_block[j << 3], &w[j]);
235 }
236
237 for (j = 16; j < 80; j++) {
238 SHA512_SCR(j);
239 }
240
241 for (j = 0; j < 8; j++) {
242 wv[j] = ctx->h[j];
243 }
244
245 for (j = 0; j < 80; j++) {
246 t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
247 + sha512_k[j] + w[j];
248 t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
249 wv[7] = wv[6];
250 wv[6] = wv[5];
251 wv[5] = wv[4];
252 wv[4] = wv[3] + t1;
253 wv[3] = wv[2];
254 wv[2] = wv[1];
255 wv[1] = wv[0];
256 wv[0] = t1 + t2;
257 }
258
259 for (j = 0; j < 8; j++)
260 ctx->h[j] += wv[j];
261 #endif /* UNROLL_LOOPS_SHA512 */
262 }
263 }
264
265
SHA512_update(VB_SHA512_CTX * ctx,const uint8_t * data,uint32_t len)266 void SHA512_update(VB_SHA512_CTX* ctx, const uint8_t* data,
267 uint32_t len) {
268 unsigned int block_nb;
269 unsigned int new_len, rem_len, tmp_len;
270 const uint8_t* shifted_data;
271
272 tmp_len = SHA512_BLOCK_SIZE - ctx->len;
273 rem_len = len < tmp_len ? len : tmp_len;
274
275 Memcpy(&ctx->block[ctx->len], data, rem_len);
276
277 if (ctx->len + len < SHA512_BLOCK_SIZE) {
278 ctx->len += len;
279 return;
280 }
281
282 new_len = len - rem_len;
283 block_nb = new_len / SHA512_BLOCK_SIZE;
284
285 shifted_data = data + rem_len;
286
287 SHA512_transform(ctx, ctx->block, 1);
288 SHA512_transform(ctx, shifted_data, block_nb);
289
290 rem_len = new_len % SHA512_BLOCK_SIZE;
291
292 Memcpy(ctx->block, &shifted_data[block_nb << 7],
293 rem_len);
294
295 ctx->len = rem_len;
296 ctx->tot_len += (block_nb + 1) << 7;
297 }
298
SHA512_final(VB_SHA512_CTX * ctx)299 uint8_t* SHA512_final(VB_SHA512_CTX* ctx)
300 {
301 unsigned int block_nb;
302 unsigned int pm_len;
303 unsigned int len_b;
304
305 #ifndef UNROLL_LOOPS_SHA512
306 int i;
307 #endif
308
309 block_nb = 1 + ((SHA512_BLOCK_SIZE - 17)
310 < (ctx->len % SHA512_BLOCK_SIZE));
311
312 len_b = (ctx->tot_len + ctx->len) << 3;
313 pm_len = block_nb << 7;
314
315 Memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
316 ctx->block[ctx->len] = 0x80;
317 UNPACK32(len_b, ctx->block + pm_len - 4);
318
319 SHA512_transform(ctx, ctx->block, block_nb);
320
321 #ifdef UNROLL_LOOPS_SHA512
322 UNPACK64(ctx->h[0], &ctx->buf[ 0]);
323 UNPACK64(ctx->h[1], &ctx->buf[ 8]);
324 UNPACK64(ctx->h[2], &ctx->buf[16]);
325 UNPACK64(ctx->h[3], &ctx->buf[24]);
326 UNPACK64(ctx->h[4], &ctx->buf[32]);
327 UNPACK64(ctx->h[5], &ctx->buf[40]);
328 UNPACK64(ctx->h[6], &ctx->buf[48]);
329 UNPACK64(ctx->h[7], &ctx->buf[56]);
330 #else
331 for (i = 0 ; i < 8; i++)
332 UNPACK64(ctx->h[i], &ctx->buf[i << 3]);
333 #endif /* UNROLL_LOOPS_SHA512 */
334
335 return ctx->buf;
336 }
337
338
internal_SHA512(const uint8_t * data,uint64_t len,uint8_t * digest)339 uint8_t* internal_SHA512(const uint8_t* data, uint64_t len, uint8_t* digest) {
340 const uint8_t* input_ptr;
341 const uint8_t* result;
342 uint64_t remaining_len;
343 int i;
344 VB_SHA512_CTX ctx;
345 SHA512_init(&ctx);
346
347 input_ptr = data;
348 remaining_len = len;
349
350 /* Process data in at most UINT32_MAX byte chunks at a time. */
351 while (remaining_len) {
352 uint32_t block_size;
353 block_size = (uint32_t) ((remaining_len >= UINT32_MAX) ?
354 UINT32_MAX : remaining_len);
355 SHA512_update(&ctx, input_ptr, block_size);
356 remaining_len -= block_size;
357 input_ptr += block_size;
358 }
359
360 result = SHA512_final(&ctx);
361 for (i = 0; i < SHA512_DIGEST_SIZE; ++i) {
362 digest[i] = *result++;
363 }
364 return digest;
365 }
366