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 HKS_IF_TRUE_LOGE_RETURN(spec->keyLen != HKS_SM4_KEY_SIZE_128, HKS_ERROR_INVALID_ARGUMENT,
41 "Invlid sm4 key len %" LOG_PUBLIC "x!", spec->keyLen)
42 return HKS_SUCCESS;
43 }
44
HksOpensslSm4GenerateKey(const struct HksKeySpec * spec,struct HksBlob * key)45 int32_t HksOpensslSm4GenerateKey(const struct HksKeySpec *spec, struct HksBlob *key)
46 {
47 HKS_IF_NOT_SUCC_LOGE_RETURN(Sm4GenKeyCheckParam(spec),
48 HKS_ERROR_INVALID_ARGUMENT, "sm4 generate key invalid params!")
49
50 return HksOpensslGenerateRandomKey(spec->keyLen, key);
51 }
52 #endif
53
GetSm4CipherType(uint32_t keySize,uint32_t mode)54 static const EVP_CIPHER *GetSm4CipherType(uint32_t keySize, uint32_t mode)
55 {
56 HKS_IF_TRUE_RETURN(keySize != HKS_KEY_BYTES(HKS_SM4_KEY_SIZE_128), NULL)
57
58 switch (mode) {
59 case HKS_MODE_CBC:
60 return EVP_sm4_cbc();
61 case HKS_MODE_ECB:
62 return EVP_sm4_ecb();
63 case HKS_MODE_CTR:
64 return EVP_sm4_ctr();
65 case HKS_MODE_CFB:
66 return EVP_sm4_cfb();
67 case HKS_MODE_OFB:
68 return EVP_sm4_ofb();
69 default:
70 HKS_LOG_E("Unsupport sm4 mode! mode = %" LOG_PUBLIC "u", mode);
71 return NULL;
72 }
73 }
74
HksOpensslSm4EncryptInit(void ** cryptoCtx,const struct HksBlob * key,const struct HksUsageSpec * usageSpec)75 int32_t HksOpensslSm4EncryptInit(void **cryptoCtx, const struct HksBlob *key, const struct HksUsageSpec *usageSpec)
76 {
77 int32_t ret;
78 switch (usageSpec->mode) {
79 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
80 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
81 defined(HKS_SUPPORT_SM4_ECB_PKCS7) || defined(HKS_SUPPORT_SM4_CFB_NOPADDING) || \
82 defined(HKS_SUPPORT_SM4_OFB_NOPADDING)
83 case HKS_MODE_CBC:
84 case HKS_MODE_CTR:
85 case HKS_MODE_ECB:
86 case HKS_MODE_CFB:
87 case HKS_MODE_OFB:
88 ret = OpensslBlockCipherCryptInit(key, usageSpec, true, cryptoCtx, GetSm4CipherType);
89 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
90 "OpensslBlockCipherCryptInit for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
91 break;
92 #endif
93 default:
94 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", usageSpec->mode);
95 return HKS_ERROR_INVALID_ARGUMENT;
96 }
97
98 return HKS_SUCCESS;
99 }
100
HksOpensslSm4EncryptUpdate(void * cryptoCtx,const struct HksBlob * message,struct HksBlob * cipherText)101 int32_t HksOpensslSm4EncryptUpdate(void *cryptoCtx, const struct HksBlob *message, struct HksBlob *cipherText)
102 {
103 HKS_IF_NULL_LOGE_RETURN(cryptoCtx, HKS_ERROR_INVALID_ARGUMENT, "cryptoCtx is NULL")
104
105 struct HksOpensslBlockCipherCtx *context = (struct HksOpensslBlockCipherCtx *)cryptoCtx;
106 uint32_t mode = context->mode;
107
108 int32_t ret;
109 switch (mode) {
110 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
111 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
112 defined(HKS_SUPPORT_SM4_ECB_PKCS7) || defined(HKS_SUPPORT_SM4_CFB_NOPADDING) || \
113 defined(HKS_SUPPORT_SM4_OFB_NOPADDING)
114 case HKS_MODE_CBC:
115 case HKS_MODE_CTR:
116 case HKS_MODE_ECB:
117 case HKS_MODE_CFB:
118 case HKS_MODE_OFB:
119 ret = OpensslBlockCipherEncryptUpdate(cryptoCtx, message, cipherText);
120 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
121 "OpensslBlockCipherEncryptUpdate for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
122 break;
123 #endif
124 default:
125 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", mode);
126 return HKS_ERROR_INVALID_ARGUMENT;
127 }
128
129 return HKS_SUCCESS;
130 }
131
HksOpensslSm4EncryptFinal(void ** cryptoCtx,const struct HksBlob * message,struct HksBlob * cipherText,struct HksBlob * tagAead)132 int32_t HksOpensslSm4EncryptFinal(void **cryptoCtx, const struct HksBlob *message, struct HksBlob *cipherText,
133 struct HksBlob *tagAead)
134 {
135 (void)(tagAead); // sm4 do not support CCM or GCM, therefore tag is not used
136 struct HksOpensslBlockCipherCtx *ctx = (struct HksOpensslBlockCipherCtx *)*cryptoCtx;
137 uint32_t mode = ctx->mode;
138
139 int32_t ret;
140 switch (mode) {
141 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
142 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
143 defined(HKS_SUPPORT_SM4_ECB_PKCS7) || defined(HKS_SUPPORT_SM4_CFB_NOPADDING) || \
144 defined(HKS_SUPPORT_SM4_OFB_NOPADDING)
145 case HKS_MODE_CBC:
146 case HKS_MODE_CTR:
147 case HKS_MODE_ECB:
148 case HKS_MODE_CFB:
149 case HKS_MODE_OFB:
150 ret = OpensslBlockCipherEncryptFinalThree(cryptoCtx, message, cipherText);
151 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
152 "OpensslBlockCipherEncryptFinalThree for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
153 break;
154 #endif
155 default:
156 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", mode);
157 return HKS_ERROR_INVALID_ARGUMENT;
158 }
159
160 return HKS_SUCCESS;
161 }
162
HksOpensslSm4DecryptInit(void ** cryptoCtx,const struct HksBlob * key,const struct HksUsageSpec * usageSpec)163 int32_t HksOpensslSm4DecryptInit(void **cryptoCtx, const struct HksBlob *key,
164 const struct HksUsageSpec *usageSpec)
165 {
166 int32_t ret;
167 switch (usageSpec->mode) {
168 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
169 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
170 defined(HKS_SUPPORT_SM4_ECB_PKCS7) || defined(HKS_SUPPORT_SM4_CFB_NOPADDING) || \
171 defined(HKS_SUPPORT_SM4_OFB_NOPADDING)
172 case HKS_MODE_CBC:
173 case HKS_MODE_CTR:
174 case HKS_MODE_ECB:
175 case HKS_MODE_CFB:
176 case HKS_MODE_OFB:
177 ret = OpensslBlockCipherCryptInit(key, usageSpec, false, cryptoCtx, GetSm4CipherType);
178 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
179 "OpensslBlockCipherCryptInit for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
180 break;
181 #endif
182 default:
183 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", usageSpec->mode);
184 return HKS_ERROR_INVALID_ARGUMENT;
185 }
186
187 return ret;
188 }
189
HksOpensslSm4DecryptUpdate(void * cryptoCtx,const struct HksBlob * message,struct HksBlob * plainText)190 int32_t HksOpensslSm4DecryptUpdate(void *cryptoCtx, const struct HksBlob *message, struct HksBlob *plainText)
191 {
192 struct HksOpensslBlockCipherCtx *contex = (struct HksOpensslBlockCipherCtx *)cryptoCtx;
193 uint32_t mode = contex->mode;
194
195 int32_t ret;
196 switch (mode) {
197 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
198 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
199 defined(HKS_SUPPORT_SM4_ECB_PKCS7) || defined(HKS_SUPPORT_SM4_CFB_NOPADDING) || \
200 defined(HKS_SUPPORT_SM4_OFB_NOPADDING)
201 case HKS_MODE_CBC:
202 case HKS_MODE_CTR:
203 case HKS_MODE_ECB:
204 case HKS_MODE_CFB:
205 case HKS_MODE_OFB:
206 ret = OpensslBlockCipherDecryptUpdate(cryptoCtx, message, plainText);
207 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
208 "OpensslBlockCipherDecryptUpdate for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
209 break;
210 #endif
211 default:
212 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", mode);
213 return HKS_ERROR_INVALID_ARGUMENT;
214 }
215
216 return ret;
217 }
218
HksOpensslSm4DecryptFinal(void ** cryptoCtx,const struct HksBlob * message,struct HksBlob * cipherText,struct HksBlob * tagAead)219 int32_t HksOpensslSm4DecryptFinal(void **cryptoCtx, const struct HksBlob *message, struct HksBlob *cipherText,
220 struct HksBlob *tagAead)
221 {
222 HksOpensslBlockCipherCtx *context = (HksOpensslBlockCipherCtx *)*cryptoCtx;
223 uint32_t mode = context->mode;
224
225 int32_t ret;
226 switch (mode) {
227 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
228 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
229 defined(HKS_SUPPORT_SM4_ECB_PKCS7) || defined(HKS_SUPPORT_SM4_CFB_NOPADDING) || \
230 defined(HKS_SUPPORT_SM4_OFB_NOPADDING)
231 case HKS_MODE_CBC:
232 case HKS_MODE_CTR:
233 case HKS_MODE_ECB:
234 case HKS_MODE_CFB:
235 case HKS_MODE_OFB:
236 ret = OpensslBlockCipherDecryptFinalThree(cryptoCtx, message, cipherText);
237 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
238 "OpensslBlockCipherDecryptFinalThree for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
239 break;
240 #endif
241 default:
242 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", mode);
243 return HKS_ERROR_INVALID_ARGUMENT;
244 }
245
246 return HKS_SUCCESS;
247 }
248
HksOpensslSm4HalFreeCtx(void ** cryptoCtx)249 void HksOpensslSm4HalFreeCtx(void **cryptoCtx)
250 {
251 HKS_IF_TRUE_LOGE_RETURN_VOID(cryptoCtx == NULL || *cryptoCtx == NULL, "Openssl sm4 free ctx is null")
252
253 HksOpensslBlockCipherCtx *opensslSm4Ctx = (HksOpensslBlockCipherCtx *)*cryptoCtx;
254 switch (opensslSm4Ctx->mode) {
255 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
256 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
257 defined(HKS_SUPPORT_SM4_ECB_PKCS7) || defined(HKS_SUPPORT_SM4_CFB_NOPADDING) || \
258 defined(HKS_SUPPORT_SM4_OFB_NOPADDING)
259 case HKS_MODE_CBC:
260 case HKS_MODE_CTR:
261 case HKS_MODE_ECB:
262 case HKS_MODE_CFB:
263 case HKS_MODE_OFB:
264 if ((EVP_CIPHER_CTX *)opensslSm4Ctx->append != NULL) {
265 EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)opensslSm4Ctx->append);
266 opensslSm4Ctx->append = NULL;
267 }
268 break;
269 #endif
270 default:
271 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", opensslSm4Ctx->mode);
272 break;
273 }
274
275 HKS_FREE(*cryptoCtx);
276 }
277
HksOpensslSm4Encrypt(const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const struct HksBlob * message,struct HksBlob * cipherText)278 int32_t HksOpensslSm4Encrypt(const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
279 const struct HksBlob *message, struct HksBlob *cipherText)
280 {
281 EVP_CIPHER_CTX *ctx = NULL;
282 struct HksBlob tmpCipherText = *cipherText;
283
284 int32_t ret;
285 switch (usageSpec->mode) {
286 case HKS_MODE_CBC:
287 case HKS_MODE_CTR:
288 case HKS_MODE_ECB:
289 ret = OpensslBlockCipherCryptInit(key, usageSpec, true, (void **)&ctx, GetSm4CipherType);
290 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
291 "OpensslBlockCipherCryptInit fail, ret = %" LOG_PUBLIC "d", ret)
292
293 ret = OpensslBlockCipherEncryptFinalThree((void **)&ctx, message, &tmpCipherText);
294 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
295 "OpensslBlockCipherEncryptFinalThree fail, ret = %" LOG_PUBLIC "d", ret)
296 break;
297 default:
298 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", usageSpec->mode);
299 return HKS_ERROR_INVALID_ARGUMENT;
300 }
301
302 cipherText->size = tmpCipherText.size;
303 return ret;
304 }
305
HksOpensslSm4Decrypt(const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const struct HksBlob * message,struct HksBlob * plaintext)306 int32_t HksOpensslSm4Decrypt(const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
307 const struct HksBlob *message, struct HksBlob *plaintext)
308 {
309 EVP_CIPHER_CTX *ctx = NULL;
310 struct HksBlob tmpPlaintext = *plaintext;
311
312 int32_t ret;
313 switch (usageSpec->mode) {
314 case HKS_MODE_CBC:
315 case HKS_MODE_CTR:
316 case HKS_MODE_ECB:
317 ret = OpensslBlockCipherCryptInit(key, usageSpec, false, (void **)&ctx, GetSm4CipherType);
318 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
319 "OpensslBlockCipherCryptInit fail, ret = %" LOG_PUBLIC "d", ret)
320
321 ret = OpensslBlockCipherDecryptFinalThree((void **)&ctx, message, &tmpPlaintext);
322 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
323 "OpensslBlockCipherDecryptFinalThree fail, ret = %" LOG_PUBLIC "d", ret)
324 break;
325 default:
326 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", usageSpec->mode);
327 return HKS_ERROR_INVALID_ARGUMENT;
328 }
329
330 plaintext->size = tmpPlaintext.size;
331 return ret;
332 }
333
334 #endif
335