xref: /openbsd/lib/libcrypto/evp/e_sm4.c (revision 4bdff4be)
1 /*	$OpenBSD: e_sm4.c,v 1.12 2024/01/04 17:38:36 tb Exp $	*/
2 /*
3  * Copyright (c) 2017, 2019 Ribose Inc
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <openssl/opensslconf.h>
19 
20 #ifndef OPENSSL_NO_SM4
21 #include <openssl/evp.h>
22 #include <openssl/modes.h>
23 #include <openssl/sm4.h>
24 
25 #include "evp_local.h"
26 
27 typedef struct {
28 	SM4_KEY ks;
29 } EVP_SM4_KEY;
30 
31 static int
32 sm4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
33     const unsigned char *iv, int enc)
34 {
35 	SM4_set_key(key, ctx->cipher_data);
36 	return 1;
37 }
38 
39 static void
40 sm4_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t len,
41     const SM4_KEY *key, unsigned char *ivec, const int enc)
42 {
43 	if (enc)
44 		CRYPTO_cbc128_encrypt(in, out, len, key, ivec,
45 		    (block128_f)SM4_encrypt);
46 	else
47 		CRYPTO_cbc128_decrypt(in, out, len, key, ivec,
48 		    (block128_f)SM4_decrypt);
49 }
50 
51 static void
52 sm4_cfb128_encrypt(const unsigned char *in, unsigned char *out, size_t length,
53     const SM4_KEY *key, unsigned char *ivec, int *num, const int enc)
54 {
55 	CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc,
56 	    (block128_f)SM4_encrypt);
57 }
58 
59 static void
60 sm4_ecb_encrypt(const unsigned char *in, unsigned char *out, const SM4_KEY *key,
61     const int enc)
62 {
63 	if (enc)
64 		SM4_encrypt(in, out, key);
65 	else
66 		SM4_decrypt(in, out, key);
67 }
68 
69 static void
70 sm4_ofb128_encrypt(const unsigned char *in, unsigned char *out, size_t length,
71     const SM4_KEY *key, unsigned char *ivec, int *num)
72 {
73 	CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num,
74 	    (block128_f)SM4_encrypt);
75 }
76 
77 static int
78 sm4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
79 {
80 	while (inl >= EVP_MAXCHUNK) {
81 		sm4_cbc_encrypt(in, out, EVP_MAXCHUNK, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
82 		inl -= EVP_MAXCHUNK;
83 		in += EVP_MAXCHUNK;
84 		out += EVP_MAXCHUNK;
85 	}
86 
87 	if (inl)
88 		sm4_cbc_encrypt(in, out, inl, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
89 
90 	return 1;
91 }
92 
93 static int
94 sm4_cfb128_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
95 {
96 	size_t chunk = EVP_MAXCHUNK;
97 
98 	if (inl < chunk)
99 		chunk = inl;
100 
101 	while (inl && inl >= chunk) {
102 		sm4_cfb128_encrypt(in, out, chunk, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
103 		inl -= chunk;
104 		in += chunk;
105 		out += chunk;
106 		if (inl < chunk)
107 			chunk = inl;
108 	}
109 
110 	return 1;
111 }
112 
113 static int
114 sm4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
115 {
116 	size_t i, bl;
117 
118 	bl = ctx->cipher->block_size;
119 
120 	if (inl < bl)
121 		return 1;
122 
123 	inl -= bl;
124 
125 	for (i = 0; i <= inl; i += bl)
126 		sm4_ecb_encrypt(in + i, out + i, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->encrypt);
127 
128 	return 1;
129 }
130 
131 static int
132 sm4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
133 {
134 	while (inl >= EVP_MAXCHUNK) {
135 		sm4_ofb128_encrypt(in, out, EVP_MAXCHUNK, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
136 		inl -= EVP_MAXCHUNK;
137 		in += EVP_MAXCHUNK;
138 		out += EVP_MAXCHUNK;
139 	}
140 
141 	if (inl)
142 		sm4_ofb128_encrypt(in, out, inl, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
143 
144 	return 1;
145 }
146 
147 static const EVP_CIPHER sm4_cbc = {
148 	.nid = NID_sm4_cbc,
149 	.block_size = 16,
150 	.key_len = 16,
151 	.iv_len = 16,
152 	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CBC_MODE,
153 	.init = sm4_init_key,
154 	.do_cipher = sm4_cbc_cipher,
155 	.cleanup = NULL,
156 	.ctx_size = sizeof(EVP_SM4_KEY),
157 	.set_asn1_parameters = NULL,
158 	.get_asn1_parameters = NULL,
159 	.ctrl = NULL,
160 };
161 
162 const EVP_CIPHER *
163 EVP_sm4_cbc(void)
164 {
165 	return &sm4_cbc;
166 }
167 
168 static const EVP_CIPHER sm4_cfb128 = {
169 	.nid = NID_sm4_cfb128,
170 	.block_size = 1,
171 	.key_len = 16,
172 	.iv_len = 16,
173 	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CFB_MODE,
174 	.init = sm4_init_key,
175 	.do_cipher = sm4_cfb128_cipher,
176 	.cleanup = NULL,
177 	.ctx_size = sizeof(EVP_SM4_KEY),
178 	.set_asn1_parameters = NULL,
179 	.get_asn1_parameters = NULL,
180 	.ctrl = NULL,
181 };
182 
183 const EVP_CIPHER *
184 EVP_sm4_cfb128(void)
185 {
186 	return &sm4_cfb128;
187 }
188 
189 static const EVP_CIPHER sm4_ofb = {
190 	.nid = NID_sm4_ofb128,
191 	.block_size = 1,
192 	.key_len = 16,
193 	.iv_len = 16,
194 	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_OFB_MODE,
195 	.init = sm4_init_key,
196 	.do_cipher = sm4_ofb_cipher,
197 	.cleanup = NULL,
198 	.ctx_size = sizeof(EVP_SM4_KEY),
199 	.set_asn1_parameters = NULL,
200 	.get_asn1_parameters = NULL,
201 	.ctrl = NULL,
202 };
203 
204 const EVP_CIPHER *
205 EVP_sm4_ofb(void)
206 {
207 	return &sm4_ofb;
208 }
209 
210 static const EVP_CIPHER sm4_ecb = {
211 	.nid = NID_sm4_ecb,
212 	.block_size = 16,
213 	.key_len = 16,
214 	.iv_len = 0,
215 	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_ECB_MODE,
216 	.init = sm4_init_key,
217 	.do_cipher = sm4_ecb_cipher,
218 	.cleanup = NULL,
219 	.ctx_size = sizeof(EVP_SM4_KEY),
220 	.set_asn1_parameters = NULL,
221 	.get_asn1_parameters = NULL,
222 	.ctrl = NULL,
223 };
224 
225 const EVP_CIPHER *
226 EVP_sm4_ecb(void)
227 {
228 	return &sm4_ecb;
229 }
230 
231 static int
232 sm4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in,
233     size_t len)
234 {
235 	EVP_SM4_KEY *key = ((EVP_SM4_KEY *)(ctx)->cipher_data);
236 
237 	CRYPTO_ctr128_encrypt(in, out, len, &key->ks, ctx->iv, ctx->buf,
238 	    &ctx->num, (block128_f)SM4_encrypt);
239 	return 1;
240 }
241 
242 static const EVP_CIPHER sm4_ctr_mode = {
243 	.nid = NID_sm4_ctr,
244 	.block_size = 1,
245 	.key_len = 16,
246 	.iv_len = 16,
247 	.flags = EVP_CIPH_CTR_MODE,
248 	.init = sm4_init_key,
249 	.do_cipher = sm4_ctr_cipher,
250 	.cleanup = NULL,
251 	.ctx_size = sizeof(EVP_SM4_KEY),
252 	.set_asn1_parameters = NULL,
253 	.get_asn1_parameters = NULL,
254 	.ctrl = NULL,
255 };
256 
257 const EVP_CIPHER *
258 EVP_sm4_ctr(void)
259 {
260 	return &sm4_ctr_mode;
261 }
262 #endif
263