Skip to content

Commit 4f0fc16

Browse files
Gilad Ben-Yossefherbertx
authored andcommitted
crypto: sm3 - add OSCCA SM3 secure hash
Add OSCCA SM3 secure hash (OSCCA GM/T 0004-2012 SM3) generic hash transformation. Signed-off-by: Gilad Ben-Yossef <gilad@benyossef.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent 1c9fa29 commit 4f0fc16

File tree

5 files changed

+379
-0
lines changed

5 files changed

+379
-0
lines changed

crypto/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,17 @@ config CRYPTO_SHA3
859859
References:
860860
http://keccak.noekeon.org/
861861

862+
config CRYPTO_SM3
863+
tristate "SM3 digest algorithm"
864+
select CRYPTO_HASH
865+
help
866+
SM3 secure hash function as defined by OSCCA GM/T 0004-2012 SM3).
867+
It is part of the Chinese Commercial Cryptography suite.
868+
869+
References:
870+
http://www.oscca.gov.cn/UpFile/20101222141857786.pdf
871+
https://datatracker.ietf.org/doc/html/draft-shen-sm3-hash
872+
862873
config CRYPTO_TGR192
863874
tristate "Tiger digest algorithms"
864875
select CRYPTO_HASH

crypto/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ obj-$(CONFIG_CRYPTO_SHA1) += sha1_generic.o
7070
obj-$(CONFIG_CRYPTO_SHA256) += sha256_generic.o
7171
obj-$(CONFIG_CRYPTO_SHA512) += sha512_generic.o
7272
obj-$(CONFIG_CRYPTO_SHA3) += sha3_generic.o
73+
obj-$(CONFIG_CRYPTO_SM3) += sm3_generic.o
7374
obj-$(CONFIG_CRYPTO_WP512) += wp512.o
7475
CFLAGS_wp512.o := $(call cc-option,-fno-schedule-insns) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79149
7576
obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o

crypto/sm3_generic.c

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
/*
2+
* SM3 secure hash, as specified by OSCCA GM/T 0004-2012 SM3 and
3+
* described at https://tools.ietf.org/html/draft-shen-sm3-hash-01
4+
*
5+
* Copyright (C) 2017 ARM Limited or its affiliates.
6+
* Written by Gilad Ben-Yossef <gilad@benyossef.com>
7+
*
8+
* This program is free software; you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License version 2 as
10+
* published by the Free Software Foundation.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program; if not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
21+
#include <crypto/internal/hash.h>
22+
#include <linux/init.h>
23+
#include <linux/module.h>
24+
#include <linux/mm.h>
25+
#include <linux/types.h>
26+
#include <crypto/sm3.h>
27+
#include <crypto/sm3_base.h>
28+
#include <linux/bitops.h>
29+
#include <asm/byteorder.h>
30+
#include <asm/unaligned.h>
31+
32+
const u8 sm3_zero_message_hash[SM3_DIGEST_SIZE] = {
33+
0x1A, 0xB2, 0x1D, 0x83, 0x55, 0xCF, 0xA1, 0x7F,
34+
0x8e, 0x61, 0x19, 0x48, 0x31, 0xE8, 0x1A, 0x8F,
35+
0x22, 0xBE, 0xC8, 0xC7, 0x28, 0xFE, 0xFB, 0x74,
36+
0x7E, 0xD0, 0x35, 0xEB, 0x50, 0x82, 0xAA, 0x2B
37+
};
38+
EXPORT_SYMBOL_GPL(sm3_zero_message_hash);
39+
40+
static inline u32 p0(u32 x)
41+
{
42+
return x ^ rol32(x, 9) ^ rol32(x, 17);
43+
}
44+
45+
static inline u32 p1(u32 x)
46+
{
47+
return x ^ rol32(x, 15) ^ rol32(x, 23);
48+
}
49+
50+
static inline u32 ff(unsigned int n, u32 a, u32 b, u32 c)
51+
{
52+
return (n < 16) ? (a ^ b ^ c) : ((a & b) | (a & c) | (b & c));
53+
}
54+
55+
static inline u32 gg(unsigned int n, u32 e, u32 f, u32 g)
56+
{
57+
return (n < 16) ? (e ^ f ^ g) : ((e & f) | ((~e) & g));
58+
}
59+
60+
static inline u32 t(unsigned int n)
61+
{
62+
return (n < 16) ? SM3_T1 : SM3_T2;
63+
}
64+
65+
static void sm3_expand(u32 *t, u32 *w, u32 *wt)
66+
{
67+
int i;
68+
unsigned int tmp;
69+
70+
/* load the input */
71+
for (i = 0; i <= 15; i++)
72+
w[i] = get_unaligned_be32((__u32 *)t + i);
73+
74+
for (i = 16; i <= 67; i++) {
75+
tmp = w[i - 16] ^ w[i - 9] ^ rol32(w[i - 3], 15);
76+
w[i] = p1(tmp) ^ (rol32(w[i - 13], 7)) ^ w[i - 6];
77+
}
78+
79+
for (i = 0; i <= 63; i++)
80+
wt[i] = w[i] ^ w[i + 4];
81+
}
82+
83+
static void sm3_compress(u32 *w, u32 *wt, u32 *m)
84+
{
85+
u32 ss1;
86+
u32 ss2;
87+
u32 tt1;
88+
u32 tt2;
89+
u32 a, b, c, d, e, f, g, h;
90+
int i;
91+
92+
a = m[0];
93+
b = m[1];
94+
c = m[2];
95+
d = m[3];
96+
e = m[4];
97+
f = m[5];
98+
g = m[6];
99+
h = m[7];
100+
101+
for (i = 0; i <= 63; i++) {
102+
103+
ss1 = rol32((rol32(a, 12) + e + rol32(t(i), i)), 7);
104+
105+
ss2 = ss1 ^ rol32(a, 12);
106+
107+
tt1 = ff(i, a, b, c) + d + ss2 + *wt;
108+
wt++;
109+
110+
tt2 = gg(i, e, f, g) + h + ss1 + *w;
111+
w++;
112+
113+
d = c;
114+
c = rol32(b, 9);
115+
b = a;
116+
a = tt1;
117+
h = g;
118+
g = rol32(f, 19);
119+
f = e;
120+
e = p0(tt2);
121+
}
122+
123+
m[0] = a ^ m[0];
124+
m[1] = b ^ m[1];
125+
m[2] = c ^ m[2];
126+
m[3] = d ^ m[3];
127+
m[4] = e ^ m[4];
128+
m[5] = f ^ m[5];
129+
m[6] = g ^ m[6];
130+
m[7] = h ^ m[7];
131+
132+
a = b = c = d = e = f = g = h = ss1 = ss2 = tt1 = tt2 = 0;
133+
}
134+
135+
static void sm3_transform(struct sm3_state *sst, u8 const *src)
136+
{
137+
unsigned int w[68];
138+
unsigned int wt[64];
139+
140+
sm3_expand((u32 *)src, w, wt);
141+
sm3_compress(w, wt, sst->state);
142+
143+
memzero_explicit(w, sizeof(w));
144+
memzero_explicit(wt, sizeof(wt));
145+
}
146+
147+
static void sm3_generic_block_fn(struct sm3_state *sst, u8 const *src,
148+
int blocks)
149+
{
150+
while (blocks--) {
151+
sm3_transform(sst, src);
152+
src += SM3_BLOCK_SIZE;
153+
}
154+
}
155+
156+
int crypto_sm3_update(struct shash_desc *desc, const u8 *data,
157+
unsigned int len)
158+
{
159+
return sm3_base_do_update(desc, data, len, sm3_generic_block_fn);
160+
}
161+
EXPORT_SYMBOL(crypto_sm3_update);
162+
163+
static int sm3_final(struct shash_desc *desc, u8 *out)
164+
{
165+
sm3_base_do_finalize(desc, sm3_generic_block_fn);
166+
return sm3_base_finish(desc, out);
167+
}
168+
169+
int crypto_sm3_finup(struct shash_desc *desc, const u8 *data,
170+
unsigned int len, u8 *hash)
171+
{
172+
sm3_base_do_update(desc, data, len, sm3_generic_block_fn);
173+
return sm3_final(desc, hash);
174+
}
175+
EXPORT_SYMBOL(crypto_sm3_finup);
176+
177+
static struct shash_alg sm3_alg = {
178+
.digestsize = SM3_DIGEST_SIZE,
179+
.init = sm3_base_init,
180+
.update = crypto_sm3_update,
181+
.final = sm3_final,
182+
.finup = crypto_sm3_finup,
183+
.descsize = sizeof(struct sm3_state),
184+
.base = {
185+
.cra_name = "sm3",
186+
.cra_driver_name = "sm3-generic",
187+
.cra_flags = CRYPTO_ALG_TYPE_SHASH,
188+
.cra_blocksize = SM3_BLOCK_SIZE,
189+
.cra_module = THIS_MODULE,
190+
}
191+
};
192+
193+
static int __init sm3_generic_mod_init(void)
194+
{
195+
return crypto_register_shash(&sm3_alg);
196+
}
197+
198+
static void __exit sm3_generic_mod_fini(void)
199+
{
200+
crypto_unregister_shash(&sm3_alg);
201+
}
202+
203+
module_init(sm3_generic_mod_init);
204+
module_exit(sm3_generic_mod_fini);
205+
206+
MODULE_LICENSE("GPL v2");
207+
MODULE_DESCRIPTION("SM3 Secure Hash Algorithm");
208+
209+
MODULE_ALIAS_CRYPTO("sm3");
210+
MODULE_ALIAS_CRYPTO("sm3-generic");

include/crypto/sm3.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Common values for SM3 algorithm
3+
*/
4+
5+
#ifndef _CRYPTO_SM3_H
6+
#define _CRYPTO_SM3_H
7+
8+
#include <linux/types.h>
9+
10+
#define SM3_DIGEST_SIZE 32
11+
#define SM3_BLOCK_SIZE 64
12+
13+
#define SM3_T1 0x79CC4519
14+
#define SM3_T2 0x7A879D8A
15+
16+
#define SM3_IVA 0x7380166f
17+
#define SM3_IVB 0x4914b2b9
18+
#define SM3_IVC 0x172442d7
19+
#define SM3_IVD 0xda8a0600
20+
#define SM3_IVE 0xa96f30bc
21+
#define SM3_IVF 0x163138aa
22+
#define SM3_IVG 0xe38dee4d
23+
#define SM3_IVH 0xb0fb0e4e
24+
25+
extern const u8 sm3_zero_message_hash[SM3_DIGEST_SIZE];
26+
27+
struct sm3_state {
28+
u32 state[SM3_DIGEST_SIZE / 4];
29+
u64 count;
30+
u8 buffer[SM3_BLOCK_SIZE];
31+
};
32+
33+
struct shash_desc;
34+
35+
extern int crypto_sm3_update(struct shash_desc *desc, const u8 *data,
36+
unsigned int len);
37+
38+
extern int crypto_sm3_finup(struct shash_desc *desc, const u8 *data,
39+
unsigned int len, u8 *hash);
40+
#endif

include/crypto/sm3_base.h

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* sm3_base.h - core logic for SM3 implementations
3+
*
4+
* Copyright (C) 2017 ARM Limited or its affiliates.
5+
* Written by Gilad Ben-Yossef <gilad@benyossef.com>
6+
*
7+
* This program is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License version 2 as
9+
* published by the Free Software Foundation.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program; if not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#include <crypto/internal/hash.h>
21+
#include <crypto/sm3.h>
22+
#include <linux/crypto.h>
23+
#include <linux/module.h>
24+
#include <asm/unaligned.h>
25+
26+
typedef void (sm3_block_fn)(struct sm3_state *sst, u8 const *src, int blocks);
27+
28+
static inline int sm3_base_init(struct shash_desc *desc)
29+
{
30+
struct sm3_state *sctx = shash_desc_ctx(desc);
31+
32+
sctx->state[0] = SM3_IVA;
33+
sctx->state[1] = SM3_IVB;
34+
sctx->state[2] = SM3_IVC;
35+
sctx->state[3] = SM3_IVD;
36+
sctx->state[4] = SM3_IVE;
37+
sctx->state[5] = SM3_IVF;
38+
sctx->state[6] = SM3_IVG;
39+
sctx->state[7] = SM3_IVH;
40+
sctx->count = 0;
41+
42+
return 0;
43+
}
44+
45+
static inline int sm3_base_do_update(struct shash_desc *desc,
46+
const u8 *data,
47+
unsigned int len,
48+
sm3_block_fn *block_fn)
49+
{
50+
struct sm3_state *sctx = shash_desc_ctx(desc);
51+
unsigned int partial = sctx->count % SM3_BLOCK_SIZE;
52+
53+
sctx->count += len;
54+
55+
if (unlikely((partial + len) >= SM3_BLOCK_SIZE)) {
56+
int blocks;
57+
58+
if (partial) {
59+
int p = SM3_BLOCK_SIZE - partial;
60+
61+
memcpy(sctx->buffer + partial, data, p);
62+
data += p;
63+
len -= p;
64+
65+
block_fn(sctx, sctx->buffer, 1);
66+
}
67+
68+
blocks = len / SM3_BLOCK_SIZE;
69+
len %= SM3_BLOCK_SIZE;
70+
71+
if (blocks) {
72+
block_fn(sctx, data, blocks);
73+
data += blocks * SM3_BLOCK_SIZE;
74+
}
75+
partial = 0;
76+
}
77+
if (len)
78+
memcpy(sctx->buffer + partial, data, len);
79+
80+
return 0;
81+
}
82+
83+
static inline int sm3_base_do_finalize(struct shash_desc *desc,
84+
sm3_block_fn *block_fn)
85+
{
86+
const int bit_offset = SM3_BLOCK_SIZE - sizeof(__be64);
87+
struct sm3_state *sctx = shash_desc_ctx(desc);
88+
__be64 *bits = (__be64 *)(sctx->buffer + bit_offset);
89+
unsigned int partial = sctx->count % SM3_BLOCK_SIZE;
90+
91+
sctx->buffer[partial++] = 0x80;
92+
if (partial > bit_offset) {
93+
memset(sctx->buffer + partial, 0x0, SM3_BLOCK_SIZE - partial);
94+
partial = 0;
95+
96+
block_fn(sctx, sctx->buffer, 1);
97+
}
98+
99+
memset(sctx->buffer + partial, 0x0, bit_offset - partial);
100+
*bits = cpu_to_be64(sctx->count << 3);
101+
block_fn(sctx, sctx->buffer, 1);
102+
103+
return 0;
104+
}
105+
106+
static inline int sm3_base_finish(struct shash_desc *desc, u8 *out)
107+
{
108+
struct sm3_state *sctx = shash_desc_ctx(desc);
109+
__be32 *digest = (__be32 *)out;
110+
int i;
111+
112+
for (i = 0; i < SM3_DIGEST_SIZE / sizeof(__be32); i++)
113+
put_unaligned_be32(sctx->state[i], digest++);
114+
115+
*sctx = (struct sm3_state){};
116+
return 0;
117+
}

0 commit comments

Comments
 (0)