/src/nettle-with-mini-gmp/sm4.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* sm4.c |
2 | | |
3 | | Copyright (C) 2022 Tianjia Zhang <tianjia.zhang@linux.alibaba.com> |
4 | | |
5 | | This file is part of GNU Nettle. |
6 | | |
7 | | GNU Nettle is free software: you can redistribute it and/or |
8 | | modify it under the terms of either: |
9 | | |
10 | | * the GNU Lesser General Public License as published by the Free |
11 | | Software Foundation; either version 3 of the License, or (at your |
12 | | option) any later version. |
13 | | |
14 | | or |
15 | | |
16 | | * the GNU General Public License as published by the Free |
17 | | Software Foundation; either version 2 of the License, or (at your |
18 | | option) any later version. |
19 | | |
20 | | or both in parallel, as here. |
21 | | |
22 | | GNU Nettle is distributed in the hope that it will be useful, |
23 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
24 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
25 | | General Public License for more details. |
26 | | |
27 | | You should have received copies of the GNU General Public License and |
28 | | the GNU Lesser General Public License along with this program. If |
29 | | not, see http://www.gnu.org/licenses/. |
30 | | */ |
31 | | |
32 | | #if HAVE_CONFIG_H |
33 | | # include "config.h" |
34 | | #endif |
35 | | |
36 | | #include <assert.h> |
37 | | #include <string.h> |
38 | | |
39 | | #include "sm4.h" |
40 | | |
41 | | #include "macros.h" |
42 | | |
43 | | |
44 | | static const uint32_t fk[4] = |
45 | | { |
46 | | 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc |
47 | | }; |
48 | | |
49 | | static const uint32_t ck[32] = |
50 | | { |
51 | | 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, |
52 | | 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, |
53 | | 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, |
54 | | 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, |
55 | | 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, |
56 | | 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, |
57 | | 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, |
58 | | 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 |
59 | | }; |
60 | | |
61 | | static const uint8_t sbox[256] = |
62 | | { |
63 | | 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, |
64 | | 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, |
65 | | 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, |
66 | | 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, |
67 | | 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, |
68 | | 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, |
69 | | 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, |
70 | | 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, |
71 | | 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, |
72 | | 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8, |
73 | | 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, |
74 | | 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35, |
75 | | 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, |
76 | | 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, |
77 | | 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, |
78 | | 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, |
79 | | 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, |
80 | | 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, |
81 | | 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, |
82 | | 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, |
83 | | 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, |
84 | | 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f, |
85 | | 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, |
86 | | 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, |
87 | | 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, |
88 | | 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, |
89 | | 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, |
90 | | 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, |
91 | | 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, |
92 | | 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, |
93 | | 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, |
94 | | 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48 |
95 | | }; |
96 | | |
97 | | static uint32_t |
98 | | sm4_t_non_lin_sub(uint32_t x) |
99 | 59.9k | { |
100 | 59.9k | uint32_t out; |
101 | | |
102 | 59.9k | out = (uint32_t)sbox[x & 0xff]; |
103 | 59.9k | out |= (uint32_t)sbox[(x >> 8) & 0xff] << 8; |
104 | 59.9k | out |= (uint32_t)sbox[(x >> 16) & 0xff] << 16; |
105 | 59.9k | out |= (uint32_t)sbox[(x >> 24) & 0xff] << 24; |
106 | | |
107 | 59.9k | return out; |
108 | 59.9k | } |
109 | | |
110 | | static uint32_t |
111 | | sm4_key_lin_sub(uint32_t x) |
112 | 8.67k | { |
113 | 8.67k | return x ^ ROTL32(13, x) ^ ROTL32(23, x); |
114 | 8.67k | } |
115 | | |
116 | | static uint32_t |
117 | | sm4_enc_lin_sub(uint32_t x) |
118 | 51.2k | { |
119 | 51.2k | return x ^ ROTL32(2, x) ^ ROTL32(10, x) ^ ROTL32(18, x) ^ ROTL32(24, x); |
120 | 51.2k | } |
121 | | |
122 | | static uint32_t |
123 | | sm4_key_sub(uint32_t x) |
124 | 8.67k | { |
125 | 8.67k | return sm4_key_lin_sub(sm4_t_non_lin_sub(x)); |
126 | 8.67k | } |
127 | | |
128 | | static uint32_t |
129 | | sm4_enc_sub(uint32_t x) |
130 | 51.2k | { |
131 | 51.2k | return sm4_enc_lin_sub(sm4_t_non_lin_sub(x)); |
132 | 51.2k | } |
133 | | |
134 | | static uint32_t |
135 | | sm4_round(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t rk) |
136 | 51.2k | { |
137 | 51.2k | return x0 ^ sm4_enc_sub(x1 ^ x2 ^ x3 ^ rk); |
138 | 51.2k | } |
139 | | |
140 | | static void |
141 | | sm4_set_key(struct sm4_ctx *ctx, const uint8_t *key, int encrypt) |
142 | 271 | { |
143 | 271 | uint32_t rk0, rk1, rk2, rk3; |
144 | 271 | unsigned i; |
145 | | |
146 | 271 | rk0 = READ_UINT32(key + 0) ^ fk[0]; |
147 | 271 | rk1 = READ_UINT32(key + 4) ^ fk[1]; |
148 | 271 | rk2 = READ_UINT32(key + 8) ^ fk[2]; |
149 | 271 | rk3 = READ_UINT32(key + 12) ^ fk[3]; |
150 | | |
151 | 2.43k | for (i = 0; i < 32; i += 4) |
152 | 2.16k | { |
153 | 2.16k | rk0 ^= sm4_key_sub(rk1 ^ rk2 ^ rk3 ^ ck[i + 0]); |
154 | 2.16k | rk1 ^= sm4_key_sub(rk2 ^ rk3 ^ rk0 ^ ck[i + 1]); |
155 | 2.16k | rk2 ^= sm4_key_sub(rk3 ^ rk0 ^ rk1 ^ ck[i + 2]); |
156 | 2.16k | rk3 ^= sm4_key_sub(rk0 ^ rk1 ^ rk2 ^ ck[i + 3]); |
157 | | |
158 | 2.16k | if (encrypt) |
159 | 2.16k | { |
160 | 2.16k | ctx->rkey[i + 0] = rk0; |
161 | 2.16k | ctx->rkey[i + 1] = rk1; |
162 | 2.16k | ctx->rkey[i + 2] = rk2; |
163 | 2.16k | ctx->rkey[i + 3] = rk3; |
164 | 2.16k | } |
165 | 0 | else |
166 | 0 | { |
167 | 0 | ctx->rkey[31 - 0 - i] = rk0; |
168 | 0 | ctx->rkey[31 - 1 - i] = rk1; |
169 | 0 | ctx->rkey[31 - 2 - i] = rk2; |
170 | 0 | ctx->rkey[31 - 3 - i] = rk3; |
171 | 0 | } |
172 | 2.16k | } |
173 | 271 | } |
174 | | |
175 | | void |
176 | | sm4_set_encrypt_key(struct sm4_ctx *ctx, const uint8_t *key) |
177 | 271 | { |
178 | 271 | sm4_set_key(ctx, key, 1); |
179 | 271 | } |
180 | | |
181 | | void |
182 | | sm4_set_decrypt_key(struct sm4_ctx *ctx, const uint8_t *key) |
183 | 0 | { |
184 | 0 | sm4_set_key(ctx, key, 0); |
185 | 0 | } |
186 | | |
187 | | void |
188 | | sm4_crypt(const struct sm4_ctx *context, |
189 | | size_t length, |
190 | | uint8_t *dst, |
191 | | const uint8_t *src) |
192 | 3.54k | { |
193 | 3.54k | const uint32_t *rk = context->rkey; |
194 | | |
195 | 3.54k | assert( !(length % SM4_BLOCK_SIZE) ); |
196 | | |
197 | 5.14k | for ( ; length; length -= SM4_BLOCK_SIZE) |
198 | 1.60k | { |
199 | 1.60k | uint32_t x0, x1, x2, x3; |
200 | 1.60k | unsigned i; |
201 | | |
202 | 1.60k | x0 = READ_UINT32(src + 0 * 4); |
203 | 1.60k | x1 = READ_UINT32(src + 1 * 4); |
204 | 1.60k | x2 = READ_UINT32(src + 2 * 4); |
205 | 1.60k | x3 = READ_UINT32(src + 3 * 4); |
206 | | |
207 | 14.4k | for (i = 0; i < 32; i += 4) |
208 | 12.8k | { |
209 | 12.8k | x0 = sm4_round(x0, x1, x2, x3, rk[i + 0]); |
210 | 12.8k | x1 = sm4_round(x1, x2, x3, x0, rk[i + 1]); |
211 | 12.8k | x2 = sm4_round(x2, x3, x0, x1, rk[i + 2]); |
212 | 12.8k | x3 = sm4_round(x3, x0, x1, x2, rk[i + 3]); |
213 | 12.8k | } |
214 | | |
215 | 1.60k | WRITE_UINT32(dst + 0 * 4, x3); |
216 | 1.60k | WRITE_UINT32(dst + 1 * 4, x2); |
217 | 1.60k | WRITE_UINT32(dst + 2 * 4, x1); |
218 | 1.60k | WRITE_UINT32(dst + 3 * 4, x0); |
219 | | |
220 | 1.60k | src += SM4_BLOCK_SIZE; |
221 | 1.60k | dst += SM4_BLOCK_SIZE; |
222 | 1.60k | } |
223 | 3.54k | } |