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 "2sysincludes.h"
39 #include "2common.h"
40 #include "2sha.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 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
vb2_sha512_init(struct vb2_sha512_context * ctx)154 void vb2_sha512_init(struct vb2_sha512_context *ctx)
155 {
156 #ifdef UNROLL_LOOPS_SHA512
157 ctx->h[0] = sha512_h0[0]; ctx->h[1] = sha512_h0[1];
158 ctx->h[2] = sha512_h0[2]; ctx->h[3] = sha512_h0[3];
159 ctx->h[4] = sha512_h0[4]; ctx->h[5] = sha512_h0[5];
160 ctx->h[6] = sha512_h0[6]; ctx->h[7] = sha512_h0[7];
161 #else
162 int i;
163
164 for (i = 0; i < 8; i++)
165 ctx->h[i] = sha512_h0[i];
166 #endif /* UNROLL_LOOPS_SHA512 */
167
168 ctx->size = 0;
169 ctx->total_size = 0;
170 }
171
vb2_sha512_transform(struct vb2_sha512_context * ctx,const uint8_t * message,unsigned int block_nb)172 static void vb2_sha512_transform(struct vb2_sha512_context *ctx,
173 const uint8_t *message,
174 unsigned int block_nb)
175 {
176 /* Note that these arrays use 88*8=704 bytes of stack */
177 uint64_t w[80];
178 uint64_t wv[8];
179 uint64_t t1, t2;
180 const uint8_t *sub_block;
181 int i, j;
182
183 for (i = 0; i < (int) block_nb; i++) {
184 sub_block = message + (i << 7);
185
186 #ifdef UNROLL_LOOPS_SHA512
187 PACK64(&sub_block[ 0], &w[ 0]);
188 PACK64(&sub_block[ 8], &w[ 1]);
189 PACK64(&sub_block[ 16], &w[ 2]);
190 PACK64(&sub_block[ 24], &w[ 3]);
191 PACK64(&sub_block[ 32], &w[ 4]);
192 PACK64(&sub_block[ 40], &w[ 5]);
193 PACK64(&sub_block[ 48], &w[ 6]);
194 PACK64(&sub_block[ 56], &w[ 7]);
195 PACK64(&sub_block[ 64], &w[ 8]);
196 PACK64(&sub_block[ 72], &w[ 9]);
197 PACK64(&sub_block[ 80], &w[10]);
198 PACK64(&sub_block[ 88], &w[11]);
199 PACK64(&sub_block[ 96], &w[12]);
200 PACK64(&sub_block[104], &w[13]);
201 PACK64(&sub_block[112], &w[14]);
202 PACK64(&sub_block[120], &w[15]);
203
204 SHA512_SCR(16); SHA512_SCR(17); SHA512_SCR(18); SHA512_SCR(19);
205 SHA512_SCR(20); SHA512_SCR(21); SHA512_SCR(22); SHA512_SCR(23);
206 SHA512_SCR(24); SHA512_SCR(25); SHA512_SCR(26); SHA512_SCR(27);
207 SHA512_SCR(28); SHA512_SCR(29); SHA512_SCR(30); SHA512_SCR(31);
208 SHA512_SCR(32); SHA512_SCR(33); SHA512_SCR(34); SHA512_SCR(35);
209 SHA512_SCR(36); SHA512_SCR(37); SHA512_SCR(38); SHA512_SCR(39);
210 SHA512_SCR(40); SHA512_SCR(41); SHA512_SCR(42); SHA512_SCR(43);
211 SHA512_SCR(44); SHA512_SCR(45); SHA512_SCR(46); SHA512_SCR(47);
212 SHA512_SCR(48); SHA512_SCR(49); SHA512_SCR(50); SHA512_SCR(51);
213 SHA512_SCR(52); SHA512_SCR(53); SHA512_SCR(54); SHA512_SCR(55);
214 SHA512_SCR(56); SHA512_SCR(57); SHA512_SCR(58); SHA512_SCR(59);
215 SHA512_SCR(60); SHA512_SCR(61); SHA512_SCR(62); SHA512_SCR(63);
216 SHA512_SCR(64); SHA512_SCR(65); SHA512_SCR(66); SHA512_SCR(67);
217 SHA512_SCR(68); SHA512_SCR(69); SHA512_SCR(70); SHA512_SCR(71);
218 SHA512_SCR(72); SHA512_SCR(73); SHA512_SCR(74); SHA512_SCR(75);
219 SHA512_SCR(76); SHA512_SCR(77); SHA512_SCR(78); SHA512_SCR(79);
220
221 wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
222 wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
223 wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
224 wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
225
226 j = 0;
227
228 do {
229 SHA512_EXP(0,1,2,3,4,5,6,7,j); j++;
230 SHA512_EXP(7,0,1,2,3,4,5,6,j); j++;
231 SHA512_EXP(6,7,0,1,2,3,4,5,j); j++;
232 SHA512_EXP(5,6,7,0,1,2,3,4,j); j++;
233 SHA512_EXP(4,5,6,7,0,1,2,3,j); j++;
234 SHA512_EXP(3,4,5,6,7,0,1,2,j); j++;
235 SHA512_EXP(2,3,4,5,6,7,0,1,j); j++;
236 SHA512_EXP(1,2,3,4,5,6,7,0,j); j++;
237 } while (j < 80);
238
239 ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
240 ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
241 ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
242 ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
243 #else
244 for (j = 0; j < 16; j++) {
245 PACK64(&sub_block[j << 3], &w[j]);
246 }
247
248 for (j = 16; j < 80; j++) {
249 SHA512_SCR(j);
250 }
251
252 for (j = 0; j < 8; j++) {
253 wv[j] = ctx->h[j];
254 }
255
256 for (j = 0; j < 80; j++) {
257 t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
258 + sha512_k[j] + w[j];
259 t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
260 wv[7] = wv[6];
261 wv[6] = wv[5];
262 wv[5] = wv[4];
263 wv[4] = wv[3] + t1;
264 wv[3] = wv[2];
265 wv[2] = wv[1];
266 wv[1] = wv[0];
267 wv[0] = t1 + t2;
268 }
269
270 for (j = 0; j < 8; j++)
271 ctx->h[j] += wv[j];
272 #endif /* UNROLL_LOOPS_SHA512 */
273 }
274 }
275
vb2_sha512_update(struct vb2_sha512_context * ctx,const uint8_t * data,uint32_t size)276 void vb2_sha512_update(struct vb2_sha512_context *ctx,
277 const uint8_t *data,
278 uint32_t size)
279 {
280 unsigned int block_nb;
281 unsigned int new_size, rem_size, tmp_size;
282 const uint8_t *shifted_data;
283
284 tmp_size = VB2_SHA512_BLOCK_SIZE - ctx->size;
285 rem_size = size < tmp_size ? size : tmp_size;
286
287 memcpy(&ctx->block[ctx->size], data, rem_size);
288
289 if (ctx->size + size < VB2_SHA512_BLOCK_SIZE) {
290 ctx->size += size;
291 return;
292 }
293
294 new_size = size - rem_size;
295 block_nb = new_size / VB2_SHA512_BLOCK_SIZE;
296
297 shifted_data = data + rem_size;
298
299 vb2_sha512_transform(ctx, ctx->block, 1);
300 vb2_sha512_transform(ctx, shifted_data, block_nb);
301
302 rem_size = new_size % VB2_SHA512_BLOCK_SIZE;
303
304 memcpy(ctx->block, &shifted_data[block_nb << 7],
305 rem_size);
306
307 ctx->size = rem_size;
308 ctx->total_size += (block_nb + 1) << 7;
309 }
310
vb2_sha512_finalize(struct vb2_sha512_context * ctx,uint8_t * digest)311 void vb2_sha512_finalize(struct vb2_sha512_context *ctx, uint8_t *digest)
312 {
313 unsigned int block_nb;
314 unsigned int pm_size;
315 unsigned int size_b;
316
317 #ifndef UNROLL_LOOPS_SHA512
318 int i;
319 #endif
320
321 block_nb = 1 + ((VB2_SHA512_BLOCK_SIZE - 17)
322 < (ctx->size % VB2_SHA512_BLOCK_SIZE));
323
324 size_b = (ctx->total_size + ctx->size) << 3;
325 pm_size = block_nb << 7;
326
327 memset(ctx->block + ctx->size, 0, pm_size - ctx->size);
328 ctx->block[ctx->size] = 0x80;
329 UNPACK32(size_b, ctx->block + pm_size - 4);
330
331 vb2_sha512_transform(ctx, ctx->block, block_nb);
332
333 #ifdef UNROLL_LOOPS_SHA512
334 UNPACK64(ctx->h[0], &digest[ 0]);
335 UNPACK64(ctx->h[1], &digest[ 8]);
336 UNPACK64(ctx->h[2], &digest[16]);
337 UNPACK64(ctx->h[3], &digest[24]);
338 UNPACK64(ctx->h[4], &digest[32]);
339 UNPACK64(ctx->h[5], &digest[40]);
340 UNPACK64(ctx->h[6], &digest[48]);
341 UNPACK64(ctx->h[7], &digest[56]);
342 #else
343 for (i = 0 ; i < 8; i++)
344 UNPACK64(ctx->h[i], &digest[i << 3]);
345 #endif /* UNROLL_LOOPS_SHA512 */
346 }
347