xref: /rk3399_rockchip-uboot/lib/sha256.c (revision 2b9912e6a7df7b1f60beb7942bd0e6fa5f9d0167)
178acc472SPeter Tyser /*
278acc472SPeter Tyser  * FIPS-180-2 compliant SHA-256 implementation
378acc472SPeter Tyser  *
478acc472SPeter Tyser  * Copyright (C) 2001-2003  Christophe Devine
578acc472SPeter Tyser  *
61a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
778acc472SPeter Tyser  */
878acc472SPeter Tyser 
978acc472SPeter Tyser #ifndef USE_HOSTCC
1078acc472SPeter Tyser #include <common.h>
11822ef00eSAndreas Bießmann #include <linux/string.h>
12822ef00eSAndreas Bießmann #else
13822ef00eSAndreas Bießmann #include <string.h>
1478acc472SPeter Tyser #endif /* USE_HOSTCC */
1578acc472SPeter Tyser #include <watchdog.h>
16*2b9912e6SJeroen Hofstee #include <u-boot/sha256.h>
1778acc472SPeter Tyser 
1878acc472SPeter Tyser /*
1978acc472SPeter Tyser  * 32-bit integer manipulation macros (big endian)
2078acc472SPeter Tyser  */
2178acc472SPeter Tyser #ifndef GET_UINT32_BE
2278acc472SPeter Tyser #define GET_UINT32_BE(n,b,i) {				\
2378acc472SPeter Tyser 	(n) = ( (unsigned long) (b)[(i)    ] << 24 )	\
2478acc472SPeter Tyser 	    | ( (unsigned long) (b)[(i) + 1] << 16 )	\
2578acc472SPeter Tyser 	    | ( (unsigned long) (b)[(i) + 2] <<  8 )	\
2678acc472SPeter Tyser 	    | ( (unsigned long) (b)[(i) + 3]       );	\
2778acc472SPeter Tyser }
2878acc472SPeter Tyser #endif
2978acc472SPeter Tyser #ifndef PUT_UINT32_BE
3078acc472SPeter Tyser #define PUT_UINT32_BE(n,b,i) {				\
3178acc472SPeter Tyser 	(b)[(i)    ] = (unsigned char) ( (n) >> 24 );	\
3278acc472SPeter Tyser 	(b)[(i) + 1] = (unsigned char) ( (n) >> 16 );	\
3378acc472SPeter Tyser 	(b)[(i) + 2] = (unsigned char) ( (n) >>  8 );	\
3478acc472SPeter Tyser 	(b)[(i) + 3] = (unsigned char) ( (n)       );	\
3578acc472SPeter Tyser }
3678acc472SPeter Tyser #endif
3778acc472SPeter Tyser 
3878acc472SPeter Tyser void sha256_starts(sha256_context * ctx)
3978acc472SPeter Tyser {
4078acc472SPeter Tyser 	ctx->total[0] = 0;
4178acc472SPeter Tyser 	ctx->total[1] = 0;
4278acc472SPeter Tyser 
4378acc472SPeter Tyser 	ctx->state[0] = 0x6A09E667;
4478acc472SPeter Tyser 	ctx->state[1] = 0xBB67AE85;
4578acc472SPeter Tyser 	ctx->state[2] = 0x3C6EF372;
4678acc472SPeter Tyser 	ctx->state[3] = 0xA54FF53A;
4778acc472SPeter Tyser 	ctx->state[4] = 0x510E527F;
4878acc472SPeter Tyser 	ctx->state[5] = 0x9B05688C;
4978acc472SPeter Tyser 	ctx->state[6] = 0x1F83D9AB;
5078acc472SPeter Tyser 	ctx->state[7] = 0x5BE0CD19;
5178acc472SPeter Tyser }
5278acc472SPeter Tyser 
53ec7381fbSSimon Glass static void sha256_process(sha256_context *ctx, const uint8_t data[64])
5478acc472SPeter Tyser {
5578acc472SPeter Tyser 	uint32_t temp1, temp2;
5678acc472SPeter Tyser 	uint32_t W[64];
5778acc472SPeter Tyser 	uint32_t A, B, C, D, E, F, G, H;
5878acc472SPeter Tyser 
5978acc472SPeter Tyser 	GET_UINT32_BE(W[0], data, 0);
6078acc472SPeter Tyser 	GET_UINT32_BE(W[1], data, 4);
6178acc472SPeter Tyser 	GET_UINT32_BE(W[2], data, 8);
6278acc472SPeter Tyser 	GET_UINT32_BE(W[3], data, 12);
6378acc472SPeter Tyser 	GET_UINT32_BE(W[4], data, 16);
6478acc472SPeter Tyser 	GET_UINT32_BE(W[5], data, 20);
6578acc472SPeter Tyser 	GET_UINT32_BE(W[6], data, 24);
6678acc472SPeter Tyser 	GET_UINT32_BE(W[7], data, 28);
6778acc472SPeter Tyser 	GET_UINT32_BE(W[8], data, 32);
6878acc472SPeter Tyser 	GET_UINT32_BE(W[9], data, 36);
6978acc472SPeter Tyser 	GET_UINT32_BE(W[10], data, 40);
7078acc472SPeter Tyser 	GET_UINT32_BE(W[11], data, 44);
7178acc472SPeter Tyser 	GET_UINT32_BE(W[12], data, 48);
7278acc472SPeter Tyser 	GET_UINT32_BE(W[13], data, 52);
7378acc472SPeter Tyser 	GET_UINT32_BE(W[14], data, 56);
7478acc472SPeter Tyser 	GET_UINT32_BE(W[15], data, 60);
7578acc472SPeter Tyser 
7678acc472SPeter Tyser #define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
7778acc472SPeter Tyser #define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
7878acc472SPeter Tyser 
7978acc472SPeter Tyser #define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
8078acc472SPeter Tyser #define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
8178acc472SPeter Tyser 
8278acc472SPeter Tyser #define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
8378acc472SPeter Tyser #define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
8478acc472SPeter Tyser 
8578acc472SPeter Tyser #define F0(x,y,z) ((x & y) | (z & (x | y)))
8678acc472SPeter Tyser #define F1(x,y,z) (z ^ (x & (y ^ z)))
8778acc472SPeter Tyser 
8878acc472SPeter Tyser #define R(t)					\
8978acc472SPeter Tyser (						\
9078acc472SPeter Tyser 	W[t] = S1(W[t - 2]) + W[t - 7] +	\
9178acc472SPeter Tyser 		S0(W[t - 15]) + W[t - 16]	\
9278acc472SPeter Tyser )
9378acc472SPeter Tyser 
9478acc472SPeter Tyser #define P(a,b,c,d,e,f,g,h,x,K) {		\
9578acc472SPeter Tyser 	temp1 = h + S3(e) + F1(e,f,g) + K + x;	\
9678acc472SPeter Tyser 	temp2 = S2(a) + F0(a,b,c);		\
9778acc472SPeter Tyser 	d += temp1; h = temp1 + temp2;		\
9878acc472SPeter Tyser }
9978acc472SPeter Tyser 
10078acc472SPeter Tyser 	A = ctx->state[0];
10178acc472SPeter Tyser 	B = ctx->state[1];
10278acc472SPeter Tyser 	C = ctx->state[2];
10378acc472SPeter Tyser 	D = ctx->state[3];
10478acc472SPeter Tyser 	E = ctx->state[4];
10578acc472SPeter Tyser 	F = ctx->state[5];
10678acc472SPeter Tyser 	G = ctx->state[6];
10778acc472SPeter Tyser 	H = ctx->state[7];
10878acc472SPeter Tyser 
10978acc472SPeter Tyser 	P(A, B, C, D, E, F, G, H, W[0], 0x428A2F98);
11078acc472SPeter Tyser 	P(H, A, B, C, D, E, F, G, W[1], 0x71374491);
11178acc472SPeter Tyser 	P(G, H, A, B, C, D, E, F, W[2], 0xB5C0FBCF);
11278acc472SPeter Tyser 	P(F, G, H, A, B, C, D, E, W[3], 0xE9B5DBA5);
11378acc472SPeter Tyser 	P(E, F, G, H, A, B, C, D, W[4], 0x3956C25B);
11478acc472SPeter Tyser 	P(D, E, F, G, H, A, B, C, W[5], 0x59F111F1);
11578acc472SPeter Tyser 	P(C, D, E, F, G, H, A, B, W[6], 0x923F82A4);
11678acc472SPeter Tyser 	P(B, C, D, E, F, G, H, A, W[7], 0xAB1C5ED5);
11778acc472SPeter Tyser 	P(A, B, C, D, E, F, G, H, W[8], 0xD807AA98);
11878acc472SPeter Tyser 	P(H, A, B, C, D, E, F, G, W[9], 0x12835B01);
11978acc472SPeter Tyser 	P(G, H, A, B, C, D, E, F, W[10], 0x243185BE);
12078acc472SPeter Tyser 	P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3);
12178acc472SPeter Tyser 	P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74);
12278acc472SPeter Tyser 	P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE);
12378acc472SPeter Tyser 	P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7);
12478acc472SPeter Tyser 	P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174);
12578acc472SPeter Tyser 	P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1);
12678acc472SPeter Tyser 	P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786);
12778acc472SPeter Tyser 	P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6);
12878acc472SPeter Tyser 	P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC);
12978acc472SPeter Tyser 	P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F);
13078acc472SPeter Tyser 	P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA);
13178acc472SPeter Tyser 	P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC);
13278acc472SPeter Tyser 	P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA);
13378acc472SPeter Tyser 	P(A, B, C, D, E, F, G, H, R(24), 0x983E5152);
13478acc472SPeter Tyser 	P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D);
13578acc472SPeter Tyser 	P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8);
13678acc472SPeter Tyser 	P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7);
13778acc472SPeter Tyser 	P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3);
13878acc472SPeter Tyser 	P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147);
13978acc472SPeter Tyser 	P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351);
14078acc472SPeter Tyser 	P(B, C, D, E, F, G, H, A, R(31), 0x14292967);
14178acc472SPeter Tyser 	P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85);
14278acc472SPeter Tyser 	P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138);
14378acc472SPeter Tyser 	P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC);
14478acc472SPeter Tyser 	P(F, G, H, A, B, C, D, E, R(35), 0x53380D13);
14578acc472SPeter Tyser 	P(E, F, G, H, A, B, C, D, R(36), 0x650A7354);
14678acc472SPeter Tyser 	P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB);
14778acc472SPeter Tyser 	P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E);
14878acc472SPeter Tyser 	P(B, C, D, E, F, G, H, A, R(39), 0x92722C85);
14978acc472SPeter Tyser 	P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1);
15078acc472SPeter Tyser 	P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B);
15178acc472SPeter Tyser 	P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70);
15278acc472SPeter Tyser 	P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3);
15378acc472SPeter Tyser 	P(E, F, G, H, A, B, C, D, R(44), 0xD192E819);
15478acc472SPeter Tyser 	P(D, E, F, G, H, A, B, C, R(45), 0xD6990624);
15578acc472SPeter Tyser 	P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585);
15678acc472SPeter Tyser 	P(B, C, D, E, F, G, H, A, R(47), 0x106AA070);
15778acc472SPeter Tyser 	P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116);
15878acc472SPeter Tyser 	P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08);
15978acc472SPeter Tyser 	P(G, H, A, B, C, D, E, F, R(50), 0x2748774C);
16078acc472SPeter Tyser 	P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5);
16178acc472SPeter Tyser 	P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3);
16278acc472SPeter Tyser 	P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A);
16378acc472SPeter Tyser 	P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F);
16478acc472SPeter Tyser 	P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3);
16578acc472SPeter Tyser 	P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE);
16678acc472SPeter Tyser 	P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F);
16778acc472SPeter Tyser 	P(G, H, A, B, C, D, E, F, R(58), 0x84C87814);
16878acc472SPeter Tyser 	P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208);
16978acc472SPeter Tyser 	P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA);
17078acc472SPeter Tyser 	P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB);
17178acc472SPeter Tyser 	P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7);
17278acc472SPeter Tyser 	P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2);
17378acc472SPeter Tyser 
17478acc472SPeter Tyser 	ctx->state[0] += A;
17578acc472SPeter Tyser 	ctx->state[1] += B;
17678acc472SPeter Tyser 	ctx->state[2] += C;
17778acc472SPeter Tyser 	ctx->state[3] += D;
17878acc472SPeter Tyser 	ctx->state[4] += E;
17978acc472SPeter Tyser 	ctx->state[5] += F;
18078acc472SPeter Tyser 	ctx->state[6] += G;
18178acc472SPeter Tyser 	ctx->state[7] += H;
18278acc472SPeter Tyser }
18378acc472SPeter Tyser 
184ec7381fbSSimon Glass void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length)
18578acc472SPeter Tyser {
18678acc472SPeter Tyser 	uint32_t left, fill;
18778acc472SPeter Tyser 
18878acc472SPeter Tyser 	if (!length)
18978acc472SPeter Tyser 		return;
19078acc472SPeter Tyser 
19178acc472SPeter Tyser 	left = ctx->total[0] & 0x3F;
19278acc472SPeter Tyser 	fill = 64 - left;
19378acc472SPeter Tyser 
19478acc472SPeter Tyser 	ctx->total[0] += length;
19578acc472SPeter Tyser 	ctx->total[0] &= 0xFFFFFFFF;
19678acc472SPeter Tyser 
19778acc472SPeter Tyser 	if (ctx->total[0] < length)
19878acc472SPeter Tyser 		ctx->total[1]++;
19978acc472SPeter Tyser 
20078acc472SPeter Tyser 	if (left && length >= fill) {
20178acc472SPeter Tyser 		memcpy((void *) (ctx->buffer + left), (void *) input, fill);
20278acc472SPeter Tyser 		sha256_process(ctx, ctx->buffer);
20378acc472SPeter Tyser 		length -= fill;
20478acc472SPeter Tyser 		input += fill;
20578acc472SPeter Tyser 		left = 0;
20678acc472SPeter Tyser 	}
20778acc472SPeter Tyser 
20878acc472SPeter Tyser 	while (length >= 64) {
20978acc472SPeter Tyser 		sha256_process(ctx, input);
21078acc472SPeter Tyser 		length -= 64;
21178acc472SPeter Tyser 		input += 64;
21278acc472SPeter Tyser 	}
21378acc472SPeter Tyser 
21478acc472SPeter Tyser 	if (length)
21578acc472SPeter Tyser 		memcpy((void *) (ctx->buffer + left), (void *) input, length);
21678acc472SPeter Tyser }
21778acc472SPeter Tyser 
21878acc472SPeter Tyser static uint8_t sha256_padding[64] = {
21978acc472SPeter Tyser 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22078acc472SPeter Tyser 	   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22178acc472SPeter Tyser 	   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22278acc472SPeter Tyser 	   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
22378acc472SPeter Tyser };
22478acc472SPeter Tyser 
22578acc472SPeter Tyser void sha256_finish(sha256_context * ctx, uint8_t digest[32])
22678acc472SPeter Tyser {
22778acc472SPeter Tyser 	uint32_t last, padn;
22878acc472SPeter Tyser 	uint32_t high, low;
22978acc472SPeter Tyser 	uint8_t msglen[8];
23078acc472SPeter Tyser 
23178acc472SPeter Tyser 	high = ((ctx->total[0] >> 29)
23278acc472SPeter Tyser 		| (ctx->total[1] << 3));
23378acc472SPeter Tyser 	low = (ctx->total[0] << 3);
23478acc472SPeter Tyser 
23578acc472SPeter Tyser 	PUT_UINT32_BE(high, msglen, 0);
23678acc472SPeter Tyser 	PUT_UINT32_BE(low, msglen, 4);
23778acc472SPeter Tyser 
23878acc472SPeter Tyser 	last = ctx->total[0] & 0x3F;
23978acc472SPeter Tyser 	padn = (last < 56) ? (56 - last) : (120 - last);
24078acc472SPeter Tyser 
24178acc472SPeter Tyser 	sha256_update(ctx, sha256_padding, padn);
24278acc472SPeter Tyser 	sha256_update(ctx, msglen, 8);
24378acc472SPeter Tyser 
24478acc472SPeter Tyser 	PUT_UINT32_BE(ctx->state[0], digest, 0);
24578acc472SPeter Tyser 	PUT_UINT32_BE(ctx->state[1], digest, 4);
24678acc472SPeter Tyser 	PUT_UINT32_BE(ctx->state[2], digest, 8);
24778acc472SPeter Tyser 	PUT_UINT32_BE(ctx->state[3], digest, 12);
24878acc472SPeter Tyser 	PUT_UINT32_BE(ctx->state[4], digest, 16);
24978acc472SPeter Tyser 	PUT_UINT32_BE(ctx->state[5], digest, 20);
25078acc472SPeter Tyser 	PUT_UINT32_BE(ctx->state[6], digest, 24);
25178acc472SPeter Tyser 	PUT_UINT32_BE(ctx->state[7], digest, 28);
25278acc472SPeter Tyser }
253ec7381fbSSimon Glass 
254ec7381fbSSimon Glass /*
255ec7381fbSSimon Glass  * Output = SHA-256( input buffer ). Trigger the watchdog every 'chunk_sz'
256ec7381fbSSimon Glass  * bytes of input processed.
257ec7381fbSSimon Glass  */
258ec7381fbSSimon Glass void sha256_csum_wd(const unsigned char *input, unsigned int ilen,
259ec7381fbSSimon Glass 		unsigned char *output, unsigned int chunk_sz)
260ec7381fbSSimon Glass {
261ec7381fbSSimon Glass 	sha256_context ctx;
262ec7381fbSSimon Glass #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
2632842c1c2SHeiko Schocher 	const unsigned char *end;
2642842c1c2SHeiko Schocher 	unsigned char *curr;
265ec7381fbSSimon Glass 	int chunk;
266ec7381fbSSimon Glass #endif
267ec7381fbSSimon Glass 
268ec7381fbSSimon Glass 	sha256_starts(&ctx);
269ec7381fbSSimon Glass 
270ec7381fbSSimon Glass #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
2712842c1c2SHeiko Schocher 	curr = (unsigned char *)input;
272ec7381fbSSimon Glass 	end = input + ilen;
273ec7381fbSSimon Glass 	while (curr < end) {
274ec7381fbSSimon Glass 		chunk = end - curr;
275ec7381fbSSimon Glass 		if (chunk > chunk_sz)
276ec7381fbSSimon Glass 			chunk = chunk_sz;
277ec7381fbSSimon Glass 		sha256_update(&ctx, curr, chunk);
278ec7381fbSSimon Glass 		curr += chunk;
279ec7381fbSSimon Glass 		WATCHDOG_RESET();
280ec7381fbSSimon Glass 	}
281ec7381fbSSimon Glass #else
282ec7381fbSSimon Glass 	sha256_update(&ctx, input, ilen);
283ec7381fbSSimon Glass #endif
284ec7381fbSSimon Glass 
285ec7381fbSSimon Glass 	sha256_finish(&ctx, output);
286ec7381fbSSimon Glass }
287