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