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
GetSm4CbcCipherType(uint32_t keySize)56 static const EVP_CIPHER *GetSm4CbcCipherType(uint32_t keySize)
57 {
58 switch (keySize) {
59 case HKS_KEY_BYTES(HKS_AES_KEY_SIZE_128):
60 return EVP_sm4_cbc();
61 default:
62 return NULL;
63 }
64 }
65
GetSm4CtrCipherType(uint32_t keySize)66 static const EVP_CIPHER *GetSm4CtrCipherType(uint32_t keySize)
67 {
68 switch (keySize) {
69 case HKS_KEY_BYTES(HKS_AES_KEY_SIZE_128):
70 return EVP_sm4_ctr();
71 default:
72 return NULL;
73 }
74 }
75
GetSm4EcbCipherType(uint32_t keySize)76 static const EVP_CIPHER *GetSm4EcbCipherType(uint32_t keySize)
77 {
78 switch (keySize) {
79 case HKS_KEY_BYTES(HKS_AES_KEY_SIZE_128):
80 return EVP_sm4_ecb();
81 default:
82 return NULL;
83 }
84 }
85
GetSm4CipherType(uint32_t keySize,uint32_t mode)86 static const EVP_CIPHER *GetSm4CipherType(uint32_t keySize, uint32_t mode)
87 {
88 return GetBlockCipherType(keySize, mode, GetSm4CbcCipherType, GetSm4CtrCipherType, GetSm4EcbCipherType);
89 }
90
HksOpensslSm4EncryptInit(void ** cryptoCtx,const struct HksBlob * key,const struct HksUsageSpec * usageSpec)91 int32_t HksOpensslSm4EncryptInit(void **cryptoCtx, const struct HksBlob *key, const struct HksUsageSpec *usageSpec)
92 {
93 int32_t ret;
94 switch (usageSpec->mode) {
95 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
96 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
97 defined(HKS_SUPPORT_SM4_ECB_PKCS7)
98 case HKS_MODE_CBC:
99 case HKS_MODE_CTR:
100 case HKS_MODE_ECB:
101 ret = OpensslBlockCipherCryptInit(key, usageSpec, true, cryptoCtx, GetSm4CipherType);
102 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
103 "OpensslBlockCipherCryptInit for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
104 break;
105 #endif
106 default:
107 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", usageSpec->mode);
108 return HKS_ERROR_INVALID_ARGUMENT;
109 }
110
111 return HKS_SUCCESS;
112 }
113
HksOpensslSm4EncryptUpdate(void * cryptoCtx,const struct HksBlob * message,struct HksBlob * cipherText)114 int32_t HksOpensslSm4EncryptUpdate(void *cryptoCtx, const struct HksBlob *message, struct HksBlob *cipherText)
115 {
116 HKS_IF_NULL_LOGE_RETURN(cryptoCtx, HKS_ERROR_INVALID_ARGUMENT, "cryptoCtx is NULL")
117
118 struct HksOpensslBlockCipherCtx *context = (struct HksOpensslBlockCipherCtx *)cryptoCtx;
119 uint32_t mode = context->mode;
120
121 int32_t ret;
122 switch (mode) {
123 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
124 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
125 defined(HKS_SUPPORT_SM4_ECB_PKCS7)
126 case HKS_MODE_CBC:
127 case HKS_MODE_CTR:
128 case HKS_MODE_ECB:
129 ret = OpensslBlockCipherEncryptUpdate(cryptoCtx, message, cipherText);
130 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
131 "OpensslBlockCipherEncryptUpdate for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
132 break;
133 #endif
134 default:
135 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", mode);
136 return HKS_ERROR_INVALID_ARGUMENT;
137 }
138
139 return HKS_SUCCESS;
140 }
141
HksOpensslSm4EncryptFinal(void ** cryptoCtx,const struct HksBlob * message,struct HksBlob * cipherText,struct HksBlob * tagAead)142 int32_t HksOpensslSm4EncryptFinal(void **cryptoCtx, const struct HksBlob *message, struct HksBlob *cipherText,
143 struct HksBlob *tagAead)
144 {
145 (void)(tagAead); // sm4 do not support CCM or GCM, therefore tag is not used
146 struct HksOpensslBlockCipherCtx *ctx = (struct HksOpensslBlockCipherCtx *)*cryptoCtx;
147 uint32_t mode = ctx->mode;
148
149 int32_t ret;
150 switch (mode) {
151 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
152 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
153 defined(HKS_SUPPORT_SM4_ECB_PKCS7)
154 case HKS_MODE_CBC:
155 case HKS_MODE_CTR:
156 case HKS_MODE_ECB:
157 ret = OpensslBlockCipherEncryptFinalThree(cryptoCtx, message, cipherText);
158 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
159 "OpensslBlockCipherEncryptFinalThree for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
160 break;
161 #endif
162 default:
163 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", mode);
164 return HKS_ERROR_INVALID_ARGUMENT;
165 }
166
167 return HKS_SUCCESS;
168 }
169
HksOpensslSm4DecryptInit(void ** cryptoCtx,const struct HksBlob * key,const struct HksUsageSpec * usageSpec)170 int32_t HksOpensslSm4DecryptInit(void **cryptoCtx, const struct HksBlob *key,
171 const struct HksUsageSpec *usageSpec)
172 {
173 int32_t ret;
174 switch (usageSpec->mode) {
175 case HKS_MODE_CBC:
176 case HKS_MODE_CTR:
177 case HKS_MODE_ECB:
178 ret = OpensslBlockCipherCryptInit(key, usageSpec, false, cryptoCtx, GetSm4CipherType);
179 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
180 "OpensslBlockCipherCryptInit for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
181 break;
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 case HKS_MODE_CBC:
198 case HKS_MODE_CTR:
199 case HKS_MODE_ECB:
200 ret = OpensslBlockCipherDecryptUpdate(cryptoCtx, message, plainText);
201 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
202 "OpensslBlockCipherDecryptUpdate for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
203 break;
204 default:
205 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", mode);
206 return HKS_ERROR_INVALID_ARGUMENT;
207 }
208
209 return ret;
210 }
211
HksOpensslSm4DecryptFinal(void ** cryptoCtx,const struct HksBlob * message,struct HksBlob * cipherText,struct HksBlob * tagAead)212 int32_t HksOpensslSm4DecryptFinal(void **cryptoCtx, const struct HksBlob *message, struct HksBlob *cipherText,
213 struct HksBlob *tagAead)
214 {
215 HksOpensslBlockCipherCtx *context = (HksOpensslBlockCipherCtx *)*cryptoCtx;
216 uint32_t mode = context->mode;
217
218 int32_t ret;
219 switch (mode) {
220 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
221 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
222 defined(HKS_SUPPORT_SM4_ECB_PKCS7)
223 case HKS_MODE_CBC:
224 case HKS_MODE_CTR:
225 case HKS_MODE_ECB:
226 ret = OpensslBlockCipherDecryptFinalThree(cryptoCtx, message, cipherText);
227 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
228 "OpensslBlockCipherDecryptFinalThree for sm4 fail, ret = %" LOG_PUBLIC "d", ret)
229 break;
230 #endif
231 default:
232 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", mode);
233 return HKS_ERROR_INVALID_ARGUMENT;
234 }
235
236 return HKS_SUCCESS;
237 }
238
HksOpensslSm4HalFreeCtx(void ** cryptoCtx)239 void HksOpensslSm4HalFreeCtx(void **cryptoCtx)
240 {
241 if (cryptoCtx == NULL || *cryptoCtx == NULL) {
242 HKS_LOG_E("Openssl sm4 free ctx is null");
243 return;
244 }
245
246 HksOpensslBlockCipherCtx *opensslSm4Ctx = (HksOpensslBlockCipherCtx *)*cryptoCtx;
247 switch (opensslSm4Ctx->mode) {
248 #if defined(HKS_SUPPORT_SM4_CBC_NOPADDING) || defined(HKS_SUPPORT_SM4_CBC_PKCS7) || \
249 defined(HKS_SUPPORT_SM4_CTR_NOPADDING) || defined(HKS_SUPPORT_SM4_ECB_NOPADDING) || \
250 defined(HKS_SUPPORT_SM4_ECB_PKCS7)
251 case HKS_MODE_CBC:
252 case HKS_MODE_CTR:
253 case HKS_MODE_ECB:
254 if ((EVP_CIPHER_CTX *)opensslSm4Ctx->append != NULL) {
255 EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)opensslSm4Ctx->append);
256 opensslSm4Ctx->append = NULL;
257 }
258 break;
259 #endif
260 default:
261 HKS_LOG_E("Unsupport sm4 mode! mode = 0x%" LOG_PUBLIC "x", opensslSm4Ctx->mode);
262 break;
263 }
264
265 HKS_FREE_PTR(*cryptoCtx);
266 }
267
268 #endif
269