xref: /openssl/crypto/evp/e_sm4.c (revision fecb3aae)
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