Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Gilad Ben-Yossef and committed by
Herbert Xu
4f0fc160 1c9fa294

+379
+11
crypto/Kconfig
··· 859 859 References: 860 860 http://keccak.noekeon.org/ 861 861 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 + 862 873 config CRYPTO_TGR192 863 874 tristate "Tiger digest algorithms" 864 875 select CRYPTO_HASH
+1
crypto/Makefile
··· 70 70 obj-$(CONFIG_CRYPTO_SHA256) += sha256_generic.o 71 71 obj-$(CONFIG_CRYPTO_SHA512) += sha512_generic.o 72 72 obj-$(CONFIG_CRYPTO_SHA3) += sha3_generic.o 73 + obj-$(CONFIG_CRYPTO_SM3) += sm3_generic.o 73 74 obj-$(CONFIG_CRYPTO_WP512) += wp512.o 74 75 CFLAGS_wp512.o := $(call cc-option,-fno-schedule-insns) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79149 75 76 obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o
+210
crypto/sm3_generic.c
··· 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");
+40
include/crypto/sm3.h
··· 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
+117
include/crypto/sm3_base.h
··· 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 + }