1ade6f848SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2ade6f848SJerome Forissier /*
3ade6f848SJerome Forissier * Copyright Copyright (c) 2019 Huawei Technologies Co., Ltd
4ade6f848SJerome Forissier */
5ade6f848SJerome Forissier /*
6ade6f848SJerome Forissier * SM4 Encryption algorithm (SMS4 algorithm)
7ade6f848SJerome Forissier * GM/T 0002-2012 Chinese National Standard ref:http://www.oscca.gov.cn/
8ade6f848SJerome Forissier * thanks to Xyssl
9ade6f848SJerome Forissier * thnaks and refers to http://hi.baidu.com/numax/blog/item/80addfefddfb93e4cf1b3e61.html
10ade6f848SJerome Forissier * author:goldboar
11ade6f848SJerome Forissier * email:goldboar@163.com
12ade6f848SJerome Forissier * 2012-4-20
13ade6f848SJerome Forissier */
14ade6f848SJerome Forissier
15ade6f848SJerome Forissier #include "sm4.h"
16ade6f848SJerome Forissier #include <assert.h>
17ade6f848SJerome Forissier #include <string.h>
18ade6f848SJerome Forissier
19ade6f848SJerome Forissier #define GET_UINT32_BE(n, b, i) \
20ade6f848SJerome Forissier do { \
21ade6f848SJerome Forissier (n) = ((uint32_t)(b)[(i)] << 24) | \
22ade6f848SJerome Forissier ((uint32_t)(b)[(i) + 1] << 16) | \
23ade6f848SJerome Forissier ((uint32_t)(b)[(i) + 2] << 8) | \
24ade6f848SJerome Forissier ((uint32_t)(b)[(i) + 3]); \
25ade6f848SJerome Forissier } while (0)
26ade6f848SJerome Forissier
27ade6f848SJerome Forissier #define PUT_UINT32_BE(n, b, i) \
28ade6f848SJerome Forissier do { \
29ade6f848SJerome Forissier (b)[(i)] = (uint8_t)((n) >> 24); \
30ade6f848SJerome Forissier (b)[(i) + 1] = (uint8_t)((n) >> 16); \
31ade6f848SJerome Forissier (b)[(i) + 2] = (uint8_t)((n) >> 8); \
32ade6f848SJerome Forissier (b)[(i) + 3] = (uint8_t)((n)); \
33ade6f848SJerome Forissier } while (0)
34ade6f848SJerome Forissier
35ade6f848SJerome Forissier #define SHL(x, n) (((x) & 0xFFFFFFFF) << (n))
36ade6f848SJerome Forissier #define ROTL(x, n) (SHL((x), (n)) | ((x) >> (32 - (n))))
37ade6f848SJerome Forissier
38ade6f848SJerome Forissier #define SWAP(a, b) { uint32_t t = a; a = b; b = t; t = 0; }
39ade6f848SJerome Forissier
40ade6f848SJerome Forissier /*
41ade6f848SJerome Forissier * Expanded SM4 S-boxes
42ade6f848SJerome Forissier */
43ade6f848SJerome Forissier static const uint8_t SboxTable[16][16] = {
44ade6f848SJerome Forissier {0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7,
45ade6f848SJerome Forissier 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05},
46ade6f848SJerome Forissier {0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3,
47ade6f848SJerome Forissier 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99},
48ade6f848SJerome Forissier {0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a,
49ade6f848SJerome Forissier 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62},
50ade6f848SJerome Forissier {0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95,
51ade6f848SJerome Forissier 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6},
52ade6f848SJerome Forissier {0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba,
53ade6f848SJerome Forissier 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8},
54ade6f848SJerome Forissier {0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b,
55ade6f848SJerome Forissier 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35},
56ade6f848SJerome Forissier {0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2,
57ade6f848SJerome Forissier 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87},
58ade6f848SJerome Forissier {0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52,
59ade6f848SJerome Forissier 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e},
60ade6f848SJerome Forissier {0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5,
61ade6f848SJerome Forissier 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1},
62ade6f848SJerome Forissier {0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,
63ade6f848SJerome Forissier 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3},
64ade6f848SJerome Forissier {0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60,
65ade6f848SJerome Forissier 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f},
66ade6f848SJerome Forissier {0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f,
67ade6f848SJerome Forissier 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51},
68ade6f848SJerome Forissier {0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f,
69ade6f848SJerome Forissier 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8},
70ade6f848SJerome Forissier {0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd,
71ade6f848SJerome Forissier 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0},
72ade6f848SJerome Forissier {0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e,
73ade6f848SJerome Forissier 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84},
74ade6f848SJerome Forissier {0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20,
75ade6f848SJerome Forissier 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48}
76ade6f848SJerome Forissier };
77ade6f848SJerome Forissier
78ade6f848SJerome Forissier /* System parameter */
79ade6f848SJerome Forissier static const uint32_t FK[4] = {
80ade6f848SJerome Forissier 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc
81ade6f848SJerome Forissier };
82ade6f848SJerome Forissier
83ade6f848SJerome Forissier /* Fixed parameter */
84ade6f848SJerome Forissier static const uint32_t CK[32] = {
85ade6f848SJerome Forissier 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
86ade6f848SJerome Forissier 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
87ade6f848SJerome Forissier 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
88ade6f848SJerome Forissier 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
89ade6f848SJerome Forissier 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
90ade6f848SJerome Forissier 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
91ade6f848SJerome Forissier 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
92ade6f848SJerome Forissier 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
93ade6f848SJerome Forissier };
94ade6f848SJerome Forissier
sm4Sbox(uint8_t inch)95ade6f848SJerome Forissier static uint8_t sm4Sbox(uint8_t inch)
96ade6f848SJerome Forissier {
97ade6f848SJerome Forissier uint8_t *tab = (uint8_t *)SboxTable;
98ade6f848SJerome Forissier
99ade6f848SJerome Forissier return tab[inch];
100ade6f848SJerome Forissier }
101ade6f848SJerome Forissier
sm4Lt(uint32_t ka)102ade6f848SJerome Forissier static uint32_t sm4Lt(uint32_t ka)
103ade6f848SJerome Forissier {
104ade6f848SJerome Forissier uint32_t bb = 0;
105ade6f848SJerome Forissier uint8_t a[4];
106ade6f848SJerome Forissier uint8_t b[4];
107ade6f848SJerome Forissier
108ade6f848SJerome Forissier PUT_UINT32_BE(ka, a, 0);
109ade6f848SJerome Forissier b[0] = sm4Sbox(a[0]);
110ade6f848SJerome Forissier b[1] = sm4Sbox(a[1]);
111ade6f848SJerome Forissier b[2] = sm4Sbox(a[2]);
112ade6f848SJerome Forissier b[3] = sm4Sbox(a[3]);
113ade6f848SJerome Forissier GET_UINT32_BE(bb, b, 0);
114ade6f848SJerome Forissier
115ade6f848SJerome Forissier return bb ^ ROTL(bb, 2) ^ ROTL(bb, 10) ^ ROTL(bb, 18) ^ ROTL(bb, 24);
116ade6f848SJerome Forissier }
117ade6f848SJerome Forissier
sm4F(uint32_t x0,uint32_t x1,uint32_t x2,uint32_t x3,uint32_t rk)118ade6f848SJerome Forissier static uint32_t sm4F(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3,
119ade6f848SJerome Forissier uint32_t rk)
120ade6f848SJerome Forissier {
121ade6f848SJerome Forissier return x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk);
122ade6f848SJerome Forissier }
123ade6f848SJerome Forissier
sm4CalciRK(uint32_t ka)124ade6f848SJerome Forissier static uint32_t sm4CalciRK(uint32_t ka)
125ade6f848SJerome Forissier {
126ade6f848SJerome Forissier uint32_t bb = 0;
127ade6f848SJerome Forissier uint8_t a[4];
128ade6f848SJerome Forissier uint8_t b[4];
129ade6f848SJerome Forissier
130ade6f848SJerome Forissier PUT_UINT32_BE(ka, a, 0);
131ade6f848SJerome Forissier b[0] = sm4Sbox(a[0]);
132ade6f848SJerome Forissier b[1] = sm4Sbox(a[1]);
133ade6f848SJerome Forissier b[2] = sm4Sbox(a[2]);
134ade6f848SJerome Forissier b[3] = sm4Sbox(a[3]);
135ade6f848SJerome Forissier GET_UINT32_BE(bb, b, 0);
136ade6f848SJerome Forissier
137ade6f848SJerome Forissier return bb ^ ROTL(bb, 13) ^ ROTL(bb, 23);
138ade6f848SJerome Forissier }
139ade6f848SJerome Forissier
sm4_setkey(uint32_t SK[32],const uint8_t key[16])140ade6f848SJerome Forissier static void sm4_setkey(uint32_t SK[32], const uint8_t key[16])
141ade6f848SJerome Forissier {
142ade6f848SJerome Forissier uint32_t MK[4];
143ade6f848SJerome Forissier uint32_t k[36];
144ade6f848SJerome Forissier uint32_t i = 0;
145ade6f848SJerome Forissier
146ade6f848SJerome Forissier GET_UINT32_BE(MK[0], key, 0);
147ade6f848SJerome Forissier GET_UINT32_BE(MK[1], key, 4);
148ade6f848SJerome Forissier GET_UINT32_BE(MK[2], key, 8);
149ade6f848SJerome Forissier GET_UINT32_BE(MK[3], key, 12);
150ade6f848SJerome Forissier
151ade6f848SJerome Forissier k[0] = MK[0] ^ FK[0];
152ade6f848SJerome Forissier k[1] = MK[1] ^ FK[1];
153ade6f848SJerome Forissier k[2] = MK[2] ^ FK[2];
154ade6f848SJerome Forissier k[3] = MK[3] ^ FK[3];
155ade6f848SJerome Forissier
156ade6f848SJerome Forissier for (i = 0; i < 32; i++) {
157ade6f848SJerome Forissier k[i + 4] = k[i] ^ sm4CalciRK(k[i + 1] ^ k[i + 2] ^ k[i + 3] ^
158ade6f848SJerome Forissier CK[i]);
159ade6f848SJerome Forissier SK[i] = k[i + 4];
160ade6f848SJerome Forissier }
161ade6f848SJerome Forissier }
162ade6f848SJerome Forissier
sm4_one_round(uint32_t sk[32],const uint8_t input[16],uint8_t output[16])163ade6f848SJerome Forissier static void sm4_one_round(uint32_t sk[32], const uint8_t input[16],
164ade6f848SJerome Forissier uint8_t output[16])
165ade6f848SJerome Forissier {
166ade6f848SJerome Forissier uint32_t i = 0;
167ade6f848SJerome Forissier uint32_t ulbuf[36];
168ade6f848SJerome Forissier
169ade6f848SJerome Forissier memset(ulbuf, 0, sizeof(ulbuf));
170ade6f848SJerome Forissier
171ade6f848SJerome Forissier GET_UINT32_BE(ulbuf[0], input, 0);
172ade6f848SJerome Forissier GET_UINT32_BE(ulbuf[1], input, 4);
173ade6f848SJerome Forissier GET_UINT32_BE(ulbuf[2], input, 8);
174ade6f848SJerome Forissier GET_UINT32_BE(ulbuf[3], input, 12);
175ade6f848SJerome Forissier
176ade6f848SJerome Forissier for (i = 0; i < 32; i++)
177ade6f848SJerome Forissier ulbuf[i + 4] = sm4F(ulbuf[i], ulbuf[i + 1], ulbuf[i + 2],
178ade6f848SJerome Forissier ulbuf[i + 3], sk[i]);
179ade6f848SJerome Forissier
180ade6f848SJerome Forissier PUT_UINT32_BE(ulbuf[35], output, 0);
181ade6f848SJerome Forissier PUT_UINT32_BE(ulbuf[34], output, 4);
182ade6f848SJerome Forissier PUT_UINT32_BE(ulbuf[33], output, 8);
183ade6f848SJerome Forissier PUT_UINT32_BE(ulbuf[32], output, 12);
184ade6f848SJerome Forissier }
185ade6f848SJerome Forissier
sm4_setkey_enc(struct sm4_context * ctx,const uint8_t key[16])186ade6f848SJerome Forissier void sm4_setkey_enc(struct sm4_context *ctx, const uint8_t key[16])
187ade6f848SJerome Forissier {
188ade6f848SJerome Forissier ctx->mode = SM4_ENCRYPT;
189ade6f848SJerome Forissier sm4_setkey(ctx->sk, key);
190ade6f848SJerome Forissier }
191ade6f848SJerome Forissier
sm4_setkey_dec(struct sm4_context * ctx,const uint8_t key[16])192ade6f848SJerome Forissier void sm4_setkey_dec(struct sm4_context *ctx, const uint8_t key[16])
193ade6f848SJerome Forissier {
194ade6f848SJerome Forissier int i;
195ade6f848SJerome Forissier
196ade6f848SJerome Forissier ctx->mode = SM4_DECRYPT;
197ade6f848SJerome Forissier sm4_setkey(ctx->sk, key);
198ade6f848SJerome Forissier
199ade6f848SJerome Forissier for (i = 0; i < 16; i++)
200ade6f848SJerome Forissier SWAP(ctx->sk[i], ctx->sk[31 - i]);
201ade6f848SJerome Forissier }
202ade6f848SJerome Forissier
sm4_crypt_ecb(struct sm4_context * ctx,size_t length,const uint8_t * input,uint8_t * output)203ade6f848SJerome Forissier void sm4_crypt_ecb(struct sm4_context *ctx, size_t length, const uint8_t *input,
204ade6f848SJerome Forissier uint8_t *output)
205ade6f848SJerome Forissier {
206ade6f848SJerome Forissier assert(!(length % 16));
207ade6f848SJerome Forissier
208ade6f848SJerome Forissier while (length > 0) {
209ade6f848SJerome Forissier sm4_one_round(ctx->sk, input, output);
210ade6f848SJerome Forissier input += 16;
211ade6f848SJerome Forissier output += 16;
212ade6f848SJerome Forissier length -= 16;
213ade6f848SJerome Forissier }
214ade6f848SJerome Forissier }
215ade6f848SJerome Forissier
sm4_crypt_cbc(struct sm4_context * ctx,size_t length,uint8_t iv[16],const uint8_t * input,uint8_t * output)216ade6f848SJerome Forissier void sm4_crypt_cbc(struct sm4_context *ctx, size_t length, uint8_t iv[16],
217ade6f848SJerome Forissier const uint8_t *input, uint8_t *output)
218ade6f848SJerome Forissier {
219ade6f848SJerome Forissier int i;
220ade6f848SJerome Forissier uint8_t temp[16];
221ade6f848SJerome Forissier
222ade6f848SJerome Forissier assert(!(length % 16));
223ade6f848SJerome Forissier
224ade6f848SJerome Forissier if (ctx->mode == SM4_ENCRYPT) {
225ade6f848SJerome Forissier while (length > 0) {
226ade6f848SJerome Forissier for (i = 0; i < 16; i++)
227ade6f848SJerome Forissier output[i] = (uint8_t)(input[i] ^ iv[i]);
228ade6f848SJerome Forissier sm4_one_round(ctx->sk, output, output);
229ade6f848SJerome Forissier memcpy(iv, output, 16);
230ade6f848SJerome Forissier input += 16;
231ade6f848SJerome Forissier output += 16;
232ade6f848SJerome Forissier length -= 16;
233ade6f848SJerome Forissier }
234ade6f848SJerome Forissier } else {
235ade6f848SJerome Forissier /* SM4_DECRYPT */
236ade6f848SJerome Forissier while (length > 0) {
237ade6f848SJerome Forissier memcpy(temp, input, 16);
238ade6f848SJerome Forissier sm4_one_round(ctx->sk, input, output);
239ade6f848SJerome Forissier for (i = 0; i < 16; i++)
240ade6f848SJerome Forissier output[i] = (uint8_t)(output[i] ^ iv[i]);
241ade6f848SJerome Forissier memcpy(iv, temp, 16);
242ade6f848SJerome Forissier input += 16;
243ade6f848SJerome Forissier output += 16;
244ade6f848SJerome Forissier length -= 16;
245ade6f848SJerome Forissier }
246ade6f848SJerome Forissier }
247ade6f848SJerome Forissier }
248ade6f848SJerome Forissier
sm4_crypt_ctr(struct sm4_context * ctx,size_t length,uint8_t ctr[16],const uint8_t * input,uint8_t * output)249ade6f848SJerome Forissier void sm4_crypt_ctr(struct sm4_context *ctx, size_t length, uint8_t ctr[16],
250ade6f848SJerome Forissier const uint8_t *input, uint8_t *output)
251ade6f848SJerome Forissier {
252ade6f848SJerome Forissier int i;
253ade6f848SJerome Forissier uint8_t temp[16];
254ade6f848SJerome Forissier
255ade6f848SJerome Forissier assert(!(length % 16));
256ade6f848SJerome Forissier
257ade6f848SJerome Forissier while (length > 0) {
258ade6f848SJerome Forissier memcpy(temp, ctr, 16);
259ade6f848SJerome Forissier sm4_one_round(ctx->sk, ctr, ctr);
260ade6f848SJerome Forissier for (i = 0; i < 16; i++)
261ade6f848SJerome Forissier output[i] = (uint8_t)(input[i] ^ ctr[i]);
262ade6f848SJerome Forissier memcpy(ctr, temp, 16);
263ade6f848SJerome Forissier for (i = 16; i > 0; i--)
264ade6f848SJerome Forissier if (++ctr[i - 1])
265ade6f848SJerome Forissier break;
266ade6f848SJerome Forissier input += 16;
267ade6f848SJerome Forissier output += 16;
268ade6f848SJerome Forissier length -= 16;
269ade6f848SJerome Forissier }
270ade6f848SJerome Forissier }
271*b21f583dSPingan Xie
xts_multi(unsigned char * in,unsigned char * out)272*b21f583dSPingan Xie static void xts_multi(unsigned char *in, unsigned char *out)
273*b21f583dSPingan Xie {
274*b21f583dSPingan Xie uint8_t tt = 0;
275*b21f583dSPingan Xie uint8_t t = 0;
276*b21f583dSPingan Xie int i = 0;
277*b21f583dSPingan Xie
278*b21f583dSPingan Xie for (i = 0; i < 16; i++) {
279*b21f583dSPingan Xie tt = in[i] >> 7;
280*b21f583dSPingan Xie out[i] = ((in[i] << 1) | t) & 0xFF;
281*b21f583dSPingan Xie t = tt;
282*b21f583dSPingan Xie }
283*b21f583dSPingan Xie
284*b21f583dSPingan Xie out[0] ^= (0x87 & (0 - tt));
285*b21f583dSPingan Xie }
286*b21f583dSPingan Xie
xor_128(const uint8_t a[16],const uint8_t b[16],uint8_t c[16])287*b21f583dSPingan Xie static void xor_128(const uint8_t a[16], const uint8_t b[16], uint8_t c[16])
288*b21f583dSPingan Xie {
289*b21f583dSPingan Xie int i = 0;
290*b21f583dSPingan Xie
291*b21f583dSPingan Xie for (i = 0; i < 16; i++)
292*b21f583dSPingan Xie c[i] = a[i] ^ b[i];
293*b21f583dSPingan Xie }
294*b21f583dSPingan Xie
sm4_crypt_xts(struct sm4_context * ctx,struct sm4_context * ctx_ek,struct sm4_context * ctx_dk,size_t len,uint8_t * iv,const uint8_t * input,uint8_t * output)295*b21f583dSPingan Xie void sm4_crypt_xts(struct sm4_context *ctx, struct sm4_context *ctx_ek,
296*b21f583dSPingan Xie struct sm4_context *ctx_dk, size_t len, uint8_t *iv,
297*b21f583dSPingan Xie const uint8_t *input, uint8_t *output)
298*b21f583dSPingan Xie {
299*b21f583dSPingan Xie uint8_t tweak[16] = { };
300*b21f583dSPingan Xie uint8_t tweak1[16] = { };
301*b21f583dSPingan Xie uint8_t ct[16] = { };
302*b21f583dSPingan Xie size_t i = 0;
303*b21f583dSPingan Xie
304*b21f583dSPingan Xie assert(len >= 16);
305*b21f583dSPingan Xie
306*b21f583dSPingan Xie sm4_one_round(ctx_ek->sk, iv, tweak);
307*b21f583dSPingan Xie
308*b21f583dSPingan Xie if (ctx->mode == SM4_DECRYPT && (len % 16))
309*b21f583dSPingan Xie len -= 16;
310*b21f583dSPingan Xie
311*b21f583dSPingan Xie while (len >= 16) {
312*b21f583dSPingan Xie xor_128(input, tweak, ct);
313*b21f583dSPingan Xie sm4_one_round(ctx->sk, ct, ct);
314*b21f583dSPingan Xie xor_128(ct, tweak, output);
315*b21f583dSPingan Xie
316*b21f583dSPingan Xie xts_multi(tweak, tweak);
317*b21f583dSPingan Xie len -= 16;
318*b21f583dSPingan Xie if (len == 0) {
319*b21f583dSPingan Xie sm4_one_round(ctx_dk->sk, tweak, iv);
320*b21f583dSPingan Xie return;
321*b21f583dSPingan Xie }
322*b21f583dSPingan Xie input += 16;
323*b21f583dSPingan Xie output += 16;
324*b21f583dSPingan Xie }
325*b21f583dSPingan Xie
326*b21f583dSPingan Xie if (ctx->mode == SM4_ENCRYPT) {
327*b21f583dSPingan Xie memcpy(ct, output - 16, 16);
328*b21f583dSPingan Xie for (i = 0; i < len; i++) {
329*b21f583dSPingan Xie output[i] = ct[i];
330*b21f583dSPingan Xie ct[i] = input[i];
331*b21f583dSPingan Xie }
332*b21f583dSPingan Xie
333*b21f583dSPingan Xie xor_128(ct, tweak, ct);
334*b21f583dSPingan Xie sm4_one_round(ctx->sk, ct, ct);
335*b21f583dSPingan Xie xor_128(ct, tweak, ct);
336*b21f583dSPingan Xie memcpy(output - 16, ct, 16);
337*b21f583dSPingan Xie } else {
338*b21f583dSPingan Xie xts_multi(tweak, tweak1);
339*b21f583dSPingan Xie xor_128(input, tweak1, ct);
340*b21f583dSPingan Xie sm4_one_round(ctx->sk, ct, ct);
341*b21f583dSPingan Xie xor_128(ct, tweak1, ct);
342*b21f583dSPingan Xie
343*b21f583dSPingan Xie for (i = 0; i < len; ++i) {
344*b21f583dSPingan Xie output[16 + i] = ct[i];
345*b21f583dSPingan Xie ct[i] = input[16 + i];
346*b21f583dSPingan Xie }
347*b21f583dSPingan Xie xor_128(ct, tweak, ct);
348*b21f583dSPingan Xie sm4_one_round(ctx->sk, ct, ct);
349*b21f583dSPingan Xie xor_128(ct, tweak, output);
350*b21f583dSPingan Xie }
351*b21f583dSPingan Xie }
352