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