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
103static const uint64_t sha512_h0[8] = {
104  0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
105  0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
106  0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
107  0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL};
108
109static 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
154void 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
172static 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
266void 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
299uint8_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
339uint8_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