xref: /linux/crypto/sm3.c (revision d2825fa9)
1d2825fa9SJason A. Donenfeld /* SPDX-License-Identifier: GPL-2.0-only */
2d2825fa9SJason A. Donenfeld /*
3d2825fa9SJason A. Donenfeld  * SM3 secure hash, as specified by OSCCA GM/T 0004-2012 SM3 and described
4d2825fa9SJason A. Donenfeld  * at https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3-02
5d2825fa9SJason A. Donenfeld  *
6d2825fa9SJason A. Donenfeld  * Copyright (C) 2017 ARM Limited or its affiliates.
7d2825fa9SJason A. Donenfeld  * Copyright (C) 2017 Gilad Ben-Yossef <gilad@benyossef.com>
8d2825fa9SJason A. Donenfeld  * Copyright (C) 2021 Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
9d2825fa9SJason A. Donenfeld  */
10d2825fa9SJason A. Donenfeld 
11d2825fa9SJason A. Donenfeld #include <linux/module.h>
12d2825fa9SJason A. Donenfeld #include <asm/unaligned.h>
13d2825fa9SJason A. Donenfeld #include <crypto/sm3.h>
14d2825fa9SJason A. Donenfeld 
15d2825fa9SJason A. Donenfeld static const u32 ____cacheline_aligned K[64] = {
16d2825fa9SJason A. Donenfeld 	0x79cc4519, 0xf3988a32, 0xe7311465, 0xce6228cb,
17d2825fa9SJason A. Donenfeld 	0x9cc45197, 0x3988a32f, 0x7311465e, 0xe6228cbc,
18d2825fa9SJason A. Donenfeld 	0xcc451979, 0x988a32f3, 0x311465e7, 0x6228cbce,
19d2825fa9SJason A. Donenfeld 	0xc451979c, 0x88a32f39, 0x11465e73, 0x228cbce6,
20d2825fa9SJason A. Donenfeld 	0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c,
21d2825fa9SJason A. Donenfeld 	0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce,
22d2825fa9SJason A. Donenfeld 	0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec,
23d2825fa9SJason A. Donenfeld 	0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5,
24d2825fa9SJason A. Donenfeld 	0x7a879d8a, 0xf50f3b14, 0xea1e7629, 0xd43cec53,
25d2825fa9SJason A. Donenfeld 	0xa879d8a7, 0x50f3b14f, 0xa1e7629e, 0x43cec53d,
26d2825fa9SJason A. Donenfeld 	0x879d8a7a, 0x0f3b14f5, 0x1e7629ea, 0x3cec53d4,
27d2825fa9SJason A. Donenfeld 	0x79d8a7a8, 0xf3b14f50, 0xe7629ea1, 0xcec53d43,
28d2825fa9SJason A. Donenfeld 	0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c,
29d2825fa9SJason A. Donenfeld 	0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce,
30d2825fa9SJason A. Donenfeld 	0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec,
31d2825fa9SJason A. Donenfeld 	0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5
32d2825fa9SJason A. Donenfeld };
33d2825fa9SJason A. Donenfeld 
34d2825fa9SJason A. Donenfeld /*
35d2825fa9SJason A. Donenfeld  * Transform the message X which consists of 16 32-bit-words. See
36d2825fa9SJason A. Donenfeld  * GM/T 004-2012 for details.
37d2825fa9SJason A. Donenfeld  */
38d2825fa9SJason A. Donenfeld #define R(i, a, b, c, d, e, f, g, h, t, w1, w2)			\
39d2825fa9SJason A. Donenfeld 	do {							\
40d2825fa9SJason A. Donenfeld 		ss1 = rol32((rol32((a), 12) + (e) + (t)), 7);	\
41d2825fa9SJason A. Donenfeld 		ss2 = ss1 ^ rol32((a), 12);			\
42d2825fa9SJason A. Donenfeld 		d += FF ## i(a, b, c) + ss2 + ((w1) ^ (w2));	\
43d2825fa9SJason A. Donenfeld 		h += GG ## i(e, f, g) + ss1 + (w1);		\
44d2825fa9SJason A. Donenfeld 		b = rol32((b), 9);				\
45d2825fa9SJason A. Donenfeld 		f = rol32((f), 19);				\
46d2825fa9SJason A. Donenfeld 		h = P0((h));					\
47d2825fa9SJason A. Donenfeld 	} while (0)
48d2825fa9SJason A. Donenfeld 
49d2825fa9SJason A. Donenfeld #define R1(a, b, c, d, e, f, g, h, t, w1, w2) \
50d2825fa9SJason A. Donenfeld 	R(1, a, b, c, d, e, f, g, h, t, w1, w2)
51d2825fa9SJason A. Donenfeld #define R2(a, b, c, d, e, f, g, h, t, w1, w2) \
52d2825fa9SJason A. Donenfeld 	R(2, a, b, c, d, e, f, g, h, t, w1, w2)
53d2825fa9SJason A. Donenfeld 
54d2825fa9SJason A. Donenfeld #define FF1(x, y, z)  (x ^ y ^ z)
55d2825fa9SJason A. Donenfeld #define FF2(x, y, z)  ((x & y) | (x & z) | (y & z))
56d2825fa9SJason A. Donenfeld 
57d2825fa9SJason A. Donenfeld #define GG1(x, y, z)  FF1(x, y, z)
58d2825fa9SJason A. Donenfeld #define GG2(x, y, z)  ((x & y) | (~x & z))
59d2825fa9SJason A. Donenfeld 
60d2825fa9SJason A. Donenfeld /* Message expansion */
61d2825fa9SJason A. Donenfeld #define P0(x) ((x) ^ rol32((x), 9) ^ rol32((x), 17))
62d2825fa9SJason A. Donenfeld #define P1(x) ((x) ^ rol32((x), 15) ^ rol32((x), 23))
63d2825fa9SJason A. Donenfeld #define I(i)  (W[i] = get_unaligned_be32(data + i * 4))
64d2825fa9SJason A. Donenfeld #define W1(i) (W[i & 0x0f])
65d2825fa9SJason A. Donenfeld #define W2(i) (W[i & 0x0f] =				\
66d2825fa9SJason A. Donenfeld 		P1(W[i & 0x0f]				\
67d2825fa9SJason A. Donenfeld 			^ W[(i-9) & 0x0f]		\
68d2825fa9SJason A. Donenfeld 			^ rol32(W[(i-3) & 0x0f], 15))	\
69d2825fa9SJason A. Donenfeld 		^ rol32(W[(i-13) & 0x0f], 7)		\
70d2825fa9SJason A. Donenfeld 		^ W[(i-6) & 0x0f])
71d2825fa9SJason A. Donenfeld 
sm3_transform(struct sm3_state * sctx,u8 const * data,u32 W[16])72d2825fa9SJason A. Donenfeld static void sm3_transform(struct sm3_state *sctx, u8 const *data, u32 W[16])
73d2825fa9SJason A. Donenfeld {
74d2825fa9SJason A. Donenfeld 	u32 a, b, c, d, e, f, g, h, ss1, ss2;
75d2825fa9SJason A. Donenfeld 
76d2825fa9SJason A. Donenfeld 	a = sctx->state[0];
77d2825fa9SJason A. Donenfeld 	b = sctx->state[1];
78d2825fa9SJason A. Donenfeld 	c = sctx->state[2];
79d2825fa9SJason A. Donenfeld 	d = sctx->state[3];
80d2825fa9SJason A. Donenfeld 	e = sctx->state[4];
81d2825fa9SJason A. Donenfeld 	f = sctx->state[5];
82d2825fa9SJason A. Donenfeld 	g = sctx->state[6];
83d2825fa9SJason A. Donenfeld 	h = sctx->state[7];
84d2825fa9SJason A. Donenfeld 
85d2825fa9SJason A. Donenfeld 	R1(a, b, c, d, e, f, g, h, K[0], I(0), I(4));
86d2825fa9SJason A. Donenfeld 	R1(d, a, b, c, h, e, f, g, K[1], I(1), I(5));
87d2825fa9SJason A. Donenfeld 	R1(c, d, a, b, g, h, e, f, K[2], I(2), I(6));
88d2825fa9SJason A. Donenfeld 	R1(b, c, d, a, f, g, h, e, K[3], I(3), I(7));
89d2825fa9SJason A. Donenfeld 	R1(a, b, c, d, e, f, g, h, K[4], W1(4), I(8));
90d2825fa9SJason A. Donenfeld 	R1(d, a, b, c, h, e, f, g, K[5], W1(5), I(9));
91d2825fa9SJason A. Donenfeld 	R1(c, d, a, b, g, h, e, f, K[6], W1(6), I(10));
92d2825fa9SJason A. Donenfeld 	R1(b, c, d, a, f, g, h, e, K[7], W1(7), I(11));
93d2825fa9SJason A. Donenfeld 	R1(a, b, c, d, e, f, g, h, K[8], W1(8), I(12));
94d2825fa9SJason A. Donenfeld 	R1(d, a, b, c, h, e, f, g, K[9], W1(9), I(13));
95d2825fa9SJason A. Donenfeld 	R1(c, d, a, b, g, h, e, f, K[10], W1(10), I(14));
96d2825fa9SJason A. Donenfeld 	R1(b, c, d, a, f, g, h, e, K[11], W1(11), I(15));
97d2825fa9SJason A. Donenfeld 	R1(a, b, c, d, e, f, g, h, K[12], W1(12), W2(16));
98d2825fa9SJason A. Donenfeld 	R1(d, a, b, c, h, e, f, g, K[13], W1(13), W2(17));
99d2825fa9SJason A. Donenfeld 	R1(c, d, a, b, g, h, e, f, K[14], W1(14), W2(18));
100d2825fa9SJason A. Donenfeld 	R1(b, c, d, a, f, g, h, e, K[15], W1(15), W2(19));
101d2825fa9SJason A. Donenfeld 
102d2825fa9SJason A. Donenfeld 	R2(a, b, c, d, e, f, g, h, K[16], W1(16), W2(20));
103d2825fa9SJason A. Donenfeld 	R2(d, a, b, c, h, e, f, g, K[17], W1(17), W2(21));
104d2825fa9SJason A. Donenfeld 	R2(c, d, a, b, g, h, e, f, K[18], W1(18), W2(22));
105d2825fa9SJason A. Donenfeld 	R2(b, c, d, a, f, g, h, e, K[19], W1(19), W2(23));
106d2825fa9SJason A. Donenfeld 	R2(a, b, c, d, e, f, g, h, K[20], W1(20), W2(24));
107d2825fa9SJason A. Donenfeld 	R2(d, a, b, c, h, e, f, g, K[21], W1(21), W2(25));
108d2825fa9SJason A. Donenfeld 	R2(c, d, a, b, g, h, e, f, K[22], W1(22), W2(26));
109d2825fa9SJason A. Donenfeld 	R2(b, c, d, a, f, g, h, e, K[23], W1(23), W2(27));
110d2825fa9SJason A. Donenfeld 	R2(a, b, c, d, e, f, g, h, K[24], W1(24), W2(28));
111d2825fa9SJason A. Donenfeld 	R2(d, a, b, c, h, e, f, g, K[25], W1(25), W2(29));
112d2825fa9SJason A. Donenfeld 	R2(c, d, a, b, g, h, e, f, K[26], W1(26), W2(30));
113d2825fa9SJason A. Donenfeld 	R2(b, c, d, a, f, g, h, e, K[27], W1(27), W2(31));
114d2825fa9SJason A. Donenfeld 	R2(a, b, c, d, e, f, g, h, K[28], W1(28), W2(32));
115d2825fa9SJason A. Donenfeld 	R2(d, a, b, c, h, e, f, g, K[29], W1(29), W2(33));
116d2825fa9SJason A. Donenfeld 	R2(c, d, a, b, g, h, e, f, K[30], W1(30), W2(34));
117d2825fa9SJason A. Donenfeld 	R2(b, c, d, a, f, g, h, e, K[31], W1(31), W2(35));
118d2825fa9SJason A. Donenfeld 
119d2825fa9SJason A. Donenfeld 	R2(a, b, c, d, e, f, g, h, K[32], W1(32), W2(36));
120d2825fa9SJason A. Donenfeld 	R2(d, a, b, c, h, e, f, g, K[33], W1(33), W2(37));
121d2825fa9SJason A. Donenfeld 	R2(c, d, a, b, g, h, e, f, K[34], W1(34), W2(38));
122d2825fa9SJason A. Donenfeld 	R2(b, c, d, a, f, g, h, e, K[35], W1(35), W2(39));
123d2825fa9SJason A. Donenfeld 	R2(a, b, c, d, e, f, g, h, K[36], W1(36), W2(40));
124d2825fa9SJason A. Donenfeld 	R2(d, a, b, c, h, e, f, g, K[37], W1(37), W2(41));
125d2825fa9SJason A. Donenfeld 	R2(c, d, a, b, g, h, e, f, K[38], W1(38), W2(42));
126d2825fa9SJason A. Donenfeld 	R2(b, c, d, a, f, g, h, e, K[39], W1(39), W2(43));
127d2825fa9SJason A. Donenfeld 	R2(a, b, c, d, e, f, g, h, K[40], W1(40), W2(44));
128d2825fa9SJason A. Donenfeld 	R2(d, a, b, c, h, e, f, g, K[41], W1(41), W2(45));
129d2825fa9SJason A. Donenfeld 	R2(c, d, a, b, g, h, e, f, K[42], W1(42), W2(46));
130d2825fa9SJason A. Donenfeld 	R2(b, c, d, a, f, g, h, e, K[43], W1(43), W2(47));
131d2825fa9SJason A. Donenfeld 	R2(a, b, c, d, e, f, g, h, K[44], W1(44), W2(48));
132d2825fa9SJason A. Donenfeld 	R2(d, a, b, c, h, e, f, g, K[45], W1(45), W2(49));
133d2825fa9SJason A. Donenfeld 	R2(c, d, a, b, g, h, e, f, K[46], W1(46), W2(50));
134d2825fa9SJason A. Donenfeld 	R2(b, c, d, a, f, g, h, e, K[47], W1(47), W2(51));
135d2825fa9SJason A. Donenfeld 
136d2825fa9SJason A. Donenfeld 	R2(a, b, c, d, e, f, g, h, K[48], W1(48), W2(52));
137d2825fa9SJason A. Donenfeld 	R2(d, a, b, c, h, e, f, g, K[49], W1(49), W2(53));
138d2825fa9SJason A. Donenfeld 	R2(c, d, a, b, g, h, e, f, K[50], W1(50), W2(54));
139d2825fa9SJason A. Donenfeld 	R2(b, c, d, a, f, g, h, e, K[51], W1(51), W2(55));
140d2825fa9SJason A. Donenfeld 	R2(a, b, c, d, e, f, g, h, K[52], W1(52), W2(56));
141d2825fa9SJason A. Donenfeld 	R2(d, a, b, c, h, e, f, g, K[53], W1(53), W2(57));
142d2825fa9SJason A. Donenfeld 	R2(c, d, a, b, g, h, e, f, K[54], W1(54), W2(58));
143d2825fa9SJason A. Donenfeld 	R2(b, c, d, a, f, g, h, e, K[55], W1(55), W2(59));
144d2825fa9SJason A. Donenfeld 	R2(a, b, c, d, e, f, g, h, K[56], W1(56), W2(60));
145d2825fa9SJason A. Donenfeld 	R2(d, a, b, c, h, e, f, g, K[57], W1(57), W2(61));
146d2825fa9SJason A. Donenfeld 	R2(c, d, a, b, g, h, e, f, K[58], W1(58), W2(62));
147d2825fa9SJason A. Donenfeld 	R2(b, c, d, a, f, g, h, e, K[59], W1(59), W2(63));
148d2825fa9SJason A. Donenfeld 	R2(a, b, c, d, e, f, g, h, K[60], W1(60), W2(64));
149d2825fa9SJason A. Donenfeld 	R2(d, a, b, c, h, e, f, g, K[61], W1(61), W2(65));
150d2825fa9SJason A. Donenfeld 	R2(c, d, a, b, g, h, e, f, K[62], W1(62), W2(66));
151d2825fa9SJason A. Donenfeld 	R2(b, c, d, a, f, g, h, e, K[63], W1(63), W2(67));
152d2825fa9SJason A. Donenfeld 
153d2825fa9SJason A. Donenfeld 	sctx->state[0] ^= a;
154d2825fa9SJason A. Donenfeld 	sctx->state[1] ^= b;
155d2825fa9SJason A. Donenfeld 	sctx->state[2] ^= c;
156d2825fa9SJason A. Donenfeld 	sctx->state[3] ^= d;
157d2825fa9SJason A. Donenfeld 	sctx->state[4] ^= e;
158d2825fa9SJason A. Donenfeld 	sctx->state[5] ^= f;
159d2825fa9SJason A. Donenfeld 	sctx->state[6] ^= g;
160d2825fa9SJason A. Donenfeld 	sctx->state[7] ^= h;
161d2825fa9SJason A. Donenfeld }
162d2825fa9SJason A. Donenfeld #undef R
163d2825fa9SJason A. Donenfeld #undef R1
164d2825fa9SJason A. Donenfeld #undef R2
165d2825fa9SJason A. Donenfeld #undef I
166d2825fa9SJason A. Donenfeld #undef W1
167d2825fa9SJason A. Donenfeld #undef W2
168d2825fa9SJason A. Donenfeld 
sm3_block(struct sm3_state * sctx,u8 const * data,int blocks,u32 W[16])169d2825fa9SJason A. Donenfeld static inline void sm3_block(struct sm3_state *sctx,
170d2825fa9SJason A. Donenfeld 		u8 const *data, int blocks, u32 W[16])
171d2825fa9SJason A. Donenfeld {
172d2825fa9SJason A. Donenfeld 	while (blocks--) {
173d2825fa9SJason A. Donenfeld 		sm3_transform(sctx, data, W);
174d2825fa9SJason A. Donenfeld 		data += SM3_BLOCK_SIZE;
175d2825fa9SJason A. Donenfeld 	}
176d2825fa9SJason A. Donenfeld }
177d2825fa9SJason A. Donenfeld 
sm3_update(struct sm3_state * sctx,const u8 * data,unsigned int len)178d2825fa9SJason A. Donenfeld void sm3_update(struct sm3_state *sctx, const u8 *data, unsigned int len)
179d2825fa9SJason A. Donenfeld {
180d2825fa9SJason A. Donenfeld 	unsigned int partial = sctx->count % SM3_BLOCK_SIZE;
181d2825fa9SJason A. Donenfeld 	u32 W[16];
182d2825fa9SJason A. Donenfeld 
183d2825fa9SJason A. Donenfeld 	sctx->count += len;
184d2825fa9SJason A. Donenfeld 
185d2825fa9SJason A. Donenfeld 	if ((partial + len) >= SM3_BLOCK_SIZE) {
186d2825fa9SJason A. Donenfeld 		int blocks;
187d2825fa9SJason A. Donenfeld 
188d2825fa9SJason A. Donenfeld 		if (partial) {
189d2825fa9SJason A. Donenfeld 			int p = SM3_BLOCK_SIZE - partial;
190d2825fa9SJason A. Donenfeld 
191d2825fa9SJason A. Donenfeld 			memcpy(sctx->buffer + partial, data, p);
192d2825fa9SJason A. Donenfeld 			data += p;
193d2825fa9SJason A. Donenfeld 			len -= p;
194d2825fa9SJason A. Donenfeld 
195d2825fa9SJason A. Donenfeld 			sm3_block(sctx, sctx->buffer, 1, W);
196d2825fa9SJason A. Donenfeld 		}
197d2825fa9SJason A. Donenfeld 
198d2825fa9SJason A. Donenfeld 		blocks = len / SM3_BLOCK_SIZE;
199d2825fa9SJason A. Donenfeld 		len %= SM3_BLOCK_SIZE;
200d2825fa9SJason A. Donenfeld 
201d2825fa9SJason A. Donenfeld 		if (blocks) {
202d2825fa9SJason A. Donenfeld 			sm3_block(sctx, data, blocks, W);
203d2825fa9SJason A. Donenfeld 			data += blocks * SM3_BLOCK_SIZE;
204d2825fa9SJason A. Donenfeld 		}
205d2825fa9SJason A. Donenfeld 
206d2825fa9SJason A. Donenfeld 		memzero_explicit(W, sizeof(W));
207d2825fa9SJason A. Donenfeld 
208d2825fa9SJason A. Donenfeld 		partial = 0;
209d2825fa9SJason A. Donenfeld 	}
210d2825fa9SJason A. Donenfeld 	if (len)
211d2825fa9SJason A. Donenfeld 		memcpy(sctx->buffer + partial, data, len);
212d2825fa9SJason A. Donenfeld }
213d2825fa9SJason A. Donenfeld EXPORT_SYMBOL_GPL(sm3_update);
214d2825fa9SJason A. Donenfeld 
sm3_final(struct sm3_state * sctx,u8 * out)215d2825fa9SJason A. Donenfeld void sm3_final(struct sm3_state *sctx, u8 *out)
216d2825fa9SJason A. Donenfeld {
217d2825fa9SJason A. Donenfeld 	const int bit_offset = SM3_BLOCK_SIZE - sizeof(u64);
218d2825fa9SJason A. Donenfeld 	__be64 *bits = (__be64 *)(sctx->buffer + bit_offset);
219d2825fa9SJason A. Donenfeld 	__be32 *digest = (__be32 *)out;
220d2825fa9SJason A. Donenfeld 	unsigned int partial = sctx->count % SM3_BLOCK_SIZE;
221d2825fa9SJason A. Donenfeld 	u32 W[16];
222d2825fa9SJason A. Donenfeld 	int i;
223d2825fa9SJason A. Donenfeld 
224d2825fa9SJason A. Donenfeld 	sctx->buffer[partial++] = 0x80;
225d2825fa9SJason A. Donenfeld 	if (partial > bit_offset) {
226d2825fa9SJason A. Donenfeld 		memset(sctx->buffer + partial, 0, SM3_BLOCK_SIZE - partial);
227d2825fa9SJason A. Donenfeld 		partial = 0;
228d2825fa9SJason A. Donenfeld 
229d2825fa9SJason A. Donenfeld 		sm3_block(sctx, sctx->buffer, 1, W);
230d2825fa9SJason A. Donenfeld 	}
231d2825fa9SJason A. Donenfeld 
232d2825fa9SJason A. Donenfeld 	memset(sctx->buffer + partial, 0, bit_offset - partial);
233d2825fa9SJason A. Donenfeld 	*bits = cpu_to_be64(sctx->count << 3);
234d2825fa9SJason A. Donenfeld 	sm3_block(sctx, sctx->buffer, 1, W);
235d2825fa9SJason A. Donenfeld 
236d2825fa9SJason A. Donenfeld 	for (i = 0; i < 8; i++)
237d2825fa9SJason A. Donenfeld 		put_unaligned_be32(sctx->state[i], digest++);
238d2825fa9SJason A. Donenfeld 
239d2825fa9SJason A. Donenfeld 	/* Zeroize sensitive information. */
240d2825fa9SJason A. Donenfeld 	memzero_explicit(W, sizeof(W));
241d2825fa9SJason A. Donenfeld 	memzero_explicit(sctx, sizeof(*sctx));
242d2825fa9SJason A. Donenfeld }
243d2825fa9SJason A. Donenfeld EXPORT_SYMBOL_GPL(sm3_final);
244d2825fa9SJason A. Donenfeld 
245d2825fa9SJason A. Donenfeld MODULE_DESCRIPTION("Generic SM3 library");
246d2825fa9SJason A. Donenfeld MODULE_LICENSE("GPL v2");
247