• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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