1 /* SHA-256 and SHA-512 implementation based on code by Oliver Gay
2 * <[email protected]> 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 <[email protected]>
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 "2common.h"
39 #include "2sha.h"
40 #include "2sysincludes.h"
41
42 #define SHFR(x, n) (x >> n)
43 #define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
44 #define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
45 #define CH(x, y, z) ((x & y) ^ (~x & z))
46 #define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
47
48 #define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
49 #define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
50 #define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7))
51 #define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6))
52
53 #define UNPACK32(x, str) \
54 { \
55 *((str) + 3) = (uint8_t) ((x) ); \
56 *((str) + 2) = (uint8_t) ((x) >> 8); \
57 *((str) + 1) = (uint8_t) ((x) >> 16); \
58 *((str) + 0) = (uint8_t) ((x) >> 24); \
59 }
60
61 #define UNPACK64(x, str) \
62 { \
63 *((str) + 7) = (uint8_t) x; \
64 *((str) + 6) = (uint8_t) ((uint64_t)x >> 8); \
65 *((str) + 5) = (uint8_t) ((uint64_t)x >> 16); \
66 *((str) + 4) = (uint8_t) ((uint64_t)x >> 24); \
67 *((str) + 3) = (uint8_t) ((uint64_t)x >> 32); \
68 *((str) + 2) = (uint8_t) ((uint64_t)x >> 40); \
69 *((str) + 1) = (uint8_t) ((uint64_t)x >> 48); \
70 *((str) + 0) = (uint8_t) ((uint64_t)x >> 56); \
71 }
72
73 #define PACK64(str, x) \
74 { \
75 *(x) = ((uint64_t) *((str) + 7) ) \
76 | ((uint64_t) *((str) + 6) << 8) \
77 | ((uint64_t) *((str) + 5) << 16) \
78 | ((uint64_t) *((str) + 4) << 24) \
79 | ((uint64_t) *((str) + 3) << 32) \
80 | ((uint64_t) *((str) + 2) << 40) \
81 | ((uint64_t) *((str) + 1) << 48) \
82 | ((uint64_t) *((str) + 0) << 56); \
83 }
84
85 /* Macros used for loops unrolling */
86
87 #define SHA512_SCR(i) \
88 { \
89 w[i] = SHA512_F4(w[i - 2]) + w[i - 7] \
90 + SHA512_F3(w[i - 15]) + w[i - 16]; \
91 }
92
93 #define SHA512_EXP(a, b, c, d, e, f, g ,h, j) \
94 { \
95 t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
96 + sha512_k[j] + w[j]; \
97 t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
98 wv[d] += t1; \
99 wv[h] = t1 + t2; \
100 }
101
102 static const uint64_t sha512_h0[8] = {
103 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
104 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
105 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
106 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
107 };
108
109 static const uint64_t sha384_h0[8] = {
110 0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL,
111 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL,
112 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL,
113 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL
114 };
115
116 static const uint64_t sha512_k[80] = {
117 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
118 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
119 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
120 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
121 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
122 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
123 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
124 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
125 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
126 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
127 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
128 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
129 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
130 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
131 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
132 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
133 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
134 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
135 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
136 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
137 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
138 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
139 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
140 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
141 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
142 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
143 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
144 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
145 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
146 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
147 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
148 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
149 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
150 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
151 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
152 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
153 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
154 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
155 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
156 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
157 };
158
159 /* SHA-512 implementation */
160
vb2_sha512_init(struct vb2_sha512_context * ctx,enum vb2_hash_algorithm algo)161 void vb2_sha512_init(struct vb2_sha512_context *ctx,
162 enum vb2_hash_algorithm algo)
163 {
164 const uint64_t *h0 = algo == VB2_HASH_SHA384 ? sha384_h0 : sha512_h0;
165
166 #ifdef UNROLL_LOOPS_SHA512
167 ctx->h[0] = h0[0]; ctx->h[1] = h0[1];
168 ctx->h[2] = h0[2]; ctx->h[3] = h0[3];
169 ctx->h[4] = h0[4]; ctx->h[5] = h0[5];
170 ctx->h[6] = h0[6]; ctx->h[7] = h0[7];
171 #else
172 int i;
173
174 for (i = 0; i < 8; i++)
175 ctx->h[i] = h0[i];
176 #endif /* UNROLL_LOOPS_SHA512 */
177
178 ctx->size = 0;
179 ctx->total_size = 0;
180 }
181
vb2_sha512_transform(struct vb2_sha512_context * ctx,const uint8_t * message,unsigned int block_nb)182 static void vb2_sha512_transform(struct vb2_sha512_context *ctx,
183 const uint8_t *message,
184 unsigned int block_nb)
185 {
186 /* Note that these arrays use 88*8=704 bytes of stack */
187 uint64_t w[80];
188 uint64_t wv[8];
189 uint64_t t1, t2;
190 const uint8_t *sub_block;
191 int i, j;
192
193 for (i = 0; i < (int) block_nb; i++) {
194 sub_block = message + (i << 7);
195
196 #ifdef UNROLL_LOOPS_SHA512
197 PACK64(&sub_block[ 0], &w[ 0]);
198 PACK64(&sub_block[ 8], &w[ 1]);
199 PACK64(&sub_block[ 16], &w[ 2]);
200 PACK64(&sub_block[ 24], &w[ 3]);
201 PACK64(&sub_block[ 32], &w[ 4]);
202 PACK64(&sub_block[ 40], &w[ 5]);
203 PACK64(&sub_block[ 48], &w[ 6]);
204 PACK64(&sub_block[ 56], &w[ 7]);
205 PACK64(&sub_block[ 64], &w[ 8]);
206 PACK64(&sub_block[ 72], &w[ 9]);
207 PACK64(&sub_block[ 80], &w[10]);
208 PACK64(&sub_block[ 88], &w[11]);
209 PACK64(&sub_block[ 96], &w[12]);
210 PACK64(&sub_block[104], &w[13]);
211 PACK64(&sub_block[112], &w[14]);
212 PACK64(&sub_block[120], &w[15]);
213
214 SHA512_SCR(16); SHA512_SCR(17); SHA512_SCR(18); SHA512_SCR(19);
215 SHA512_SCR(20); SHA512_SCR(21); SHA512_SCR(22); SHA512_SCR(23);
216 SHA512_SCR(24); SHA512_SCR(25); SHA512_SCR(26); SHA512_SCR(27);
217 SHA512_SCR(28); SHA512_SCR(29); SHA512_SCR(30); SHA512_SCR(31);
218 SHA512_SCR(32); SHA512_SCR(33); SHA512_SCR(34); SHA512_SCR(35);
219 SHA512_SCR(36); SHA512_SCR(37); SHA512_SCR(38); SHA512_SCR(39);
220 SHA512_SCR(40); SHA512_SCR(41); SHA512_SCR(42); SHA512_SCR(43);
221 SHA512_SCR(44); SHA512_SCR(45); SHA512_SCR(46); SHA512_SCR(47);
222 SHA512_SCR(48); SHA512_SCR(49); SHA512_SCR(50); SHA512_SCR(51);
223 SHA512_SCR(52); SHA512_SCR(53); SHA512_SCR(54); SHA512_SCR(55);
224 SHA512_SCR(56); SHA512_SCR(57); SHA512_SCR(58); SHA512_SCR(59);
225 SHA512_SCR(60); SHA512_SCR(61); SHA512_SCR(62); SHA512_SCR(63);
226 SHA512_SCR(64); SHA512_SCR(65); SHA512_SCR(66); SHA512_SCR(67);
227 SHA512_SCR(68); SHA512_SCR(69); SHA512_SCR(70); SHA512_SCR(71);
228 SHA512_SCR(72); SHA512_SCR(73); SHA512_SCR(74); SHA512_SCR(75);
229 SHA512_SCR(76); SHA512_SCR(77); SHA512_SCR(78); SHA512_SCR(79);
230
231 wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
232 wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
233 wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
234 wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
235
236 j = 0;
237
238 do {
239 SHA512_EXP(0,1,2,3,4,5,6,7,j); j++;
240 SHA512_EXP(7,0,1,2,3,4,5,6,j); j++;
241 SHA512_EXP(6,7,0,1,2,3,4,5,j); j++;
242 SHA512_EXP(5,6,7,0,1,2,3,4,j); j++;
243 SHA512_EXP(4,5,6,7,0,1,2,3,j); j++;
244 SHA512_EXP(3,4,5,6,7,0,1,2,j); j++;
245 SHA512_EXP(2,3,4,5,6,7,0,1,j); j++;
246 SHA512_EXP(1,2,3,4,5,6,7,0,j); j++;
247 } while (j < 80);
248
249 ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
250 ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
251 ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
252 ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
253 #else
254 for (j = 0; j < 16; j++) {
255 PACK64(&sub_block[j << 3], &w[j]);
256 }
257
258 for (j = 16; j < 80; j++) {
259 SHA512_SCR(j);
260 }
261
262 for (j = 0; j < 8; j++) {
263 wv[j] = ctx->h[j];
264 }
265
266 for (j = 0; j < 80; j++) {
267 t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
268 + sha512_k[j] + w[j];
269 t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
270 wv[7] = wv[6];
271 wv[6] = wv[5];
272 wv[5] = wv[4];
273 wv[4] = wv[3] + t1;
274 wv[3] = wv[2];
275 wv[2] = wv[1];
276 wv[1] = wv[0];
277 wv[0] = t1 + t2;
278 }
279
280 for (j = 0; j < 8; j++)
281 ctx->h[j] += wv[j];
282 #endif /* UNROLL_LOOPS_SHA512 */
283 }
284 }
285
vb2_sha512_update(struct vb2_sha512_context * ctx,const uint8_t * data,uint32_t size)286 void vb2_sha512_update(struct vb2_sha512_context *ctx,
287 const uint8_t *data,
288 uint32_t size)
289 {
290 unsigned int block_nb;
291 unsigned int new_size, rem_size, tmp_size;
292 const uint8_t *shifted_data;
293
294 tmp_size = VB2_SHA512_BLOCK_SIZE - ctx->size;
295 rem_size = size < tmp_size ? size : tmp_size;
296
297 memcpy(&ctx->block[ctx->size], data, rem_size);
298
299 if (ctx->size + size < VB2_SHA512_BLOCK_SIZE) {
300 ctx->size += size;
301 return;
302 }
303
304 new_size = size - rem_size;
305 block_nb = new_size / VB2_SHA512_BLOCK_SIZE;
306
307 shifted_data = data + rem_size;
308
309 vb2_sha512_transform(ctx, ctx->block, 1);
310 vb2_sha512_transform(ctx, shifted_data, block_nb);
311
312 rem_size = new_size % VB2_SHA512_BLOCK_SIZE;
313
314 memcpy(ctx->block, &shifted_data[block_nb << 7],
315 rem_size);
316
317 ctx->size = rem_size;
318 ctx->total_size += (block_nb + 1) << 7;
319 }
320
vb2_sha512_finalize(struct vb2_sha512_context * ctx,uint8_t * digest,enum vb2_hash_algorithm algo)321 void vb2_sha512_finalize(struct vb2_sha512_context *ctx, uint8_t *digest,
322 enum vb2_hash_algorithm algo)
323 {
324 unsigned int block_nb;
325 unsigned int pm_size;
326 unsigned int size_b;
327
328 #ifndef UNROLL_LOOPS_SHA512
329 int i;
330 #endif
331
332 block_nb = 1 + ((VB2_SHA512_BLOCK_SIZE - 17)
333 < (ctx->size % VB2_SHA512_BLOCK_SIZE));
334
335 size_b = (ctx->total_size + ctx->size) << 3;
336 pm_size = block_nb << 7;
337
338 memset(ctx->block + ctx->size, 0, pm_size - ctx->size);
339 ctx->block[ctx->size] = 0x80;
340 UNPACK32(size_b, ctx->block + pm_size - 4);
341
342 vb2_sha512_transform(ctx, ctx->block, block_nb);
343
344 #ifdef UNROLL_LOOPS_SHA512
345 UNPACK64(ctx->h[0], &digest[ 0]);
346 UNPACK64(ctx->h[1], &digest[ 8]);
347 UNPACK64(ctx->h[2], &digest[16]);
348 UNPACK64(ctx->h[3], &digest[24]);
349 UNPACK64(ctx->h[4], &digest[32]);
350 UNPACK64(ctx->h[5], &digest[40]);
351 if (algo != VB2_HASH_SHA384) {
352 UNPACK64(ctx->h[6], &digest[48]);
353 UNPACK64(ctx->h[7], &digest[56]);
354 }
355 #else
356 for (i = 0 ; i < (algo == VB2_HASH_SHA384 ? 6 : 8); i++)
357 UNPACK64(ctx->h[i], &digest[i << 3]);
358 #endif /* UNROLL_LOOPS_SHA512 */
359 }
360