1 /*
2 * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright 2017 Ribose Inc. All Rights Reserved.
4 * Ported from Ribose contributions from Botan.
5 *
6 * Licensed under the Apache License 2.0 (the "License"). You may not use
7 * this file except in compliance with the License. You can obtain a copy
8 * in the file LICENSE in the source distribution or at
9 * https://www.openssl.org/source/license.html
10 */
11
12 #include "internal/deprecated.h"
13
14 #include "internal/cryptlib.h"
15 #ifndef OPENSSL_NO_SM4
16 # include <openssl/evp.h>
17 # include <openssl/modes.h>
18 # include "crypto/sm4.h"
19 # include "crypto/evp.h"
20 # include "crypto/sm4_platform.h"
21 # include "evp_local.h"
22
23 typedef struct {
24 union {
25 OSSL_UNION_ALIGN;
26 SM4_KEY ks;
27 } ks;
28 block128_f block;
29 union {
30 ecb128_f ecb;
31 cbc128_f cbc;
32 ctr128_f ctr;
33 } stream;
34 } EVP_SM4_KEY;
35
36 # define BLOCK_CIPHER_generic(nid,blocksize,ivlen,nmode,mode,MODE,flags) \
37 static const EVP_CIPHER sm4_##mode = { \
38 nid##_##nmode,blocksize,128/8,ivlen, \
39 flags|EVP_CIPH_##MODE##_MODE, \
40 EVP_ORIG_GLOBAL, \
41 sm4_init_key, \
42 sm4_##mode##_cipher, \
43 NULL, \
44 sizeof(EVP_SM4_KEY), \
45 NULL,NULL,NULL,NULL }; \
46 const EVP_CIPHER *EVP_sm4_##mode(void) \
47 { return &sm4_##mode; }
48
49 #define DEFINE_BLOCK_CIPHERS(nid,flags) \
50 BLOCK_CIPHER_generic(nid,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
51 BLOCK_CIPHER_generic(nid,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
52 BLOCK_CIPHER_generic(nid,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
53 BLOCK_CIPHER_generic(nid,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
54 BLOCK_CIPHER_generic(nid,1,16,ctr,ctr,CTR,flags)
55
sm4_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)56 static int sm4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
57 const unsigned char *iv, int enc)
58 {
59 int mode;
60 EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx);
61
62 mode = EVP_CIPHER_CTX_get_mode(ctx);
63 if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
64 && !enc) {
65 #ifdef HWSM4_CAPABLE
66 if (HWSM4_CAPABLE) {
67 HWSM4_set_decrypt_key(key, &dat->ks.ks);
68 dat->block = (block128_f) HWSM4_decrypt;
69 dat->stream.cbc = NULL;
70 # ifdef HWSM4_cbc_encrypt
71 if (mode == EVP_CIPH_CBC_MODE)
72 dat->stream.cbc = (cbc128_f) HWSM4_cbc_encrypt;
73 # endif
74 # ifdef HWSM4_ecb_encrypt
75 if (mode == EVP_CIPH_ECB_MODE)
76 dat->stream.ecb = (ecb128_f) HWSM4_ecb_encrypt;
77 # endif
78 } else
79 #endif
80 #ifdef VPSM4_CAPABLE
81 if (VPSM4_CAPABLE) {
82 vpsm4_set_decrypt_key(key, &dat->ks.ks);
83 dat->block = (block128_f) vpsm4_decrypt;
84 dat->stream.cbc = NULL;
85 if (mode == EVP_CIPH_CBC_MODE)
86 dat->stream.cbc = (cbc128_f) vpsm4_cbc_encrypt;
87 else if (mode == EVP_CIPH_ECB_MODE)
88 dat->stream.ecb = (ecb128_f) vpsm4_ecb_encrypt;
89 } else
90 #endif
91 {
92 dat->block = (block128_f) ossl_sm4_decrypt;
93 ossl_sm4_set_key(key, EVP_CIPHER_CTX_get_cipher_data(ctx));
94 }
95 } else
96 #ifdef HWSM4_CAPABLE
97 if (HWSM4_CAPABLE) {
98 HWSM4_set_encrypt_key(key, &dat->ks.ks);
99 dat->block = (block128_f) HWSM4_encrypt;
100 dat->stream.cbc = NULL;
101 # ifdef HWSM4_cbc_encrypt
102 if (mode == EVP_CIPH_CBC_MODE)
103 dat->stream.cbc = (cbc128_f) HWSM4_cbc_encrypt;
104 else
105 # endif
106 # ifdef HWSM4_ecb_encrypt
107 if (mode == EVP_CIPH_ECB_MODE)
108 dat->stream.ecb = (ecb128_f) HWSM4_ecb_encrypt;
109 else
110 # endif
111 # ifdef HWSM4_ctr32_encrypt_blocks
112 if (mode == EVP_CIPH_CTR_MODE)
113 dat->stream.ctr = (ctr128_f) HWSM4_ctr32_encrypt_blocks;
114 else
115 # endif
116 (void)0; /* terminate potentially open 'else' */
117 } else
118 #endif
119 #ifdef VPSM4_CAPABLE
120 if (VPSM4_CAPABLE) {
121 vpsm4_set_encrypt_key(key, &dat->ks.ks);
122 dat->block = (block128_f) vpsm4_encrypt;
123 dat->stream.cbc = NULL;
124 if (mode == EVP_CIPH_CBC_MODE)
125 dat->stream.cbc = (cbc128_f) vpsm4_cbc_encrypt;
126 else if (mode == EVP_CIPH_ECB_MODE)
127 dat->stream.ecb = (ecb128_f) vpsm4_ecb_encrypt;
128 else if (mode == EVP_CIPH_CTR_MODE)
129 dat->stream.ctr = (ctr128_f) vpsm4_ctr32_encrypt_blocks;
130 } else
131 #endif
132 {
133 dat->block = (block128_f) ossl_sm4_encrypt;
134 ossl_sm4_set_key(key, EVP_CIPHER_CTX_get_cipher_data(ctx));
135 }
136 return 1;
137 }
138
sm4_cbc_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)139 static int sm4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
140 const unsigned char *in, size_t len)
141 {
142 EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx);
143
144 if (dat->stream.cbc)
145 (*dat->stream.cbc) (in, out, len, &dat->ks.ks, ctx->iv,
146 EVP_CIPHER_CTX_is_encrypting(ctx));
147 else if (EVP_CIPHER_CTX_is_encrypting(ctx))
148 CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv,
149 dat->block);
150 else
151 CRYPTO_cbc128_decrypt(in, out, len, &dat->ks,
152 ctx->iv, dat->block);
153 return 1;
154 }
155
sm4_cfb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)156 static int sm4_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
157 const unsigned char *in, size_t len)
158 {
159 EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx);
160 int num = EVP_CIPHER_CTX_get_num(ctx);
161
162 CRYPTO_cfb128_encrypt(in, out, len, &dat->ks,
163 ctx->iv, &num,
164 EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
165 EVP_CIPHER_CTX_set_num(ctx, num);
166 return 1;
167 }
168
sm4_ecb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)169 static int sm4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
170 const unsigned char *in, size_t len)
171 {
172 size_t bl = EVP_CIPHER_CTX_get_block_size(ctx);
173 size_t i;
174 EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx);
175
176 if (len < bl)
177 return 1;
178
179 if (dat->stream.ecb != NULL)
180 (*dat->stream.ecb) (in, out, len, &dat->ks.ks,
181 EVP_CIPHER_CTX_is_encrypting(ctx));
182 else
183 for (i = 0, len -= bl; i <= len; i += bl)
184 (*dat->block) (in + i, out + i, &dat->ks);
185
186 return 1;
187 }
188
sm4_ofb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)189 static int sm4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
190 const unsigned char *in, size_t len)
191 {
192 EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx);
193 int num = EVP_CIPHER_CTX_get_num(ctx);
194
195 CRYPTO_ofb128_encrypt(in, out, len, &dat->ks,
196 ctx->iv, &num, dat->block);
197 EVP_CIPHER_CTX_set_num(ctx, num);
198 return 1;
199 }
200
sm4_ctr_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)201 static int sm4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
202 const unsigned char *in, size_t len)
203 {
204 int n = EVP_CIPHER_CTX_get_num(ctx);
205 unsigned int num;
206 EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx);
207
208 if (n < 0)
209 return 0;
210 num = (unsigned int)n;
211
212 if (dat->stream.ctr)
213 CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks,
214 ctx->iv,
215 EVP_CIPHER_CTX_buf_noconst(ctx),
216 &num, dat->stream.ctr);
217 else
218 CRYPTO_ctr128_encrypt(in, out, len, &dat->ks,
219 ctx->iv,
220 EVP_CIPHER_CTX_buf_noconst(ctx), &num,
221 dat->block);
222 EVP_CIPHER_CTX_set_num(ctx, num);
223 return 1;
224 }
225
226 DEFINE_BLOCK_CIPHERS(NID_sm4, 0)
227 #endif
228