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