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 #include "des_openssl.h"
17 #include "log.h"
18 #include "blob.h"
19 #include "memory.h"
20 #include "result.h"
21 #include "utils.h"
22 #include "securec.h"
23 #include "aes_openssl_common.h"
24 #include "sym_common_defines.h"
25 #include "openssl_adapter.h"
26 #include "openssl_common.h"
27 #include "openssl_class.h"
28
29 #define DES_BLOCK_SIZE 8
30 #define DES_SIZE_64 8
31 #define DES_IV_SIZE 8
32 #define TRIPLE_DES_SIZE_192 24
33
34 typedef struct {
35 HcfCipherGeneratorSpi base;
36 CipherAttr attr;
37 CipherData *cipherData;
38 } HcfCipherDesGeneratorSpiOpensslImpl;
39
GetDesGeneratorClass(void)40 static const char *GetDesGeneratorClass(void)
41 {
42 return OPENSSL_3DES_CIPHER_CLASS;
43 }
44
DefaultCipherType(void)45 static const EVP_CIPHER *DefaultCipherType(void)
46 {
47 return OpensslEvpDesEde3Ecb();
48 }
49
Get3DesCipherType(HcfCipherDesGeneratorSpiOpensslImpl * impl)50 static const EVP_CIPHER *Get3DesCipherType(HcfCipherDesGeneratorSpiOpensslImpl *impl)
51 {
52 switch (impl->attr.mode) {
53 case HCF_ALG_MODE_ECB:
54 return OpensslEvpDesEde3Ecb();
55 case HCF_ALG_MODE_CBC:
56 return OpensslEvpDesEde3Cbc();
57 case HCF_ALG_MODE_OFB:
58 return OpensslEvpDesEde3Ofb();
59 case HCF_ALG_MODE_CFB:
60 case HCF_ALG_MODE_CFB64:
61 return OpensslEvpDesEde3Cfb64();
62 case HCF_ALG_MODE_CFB1:
63 return OpensslEvpDesEde3Cfb1();
64 case HCF_ALG_MODE_CFB8:
65 return OpensslEvpDesEde3Cfb8();
66 default:
67 break;
68 }
69 return DefaultCipherType();
70 }
71
GetDesCipherType(HcfCipherDesGeneratorSpiOpensslImpl * impl)72 static const EVP_CIPHER *GetDesCipherType(HcfCipherDesGeneratorSpiOpensslImpl *impl)
73 {
74 switch (impl->attr.mode) {
75 case HCF_ALG_MODE_ECB:
76 return OpensslEvpDesEcb();
77 case HCF_ALG_MODE_CBC:
78 return OpensslEvpDesCbc();
79 case HCF_ALG_MODE_OFB:
80 return OpensslEvpDesOfb();
81 case HCF_ALG_MODE_CFB:
82 case HCF_ALG_MODE_CFB64:
83 return OpensslEvpDesCfb64();
84 case HCF_ALG_MODE_CFB1:
85 return OpensslEvpDesCfb1();
86 case HCF_ALG_MODE_CFB8:
87 return OpensslEvpDesCfb8();
88 default:
89 break;
90 }
91 return OpensslEvpDesEcb();
92 }
93
InitCipherData(enum HcfCryptoMode opMode,CipherData ** cipherData)94 static HcfResult InitCipherData(enum HcfCryptoMode opMode, CipherData **cipherData)
95 {
96 HcfResult ret = HCF_INVALID_PARAMS;
97
98 *cipherData = (CipherData *)HcfMalloc(sizeof(CipherData), 0);
99 if (*cipherData == NULL) {
100 LOGE("malloc failed.");
101 return HCF_ERR_MALLOC;
102 }
103
104 (*cipherData)->enc = opMode;
105 (*cipherData)->ctx = OpensslEvpCipherCtxNew();
106 if ((*cipherData)->ctx == NULL) {
107 HcfPrintOpensslError();
108 LOGD("[error] Failed to allocate ctx memroy.");
109 goto clearup;
110 }
111
112 ret = HCF_SUCCESS;
113 return ret;
114 clearup:
115 FreeCipherData(cipherData);
116 return ret;
117 }
118
ValidateCipherInitParams(HcfCipherGeneratorSpi * self,HcfKey * key)119 static HcfResult ValidateCipherInitParams(HcfCipherGeneratorSpi *self, HcfKey *key)
120 {
121 if ((self == NULL) || (key == NULL)) {
122 LOGE("Invalid input parameter.");
123 return HCF_INVALID_PARAMS;
124 }
125 if (!HcfIsClassMatch((const HcfObjectBase *)self, GetDesGeneratorClass())) {
126 LOGE("Class is not match.");
127 return HCF_INVALID_PARAMS;
128 }
129 if (!HcfIsClassMatch((const HcfObjectBase *)key, OPENSSL_SYM_KEY_CLASS)) {
130 LOGE("Class is not match.");
131 return HCF_INVALID_PARAMS;
132 }
133 return HCF_SUCCESS;
134 }
135
GetCipherType(HcfCipherDesGeneratorSpiOpensslImpl * cipherImpl,SymKeyImpl * keyImpl)136 static const EVP_CIPHER *GetCipherType(HcfCipherDesGeneratorSpiOpensslImpl *cipherImpl, SymKeyImpl *keyImpl)
137 {
138 if (cipherImpl->attr.algo == HCF_ALG_3DES) {
139 if (keyImpl->keyMaterial.len < TRIPLE_DES_SIZE_192) {
140 LOGE("Init failed, the input key size is smaller than keySize specified in cipher.");
141 return NULL;
142 }
143 return Get3DesCipherType(cipherImpl);
144 } else if (cipherImpl->attr.algo == HCF_ALG_DES) {
145 if (keyImpl->keyMaterial.len != DES_SIZE_64) {
146 LOGE("Init failed, the input key size is smaller than keySize specified in cipher.");
147 return NULL;
148 }
149 return GetDesCipherType(cipherImpl);
150 }
151 return NULL;
152 }
153
GetIvData(HcfCipherDesGeneratorSpiOpensslImpl * cipherImpl,HcfParamsSpec * params)154 static const unsigned char *GetIvData(HcfCipherDesGeneratorSpiOpensslImpl *cipherImpl, HcfParamsSpec *params)
155 {
156 if (cipherImpl == NULL) {
157 LOGE("cipherImpl is NULL.");
158 return NULL;
159 }
160
161 // ECB mode does not require an IV
162 if (cipherImpl->attr.mode == HCF_ALG_MODE_ECB) {
163 return NULL;
164 }
165
166 if (params == NULL) {
167 LOGE("params is NULL, but IV is required for non-ECB modes.");
168 return NULL;
169 }
170
171 HcfIvParamsSpec *spec = (HcfIvParamsSpec *)params;
172
173 if (spec->iv.data == NULL) {
174 LOGE("IV data is NULL, but IV is required for non-ECB modes.");
175 return NULL;
176 }
177
178 if (cipherImpl->attr.algo == HCF_ALG_DES) {
179 // Ensure IV length is exactly 8 bytes for DES
180 if (spec->iv.len != DES_IV_SIZE) {
181 LOGE("DES IV length is invalid.");
182 return NULL;
183 }
184 return (const unsigned char *)spec->iv.data;
185 } else if (cipherImpl->attr.algo == HCF_ALG_3DES) {
186 // For 3DES, IV length is not strictly validated here
187 return (const unsigned char *)spec->iv.data;
188 } else {
189 LOGE("Unsupported algorithm for IV retrieval.");
190 return NULL;
191 }
192 }
193
EngineCipherInit(HcfCipherGeneratorSpi * self,enum HcfCryptoMode opMode,HcfKey * key,HcfParamsSpec * params)194 static HcfResult EngineCipherInit(HcfCipherGeneratorSpi *self, enum HcfCryptoMode opMode,
195 HcfKey *key, HcfParamsSpec *params)
196 {
197 HcfResult ret = ValidateCipherInitParams(self, key);
198 if (ret != HCF_SUCCESS) {
199 return ret;
200 }
201
202 HcfCipherDesGeneratorSpiOpensslImpl *cipherImpl = (HcfCipherDesGeneratorSpiOpensslImpl *)self;
203 SymKeyImpl *keyImpl = (SymKeyImpl *)key;
204 int32_t enc = (opMode == ENCRYPT_MODE) ? 1 : 0;
205
206 const EVP_CIPHER *cipher = GetCipherType(cipherImpl, keyImpl);
207 if (cipher == NULL) {
208 return HCF_INVALID_PARAMS;
209 }
210
211 if (InitCipherData(opMode, &(cipherImpl->cipherData)) != HCF_SUCCESS) {
212 LOGE("InitCipherData failed");
213 return HCF_INVALID_PARAMS;
214 }
215
216 ret = HCF_ERR_CRYPTO_OPERATION;
217 CipherData *data = cipherImpl->cipherData;
218
219 if (OpensslEvpCipherInit(data->ctx, cipher, NULL, NULL, enc) != HCF_OPENSSL_SUCCESS) {
220 HcfPrintOpensslError();
221 LOGD("[error] Cipher init failed.");
222 goto clearup;
223 }
224 const unsigned char *iv = GetIvData(cipherImpl, params);
225 if ((iv == NULL) && (cipherImpl->attr.mode != HCF_ALG_MODE_ECB) && (cipherImpl->attr.algo == HCF_ALG_DES)) {
226 LOGE("IV is required for non-ECB modes.");
227 ret = HCF_INVALID_PARAMS;
228 goto clearup;
229 }
230 if (OpensslEvpCipherInit(data->ctx, NULL, keyImpl->keyMaterial.data, iv, enc) != HCF_OPENSSL_SUCCESS) {
231 HcfPrintOpensslError();
232 LOGD("[error] Cipher init key and iv failed.");
233 goto clearup;
234 }
235 int32_t padding = (cipherImpl->attr.paddingMode == HCF_ALG_NOPADDING) ? 0 : EVP_PADDING_PKCS7;
236 if (OpensslEvpCipherCtxSetPadding(data->ctx, padding) != HCF_OPENSSL_SUCCESS) {
237 HcfPrintOpensslError();
238 LOGD("[error] Set padding failed.");
239 goto clearup;
240 }
241 return HCF_SUCCESS;
242
243 clearup:
244 if (cipherImpl->cipherData != NULL) {
245 FreeCipherData(&(cipherImpl->cipherData));
246 }
247 return ret;
248 }
249
AllocateOutput(HcfBlob * input,HcfBlob * output)250 static HcfResult AllocateOutput(HcfBlob *input, HcfBlob *output)
251 {
252 uint32_t outLen = DES_BLOCK_SIZE;
253 if (HcfIsBlobValid(input)) {
254 outLen += input->len;
255 }
256 output->data = (uint8_t *)HcfMalloc(outLen, 0);
257 if (output->data == NULL) {
258 LOGE("Malloc output failed.");
259 return HCF_ERR_MALLOC;
260 }
261 output->len = outLen;
262 return HCF_SUCCESS;
263 }
264
EngineUpdate(HcfCipherGeneratorSpi * self,HcfBlob * input,HcfBlob * output)265 static HcfResult EngineUpdate(HcfCipherGeneratorSpi *self, HcfBlob *input, HcfBlob *output)
266 {
267 if ((self == NULL) || (input == NULL) || (output == NULL)) {
268 LOGE("Invalid input parameter.");
269 return HCF_INVALID_PARAMS;
270 }
271 if (!HcfIsClassMatch((const HcfObjectBase *)self, GetDesGeneratorClass())) {
272 LOGE("Class is not match.");
273 return HCF_INVALID_PARAMS;
274 }
275
276 HcfCipherDesGeneratorSpiOpensslImpl *cipherImpl = (HcfCipherDesGeneratorSpiOpensslImpl *)self;
277 CipherData *data = cipherImpl->cipherData;
278 if (data == NULL) {
279 LOGE("CipherData is null.");
280 return HCF_INVALID_PARAMS;
281 }
282 HcfResult res = AllocateOutput(input, output);
283 if (res != HCF_SUCCESS) {
284 LOGE("AllocateOutput failed.");
285 goto clearup;
286 }
287
288 int32_t ret = OpensslEvpCipherUpdate(data->ctx, output->data, (int *)&output->len,
289 input->data, input->len);
290 if (ret != HCF_OPENSSL_SUCCESS) {
291 HcfPrintOpensslError();
292 LOGD("[error] Cipher update failed.");
293 res = HCF_ERR_CRYPTO_OPERATION;
294 goto clearup;
295 }
296 res = HCF_SUCCESS;
297 clearup:
298 if (res != HCF_SUCCESS) {
299 HcfBlobDataClearAndFree(output);
300 FreeCipherData(&(cipherImpl->cipherData));
301 } else {
302 FreeRedundantOutput(output);
303 }
304 return res;
305 }
306
DesDoFinal(CipherData * data,HcfBlob * input,HcfBlob * output)307 static HcfResult DesDoFinal(CipherData *data, HcfBlob *input, HcfBlob *output)
308 {
309 int32_t ret;
310 uint32_t len = 0;
311
312 if (HcfIsBlobValid(input)) {
313 ret = OpensslEvpCipherUpdate(data->ctx, output->data, (int *)&output->len,
314 input->data, input->len);
315 if (ret != HCF_OPENSSL_SUCCESS) {
316 HcfPrintOpensslError();
317 LOGD("[error] Cipher update failed.");
318 return HCF_ERR_CRYPTO_OPERATION;
319 }
320 len += output->len;
321 }
322 ret = OpensslEvpCipherFinalEx(data->ctx, output->data + len, (int *)&output->len);
323 if (ret != HCF_OPENSSL_SUCCESS) {
324 HcfPrintOpensslError();
325 LOGD("[error] Cipher final filed.");
326 return HCF_ERR_CRYPTO_OPERATION;
327 }
328 output->len += len;
329 return HCF_SUCCESS;
330 }
331
EngineDoFinal(HcfCipherGeneratorSpi * self,HcfBlob * input,HcfBlob * output)332 static HcfResult EngineDoFinal(HcfCipherGeneratorSpi *self, HcfBlob *input, HcfBlob *output)
333 {
334 if ((self == NULL) || (output == NULL)) { /* input maybe is null */
335 LOGE("Invalid input parameter.");
336 return HCF_INVALID_PARAMS;
337 }
338 if (!HcfIsClassMatch((const HcfObjectBase *)self, GetDesGeneratorClass())) {
339 LOGE("Class is not match.");
340 return HCF_INVALID_PARAMS;
341 }
342 HcfCipherDesGeneratorSpiOpensslImpl *cipherImpl = (HcfCipherDesGeneratorSpiOpensslImpl *)self;
343 CipherData *data = cipherImpl->cipherData;
344 if (data == NULL) {
345 LOGE("CipherData is null.");
346 return HCF_INVALID_PARAMS;
347 }
348
349 HcfResult res = AllocateOutput(input, output);
350 if (res != HCF_SUCCESS) {
351 LOGE("AllocateOutput failed.");
352 goto clearup;
353 }
354 res = DesDoFinal(data, input, output);
355 if (res != HCF_SUCCESS) {
356 LOGD("[error] DesDoFinal failed.");
357 }
358 clearup:
359 if (res != HCF_SUCCESS) {
360 HcfBlobDataClearAndFree(output);
361 } else {
362 FreeRedundantOutput(output);
363 }
364 FreeCipherData(&(cipherImpl->cipherData));
365 return res;
366 }
367
EngineDesGeneratorDestroy(HcfObjectBase * self)368 static void EngineDesGeneratorDestroy(HcfObjectBase *self)
369 {
370 if (self == NULL) {
371 return;
372 }
373 if (!HcfIsClassMatch(self, GetDesGeneratorClass())) {
374 LOGE("Class is not match.");
375 return;
376 }
377 HcfCipherDesGeneratorSpiOpensslImpl *impl = (HcfCipherDesGeneratorSpiOpensslImpl *)self;
378 FreeCipherData(&(impl->cipherData));
379 HcfFree(impl);
380 }
381
GetDesCipherSpecString(HcfCipherGeneratorSpi * self,CipherSpecItem item,char ** returnString)382 static HcfResult GetDesCipherSpecString(HcfCipherGeneratorSpi *self, CipherSpecItem item, char **returnString)
383 {
384 (void)self;
385 (void)item;
386 (void)returnString;
387 return HCF_NOT_SUPPORT;
388 }
389
GetDesCipherSpecUint8Array(HcfCipherGeneratorSpi * self,CipherSpecItem item,HcfBlob * returnUint8Array)390 static HcfResult GetDesCipherSpecUint8Array(HcfCipherGeneratorSpi *self, CipherSpecItem item, HcfBlob *returnUint8Array)
391 {
392 (void)self;
393 (void)item;
394 (void)returnUint8Array;
395 return HCF_NOT_SUPPORT;
396 }
397
SetDesCipherSpecUint8Array(HcfCipherGeneratorSpi * self,CipherSpecItem item,HcfBlob blob)398 static HcfResult SetDesCipherSpecUint8Array(HcfCipherGeneratorSpi *self, CipherSpecItem item, HcfBlob blob)
399 {
400 (void)self;
401 (void)item;
402 (void)blob;
403 return HCF_NOT_SUPPORT;
404 }
405
HcfCipherDesGeneratorSpiCreate(CipherAttr * attr,HcfCipherGeneratorSpi ** generator)406 HcfResult HcfCipherDesGeneratorSpiCreate(CipherAttr *attr, HcfCipherGeneratorSpi **generator)
407 {
408 if ((attr == NULL) || (generator == NULL)) {
409 LOGE("Invalid input parameter.");
410 return HCF_INVALID_PARAMS;
411 }
412 HcfCipherDesGeneratorSpiOpensslImpl *returnImpl = (HcfCipherDesGeneratorSpiOpensslImpl *)HcfMalloc(
413 sizeof(HcfCipherDesGeneratorSpiOpensslImpl), 0);
414 if (returnImpl == NULL) {
415 LOGE("Failed to allocate returnImpl memroy.");
416 return HCF_ERR_MALLOC;
417 }
418 (void)memcpy_s(&returnImpl->attr, sizeof(CipherAttr), attr, sizeof(CipherAttr));
419 returnImpl->base.init = EngineCipherInit;
420 returnImpl->base.update = EngineUpdate;
421 returnImpl->base.doFinal = EngineDoFinal;
422 returnImpl->base.getCipherSpecString = GetDesCipherSpecString;
423 returnImpl->base.getCipherSpecUint8Array = GetDesCipherSpecUint8Array;
424 returnImpl->base.setCipherSpecUint8Array = SetDesCipherSpecUint8Array;
425 returnImpl->base.base.destroy = EngineDesGeneratorDestroy;
426 returnImpl->base.base.getClass = GetDesGeneratorClass;
427
428 *generator = (HcfCipherGeneratorSpi *)returnImpl;
429 return HCF_SUCCESS;
430 }
431