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