xref: /rk3399_rockchip-uboot/lib/sha256.c (revision ec7381fbf6f77cc465eb06a1ab6f8a99df1e487c)
178acc472SPeter Tyser /*
278acc472SPeter Tyser  * FIPS-180-2 compliant SHA-256 implementation
378acc472SPeter Tyser  *
478acc472SPeter Tyser  * Copyright (C) 2001-2003  Christophe Devine
578acc472SPeter Tyser  *
678acc472SPeter Tyser  * This program is free software; you can redistribute it and/or modify
778acc472SPeter Tyser  * it under the terms of the GNU General Public License as published by
878acc472SPeter Tyser  * the Free Software Foundation; either version 2 of the License, or
978acc472SPeter Tyser  * (at your option) any later version.
1078acc472SPeter Tyser  *
1178acc472SPeter Tyser  * This program is distributed in the hope that it will be useful,
1278acc472SPeter Tyser  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1378acc472SPeter Tyser  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1478acc472SPeter Tyser  * GNU General Public License for more details.
1578acc472SPeter Tyser  *
1678acc472SPeter Tyser  * You should have received a copy of the GNU General Public License
1778acc472SPeter Tyser  * along with this program; if not, write to the Free Software
1878acc472SPeter Tyser  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1978acc472SPeter Tyser  */
2078acc472SPeter Tyser 
2178acc472SPeter Tyser #ifndef USE_HOSTCC
2278acc472SPeter Tyser #include <common.h>
2378acc472SPeter Tyser #endif /* USE_HOSTCC */
2478acc472SPeter Tyser #include <watchdog.h>
2578acc472SPeter Tyser #include <linux/string.h>
2678acc472SPeter Tyser #include <sha256.h>
2778acc472SPeter Tyser 
2878acc472SPeter Tyser /*
2978acc472SPeter Tyser  * 32-bit integer manipulation macros (big endian)
3078acc472SPeter Tyser  */
3178acc472SPeter Tyser #ifndef GET_UINT32_BE
3278acc472SPeter Tyser #define GET_UINT32_BE(n,b,i) {				\
3378acc472SPeter Tyser 	(n) = ( (unsigned long) (b)[(i)    ] << 24 )	\
3478acc472SPeter Tyser 	    | ( (unsigned long) (b)[(i) + 1] << 16 )	\
3578acc472SPeter Tyser 	    | ( (unsigned long) (b)[(i) + 2] <<  8 )	\
3678acc472SPeter Tyser 	    | ( (unsigned long) (b)[(i) + 3]       );	\
3778acc472SPeter Tyser }
3878acc472SPeter Tyser #endif
3978acc472SPeter Tyser #ifndef PUT_UINT32_BE
4078acc472SPeter Tyser #define PUT_UINT32_BE(n,b,i) {				\
4178acc472SPeter Tyser 	(b)[(i)    ] = (unsigned char) ( (n) >> 24 );	\
4278acc472SPeter Tyser 	(b)[(i) + 1] = (unsigned char) ( (n) >> 16 );	\
4378acc472SPeter Tyser 	(b)[(i) + 2] = (unsigned char) ( (n) >>  8 );	\
4478acc472SPeter Tyser 	(b)[(i) + 3] = (unsigned char) ( (n)       );	\
4578acc472SPeter Tyser }
4678acc472SPeter Tyser #endif
4778acc472SPeter Tyser 
4878acc472SPeter Tyser void sha256_starts(sha256_context * ctx)
4978acc472SPeter Tyser {
5078acc472SPeter Tyser 	ctx->total[0] = 0;
5178acc472SPeter Tyser 	ctx->total[1] = 0;
5278acc472SPeter Tyser 
5378acc472SPeter Tyser 	ctx->state[0] = 0x6A09E667;
5478acc472SPeter Tyser 	ctx->state[1] = 0xBB67AE85;
5578acc472SPeter Tyser 	ctx->state[2] = 0x3C6EF372;
5678acc472SPeter Tyser 	ctx->state[3] = 0xA54FF53A;
5778acc472SPeter Tyser 	ctx->state[4] = 0x510E527F;
5878acc472SPeter Tyser 	ctx->state[5] = 0x9B05688C;
5978acc472SPeter Tyser 	ctx->state[6] = 0x1F83D9AB;
6078acc472SPeter Tyser 	ctx->state[7] = 0x5BE0CD19;
6178acc472SPeter Tyser }
6278acc472SPeter Tyser 
63*ec7381fbSSimon Glass static void sha256_process(sha256_context *ctx, const uint8_t data[64])
6478acc472SPeter Tyser {
6578acc472SPeter Tyser 	uint32_t temp1, temp2;
6678acc472SPeter Tyser 	uint32_t W[64];
6778acc472SPeter Tyser 	uint32_t A, B, C, D, E, F, G, H;
6878acc472SPeter Tyser 
6978acc472SPeter Tyser 	GET_UINT32_BE(W[0], data, 0);
7078acc472SPeter Tyser 	GET_UINT32_BE(W[1], data, 4);
7178acc472SPeter Tyser 	GET_UINT32_BE(W[2], data, 8);
7278acc472SPeter Tyser 	GET_UINT32_BE(W[3], data, 12);
7378acc472SPeter Tyser 	GET_UINT32_BE(W[4], data, 16);
7478acc472SPeter Tyser 	GET_UINT32_BE(W[5], data, 20);
7578acc472SPeter Tyser 	GET_UINT32_BE(W[6], data, 24);
7678acc472SPeter Tyser 	GET_UINT32_BE(W[7], data, 28);
7778acc472SPeter Tyser 	GET_UINT32_BE(W[8], data, 32);
7878acc472SPeter Tyser 	GET_UINT32_BE(W[9], data, 36);
7978acc472SPeter Tyser 	GET_UINT32_BE(W[10], data, 40);
8078acc472SPeter Tyser 	GET_UINT32_BE(W[11], data, 44);
8178acc472SPeter Tyser 	GET_UINT32_BE(W[12], data, 48);
8278acc472SPeter Tyser 	GET_UINT32_BE(W[13], data, 52);
8378acc472SPeter Tyser 	GET_UINT32_BE(W[14], data, 56);
8478acc472SPeter Tyser 	GET_UINT32_BE(W[15], data, 60);
8578acc472SPeter Tyser 
8678acc472SPeter Tyser #define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
8778acc472SPeter Tyser #define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
8878acc472SPeter Tyser 
8978acc472SPeter Tyser #define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
9078acc472SPeter Tyser #define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
9178acc472SPeter Tyser 
9278acc472SPeter Tyser #define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
9378acc472SPeter Tyser #define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
9478acc472SPeter Tyser 
9578acc472SPeter Tyser #define F0(x,y,z) ((x & y) | (z & (x | y)))
9678acc472SPeter Tyser #define F1(x,y,z) (z ^ (x & (y ^ z)))
9778acc472SPeter Tyser 
9878acc472SPeter Tyser #define R(t)					\
9978acc472SPeter Tyser (						\
10078acc472SPeter Tyser 	W[t] = S1(W[t - 2]) + W[t - 7] +	\
10178acc472SPeter Tyser 		S0(W[t - 15]) + W[t - 16]	\
10278acc472SPeter Tyser )
10378acc472SPeter Tyser 
10478acc472SPeter Tyser #define P(a,b,c,d,e,f,g,h,x,K) {		\
10578acc472SPeter Tyser 	temp1 = h + S3(e) + F1(e,f,g) + K + x;	\
10678acc472SPeter Tyser 	temp2 = S2(a) + F0(a,b,c);		\
10778acc472SPeter Tyser 	d += temp1; h = temp1 + temp2;		\
10878acc472SPeter Tyser }
10978acc472SPeter Tyser 
11078acc472SPeter Tyser 	A = ctx->state[0];
11178acc472SPeter Tyser 	B = ctx->state[1];
11278acc472SPeter Tyser 	C = ctx->state[2];
11378acc472SPeter Tyser 	D = ctx->state[3];
11478acc472SPeter Tyser 	E = ctx->state[4];
11578acc472SPeter Tyser 	F = ctx->state[5];
11678acc472SPeter Tyser 	G = ctx->state[6];
11778acc472SPeter Tyser 	H = ctx->state[7];
11878acc472SPeter Tyser 
11978acc472SPeter Tyser 	P(A, B, C, D, E, F, G, H, W[0], 0x428A2F98);
12078acc472SPeter Tyser 	P(H, A, B, C, D, E, F, G, W[1], 0x71374491);
12178acc472SPeter Tyser 	P(G, H, A, B, C, D, E, F, W[2], 0xB5C0FBCF);
12278acc472SPeter Tyser 	P(F, G, H, A, B, C, D, E, W[3], 0xE9B5DBA5);
12378acc472SPeter Tyser 	P(E, F, G, H, A, B, C, D, W[4], 0x3956C25B);
12478acc472SPeter Tyser 	P(D, E, F, G, H, A, B, C, W[5], 0x59F111F1);
12578acc472SPeter Tyser 	P(C, D, E, F, G, H, A, B, W[6], 0x923F82A4);
12678acc472SPeter Tyser 	P(B, C, D, E, F, G, H, A, W[7], 0xAB1C5ED5);
12778acc472SPeter Tyser 	P(A, B, C, D, E, F, G, H, W[8], 0xD807AA98);
12878acc472SPeter Tyser 	P(H, A, B, C, D, E, F, G, W[9], 0x12835B01);
12978acc472SPeter Tyser 	P(G, H, A, B, C, D, E, F, W[10], 0x243185BE);
13078acc472SPeter Tyser 	P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3);
13178acc472SPeter Tyser 	P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74);
13278acc472SPeter Tyser 	P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE);
13378acc472SPeter Tyser 	P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7);
13478acc472SPeter Tyser 	P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174);
13578acc472SPeter Tyser 	P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1);
13678acc472SPeter Tyser 	P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786);
13778acc472SPeter Tyser 	P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6);
13878acc472SPeter Tyser 	P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC);
13978acc472SPeter Tyser 	P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F);
14078acc472SPeter Tyser 	P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA);
14178acc472SPeter Tyser 	P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC);
14278acc472SPeter Tyser 	P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA);
14378acc472SPeter Tyser 	P(A, B, C, D, E, F, G, H, R(24), 0x983E5152);
14478acc472SPeter Tyser 	P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D);
14578acc472SPeter Tyser 	P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8);
14678acc472SPeter Tyser 	P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7);
14778acc472SPeter Tyser 	P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3);
14878acc472SPeter Tyser 	P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147);
14978acc472SPeter Tyser 	P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351);
15078acc472SPeter Tyser 	P(B, C, D, E, F, G, H, A, R(31), 0x14292967);
15178acc472SPeter Tyser 	P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85);
15278acc472SPeter Tyser 	P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138);
15378acc472SPeter Tyser 	P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC);
15478acc472SPeter Tyser 	P(F, G, H, A, B, C, D, E, R(35), 0x53380D13);
15578acc472SPeter Tyser 	P(E, F, G, H, A, B, C, D, R(36), 0x650A7354);
15678acc472SPeter Tyser 	P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB);
15778acc472SPeter Tyser 	P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E);
15878acc472SPeter Tyser 	P(B, C, D, E, F, G, H, A, R(39), 0x92722C85);
15978acc472SPeter Tyser 	P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1);
16078acc472SPeter Tyser 	P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B);
16178acc472SPeter Tyser 	P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70);
16278acc472SPeter Tyser 	P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3);
16378acc472SPeter Tyser 	P(E, F, G, H, A, B, C, D, R(44), 0xD192E819);
16478acc472SPeter Tyser 	P(D, E, F, G, H, A, B, C, R(45), 0xD6990624);
16578acc472SPeter Tyser 	P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585);
16678acc472SPeter Tyser 	P(B, C, D, E, F, G, H, A, R(47), 0x106AA070);
16778acc472SPeter Tyser 	P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116);
16878acc472SPeter Tyser 	P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08);
16978acc472SPeter Tyser 	P(G, H, A, B, C, D, E, F, R(50), 0x2748774C);
17078acc472SPeter Tyser 	P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5);
17178acc472SPeter Tyser 	P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3);
17278acc472SPeter Tyser 	P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A);
17378acc472SPeter Tyser 	P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F);
17478acc472SPeter Tyser 	P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3);
17578acc472SPeter Tyser 	P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE);
17678acc472SPeter Tyser 	P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F);
17778acc472SPeter Tyser 	P(G, H, A, B, C, D, E, F, R(58), 0x84C87814);
17878acc472SPeter Tyser 	P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208);
17978acc472SPeter Tyser 	P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA);
18078acc472SPeter Tyser 	P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB);
18178acc472SPeter Tyser 	P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7);
18278acc472SPeter Tyser 	P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2);
18378acc472SPeter Tyser 
18478acc472SPeter Tyser 	ctx->state[0] += A;
18578acc472SPeter Tyser 	ctx->state[1] += B;
18678acc472SPeter Tyser 	ctx->state[2] += C;
18778acc472SPeter Tyser 	ctx->state[3] += D;
18878acc472SPeter Tyser 	ctx->state[4] += E;
18978acc472SPeter Tyser 	ctx->state[5] += F;
19078acc472SPeter Tyser 	ctx->state[6] += G;
19178acc472SPeter Tyser 	ctx->state[7] += H;
19278acc472SPeter Tyser }
19378acc472SPeter Tyser 
194*ec7381fbSSimon Glass void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length)
19578acc472SPeter Tyser {
19678acc472SPeter Tyser 	uint32_t left, fill;
19778acc472SPeter Tyser 
19878acc472SPeter Tyser 	if (!length)
19978acc472SPeter Tyser 		return;
20078acc472SPeter Tyser 
20178acc472SPeter Tyser 	left = ctx->total[0] & 0x3F;
20278acc472SPeter Tyser 	fill = 64 - left;
20378acc472SPeter Tyser 
20478acc472SPeter Tyser 	ctx->total[0] += length;
20578acc472SPeter Tyser 	ctx->total[0] &= 0xFFFFFFFF;
20678acc472SPeter Tyser 
20778acc472SPeter Tyser 	if (ctx->total[0] < length)
20878acc472SPeter Tyser 		ctx->total[1]++;
20978acc472SPeter Tyser 
21078acc472SPeter Tyser 	if (left && length >= fill) {
21178acc472SPeter Tyser 		memcpy((void *) (ctx->buffer + left), (void *) input, fill);
21278acc472SPeter Tyser 		sha256_process(ctx, ctx->buffer);
21378acc472SPeter Tyser 		length -= fill;
21478acc472SPeter Tyser 		input += fill;
21578acc472SPeter Tyser 		left = 0;
21678acc472SPeter Tyser 	}
21778acc472SPeter Tyser 
21878acc472SPeter Tyser 	while (length >= 64) {
21978acc472SPeter Tyser 		sha256_process(ctx, input);
22078acc472SPeter Tyser 		length -= 64;
22178acc472SPeter Tyser 		input += 64;
22278acc472SPeter Tyser 	}
22378acc472SPeter Tyser 
22478acc472SPeter Tyser 	if (length)
22578acc472SPeter Tyser 		memcpy((void *) (ctx->buffer + left), (void *) input, length);
22678acc472SPeter Tyser }
22778acc472SPeter Tyser 
22878acc472SPeter Tyser static uint8_t sha256_padding[64] = {
22978acc472SPeter Tyser 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23078acc472SPeter Tyser 	   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23178acc472SPeter Tyser 	   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23278acc472SPeter Tyser 	   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
23378acc472SPeter Tyser };
23478acc472SPeter Tyser 
23578acc472SPeter Tyser void sha256_finish(sha256_context * ctx, uint8_t digest[32])
23678acc472SPeter Tyser {
23778acc472SPeter Tyser 	uint32_t last, padn;
23878acc472SPeter Tyser 	uint32_t high, low;
23978acc472SPeter Tyser 	uint8_t msglen[8];
24078acc472SPeter Tyser 
24178acc472SPeter Tyser 	high = ((ctx->total[0] >> 29)
24278acc472SPeter Tyser 		| (ctx->total[1] << 3));
24378acc472SPeter Tyser 	low = (ctx->total[0] << 3);
24478acc472SPeter Tyser 
24578acc472SPeter Tyser 	PUT_UINT32_BE(high, msglen, 0);
24678acc472SPeter Tyser 	PUT_UINT32_BE(low, msglen, 4);
24778acc472SPeter Tyser 
24878acc472SPeter Tyser 	last = ctx->total[0] & 0x3F;
24978acc472SPeter Tyser 	padn = (last < 56) ? (56 - last) : (120 - last);
25078acc472SPeter Tyser 
25178acc472SPeter Tyser 	sha256_update(ctx, sha256_padding, padn);
25278acc472SPeter Tyser 	sha256_update(ctx, msglen, 8);
25378acc472SPeter Tyser 
25478acc472SPeter Tyser 	PUT_UINT32_BE(ctx->state[0], digest, 0);
25578acc472SPeter Tyser 	PUT_UINT32_BE(ctx->state[1], digest, 4);
25678acc472SPeter Tyser 	PUT_UINT32_BE(ctx->state[2], digest, 8);
25778acc472SPeter Tyser 	PUT_UINT32_BE(ctx->state[3], digest, 12);
25878acc472SPeter Tyser 	PUT_UINT32_BE(ctx->state[4], digest, 16);
25978acc472SPeter Tyser 	PUT_UINT32_BE(ctx->state[5], digest, 20);
26078acc472SPeter Tyser 	PUT_UINT32_BE(ctx->state[6], digest, 24);
26178acc472SPeter Tyser 	PUT_UINT32_BE(ctx->state[7], digest, 28);
26278acc472SPeter Tyser }
263*ec7381fbSSimon Glass 
264*ec7381fbSSimon Glass /*
265*ec7381fbSSimon Glass  * Output = SHA-256( input buffer ). Trigger the watchdog every 'chunk_sz'
266*ec7381fbSSimon Glass  * bytes of input processed.
267*ec7381fbSSimon Glass  */
268*ec7381fbSSimon Glass void sha256_csum_wd(const unsigned char *input, unsigned int ilen,
269*ec7381fbSSimon Glass 		unsigned char *output, unsigned int chunk_sz)
270*ec7381fbSSimon Glass {
271*ec7381fbSSimon Glass 	sha256_context ctx;
272*ec7381fbSSimon Glass #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
273*ec7381fbSSimon Glass 	unsigned char *end, *curr;
274*ec7381fbSSimon Glass 	int chunk;
275*ec7381fbSSimon Glass #endif
276*ec7381fbSSimon Glass 
277*ec7381fbSSimon Glass 	sha256_starts(&ctx);
278*ec7381fbSSimon Glass 
279*ec7381fbSSimon Glass #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
280*ec7381fbSSimon Glass 	curr = input;
281*ec7381fbSSimon Glass 	end = input + ilen;
282*ec7381fbSSimon Glass 	while (curr < end) {
283*ec7381fbSSimon Glass 		chunk = end - curr;
284*ec7381fbSSimon Glass 		if (chunk > chunk_sz)
285*ec7381fbSSimon Glass 			chunk = chunk_sz;
286*ec7381fbSSimon Glass 		sha256_update(&ctx, curr, chunk);
287*ec7381fbSSimon Glass 		curr += chunk;
288*ec7381fbSSimon Glass 		WATCHDOG_RESET();
289*ec7381fbSSimon Glass 	}
290*ec7381fbSSimon Glass #else
291*ec7381fbSSimon Glass 	sha256_update(&ctx, input, ilen);
292*ec7381fbSSimon Glass #endif
293*ec7381fbSSimon Glass 
294*ec7381fbSSimon Glass 	sha256_finish(&ctx, output);
295*ec7381fbSSimon Glass }
296