xref: /aosp_15_r20/external/vboot_reference/firmware/2lib/2sha512.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
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