Merge tag 'csky-for-linus-6.4' of https://github.com/c-sky/csky-linux
[linux-block.git] / crypto / sm4.c
CommitLineData
2b31277a
TZ
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * SM4, as specified in
4 * https://tools.ietf.org/id/draft-ribose-cfrg-sm4-10.html
5 *
6 * Copyright (C) 2018 ARM Limited or its affiliates.
7 * Copyright (c) 2021 Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
8 */
9
10#include <linux/module.h>
11#include <asm/unaligned.h>
12#include <crypto/sm4.h>
13
73c919d3 14static const u32 ____cacheline_aligned fk[4] = {
2b31277a
TZ
15 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc
16};
17
4a7e1e5f 18static const u32 ____cacheline_aligned ck[32] = {
2b31277a
TZ
19 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
20 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
21 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
22 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
23 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
24 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
25 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
26 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
27};
28
4a7e1e5f 29static const u8 ____cacheline_aligned sbox[256] = {
2b31277a
TZ
30 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7,
31 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
32 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3,
33 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
34 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a,
35 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
36 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95,
37 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
38 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba,
39 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
40 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b,
41 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
42 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2,
43 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
44 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52,
45 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
46 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5,
47 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
48 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,
49 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
50 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60,
51 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
52 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f,
53 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
54 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f,
55 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
56 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd,
57 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
58 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e,
59 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
60 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20,
61 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48
62};
63
73c919d3
TZ
64extern const u32 crypto_sm4_fk[4] __alias(fk);
65extern const u32 crypto_sm4_ck[32] __alias(ck);
66extern const u8 crypto_sm4_sbox[256] __alias(sbox);
67
68EXPORT_SYMBOL(crypto_sm4_fk);
69EXPORT_SYMBOL(crypto_sm4_ck);
70EXPORT_SYMBOL(crypto_sm4_sbox);
71
2b31277a
TZ
72static 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] << 16;
79 out |= (u32)sbox[(x >> 24) & 0xff] << 24;
80
81 return out;
82}
83
84static inline u32 sm4_key_lin_sub(u32 x)
85{
86 return x ^ rol32(x, 13) ^ rol32(x, 23);
87}
88
89static inline u32 sm4_enc_lin_sub(u32 x)
90{
91 return x ^ rol32(x, 2) ^ rol32(x, 10) ^ rol32(x, 18) ^ rol32(x, 24);
92}
93
94static inline u32 sm4_key_sub(u32 x)
95{
96 return sm4_key_lin_sub(sm4_t_non_lin_sub(x));
97}
98
99static inline u32 sm4_enc_sub(u32 x)
100{
101 return sm4_enc_lin_sub(sm4_t_non_lin_sub(x));
102}
103
104static inline u32 sm4_round(u32 x0, u32 x1, u32 x2, u32 x3, u32 rk)
105{
106 return x0 ^ sm4_enc_sub(x1 ^ x2 ^ x3 ^ rk);
107}
108
109
110/**
111 * sm4_expandkey - Expands the SM4 key as described in GB/T 32907-2016
112 * @ctx: The location where the computed key will be stored.
113 * @in_key: The supplied key.
114 * @key_len: The length of the supplied key.
115 *
116 * Returns 0 on success. The function fails only if an invalid key size (or
117 * pointer) is supplied.
118 */
c59de48e 119int sm4_expandkey(struct sm4_ctx *ctx, const u8 *in_key,
2b31277a
TZ
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]) ^ fk[0];
130 rk[1] = get_unaligned_be32(&key[1]) ^ fk[1];
131 rk[2] = get_unaligned_be32(&key[2]) ^ fk[2];
132 rk[3] = get_unaligned_be32(&key[3]) ^ fk[3];
133
134 for (i = 0; i < 32; i += 4) {
135 rk[0] ^= sm4_key_sub(rk[1] ^ rk[2] ^ rk[3] ^ ck[i + 0]);
136 rk[1] ^= sm4_key_sub(rk[2] ^ rk[3] ^ rk[0] ^ ck[i + 1]);
137 rk[2] ^= sm4_key_sub(rk[3] ^ rk[0] ^ rk[1] ^ ck[i + 2]);
138 rk[3] ^= sm4_key_sub(rk[0] ^ rk[1] ^ rk[2] ^ ck[i + 3]);
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[0];
145 ctx->rkey_dec[31 - 1 - i] = rk[1];
146 ctx->rkey_dec[31 - 2 - i] = rk[2];
147 ctx->rkey_dec[31 - 3 - i] = rk[3];
148 }
149
150 return 0;
151}
152EXPORT_SYMBOL_GPL(sm4_expandkey);
153
154/**
155 * sm4_crypt_block - Encrypt or decrypt a single SM4 block
156 * @rk: The rkey_enc for encrypt or rkey_dec for decrypt
157 * @out: Buffer to store output data
158 * @in: Buffer containing the input data
159 */
160void sm4_crypt_block(const u32 *rk, u8 *out, const u8 *in)
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[2], x[3], rk[i + 0]);
171 x[1] = sm4_round(x[1], x[2], x[3], x[0], rk[i + 1]);
172 x[2] = sm4_round(x[2], x[3], x[0], x[1], rk[i + 2]);
173 x[3] = sm4_round(x[3], x[0], x[1], x[2], rk[i + 3]);
174 }
175
176 put_unaligned_be32(x[3 - 0], out + 0 * 4);
177 put_unaligned_be32(x[3 - 1], out + 1 * 4);
178 put_unaligned_be32(x[3 - 2], out + 2 * 4);
179 put_unaligned_be32(x[3 - 3], out + 3 * 4);
180}
181EXPORT_SYMBOL_GPL(sm4_crypt_block);
182
183MODULE_DESCRIPTION("Generic SM4 library");
184MODULE_LICENSE("GPL v2");