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