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