1 // SPDX-License-Identifier: GPL-2.0-only 1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 2 /* 3 * SM3 secure hash, as specified by OSCCA GM/T 3 * SM3 secure hash, as specified by OSCCA GM/T 0004-2012 SM3 and 4 * described at https://tools.ietf.org/html/dr 4 * described at https://tools.ietf.org/html/draft-shen-sm3-hash-01 5 * 5 * 6 * Copyright (C) 2017 ARM Limited or its affil 6 * Copyright (C) 2017 ARM Limited or its affiliates. 7 * Written by Gilad Ben-Yossef <gilad@benyosse 7 * Written by Gilad Ben-Yossef <gilad@benyossef.com> 8 * Copyright (C) 2021 Tianjia Zhang <tianjia.z << 9 */ 8 */ 10 9 11 #include <crypto/internal/hash.h> 10 #include <crypto/internal/hash.h> 12 #include <linux/init.h> 11 #include <linux/init.h> 13 #include <linux/module.h> 12 #include <linux/module.h> 14 #include <linux/mm.h> 13 #include <linux/mm.h> 15 #include <linux/types.h> 14 #include <linux/types.h> 16 #include <crypto/sm3.h> 15 #include <crypto/sm3.h> 17 #include <crypto/sm3_base.h> 16 #include <crypto/sm3_base.h> 18 #include <linux/bitops.h> 17 #include <linux/bitops.h> 19 #include <asm/byteorder.h> 18 #include <asm/byteorder.h> 20 #include <asm/unaligned.h> 19 #include <asm/unaligned.h> 21 20 22 const u8 sm3_zero_message_hash[SM3_DIGEST_SIZE 21 const u8 sm3_zero_message_hash[SM3_DIGEST_SIZE] = { 23 0x1A, 0xB2, 0x1D, 0x83, 0x55, 0xCF, 0x 22 0x1A, 0xB2, 0x1D, 0x83, 0x55, 0xCF, 0xA1, 0x7F, 24 0x8e, 0x61, 0x19, 0x48, 0x31, 0xE8, 0x 23 0x8e, 0x61, 0x19, 0x48, 0x31, 0xE8, 0x1A, 0x8F, 25 0x22, 0xBE, 0xC8, 0xC7, 0x28, 0xFE, 0x 24 0x22, 0xBE, 0xC8, 0xC7, 0x28, 0xFE, 0xFB, 0x74, 26 0x7E, 0xD0, 0x35, 0xEB, 0x50, 0x82, 0x 25 0x7E, 0xD0, 0x35, 0xEB, 0x50, 0x82, 0xAA, 0x2B 27 }; 26 }; 28 EXPORT_SYMBOL_GPL(sm3_zero_message_hash); 27 EXPORT_SYMBOL_GPL(sm3_zero_message_hash); 29 28 30 static int crypto_sm3_update(struct shash_desc !! 29 static inline u32 p0(u32 x) >> 30 { >> 31 return x ^ rol32(x, 9) ^ rol32(x, 17); >> 32 } >> 33 >> 34 static inline u32 p1(u32 x) >> 35 { >> 36 return x ^ rol32(x, 15) ^ rol32(x, 23); >> 37 } >> 38 >> 39 static inline u32 ff(unsigned int n, u32 a, u32 b, u32 c) >> 40 { >> 41 return (n < 16) ? (a ^ b ^ c) : ((a & b) | (a & c) | (b & c)); >> 42 } >> 43 >> 44 static inline u32 gg(unsigned int n, u32 e, u32 f, u32 g) >> 45 { >> 46 return (n < 16) ? (e ^ f ^ g) : ((e & f) | ((~e) & g)); >> 47 } >> 48 >> 49 static inline u32 t(unsigned int n) >> 50 { >> 51 return (n < 16) ? SM3_T1 : SM3_T2; >> 52 } >> 53 >> 54 static void sm3_expand(u32 *t, u32 *w, u32 *wt) >> 55 { >> 56 int i; >> 57 unsigned int tmp; >> 58 >> 59 /* load the input */ >> 60 for (i = 0; i <= 15; i++) >> 61 w[i] = get_unaligned_be32((__u32 *)t + i); >> 62 >> 63 for (i = 16; i <= 67; i++) { >> 64 tmp = w[i - 16] ^ w[i - 9] ^ rol32(w[i - 3], 15); >> 65 w[i] = p1(tmp) ^ (rol32(w[i - 13], 7)) ^ w[i - 6]; >> 66 } >> 67 >> 68 for (i = 0; i <= 63; i++) >> 69 wt[i] = w[i] ^ w[i + 4]; >> 70 } >> 71 >> 72 static void sm3_compress(u32 *w, u32 *wt, u32 *m) >> 73 { >> 74 u32 ss1; >> 75 u32 ss2; >> 76 u32 tt1; >> 77 u32 tt2; >> 78 u32 a, b, c, d, e, f, g, h; >> 79 int i; >> 80 >> 81 a = m[0]; >> 82 b = m[1]; >> 83 c = m[2]; >> 84 d = m[3]; >> 85 e = m[4]; >> 86 f = m[5]; >> 87 g = m[6]; >> 88 h = m[7]; >> 89 >> 90 for (i = 0; i <= 63; i++) { >> 91 >> 92 ss1 = rol32((rol32(a, 12) + e + rol32(t(i), i & 31)), 7); >> 93 >> 94 ss2 = ss1 ^ rol32(a, 12); >> 95 >> 96 tt1 = ff(i, a, b, c) + d + ss2 + *wt; >> 97 wt++; >> 98 >> 99 tt2 = gg(i, e, f, g) + h + ss1 + *w; >> 100 w++; >> 101 >> 102 d = c; >> 103 c = rol32(b, 9); >> 104 b = a; >> 105 a = tt1; >> 106 h = g; >> 107 g = rol32(f, 19); >> 108 f = e; >> 109 e = p0(tt2); >> 110 } >> 111 >> 112 m[0] = a ^ m[0]; >> 113 m[1] = b ^ m[1]; >> 114 m[2] = c ^ m[2]; >> 115 m[3] = d ^ m[3]; >> 116 m[4] = e ^ m[4]; >> 117 m[5] = f ^ m[5]; >> 118 m[6] = g ^ m[6]; >> 119 m[7] = h ^ m[7]; >> 120 >> 121 a = b = c = d = e = f = g = h = ss1 = ss2 = tt1 = tt2 = 0; >> 122 } >> 123 >> 124 static void sm3_transform(struct sm3_state *sst, u8 const *src) >> 125 { >> 126 unsigned int w[68]; >> 127 unsigned int wt[64]; >> 128 >> 129 sm3_expand((u32 *)src, w, wt); >> 130 sm3_compress(w, wt, sst->state); >> 131 >> 132 memzero_explicit(w, sizeof(w)); >> 133 memzero_explicit(wt, sizeof(wt)); >> 134 } >> 135 >> 136 static void sm3_generic_block_fn(struct sm3_state *sst, u8 const *src, >> 137 int blocks) >> 138 { >> 139 while (blocks--) { >> 140 sm3_transform(sst, src); >> 141 src += SM3_BLOCK_SIZE; >> 142 } >> 143 } >> 144 >> 145 int crypto_sm3_update(struct shash_desc *desc, const u8 *data, 31 unsigned int len) 146 unsigned int len) 32 { 147 { 33 sm3_update(shash_desc_ctx(desc), data, !! 148 return sm3_base_do_update(desc, data, len, sm3_generic_block_fn); 34 return 0; << 35 } 149 } >> 150 EXPORT_SYMBOL(crypto_sm3_update); 36 151 37 static int crypto_sm3_final(struct shash_desc !! 152 int crypto_sm3_final(struct shash_desc *desc, u8 *out) 38 { 153 { 39 sm3_final(shash_desc_ctx(desc), out); !! 154 sm3_base_do_finalize(desc, sm3_generic_block_fn); 40 return 0; !! 155 return sm3_base_finish(desc, out); 41 } 156 } >> 157 EXPORT_SYMBOL(crypto_sm3_final); 42 158 43 static int crypto_sm3_finup(struct shash_desc !! 159 int crypto_sm3_finup(struct shash_desc *desc, const u8 *data, 44 unsigned int len, u8 * 160 unsigned int len, u8 *hash) 45 { 161 { 46 struct sm3_state *sctx = shash_desc_ct !! 162 sm3_base_do_update(desc, data, len, sm3_generic_block_fn); 47 !! 163 return crypto_sm3_final(desc, hash); 48 if (len) << 49 sm3_update(sctx, data, len); << 50 sm3_final(sctx, hash); << 51 return 0; << 52 } 164 } >> 165 EXPORT_SYMBOL(crypto_sm3_finup); 53 166 54 static struct shash_alg sm3_alg = { 167 static struct shash_alg sm3_alg = { 55 .digestsize = SM3_DIGEST_SIZ 168 .digestsize = SM3_DIGEST_SIZE, 56 .init = sm3_base_init, 169 .init = sm3_base_init, 57 .update = crypto_sm3_upd 170 .update = crypto_sm3_update, 58 .final = crypto_sm3_fin 171 .final = crypto_sm3_final, 59 .finup = crypto_sm3_fin 172 .finup = crypto_sm3_finup, 60 .descsize = sizeof(struct 173 .descsize = sizeof(struct sm3_state), 61 .base = { 174 .base = { 62 .cra_name = "sm3", 175 .cra_name = "sm3", 63 .cra_driver_name = "sm3-g 176 .cra_driver_name = "sm3-generic", 64 .cra_priority = 100, << 65 .cra_blocksize = SM3_BL 177 .cra_blocksize = SM3_BLOCK_SIZE, 66 .cra_module = THIS_M 178 .cra_module = THIS_MODULE, 67 } 179 } 68 }; 180 }; 69 181 70 static int __init sm3_generic_mod_init(void) 182 static int __init sm3_generic_mod_init(void) 71 { 183 { 72 return crypto_register_shash(&sm3_alg) 184 return crypto_register_shash(&sm3_alg); 73 } 185 } 74 186 75 static void __exit sm3_generic_mod_fini(void) 187 static void __exit sm3_generic_mod_fini(void) 76 { 188 { 77 crypto_unregister_shash(&sm3_alg); 189 crypto_unregister_shash(&sm3_alg); 78 } 190 } 79 191 80 subsys_initcall(sm3_generic_mod_init); 192 subsys_initcall(sm3_generic_mod_init); 81 module_exit(sm3_generic_mod_fini); 193 module_exit(sm3_generic_mod_fini); 82 194 83 MODULE_LICENSE("GPL v2"); 195 MODULE_LICENSE("GPL v2"); 84 MODULE_DESCRIPTION("SM3 Secure Hash Algorithm" 196 MODULE_DESCRIPTION("SM3 Secure Hash Algorithm"); 85 197 86 MODULE_ALIAS_CRYPTO("sm3"); 198 MODULE_ALIAS_CRYPTO("sm3"); 87 MODULE_ALIAS_CRYPTO("sm3-generic"); 199 MODULE_ALIAS_CRYPTO("sm3-generic"); 88 200
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.