1 /*
2 * Copyright (c) 2024 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_DES_C
23
24 #include <openssl/des.h>
25 #include <openssl/evp.h>
26
27 #include "hks_cfi.h"
28 #include "hks_log.h"
29 #include "hks_mem.h"
30 #include "hks_openssl_des.h"
31 #include "hks_openssl_engine.h"
32 #include "hks_template.h"
33 #include "securec.h"
34
CheckDesKeySize(const struct HksBlob * key)35 static int32_t CheckDesKeySize(const struct HksBlob *key)
36 {
37 HKS_IF_TRUE_RETURN(key->size != HKS_KEY_BYTES(HKS_DES_KEY_SIZE_64), HKS_ERROR_INVALID_KEY_SIZE)
38 return HKS_SUCCESS;
39 }
40
41 #ifdef HKS_SUPPORT_DES_GENERATE_KEY
HksOpensslDesGenerateKey(const struct HksKeySpec * spec,struct HksBlob * key)42 int32_t HksOpensslDesGenerateKey(const struct HksKeySpec *spec, struct HksBlob *key)
43 {
44 HKS_IF_TRUE_RETURN(spec->keyLen != HKS_DES_KEY_SIZE_64, HKS_ERROR_INVALID_KEY_SIZE)
45
46 const uint32_t keyByteLen = spec->keyLen / HKS_BITS_PER_BYTE;
47 uint8_t *outKey = (uint8_t *)HksMalloc(keyByteLen);
48 HKS_IF_NULL_RETURN(outKey, HKS_ERROR_MALLOC_FAIL)
49
50 DES_cblock desKey;
51 if (DES_random_key(&desKey) != HKS_OPENSSL_SUCCESS) {
52 HKS_LOG_E("DES_random_key failed");
53 HKS_FREE(outKey);
54 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
55 }
56
57 (void)memcpy_s(outKey, keyByteLen, desKey, keyByteLen);
58 key->data = outKey;
59 key->size = keyByteLen;
60
61 return HKS_SUCCESS;
62 }
63 #endif /* HKS_SUPPORT_DES_GENERATE_KEY */
64
ENABLE_CFI(const EVP_CIPHER * OpensslGetDesCipherType (uint32_t keySize,uint32_t mode))65 ENABLE_CFI(const EVP_CIPHER *OpensslGetDesCipherType(uint32_t keySize, uint32_t mode))
66 {
67 if (keySize == HKS_KEY_BYTES(HKS_DES_KEY_SIZE_64)) {
68 switch (mode) {
69 case HKS_MODE_CBC:
70 return EVP_des_cbc();
71 case HKS_MODE_ECB:
72 return EVP_des_ecb();
73 default:
74 return NULL;
75 }
76 } else if (keySize == HKS_KEY_BYTES(HKS_3DES_KEY_SIZE_128)) {
77 switch (mode) {
78 case HKS_MODE_CBC:
79 return EVP_des_ede_cbc();
80 case HKS_MODE_ECB:
81 return EVP_des_ede_ecb();
82 default:
83 return NULL;
84 }
85 } else if (keySize == HKS_KEY_BYTES(HKS_3DES_KEY_SIZE_192)) {
86 switch (mode) {
87 case HKS_MODE_CBC:
88 return EVP_des_ede3_cbc();
89 case HKS_MODE_ECB:
90 return EVP_des_ede3_ecb();
91 default:
92 return NULL;
93 }
94 }
95 return NULL;
96 }
97
OpensslDesCipherInitParams(const struct HksBlob * key,EVP_CIPHER_CTX * ctx,bool isEncrypt,struct HksCipherParam * cipherParam)98 static int32_t OpensslDesCipherInitParams(const struct HksBlob *key, EVP_CIPHER_CTX *ctx, bool isEncrypt,
99 struct HksCipherParam *cipherParam)
100 {
101 int32_t ret = isEncrypt
102 ? EVP_EncryptInit_ex(ctx, NULL, NULL, key->data, (cipherParam == NULL) ? NULL : cipherParam->iv.data)
103 : EVP_DecryptInit_ex(ctx, NULL, NULL, key->data, (cipherParam == NULL) ? NULL : cipherParam->iv.data);
104 if (ret != HKS_OPENSSL_SUCCESS) {
105 HksLogOpensslError();
106 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
107 }
108
109 ret = EVP_CIPHER_CTX_set_padding(ctx, OPENSSL_CTX_PADDING_NONE);
110 if (ret != HKS_OPENSSL_SUCCESS) {
111 HksLogOpensslError();
112 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
113 }
114 return HKS_SUCCESS;
115 }
116
OpensslDesCipherInit(const struct HksBlob * key,const struct HksUsageSpec * usageSpec,bool isEncrypt,struct HksOpensslDesCtx * outCtx)117 static int32_t OpensslDesCipherInit(const struct HksBlob *key, const struct HksUsageSpec *usageSpec, bool isEncrypt,
118 struct HksOpensslDesCtx *outCtx)
119 {
120 int32_t ret;
121 struct HksCipherParam *cipherParam = (struct HksCipherParam *)usageSpec->algParam;
122
123 EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
124 if (ctx == NULL) {
125 HksLogOpensslError();
126 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
127 }
128
129 const EVP_CIPHER *cipher = OpensslGetDesCipherType(key->size, usageSpec->mode);
130 if (cipher == NULL) {
131 EVP_CIPHER_CTX_free(ctx);
132 return HKS_ERROR_INVALID_MODE;
133 }
134
135 ret = isEncrypt
136 ? EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL)
137 : EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL);
138 if (ret != HKS_OPENSSL_SUCCESS) {
139 HksLogOpensslError();
140 EVP_CIPHER_CTX_free(ctx);
141 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
142 }
143
144 ret = OpensslDesCipherInitParams(key, ctx, isEncrypt, cipherParam);
145 if (ret != HKS_SUCCESS) {
146 EVP_CIPHER_CTX_free(ctx);
147 HKS_LOG_E("OpensslBlockCipherCryptInitParams fail, ret = %" LOG_PUBLIC "d", ret);
148 return ret;
149 }
150 outCtx->append = (void *)ctx;
151
152 return HKS_SUCCESS;
153 }
154
DesNoPaddingCryptInit(void ** cryptoCtx,const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const bool encrypt)155 int32_t DesNoPaddingCryptInit(void **cryptoCtx, const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
156 const bool encrypt)
157 {
158 struct HksCipherParam *iv = (struct HksCipherParam *)(usageSpec->algParam);
159 HKS_IF_TRUE_LOGE_RETURN(usageSpec->mode == HKS_MODE_CBC && iv->iv.size != HKS_DES_IV_SIZE, HKS_ERROR_INVALID_IV,
160 "initialize iv fail")
161
162 struct HksOpensslDesCtx *outCtx = (struct HksOpensslDesCtx *)HksMalloc(sizeof(struct HksOpensslDesCtx));
163 HKS_IF_NULL_LOGE_RETURN(outCtx, HKS_ERROR_MALLOC_FAIL, "initialize outCtx fail")
164
165 int32_t ret = OpensslDesCipherInit(key, usageSpec, encrypt, outCtx);
166 if (ret != HKS_SUCCESS) {
167 HKS_LOG_E("openssl initialize des cipher fail");
168 HKS_FREE(outCtx);
169 return ret;
170 }
171
172 outCtx->mode = usageSpec->mode;
173 outCtx->padding = usageSpec->padding;
174
175 *cryptoCtx = (void *)outCtx;
176 return HKS_SUCCESS;
177 }
178
DesNoPaddingCryptUpdate(void * cryptoCtx,const struct HksBlob * message,const bool encrypt,struct HksBlob * cipherText)179 int32_t DesNoPaddingCryptUpdate(void *cryptoCtx, const struct HksBlob *message, const bool encrypt,
180 struct HksBlob *cipherText)
181 {
182 struct HksOpensslDesCtx *desCtx = (struct HksOpensslDesCtx *)cryptoCtx;
183 EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX *)desCtx->append;
184 HKS_IF_NULL_RETURN(ctx, HKS_ERROR_NULL_POINTER)
185
186 HKS_IF_TRUE_LOGE_RETURN(message->size % HKS_DES_BLOCK_SIZE != 0, HKS_ERROR_INVALID_ARGUMENT,
187 "DesCbcNoPaddingCryptUpdate data size invalid!")
188
189 int32_t outLen = 0;
190 int evpRet = encrypt
191 ? EVP_EncryptUpdate(ctx, cipherText->data, &outLen, message->data, message->size)
192 : EVP_DecryptUpdate(ctx, cipherText->data, &outLen, message->data, message->size);
193 if (evpRet != HKS_OPENSSL_SUCCESS) {
194 HksLogOpensslError();
195 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
196 }
197 cipherText->size = (uint32_t)outLen;
198
199 return HKS_SUCCESS;
200 }
201
DesNoPaddingCryptFinal(void ** cryptoCtx,const struct HksBlob * message,const bool encrypt,struct HksBlob * cipherText)202 int32_t DesNoPaddingCryptFinal(void **cryptoCtx, const struct HksBlob *message, const bool encrypt,
203 struct HksBlob *cipherText)
204 {
205 struct HksOpensslDesCtx *desCtx = (struct HksOpensslDesCtx *)*cryptoCtx;
206 EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX *)desCtx->append;
207 HKS_IF_NULL_RETURN(ctx, HKS_ERROR_NULL_POINTER)
208
209 HKS_IF_TRUE_LOGE_RETURN(message->size % HKS_DES_BLOCK_SIZE != 0, HKS_ERROR_INVALID_ARGUMENT,
210 "DesCbcNoPaddingCryptFinal data size invalid!")
211
212 int32_t ret = HKS_SUCCESS;
213 do {
214 int32_t outLen = 0;
215 int evpRet;
216 if (message->size != 0) {
217 evpRet = encrypt
218 ? EVP_EncryptUpdate(ctx, cipherText->data, &outLen, message->data, message->size)
219 : EVP_DecryptUpdate(ctx, cipherText->data, &outLen, message->data, message->size);
220 if (evpRet != HKS_OPENSSL_SUCCESS) {
221 HksLogOpensslError();
222 ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
223 break;
224 }
225 }
226 cipherText->size = (uint32_t)outLen;
227 evpRet = encrypt
228 ? EVP_EncryptFinal_ex(ctx, (cipherText->data + outLen), &outLen)
229 : EVP_DecryptFinal_ex(ctx, (cipherText->data + outLen), &outLen);
230 if (evpRet != HKS_OPENSSL_SUCCESS) {
231 HksLogOpensslError();
232 ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
233 break;
234 }
235 cipherText->size += (uint32_t)outLen;
236 } while (0);
237
238 EVP_CIPHER_CTX_free(ctx);
239 desCtx->append = NULL;
240
241 HksOpensslDesHalFreeCtx(cryptoCtx);
242 return ret;
243 }
244
DesCryptInit(void ** cryptoCtx,const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const bool encrypt)245 static int32_t DesCryptInit(void **cryptoCtx, const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
246 const bool encrypt)
247 {
248 switch (usageSpec->padding) {
249 #if defined(HKS_SUPPORT_DES_CBC_NOPADDING) || defined(HKS_SUPPORT_DES_ECB_NOPADDING)
250 case HKS_PADDING_NONE:
251 return DesNoPaddingCryptInit(cryptoCtx, key, usageSpec, encrypt);
252 #endif
253 default:
254 HKS_LOG_E("Unsupport padding! mode = 0x%" LOG_PUBLIC "X", usageSpec->padding);
255 return HKS_ERROR_INVALID_PADDING;
256 }
257 }
258
DesCryptUpdate(void * cryptoCtx,const uint8_t padding,const struct HksBlob * message,struct HksBlob * cipherText,const bool encrypt)259 static int32_t DesCryptUpdate(void *cryptoCtx, const uint8_t padding, const struct HksBlob *message,
260 struct HksBlob *cipherText, const bool encrypt)
261 {
262 switch (padding) {
263 #if defined(HKS_SUPPORT_DES_CBC_NOPADDING) || defined(HKS_SUPPORT_DES_ECB_NOPADDING)
264 case HKS_PADDING_NONE:
265 return DesNoPaddingCryptUpdate(cryptoCtx, message, encrypt, cipherText);
266 #endif
267 default:
268 HKS_LOG_E("Unsupport padding! mode = 0x%" LOG_PUBLIC "X", padding);
269 return HKS_ERROR_INVALID_PADDING;
270 }
271 }
272
DesCryptFinal(void ** cryptoCtx,const uint8_t padding,const struct HksBlob * message,struct HksBlob * cipherText,const bool encrypt)273 static int32_t DesCryptFinal(void **cryptoCtx, const uint8_t padding, const struct HksBlob *message,
274 struct HksBlob *cipherText, const bool encrypt)
275 {
276 switch (padding) {
277 #if defined(HKS_SUPPORT_DES_CBC_NOPADDING) || defined(HKS_SUPPORT_DES_ECB_NOPADDING)
278 case HKS_PADDING_NONE:
279 return DesNoPaddingCryptFinal(cryptoCtx, message, encrypt, cipherText);
280 #endif
281 default:
282 HKS_LOG_E("Unsupport padding! mode = 0x%" LOG_PUBLIC "X", padding);
283 return HKS_ERROR_INVALID_PADDING;
284 }
285 }
286
HksOpensslDesCryptoInit(void ** cryptoCtx,const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const bool encrypt)287 int32_t HksOpensslDesCryptoInit(void **cryptoCtx, const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
288 const bool encrypt)
289 {
290 HKS_IF_TRUE_LOGE_RETURN(CheckDesKeySize(key) != HKS_SUCCESS || cryptoCtx == NULL || usageSpec == NULL,
291 HKS_ERROR_INVALID_ARGUMENT, "Invalid des keySize = 0x%" LOG_PUBLIC "X", key->size)
292
293 switch (usageSpec->mode) {
294 #if defined(HKS_SUPPORT_DES_CBC_NOPADDING)
295 case HKS_MODE_CBC:
296 return DesCryptInit(cryptoCtx, key, usageSpec, encrypt);
297 #endif
298 #if defined(HKS_SUPPORT_DES_ECB_NOPADDING)
299 case HKS_MODE_ECB:
300 return DesCryptInit(cryptoCtx, key, usageSpec, encrypt);
301 #endif
302 default:
303 HKS_LOG_E("Unsupport key alg! mode = 0x%" LOG_PUBLIC "X", usageSpec->mode);
304 return HKS_ERROR_INVALID_MODE;
305 }
306 }
307
HksOpensslDesCryptoUpdate(void * cryptoCtx,const struct HksBlob * message,struct HksBlob * cipherText,const bool encrypt)308 int32_t HksOpensslDesCryptoUpdate(void *cryptoCtx, const struct HksBlob *message, struct HksBlob *cipherText,
309 const bool encrypt)
310 {
311 HKS_IF_NULL_LOGE_RETURN(cryptoCtx, HKS_ERROR_INVALID_ARGUMENT, "Openssl DES encrypt update param is null")
312 struct HksOpensslDesCtx *desEncryptCtx = (struct HksOpensslDesCtx *)cryptoCtx;
313
314 switch (desEncryptCtx->mode) {
315 #if defined(HKS_SUPPORT_DES_CBC_NOPADDING)
316 case HKS_MODE_CBC:
317 return DesCryptUpdate(cryptoCtx, desEncryptCtx->padding, message, cipherText, encrypt);
318 #endif
319 #if defined(HKS_SUPPORT_DES_ECB_NOPADDING)
320 case HKS_MODE_ECB:
321 return DesCryptUpdate(cryptoCtx, desEncryptCtx->padding, message, cipherText, encrypt);
322 #endif
323 default:
324 HKS_LOG_E("Unsupport key alg! mode = 0x%" LOG_PUBLIC "X", desEncryptCtx->mode);
325 return HKS_ERROR_INVALID_MODE;
326 }
327 }
328
HksOpensslDesCryptoFinal(void ** cryptoCtx,const struct HksBlob * message,struct HksBlob * cipherText,struct HksBlob * tagAead,const bool encrypt)329 int32_t HksOpensslDesCryptoFinal(void **cryptoCtx, const struct HksBlob *message, struct HksBlob *cipherText,
330 struct HksBlob *tagAead, const bool encrypt)
331 {
332 (void)tagAead;
333 struct HksOpensslDesCtx *desEncryptCtx = (struct HksOpensslDesCtx *)*cryptoCtx;
334 switch (desEncryptCtx->mode) {
335 #if defined(HKS_SUPPORT_DES_CBC_NOPADDING)
336 case HKS_MODE_CBC:
337 return DesCryptFinal(cryptoCtx, desEncryptCtx->padding, message, cipherText, encrypt);
338 #endif
339 #if defined(HKS_SUPPORT_DES_ECB_NOPADDING)
340 case HKS_MODE_ECB:
341 return DesCryptFinal(cryptoCtx, desEncryptCtx->padding, message, cipherText, encrypt);
342 #endif
343 default:
344 HKS_LOG_E("Unsupport key alg! mode = 0x%" LOG_PUBLIC "X", desEncryptCtx->mode);
345 return HKS_ERROR_INVALID_MODE;
346 }
347 }
348
HksOpensslDesHalFreeCtx(void ** cryptCtx)349 void HksOpensslDesHalFreeCtx(void **cryptCtx)
350 {
351 HKS_IF_TRUE_LOGE_RETURN_VOID(cryptCtx == NULL || *cryptCtx == NULL, "FreeCtx param context null")
352 HKS_FREE(*cryptCtx);
353 }
354 #endif /* HKS_SUPPORT_DES_C */
355