xref: /optee_os/core/crypto/sm3.c (revision e429c45ff395fd16b7eed44093e1a0a138373201)
147645577SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
247645577SJerome Forissier /*
347645577SJerome Forissier  * Copyright (c) 2019 Huawei Technologies Co., Ltd
447645577SJerome Forissier  */
547645577SJerome Forissier /*
647645577SJerome Forissier  * SM3 Hash algorithm
747645577SJerome Forissier  * thanks to Xyssl
847645577SJerome Forissier  * author:goldboar
947645577SJerome Forissier  * email:goldboar@163.com
1047645577SJerome Forissier  * 2011-10-26
1147645577SJerome Forissier  */
1247645577SJerome Forissier 
13664463b3SJens Wiklander #include <compiler.h>
14664463b3SJens Wiklander #include <crypto/crypto_accel.h>
1547645577SJerome Forissier #include <string_ext.h>
16664463b3SJens Wiklander #include <string.h>
1747645577SJerome Forissier 
1847645577SJerome Forissier #include "sm3.h"
1947645577SJerome Forissier 
20664463b3SJens Wiklander #define SM3_BLOCK_SIZE	64
21664463b3SJens Wiklander 
2247645577SJerome Forissier #define GET_UINT32_BE(n, b, i)				\
2347645577SJerome Forissier 	do {						\
2447645577SJerome Forissier 		(n) = ((uint32_t)(b)[(i)] << 24)     |	\
2547645577SJerome Forissier 		      ((uint32_t)(b)[(i) + 1] << 16) |	\
2647645577SJerome Forissier 		      ((uint32_t)(b)[(i) + 2] <<  8) |	\
2747645577SJerome Forissier 		      ((uint32_t)(b)[(i) + 3]);		\
2847645577SJerome Forissier 	} while (0)
2947645577SJerome Forissier 
3047645577SJerome Forissier #define PUT_UINT32_BE(n, b, i)				\
3147645577SJerome Forissier 	do {						\
3247645577SJerome Forissier 		(b)[(i)] = (uint8_t)((n) >> 24);	\
3347645577SJerome Forissier 		(b)[(i) + 1] = (uint8_t)((n) >> 16);	\
3447645577SJerome Forissier 		(b)[(i) + 2] = (uint8_t)((n) >>  8);	\
3547645577SJerome Forissier 		(b)[(i) + 3] = (uint8_t)((n));		\
3647645577SJerome Forissier 	} while (0)
3747645577SJerome Forissier 
sm3_init(struct sm3_context * ctx)3847645577SJerome Forissier void sm3_init(struct sm3_context *ctx)
3947645577SJerome Forissier {
4047645577SJerome Forissier 	ctx->total[0] = 0;
4147645577SJerome Forissier 	ctx->total[1] = 0;
4247645577SJerome Forissier 
4347645577SJerome Forissier 	ctx->state[0] = 0x7380166F;
4447645577SJerome Forissier 	ctx->state[1] = 0x4914B2B9;
4547645577SJerome Forissier 	ctx->state[2] = 0x172442D7;
4647645577SJerome Forissier 	ctx->state[3] = 0xDA8A0600;
4747645577SJerome Forissier 	ctx->state[4] = 0xA96F30BC;
4847645577SJerome Forissier 	ctx->state[5] = 0x163138AA;
4947645577SJerome Forissier 	ctx->state[6] = 0xE38DEE4D;
5047645577SJerome Forissier 	ctx->state[7] = 0xB0FB0E4E;
5147645577SJerome Forissier }
5247645577SJerome Forissier 
53*e429c45fSClement Faure #define SHL(x, n)	((x) << (n))
54*e429c45fSClement Faure 
rotl(uint32_t val,int shift)55*e429c45fSClement Faure static uint32_t rotl(uint32_t val, int shift)
56*e429c45fSClement Faure {
57*e429c45fSClement Faure 	shift &= 0x1F;
58*e429c45fSClement Faure 
59*e429c45fSClement Faure 	if (shift == 0)
60*e429c45fSClement Faure 		return val;
61*e429c45fSClement Faure 
62*e429c45fSClement Faure 	return SHL(val, shift) | (val >> (32 - shift));
63*e429c45fSClement Faure }
64*e429c45fSClement Faure 
65*e429c45fSClement Faure #define ROTL(x, n)	rotl((x), (n))
66*e429c45fSClement Faure 
sm3_process(struct sm3_context * ctx,const uint8_t data[64])67664463b3SJens Wiklander static void __maybe_unused sm3_process(struct sm3_context *ctx,
68664463b3SJens Wiklander 				       const uint8_t data[64])
6947645577SJerome Forissier {
7047645577SJerome Forissier 	uint32_t SS1, SS2, TT1, TT2, W[68], W1[64];
7147645577SJerome Forissier 	uint32_t A, B, C, D, E, F, G, H;
7247645577SJerome Forissier 	uint32_t T[64];
7347645577SJerome Forissier 	uint32_t Temp1, Temp2, Temp3, Temp4, Temp5;
7447645577SJerome Forissier 	int j;
7547645577SJerome Forissier 
7647645577SJerome Forissier 	for (j = 0; j < 16; j++)
7747645577SJerome Forissier 		T[j] = 0x79CC4519;
7847645577SJerome Forissier 	for (j = 16; j < 64; j++)
7947645577SJerome Forissier 		T[j] = 0x7A879D8A;
8047645577SJerome Forissier 
8147645577SJerome Forissier 	GET_UINT32_BE(W[0], data,  0);
8247645577SJerome Forissier 	GET_UINT32_BE(W[1], data,  4);
8347645577SJerome Forissier 	GET_UINT32_BE(W[2], data,  8);
8447645577SJerome Forissier 	GET_UINT32_BE(W[3], data, 12);
8547645577SJerome Forissier 	GET_UINT32_BE(W[4], data, 16);
8647645577SJerome Forissier 	GET_UINT32_BE(W[5], data, 20);
8747645577SJerome Forissier 	GET_UINT32_BE(W[6], data, 24);
8847645577SJerome Forissier 	GET_UINT32_BE(W[7], data, 28);
8947645577SJerome Forissier 	GET_UINT32_BE(W[8], data, 32);
9047645577SJerome Forissier 	GET_UINT32_BE(W[9], data, 36);
9147645577SJerome Forissier 	GET_UINT32_BE(W[10], data, 40);
9247645577SJerome Forissier 	GET_UINT32_BE(W[11], data, 44);
9347645577SJerome Forissier 	GET_UINT32_BE(W[12], data, 48);
9447645577SJerome Forissier 	GET_UINT32_BE(W[13], data, 52);
9547645577SJerome Forissier 	GET_UINT32_BE(W[14], data, 56);
9647645577SJerome Forissier 	GET_UINT32_BE(W[15], data, 60);
9747645577SJerome Forissier 
9847645577SJerome Forissier #define FF0(x, y, z)	((x) ^ (y) ^ (z))
9947645577SJerome Forissier #define FF1(x, y, z)	(((x) & (y)) | ((x) & (z)) | ((y) & (z)))
10047645577SJerome Forissier 
10147645577SJerome Forissier #define GG0(x, y, z)	((x) ^ (y) ^ (z))
10247645577SJerome Forissier #define GG1(x, y, z)	(((x) & (y)) | ((~(x)) & (z)))
10347645577SJerome Forissier 
10447645577SJerome Forissier #define P0(x)	((x) ^ ROTL((x), 9) ^ ROTL((x), 17))
10547645577SJerome Forissier #define P1(x)	((x) ^ ROTL((x), 15) ^ ROTL((x), 23))
10647645577SJerome Forissier 
10747645577SJerome Forissier 	for (j = 16; j < 68; j++) {
10847645577SJerome Forissier 		/*
10947645577SJerome Forissier 		 * W[j] = P1( W[j-16] ^ W[j-9] ^ ROTL(W[j-3],15)) ^
11047645577SJerome Forissier 		 *        ROTL(W[j - 13],7 ) ^ W[j-6];
11147645577SJerome Forissier 		 */
11247645577SJerome Forissier 
11347645577SJerome Forissier 		Temp1 = W[j - 16] ^ W[j - 9];
11447645577SJerome Forissier 		Temp2 = ROTL(W[j - 3], 15);
11547645577SJerome Forissier 		Temp3 = Temp1 ^ Temp2;
11647645577SJerome Forissier 		Temp4 = P1(Temp3);
11747645577SJerome Forissier 		Temp5 =  ROTL(W[j - 13], 7) ^ W[j - 6];
11847645577SJerome Forissier 		W[j] = Temp4 ^ Temp5;
11947645577SJerome Forissier 	}
12047645577SJerome Forissier 
12147645577SJerome Forissier 	for (j =  0; j < 64; j++)
12247645577SJerome Forissier 		W1[j] = W[j] ^ W[j + 4];
12347645577SJerome Forissier 
12447645577SJerome Forissier 	A = ctx->state[0];
12547645577SJerome Forissier 	B = ctx->state[1];
12647645577SJerome Forissier 	C = ctx->state[2];
12747645577SJerome Forissier 	D = ctx->state[3];
12847645577SJerome Forissier 	E = ctx->state[4];
12947645577SJerome Forissier 	F = ctx->state[5];
13047645577SJerome Forissier 	G = ctx->state[6];
13147645577SJerome Forissier 	H = ctx->state[7];
13247645577SJerome Forissier 
13347645577SJerome Forissier 	for (j = 0; j < 16; j++) {
13447645577SJerome Forissier 		SS1 = ROTL(ROTL(A, 12) + E + ROTL(T[j], j), 7);
13547645577SJerome Forissier 		SS2 = SS1 ^ ROTL(A, 12);
13647645577SJerome Forissier 		TT1 = FF0(A, B, C) + D + SS2 + W1[j];
13747645577SJerome Forissier 		TT2 = GG0(E, F, G) + H + SS1 + W[j];
13847645577SJerome Forissier 		D = C;
13947645577SJerome Forissier 		C = ROTL(B, 9);
14047645577SJerome Forissier 		B = A;
14147645577SJerome Forissier 		A = TT1;
14247645577SJerome Forissier 		H = G;
14347645577SJerome Forissier 		G = ROTL(F, 19);
14447645577SJerome Forissier 		F = E;
14547645577SJerome Forissier 		E = P0(TT2);
14647645577SJerome Forissier 	}
14747645577SJerome Forissier 
14847645577SJerome Forissier 	for (j = 16; j < 64; j++) {
14947645577SJerome Forissier 		SS1 = ROTL(ROTL(A, 12) + E + ROTL(T[j], j), 7);
15047645577SJerome Forissier 		SS2 = SS1 ^ ROTL(A, 12);
15147645577SJerome Forissier 		TT1 = FF1(A, B, C) + D + SS2 + W1[j];
15247645577SJerome Forissier 		TT2 = GG1(E, F, G) + H + SS1 + W[j];
15347645577SJerome Forissier 		D = C;
15447645577SJerome Forissier 		C = ROTL(B, 9);
15547645577SJerome Forissier 		B = A;
15647645577SJerome Forissier 		A = TT1;
15747645577SJerome Forissier 		H = G;
15847645577SJerome Forissier 		G = ROTL(F, 19);
15947645577SJerome Forissier 		F = E;
16047645577SJerome Forissier 		E = P0(TT2);
16147645577SJerome Forissier 	}
16247645577SJerome Forissier 
16347645577SJerome Forissier 	ctx->state[0] ^= A;
16447645577SJerome Forissier 	ctx->state[1] ^= B;
16547645577SJerome Forissier 	ctx->state[2] ^= C;
16647645577SJerome Forissier 	ctx->state[3] ^= D;
16747645577SJerome Forissier 	ctx->state[4] ^= E;
16847645577SJerome Forissier 	ctx->state[5] ^= F;
16947645577SJerome Forissier 	ctx->state[6] ^= G;
17047645577SJerome Forissier 	ctx->state[7] ^= H;
17147645577SJerome Forissier }
17247645577SJerome Forissier 
sm3_process_blocks(struct sm3_context * ctx,const uint8_t * input,unsigned int block_count)173664463b3SJens Wiklander static void sm3_process_blocks(struct sm3_context *ctx, const uint8_t *input,
174664463b3SJens Wiklander 			       unsigned int block_count)
175664463b3SJens Wiklander {
176664463b3SJens Wiklander #ifdef CFG_CRYPTO_SM3_ARM_CE
177664463b3SJens Wiklander 	if (block_count)
178664463b3SJens Wiklander 		crypto_accel_sm3_compress(ctx->state, input, block_count);
179664463b3SJens Wiklander #else
180664463b3SJens Wiklander 	unsigned int n = 0;
181664463b3SJens Wiklander 
182664463b3SJens Wiklander 	for (n = 0; n < block_count; n++)
183664463b3SJens Wiklander 		sm3_process(ctx, input + n * SM3_BLOCK_SIZE);
184664463b3SJens Wiklander #endif
185664463b3SJens Wiklander }
186664463b3SJens Wiklander 
sm3_update(struct sm3_context * ctx,const uint8_t * input,size_t ilen)18747645577SJerome Forissier void sm3_update(struct sm3_context *ctx, const uint8_t *input, size_t ilen)
18847645577SJerome Forissier {
189664463b3SJens Wiklander 	unsigned int block_count = 0;
190664463b3SJens Wiklander 	size_t fill = 0;
191664463b3SJens Wiklander 	size_t left = 0;
19247645577SJerome Forissier 
19347645577SJerome Forissier 	if (!ilen)
19447645577SJerome Forissier 		return;
19547645577SJerome Forissier 
19647645577SJerome Forissier 	left = ctx->total[0] & 0x3F;
19747645577SJerome Forissier 	fill = 64 - left;
19847645577SJerome Forissier 
19947645577SJerome Forissier 	ctx->total[0] += ilen;
20047645577SJerome Forissier 
20147645577SJerome Forissier 	if (ctx->total[0] < ilen)
20247645577SJerome Forissier 		ctx->total[1]++;
20347645577SJerome Forissier 
20447645577SJerome Forissier 	if (left && ilen >= fill) {
20547645577SJerome Forissier 		memcpy(ctx->buffer + left, input, fill);
206664463b3SJens Wiklander 		sm3_process_blocks(ctx, ctx->buffer, 1);
20747645577SJerome Forissier 		input += fill;
20847645577SJerome Forissier 		ilen -= fill;
20947645577SJerome Forissier 		left = 0;
21047645577SJerome Forissier 	}
21147645577SJerome Forissier 
212664463b3SJens Wiklander 	block_count = ilen / SM3_BLOCK_SIZE;
213664463b3SJens Wiklander 	sm3_process_blocks(ctx, input, block_count);
214664463b3SJens Wiklander 	ilen -= block_count * SM3_BLOCK_SIZE;
215664463b3SJens Wiklander 	input += block_count * SM3_BLOCK_SIZE;
21647645577SJerome Forissier 
21747645577SJerome Forissier 	if (ilen > 0)
21847645577SJerome Forissier 		memcpy(ctx->buffer + left, input, ilen);
21947645577SJerome Forissier }
22047645577SJerome Forissier 
22147645577SJerome Forissier static const uint8_t sm3_padding[64] = {
22247645577SJerome Forissier 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22347645577SJerome Forissier 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22447645577SJerome Forissier 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22547645577SJerome Forissier 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
22647645577SJerome Forissier };
22747645577SJerome Forissier 
sm3_final(struct sm3_context * ctx,uint8_t output[32])22847645577SJerome Forissier void sm3_final(struct sm3_context *ctx, uint8_t output[32])
22947645577SJerome Forissier {
23047645577SJerome Forissier 	uint32_t last, padn;
23147645577SJerome Forissier 	uint32_t high, low;
23247645577SJerome Forissier 	uint8_t msglen[8];
23347645577SJerome Forissier 
23447645577SJerome Forissier 	high = (ctx->total[0] >> 29) | (ctx->total[1] <<  3);
23547645577SJerome Forissier 	low  = ctx->total[0] << 3;
23647645577SJerome Forissier 
23747645577SJerome Forissier 	PUT_UINT32_BE(high, msglen, 0);
23847645577SJerome Forissier 	PUT_UINT32_BE(low,  msglen, 4);
23947645577SJerome Forissier 
24047645577SJerome Forissier 	last = ctx->total[0] & 0x3F;
24147645577SJerome Forissier 	padn = (last < 56) ? (56 - last) : (120 - last);
24247645577SJerome Forissier 
24347645577SJerome Forissier 	sm3_update(ctx, sm3_padding, padn);
24447645577SJerome Forissier 	sm3_update(ctx, msglen, 8);
24547645577SJerome Forissier 
24647645577SJerome Forissier 	PUT_UINT32_BE(ctx->state[0], output,  0);
24747645577SJerome Forissier 	PUT_UINT32_BE(ctx->state[1], output,  4);
24847645577SJerome Forissier 	PUT_UINT32_BE(ctx->state[2], output,  8);
24947645577SJerome Forissier 	PUT_UINT32_BE(ctx->state[3], output, 12);
25047645577SJerome Forissier 	PUT_UINT32_BE(ctx->state[4], output, 16);
25147645577SJerome Forissier 	PUT_UINT32_BE(ctx->state[5], output, 20);
25247645577SJerome Forissier 	PUT_UINT32_BE(ctx->state[6], output, 24);
25347645577SJerome Forissier 	PUT_UINT32_BE(ctx->state[7], output, 28);
25447645577SJerome Forissier }
25547645577SJerome Forissier 
sm3(const uint8_t * input,size_t ilen,uint8_t output[32])25647645577SJerome Forissier void sm3(const uint8_t *input, size_t ilen, uint8_t output[32])
25747645577SJerome Forissier {
25847645577SJerome Forissier 	struct sm3_context ctx = { };
25947645577SJerome Forissier 
26047645577SJerome Forissier 	sm3_init(&ctx);
26147645577SJerome Forissier 	sm3_update(&ctx, input, ilen);
26247645577SJerome Forissier 	sm3_final(&ctx, output);
26347645577SJerome Forissier 
26447645577SJerome Forissier 	memzero_explicit(&ctx, sizeof(ctx));
26547645577SJerome Forissier }
26647645577SJerome Forissier 
sm3_hmac_init(struct sm3_context * ctx,const uint8_t * key,size_t keylen)26747645577SJerome Forissier void sm3_hmac_init(struct sm3_context *ctx, const uint8_t *key, size_t keylen)
26847645577SJerome Forissier {
26947645577SJerome Forissier 	size_t i;
27047645577SJerome Forissier 	uint8_t sum[32];
27147645577SJerome Forissier 
27247645577SJerome Forissier 	if (keylen > 64) {
27347645577SJerome Forissier 		sm3(key, keylen, sum);
27447645577SJerome Forissier 		keylen = 32;
27547645577SJerome Forissier 		key = sum;
27647645577SJerome Forissier 	}
27747645577SJerome Forissier 
27847645577SJerome Forissier 	memset(ctx->ipad, 0x36, 64);
27947645577SJerome Forissier 	memset(ctx->opad, 0x5C, 64);
28047645577SJerome Forissier 
28147645577SJerome Forissier 	for (i = 0; i < keylen; i++) {
28247645577SJerome Forissier 		ctx->ipad[i] ^= key[i];
28347645577SJerome Forissier 		ctx->opad[i] ^= key[i];
28447645577SJerome Forissier 	}
28547645577SJerome Forissier 
28647645577SJerome Forissier 	sm3_init(ctx);
28747645577SJerome Forissier 	sm3_update(ctx, ctx->ipad, 64);
28847645577SJerome Forissier 
28947645577SJerome Forissier 	memzero_explicit(sum, sizeof(sum));
29047645577SJerome Forissier }
29147645577SJerome Forissier 
sm3_hmac_update(struct sm3_context * ctx,const uint8_t * input,size_t ilen)29247645577SJerome Forissier void sm3_hmac_update(struct sm3_context *ctx, const uint8_t *input, size_t ilen)
29347645577SJerome Forissier {
29447645577SJerome Forissier 	sm3_update(ctx, input, ilen);
29547645577SJerome Forissier }
29647645577SJerome Forissier 
sm3_hmac_final(struct sm3_context * ctx,uint8_t output[32])29747645577SJerome Forissier void sm3_hmac_final(struct sm3_context *ctx, uint8_t output[32])
29847645577SJerome Forissier {
29947645577SJerome Forissier 	uint8_t tmpbuf[32];
30047645577SJerome Forissier 
30147645577SJerome Forissier 	sm3_final(ctx, tmpbuf);
30247645577SJerome Forissier 	sm3_init(ctx);
30347645577SJerome Forissier 	sm3_update(ctx, ctx->opad, 64);
30447645577SJerome Forissier 	sm3_update(ctx, tmpbuf, 32);
30547645577SJerome Forissier 	sm3_final(ctx, output);
30647645577SJerome Forissier 
30747645577SJerome Forissier 	memzero_explicit(tmpbuf, sizeof(tmpbuf));
30847645577SJerome Forissier }
30947645577SJerome Forissier 
sm3_hmac(const uint8_t * key,size_t keylen,const uint8_t * input,size_t ilen,uint8_t output[32])31047645577SJerome Forissier void sm3_hmac(const uint8_t *key, size_t keylen, const uint8_t *input,
31147645577SJerome Forissier 	      size_t ilen, uint8_t output[32])
31247645577SJerome Forissier {
31347645577SJerome Forissier 	struct sm3_context ctx;
31447645577SJerome Forissier 
31547645577SJerome Forissier 	sm3_hmac_init(&ctx, key, keylen);
31647645577SJerome Forissier 	sm3_hmac_update(&ctx, input, ilen);
31747645577SJerome Forissier 	sm3_hmac_final(&ctx, output);
31847645577SJerome Forissier 
31947645577SJerome Forissier 	memzero_explicit(&ctx, sizeof(ctx));
32047645577SJerome Forissier }
321