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 |
|
---|
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 |
|
---|
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 |
|
---|
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 |
|
---|
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 |
|
---|
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 |
|
---|
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
|
---|