1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifdef HKS_CONFIG_FILE
17 #include HKS_CONFIG_FILE
18 #else
19 #include "hks_config.h"
20 #endif
21
22 #ifdef HKS_SUPPORT_SM4_C
23
24 #include "hks_openssl_sm4.h"
25
26 #include <openssl/evp.h>
27 #include <openssl/ossl_typ.h>
28 #include <stdbool.h>
29 #include <stddef.h>
30
31 #include "hks_log.h"
32 #include "hks_mem.h"
33 #include "hks_openssl_aes.h"
34 #include "hks_openssl_common.h"
35 #include "hks_template.h"
36
37 #ifdef HKS_SUPPORT_SM4_GENERATE_KEY
Sm4GenKeyCheckParam(const struct HksKeySpec * spec)38 static int32_t Sm4GenKeyCheckParam(const struct HksKeySpec *spec)
39 {
40 if (spec->keyLen != HKS_SM4_KEY_SIZE_128) {
41 HKS_LOG_E("Invlid sm4 key len %" LOG_PUBLIC "x!", spec->keyLen);
42 return HKS_ERROR_INVALID_ARGUMENT;
43 }
44 return HKS_SUCCESS;
45 }
46
HksOpensslSm4GenerateKey(const struct HksKeySpec * spec,struct HksBlob * key)47 int32_t HksOpensslSm4GenerateKey(const struct HksKeySpec *spec, struct HksBlob *key)
48 {
49 HKS_IF_NOT_SUCC_LOGE_RETURN(Sm4GenKeyCheckParam(spec),
50 HKS_ERROR_INVALID_ARGUMENT, "sm4 generate key invalid params!")
51
52 return HksOpensslGenerateRandomKey(spec->keyLen, key);
53 }
54 #endif
55
GetSm4CipherType(uint32_t keySize,uint32_t mode)56 static const EVP_CIPHER *GetSm4CipherType(uint32_t keySize, uint32_t mode)
57 {
58 if (keySize != HKS_KEY_BYTES(HKS_SM4_KEY_SIZE_128)) {
59 return NULL;
60 }
61 switch (mode) {
62 case HKS_MODE_CBC:
63 return EVP_sm4_cbc();
64 case HKS_MODE_ECB:
65 return EVP_sm4_ecb();
66 case HKS_MODE_CTR:
67 return EVP_sm4_ctr();
68 case HKS_MODE_CFB:
69 return EVP_sm4_cfb();
70 case HKS_MODE_OFB:
71 return EVP_sm4_ofb();
72 default:
73 HKS_LOG_E("Unsupport sm4 mode! mode = %" LOG_PUBLIC "u", mode);
74 return NULL;
75 }
76 }
77
HksOpensslSm4EncryptInit(void ** cryptoCtx,const struct HksBlob * key,const struct HksUsageSpec * usageSpec)78 int32_t HksOpensslSm4EncryptInit(void **cryptoCtx, const struct HksBlob *key, const struct HksUsageSpec *usageSpec)
79 {
80 int32_t ret;
81 switch (usageSpec->mode) {
82 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
83 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
84 defined(HKS_SUPPORT_SM4_ECB_PKCS7) || defined(HKS_SUPPORT_SM4_CFB_NOPADDING) || \
85 defined(HKS_SUPPORT_SM4_OFB_NOPADDING)
86 case HKS_MODE_CBC:
87 case HKS_MODE_CTR:
88 case HKS_MODE_ECB:
89 case HKS_MODE_CFB:
90 case HKS_MODE_OFB:
91 ret = OpensslBlockCipherCryptInit(key, usageSpec, true, cryptoCtx, GetSm4CipherType);
92 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
93 "OpensslBlockCipherCryptInit for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
94 break;
95 #endif
96 default:
97 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", usageSpec->mode);
98 return HKS_ERROR_INVALID_ARGUMENT;
99 }
100
101 return HKS_SUCCESS;
102 }
103
HksOpensslSm4EncryptUpdate(void * cryptoCtx,const struct HksBlob * message,struct HksBlob * cipherText)104 int32_t HksOpensslSm4EncryptUpdate(void *cryptoCtx, const struct HksBlob *message, struct HksBlob *cipherText)
105 {
106 HKS_IF_NULL_LOGE_RETURN(cryptoCtx, HKS_ERROR_INVALID_ARGUMENT, "cryptoCtx is NULL")
107
108 struct HksOpensslBlockCipherCtx *context = (struct HksOpensslBlockCipherCtx *)cryptoCtx;
109 uint32_t mode = context->mode;
110
111 int32_t ret;
112 switch (mode) {
113 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
114 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
115 defined(HKS_SUPPORT_SM4_ECB_PKCS7) || defined(HKS_SUPPORT_SM4_CFB_NOPADDING) || \
116 defined(HKS_SUPPORT_SM4_OFB_NOPADDING)
117 case HKS_MODE_CBC:
118 case HKS_MODE_CTR:
119 case HKS_MODE_ECB:
120 case HKS_MODE_CFB:
121 case HKS_MODE_OFB:
122 ret = OpensslBlockCipherEncryptUpdate(cryptoCtx, message, cipherText);
123 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
124 "OpensslBlockCipherEncryptUpdate for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
125 break;
126 #endif
127 default:
128 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", mode);
129 return HKS_ERROR_INVALID_ARGUMENT;
130 }
131
132 return HKS_SUCCESS;
133 }
134
HksOpensslSm4EncryptFinal(void ** cryptoCtx,const struct HksBlob * message,struct HksBlob * cipherText,struct HksBlob * tagAead)135 int32_t HksOpensslSm4EncryptFinal(void **cryptoCtx, const struct HksBlob *message, struct HksBlob *cipherText,
136 struct HksBlob *tagAead)
137 {
138 (void)(tagAead); // sm4 do not support CCM or GCM, therefore tag is not used
139 struct HksOpensslBlockCipherCtx *ctx = (struct HksOpensslBlockCipherCtx *)*cryptoCtx;
140 uint32_t mode = ctx->mode;
141
142 int32_t ret;
143 switch (mode) {
144 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
145 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
146 defined(HKS_SUPPORT_SM4_ECB_PKCS7) || defined(HKS_SUPPORT_SM4_CFB_NOPADDING) || \
147 defined(HKS_SUPPORT_SM4_OFB_NOPADDING)
148 case HKS_MODE_CBC:
149 case HKS_MODE_CTR:
150 case HKS_MODE_ECB:
151 case HKS_MODE_CFB:
152 case HKS_MODE_OFB:
153 ret = OpensslBlockCipherEncryptFinalThree(cryptoCtx, message, cipherText);
154 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
155 "OpensslBlockCipherEncryptFinalThree for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
156 break;
157 #endif
158 default:
159 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", mode);
160 return HKS_ERROR_INVALID_ARGUMENT;
161 }
162
163 return HKS_SUCCESS;
164 }
165
HksOpensslSm4DecryptInit(void ** cryptoCtx,const struct HksBlob * key,const struct HksUsageSpec * usageSpec)166 int32_t HksOpensslSm4DecryptInit(void **cryptoCtx, const struct HksBlob *key,
167 const struct HksUsageSpec *usageSpec)
168 {
169 int32_t ret;
170 switch (usageSpec->mode) {
171 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
172 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
173 defined(HKS_SUPPORT_SM4_ECB_PKCS7) || defined(HKS_SUPPORT_SM4_CFB_NOPADDING) || \
174 defined(HKS_SUPPORT_SM4_OFB_NOPADDING)
175 case HKS_MODE_CBC:
176 case HKS_MODE_CTR:
177 case HKS_MODE_ECB:
178 case HKS_MODE_CFB:
179 case HKS_MODE_OFB:
180 ret = OpensslBlockCipherCryptInit(key, usageSpec, false, cryptoCtx, GetSm4CipherType);
181 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
182 "OpensslBlockCipherCryptInit for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
183 break;
184 #endif
185 default:
186 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", usageSpec->mode);
187 return HKS_ERROR_INVALID_ARGUMENT;
188 }
189
190 return ret;
191 }
192
HksOpensslSm4DecryptUpdate(void * cryptoCtx,const struct HksBlob * message,struct HksBlob * plainText)193 int32_t HksOpensslSm4DecryptUpdate(void *cryptoCtx, const struct HksBlob *message, struct HksBlob *plainText)
194 {
195 struct HksOpensslBlockCipherCtx *contex = (struct HksOpensslBlockCipherCtx *)cryptoCtx;
196 uint32_t mode = contex->mode;
197
198 int32_t ret;
199 switch (mode) {
200 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
201 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
202 defined(HKS_SUPPORT_SM4_ECB_PKCS7) || defined(HKS_SUPPORT_SM4_CFB_NOPADDING) || \
203 defined(HKS_SUPPORT_SM4_OFB_NOPADDING)
204 case HKS_MODE_CBC:
205 case HKS_MODE_CTR:
206 case HKS_MODE_ECB:
207 case HKS_MODE_CFB:
208 case HKS_MODE_OFB:
209 ret = OpensslBlockCipherDecryptUpdate(cryptoCtx, message, plainText);
210 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
211 "OpensslBlockCipherDecryptUpdate for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
212 break;
213 #endif
214 default:
215 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", mode);
216 return HKS_ERROR_INVALID_ARGUMENT;
217 }
218
219 return ret;
220 }
221
HksOpensslSm4DecryptFinal(void ** cryptoCtx,const struct HksBlob * message,struct HksBlob * cipherText,struct HksBlob * tagAead)222 int32_t HksOpensslSm4DecryptFinal(void **cryptoCtx, const struct HksBlob *message, struct HksBlob *cipherText,
223 struct HksBlob *tagAead)
224 {
225 HksOpensslBlockCipherCtx *context = (HksOpensslBlockCipherCtx *)*cryptoCtx;
226 uint32_t mode = context->mode;
227
228 int32_t ret;
229 switch (mode) {
230 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
231 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
232 defined(HKS_SUPPORT_SM4_ECB_PKCS7) || defined(HKS_SUPPORT_SM4_CFB_NOPADDING) || \
233 defined(HKS_SUPPORT_SM4_OFB_NOPADDING)
234 case HKS_MODE_CBC:
235 case HKS_MODE_CTR:
236 case HKS_MODE_ECB:
237 case HKS_MODE_CFB:
238 case HKS_MODE_OFB:
239 ret = OpensslBlockCipherDecryptFinalThree(cryptoCtx, message, cipherText);
240 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
241 "OpensslBlockCipherDecryptFinalThree for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
242 break;
243 #endif
244 default:
245 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", mode);
246 return HKS_ERROR_INVALID_ARGUMENT;
247 }
248
249 return HKS_SUCCESS;
250 }
251
HksOpensslSm4HalFreeCtx(void ** cryptoCtx)252 void HksOpensslSm4HalFreeCtx(void **cryptoCtx)
253 {
254 if (cryptoCtx == NULL || *cryptoCtx == NULL) {
255 HKS_LOG_E("Openssl sm4 free ctx is null");
256 return;
257 }
258
259 HksOpensslBlockCipherCtx *opensslSm4Ctx = (HksOpensslBlockCipherCtx *)*cryptoCtx;
260 switch (opensslSm4Ctx->mode) {
261 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
262 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
263 defined(HKS_SUPPORT_SM4_ECB_PKCS7) || defined(HKS_SUPPORT_SM4_CFB_NOPADDING) || \
264 defined(HKS_SUPPORT_SM4_OFB_NOPADDING)
265 case HKS_MODE_CBC:
266 case HKS_MODE_CTR:
267 case HKS_MODE_ECB:
268 case HKS_MODE_CFB:
269 case HKS_MODE_OFB:
270 if ((EVP_CIPHER_CTX *)opensslSm4Ctx->append != NULL) {
271 EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)opensslSm4Ctx->append);
272 opensslSm4Ctx->append = NULL;
273 }
274 break;
275 #endif
276 default:
277 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", opensslSm4Ctx->mode);
278 break;
279 }
280
281 HKS_FREE(*cryptoCtx);
282 }
283
HksOpensslSm4Encrypt(const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const struct HksBlob * message,struct HksBlob * cipherText)284 int32_t HksOpensslSm4Encrypt(const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
285 const struct HksBlob *message, struct HksBlob *cipherText)
286 {
287 EVP_CIPHER_CTX *ctx = NULL;
288 struct HksBlob tmpCipherText = *cipherText;
289
290 int32_t ret;
291 switch (usageSpec->mode) {
292 case HKS_MODE_CBC:
293 case HKS_MODE_CTR:
294 case HKS_MODE_ECB:
295 ret = OpensslBlockCipherCryptInit(key, usageSpec, true, (void **)&ctx, GetSm4CipherType);
296 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
297 "OpensslBlockCipherCryptInit fail, ret = %" LOG_PUBLIC "d", ret)
298
299 ret = OpensslBlockCipherEncryptFinalThree((void **)&ctx, message, &tmpCipherText);
300 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
301 "OpensslBlockCipherEncryptFinalThree fail, ret = %" LOG_PUBLIC "d", ret)
302 break;
303 default:
304 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", usageSpec->mode);
305 return HKS_ERROR_INVALID_ARGUMENT;
306 }
307
308 cipherText->size = tmpCipherText.size;
309 return ret;
310 }
311
HksOpensslSm4Decrypt(const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const struct HksBlob * message,struct HksBlob * plaintext)312 int32_t HksOpensslSm4Decrypt(const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
313 const struct HksBlob *message, struct HksBlob *plaintext)
314 {
315 EVP_CIPHER_CTX *ctx = NULL;
316 struct HksBlob tmpPlaintext = *plaintext;
317
318 int32_t ret;
319 switch (usageSpec->mode) {
320 case HKS_MODE_CBC:
321 case HKS_MODE_CTR:
322 case HKS_MODE_ECB:
323 ret = OpensslBlockCipherCryptInit(key, usageSpec, false, (void **)&ctx, GetSm4CipherType);
324 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
325 "OpensslBlockCipherCryptInit fail, ret = %" LOG_PUBLIC "d", ret)
326
327 ret = OpensslBlockCipherDecryptFinalThree((void **)&ctx, message, &tmpPlaintext);
328 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
329 "OpensslBlockCipherDecryptFinalThree fail, ret = %" LOG_PUBLIC "d", ret)
330 break;
331 default:
332 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", usageSpec->mode);
333 return HKS_ERROR_INVALID_ARGUMENT;
334 }
335
336 plaintext->size = tmpPlaintext.size;
337 return ret;
338 }
339
340 #endif
341