• 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 "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