1 /* SPDX-License-Identifier: GPL-2.0-or-later * 1 2 /* 3 * SM4, as specified in 4 * https://tools.ietf.org/id/draft-ribose-cfrg 5 * 6 * Copyright (C) 2018 ARM Limited or its affil 7 * Copyright (c) 2021 Tianjia Zhang <tianjia.z 8 */ 9 10 #include <linux/module.h> 11 #include <asm/unaligned.h> 12 #include <crypto/sm4.h> 13 14 static const u32 ____cacheline_aligned fk[4] = 15 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0x 16 }; 17 18 static const u32 ____cacheline_aligned ck[32] 19 0x00070e15, 0x1c232a31, 0x383f464d, 0x 20 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0x 21 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x 22 0x50575e65, 0x6c737a81, 0x888f969d, 0x 23 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x 24 0x30373e45, 0x4c535a61, 0x686f767d, 0x 25 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0x 26 0x10171e25, 0x2c333a41, 0x484f565d, 0x 27 }; 28 29 static const u8 ____cacheline_aligned sbox[256 30 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x 31 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x 32 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x 33 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x 34 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x 35 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0x 36 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0x 37 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x 38 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x 39 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x 40 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0x 41 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x 42 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0x 43 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x 44 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x 45 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0x 46 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x 47 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x 48 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x 49 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0x 50 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0x 51 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x 52 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x 53 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x 54 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0x 55 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x 56 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x 57 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0x 58 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x 59 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0x 60 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x 61 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x 62 }; 63 64 extern const u32 crypto_sm4_fk[4] __alias(fk); 65 extern const u32 crypto_sm4_ck[32] __alias(ck) 66 extern const u8 crypto_sm4_sbox[256] __alias(s 67 68 EXPORT_SYMBOL(crypto_sm4_fk); 69 EXPORT_SYMBOL(crypto_sm4_ck); 70 EXPORT_SYMBOL(crypto_sm4_sbox); 71 72 static inline u32 sm4_t_non_lin_sub(u32 x) 73 { 74 u32 out; 75 76 out = (u32)sbox[x & 0xff]; 77 out |= (u32)sbox[(x >> 8) & 0xff] << 8 78 out |= (u32)sbox[(x >> 16) & 0xff] << 79 out |= (u32)sbox[(x >> 24) & 0xff] << 80 81 return out; 82 } 83 84 static inline u32 sm4_key_lin_sub(u32 x) 85 { 86 return x ^ rol32(x, 13) ^ rol32(x, 23) 87 } 88 89 static inline u32 sm4_enc_lin_sub(u32 x) 90 { 91 return x ^ rol32(x, 2) ^ rol32(x, 10) 92 } 93 94 static inline u32 sm4_key_sub(u32 x) 95 { 96 return sm4_key_lin_sub(sm4_t_non_lin_s 97 } 98 99 static inline u32 sm4_enc_sub(u32 x) 100 { 101 return sm4_enc_lin_sub(sm4_t_non_lin_s 102 } 103 104 static inline u32 sm4_round(u32 x0, u32 x1, u3 105 { 106 return x0 ^ sm4_enc_sub(x1 ^ x2 ^ x3 ^ 107 } 108 109 110 /** 111 * sm4_expandkey - Expands the SM4 key as desc 112 * @ctx: The location where the compute 113 * @in_key: The supplied key. 114 * @key_len: The length of the supplied key 115 * 116 * Returns 0 on success. The function fails on 117 * pointer) is supplied. 118 */ 119 int sm4_expandkey(struct sm4_ctx *ctx, const u 120 unsigned int key_len 121 { 122 u32 rk[4]; 123 const u32 *key = (u32 *)in_key; 124 int i; 125 126 if (key_len != SM4_KEY_SIZE) 127 return -EINVAL; 128 129 rk[0] = get_unaligned_be32(&key[0]) ^ 130 rk[1] = get_unaligned_be32(&key[1]) ^ 131 rk[2] = get_unaligned_be32(&key[2]) ^ 132 rk[3] = get_unaligned_be32(&key[3]) ^ 133 134 for (i = 0; i < 32; i += 4) { 135 rk[0] ^= sm4_key_sub(rk[1] ^ r 136 rk[1] ^= sm4_key_sub(rk[2] ^ r 137 rk[2] ^= sm4_key_sub(rk[3] ^ r 138 rk[3] ^= sm4_key_sub(rk[0] ^ r 139 140 ctx->rkey_enc[i + 0] = rk[0]; 141 ctx->rkey_enc[i + 1] = rk[1]; 142 ctx->rkey_enc[i + 2] = rk[2]; 143 ctx->rkey_enc[i + 3] = rk[3]; 144 ctx->rkey_dec[31 - 0 - i] = rk 145 ctx->rkey_dec[31 - 1 - i] = rk 146 ctx->rkey_dec[31 - 2 - i] = rk 147 ctx->rkey_dec[31 - 3 - i] = rk 148 } 149 150 return 0; 151 } 152 EXPORT_SYMBOL_GPL(sm4_expandkey); 153 154 /** 155 * sm4_crypt_block - Encrypt or decrypt a sing 156 * @rk: The rkey_enc for encrypt or rk 157 * @out: Buffer to store output data 158 * @in: Buffer containing the input da 159 */ 160 void sm4_crypt_block(const u32 *rk, u8 *out, c 161 { 162 u32 x[4], i; 163 164 x[0] = get_unaligned_be32(in + 0 * 4); 165 x[1] = get_unaligned_be32(in + 1 * 4); 166 x[2] = get_unaligned_be32(in + 2 * 4); 167 x[3] = get_unaligned_be32(in + 3 * 4); 168 169 for (i = 0; i < 32; i += 4) { 170 x[0] = sm4_round(x[0], x[1], x 171 x[1] = sm4_round(x[1], x[2], x 172 x[2] = sm4_round(x[2], x[3], x 173 x[3] = sm4_round(x[3], x[0], x 174 } 175 176 put_unaligned_be32(x[3 - 0], out + 0 * 177 put_unaligned_be32(x[3 - 1], out + 1 * 178 put_unaligned_be32(x[3 - 2], out + 2 * 179 put_unaligned_be32(x[3 - 3], out + 3 * 180 } 181 EXPORT_SYMBOL_GPL(sm4_crypt_block); 182 183 MODULE_DESCRIPTION("Generic SM4 library"); 184 MODULE_LICENSE("GPL v2"); 185
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.