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 "log.h"
17 #include "blob.h"
18 #include "memory.h"
19 #include "result.h"
20 #include "utils.h"
21 #include "securec.h"
22 #include "aes_openssl_common.h"
23 #include "sym_common_defines.h"
24 #include "openssl_adapter.h"
25 #include "openssl_common.h"
26 #include "openssl_class.h"
27 
28 #define DES_BLOCK_SIZE 8
29 #define DES_SIZE_192 24
30 
31 typedef struct {
32     HcfCipherGeneratorSpi base;
33     CipherAttr attr;
34     CipherData *cipherData;
35 } HcfCipherDesGeneratorSpiOpensslImpl;
36 
GetDesGeneratorClass(void)37 static const char *GetDesGeneratorClass(void)
38 {
39     return OPENSSL_3DES_CIPHER_CLASS;
40 }
41 
DefaultCipherType(void)42 static const EVP_CIPHER *DefaultCipherType(void)
43 {
44     return OpensslEvpDesEde3Ecb();
45 }
46 
GetCipherType(HcfCipherDesGeneratorSpiOpensslImpl * impl)47 static const EVP_CIPHER *GetCipherType(HcfCipherDesGeneratorSpiOpensslImpl *impl)
48 {
49     switch (impl->attr.mode) {
50         case HCF_ALG_MODE_ECB:
51             return OpensslEvpDesEde3Ecb();
52         case HCF_ALG_MODE_CBC:
53             return OpensslEvpDesEde3Cbc();
54         case HCF_ALG_MODE_OFB:
55             return OpensslEvpDesEde3Ofb();
56         case HCF_ALG_MODE_CFB:
57         case HCF_ALG_MODE_CFB64:
58             return OpensslEvpDesEde3Cfb64();
59         case HCF_ALG_MODE_CFB1:
60             return OpensslEvpDesEde3Cfb1();
61         case HCF_ALG_MODE_CFB8:
62             return OpensslEvpDesEde3Cfb8();
63         default:
64             break;
65     }
66     return DefaultCipherType();
67 }
68 
InitCipherData(enum HcfCryptoMode opMode,CipherData ** cipherData)69 static HcfResult InitCipherData(enum HcfCryptoMode opMode, CipherData **cipherData)
70 {
71     HcfResult ret = HCF_INVALID_PARAMS;
72 
73     *cipherData = (CipherData *)HcfMalloc(sizeof(CipherData), 0);
74     if (*cipherData == NULL) {
75         LOGE("malloc failed.");
76         return HCF_ERR_MALLOC;
77     }
78 
79     (*cipherData)->enc = opMode;
80     (*cipherData)->ctx = OpensslEvpCipherCtxNew();
81     if ((*cipherData)->ctx == NULL) {
82         HcfPrintOpensslError();
83         LOGD("[error] Failed to allocate ctx memroy.");
84         goto clearup;
85     }
86 
87     ret = HCF_SUCCESS;
88     return ret;
89 clearup:
90     FreeCipherData(cipherData);
91     return ret;
92 }
93 
EngineCipherInit(HcfCipherGeneratorSpi * self,enum HcfCryptoMode opMode,HcfKey * key,HcfParamsSpec * params)94 static HcfResult EngineCipherInit(HcfCipherGeneratorSpi *self, enum HcfCryptoMode opMode,
95     HcfKey *key, HcfParamsSpec *params)
96 {
97     if ((self == NULL) || (key == NULL)) { /* params maybe is null */
98         LOGE("Invalid input parameter.");
99         return HCF_INVALID_PARAMS;
100     }
101     if (!HcfIsClassMatch((const HcfObjectBase *)self, GetDesGeneratorClass())) {
102         LOGE("Class is not match.");
103         return HCF_INVALID_PARAMS;
104     }
105     if (!HcfIsClassMatch((const HcfObjectBase *)key, OPENSSL_SYM_KEY_CLASS)) {
106         LOGE("Class is not match.");
107         return HCF_INVALID_PARAMS;
108     }
109 
110     HcfCipherDesGeneratorSpiOpensslImpl *cipherImpl = (HcfCipherDesGeneratorSpiOpensslImpl *)self;
111     SymKeyImpl *keyImpl = (SymKeyImpl *)key;
112     int32_t enc = (opMode == ENCRYPT_MODE) ? 1 : 0;
113 
114     if (keyImpl->keyMaterial.len < DES_SIZE_192) {
115         LOGE("Init failed, the input key size is smaller than keySize specified in cipher.");
116         return HCF_INVALID_PARAMS;
117     }
118     if (InitCipherData(opMode,  &(cipherImpl->cipherData)) != HCF_SUCCESS) {
119         LOGE("InitCipherData failed");
120         return HCF_INVALID_PARAMS;
121     }
122     HcfResult ret = HCF_ERR_CRYPTO_OPERATION;
123     CipherData *data = cipherImpl->cipherData;
124     if (OpensslEvpCipherInit(data->ctx, GetCipherType(cipherImpl), NULL, NULL, enc) != HCF_OPENSSL_SUCCESS) {
125         HcfPrintOpensslError();
126         LOGD("[error] Cipher init failed.");
127         goto clearup;
128     }
129     if (OpensslEvpCipherInit(data->ctx, NULL, keyImpl->keyMaterial.data, GetIv(params), enc) != HCF_OPENSSL_SUCCESS) {
130         HcfPrintOpensslError();
131         LOGD("[error] Cipher init key and iv failed.");
132         goto clearup;
133     }
134     int32_t padding = (cipherImpl->attr.paddingMode == HCF_ALG_NOPADDING) ? 0 : EVP_PADDING_PKCS7;
135     if (OpensslEvpCipherCtxSetPadding(data->ctx, padding) != HCF_OPENSSL_SUCCESS) {
136         HcfPrintOpensslError();
137         LOGD("[error] Set padding failed.");
138         goto clearup;
139     }
140     return HCF_SUCCESS;
141 clearup:
142     FreeCipherData(&(cipherImpl->cipherData));
143     return ret;
144 }
145 
AllocateOutput(HcfBlob * input,HcfBlob * output)146 static HcfResult AllocateOutput(HcfBlob *input, HcfBlob *output)
147 {
148     uint32_t outLen = DES_BLOCK_SIZE;
149     if (HcfIsBlobValid(input)) {
150         outLen += input->len;
151     }
152     output->data = (uint8_t *)HcfMalloc(outLen, 0);
153     if (output->data == NULL) {
154         LOGE("Malloc output failed.");
155         return HCF_ERR_MALLOC;
156     }
157     output->len = outLen;
158     return HCF_SUCCESS;
159 }
160 
EngineUpdate(HcfCipherGeneratorSpi * self,HcfBlob * input,HcfBlob * output)161 static HcfResult EngineUpdate(HcfCipherGeneratorSpi *self, HcfBlob *input, HcfBlob *output)
162 {
163     if ((self == NULL) || (input == NULL) || (output == NULL)) {
164         LOGE("Invalid input parameter.");
165         return HCF_INVALID_PARAMS;
166     }
167     if (!HcfIsClassMatch((const HcfObjectBase *)self, GetDesGeneratorClass())) {
168         LOGE("Class is not match.");
169         return HCF_INVALID_PARAMS;
170     }
171 
172     HcfCipherDesGeneratorSpiOpensslImpl *cipherImpl = (HcfCipherDesGeneratorSpiOpensslImpl *)self;
173     CipherData *data = cipherImpl->cipherData;
174     if (data == NULL) {
175         LOGE("CipherData is null.");
176         return HCF_INVALID_PARAMS;
177     }
178     HcfResult res = AllocateOutput(input, output);
179     if (res != HCF_SUCCESS) {
180         LOGE("AllocateOutput failed.");
181         goto clearup;
182     }
183 
184     int32_t ret = OpensslEvpCipherUpdate(data->ctx, output->data, (int *)&output->len,
185         input->data, input->len);
186     if (ret != HCF_OPENSSL_SUCCESS) {
187         HcfPrintOpensslError();
188         LOGD("[error] Cipher update failed.");
189         res = HCF_ERR_CRYPTO_OPERATION;
190         goto clearup;
191     }
192     res = HCF_SUCCESS;
193 clearup:
194     if (res != HCF_SUCCESS) {
195         HcfBlobDataClearAndFree(output);
196         FreeCipherData(&(cipherImpl->cipherData));
197     } else {
198         FreeRedundantOutput(output);
199     }
200     return res;
201 }
202 
DesDoFinal(CipherData * data,HcfBlob * input,HcfBlob * output)203 static HcfResult DesDoFinal(CipherData *data, HcfBlob *input, HcfBlob *output)
204 {
205     int32_t ret;
206     uint32_t len = 0;
207 
208     if (HcfIsBlobValid(input)) {
209         ret = OpensslEvpCipherUpdate(data->ctx, output->data, (int *)&output->len,
210             input->data, input->len);
211         if (ret != HCF_OPENSSL_SUCCESS) {
212             HcfPrintOpensslError();
213             LOGD("[error] Cipher update failed.");
214             return HCF_ERR_CRYPTO_OPERATION;
215         }
216         len += output->len;
217     }
218     ret = OpensslEvpCipherFinalEx(data->ctx, output->data + len, (int *)&output->len);
219     if (ret != HCF_OPENSSL_SUCCESS) {
220         HcfPrintOpensslError();
221         LOGD("[error] Cipher final filed.");
222         return HCF_ERR_CRYPTO_OPERATION;
223     }
224     output->len += len;
225     return HCF_SUCCESS;
226 }
227 
EngineDoFinal(HcfCipherGeneratorSpi * self,HcfBlob * input,HcfBlob * output)228 static HcfResult EngineDoFinal(HcfCipherGeneratorSpi *self, HcfBlob *input, HcfBlob *output)
229 {
230     if ((self == NULL) || (output == NULL)) { /* input maybe is null */
231         LOGE("Invalid input parameter.");
232         return HCF_INVALID_PARAMS;
233     }
234     if (!HcfIsClassMatch((const HcfObjectBase *)self, GetDesGeneratorClass())) {
235         LOGE("Class is not match.");
236         return HCF_INVALID_PARAMS;
237     }
238     HcfCipherDesGeneratorSpiOpensslImpl *cipherImpl = (HcfCipherDesGeneratorSpiOpensslImpl *)self;
239     CipherData *data = cipherImpl->cipherData;
240     if (data == NULL) {
241         LOGE("CipherData is null.");
242         return HCF_INVALID_PARAMS;
243     }
244 
245     HcfResult res = AllocateOutput(input, output);
246     if (res != HCF_SUCCESS) {
247         LOGE("AllocateOutput failed.");
248         goto clearup;
249     }
250     res = DesDoFinal(data, input, output);
251     if (res != HCF_SUCCESS) {
252         LOGD("[error] DesDoFinal failed.");
253     }
254 clearup:
255     if (res != HCF_SUCCESS) {
256         HcfBlobDataClearAndFree(output);
257     } else {
258         FreeRedundantOutput(output);
259     }
260     FreeCipherData(&(cipherImpl->cipherData));
261     return res;
262 }
263 
EngineDesGeneratorDestroy(HcfObjectBase * self)264 static void EngineDesGeneratorDestroy(HcfObjectBase *self)
265 {
266     if (self == NULL) {
267         return;
268     }
269     if (!HcfIsClassMatch(self, GetDesGeneratorClass())) {
270         LOGE("Class is not match.");
271         return;
272     }
273     HcfCipherDesGeneratorSpiOpensslImpl *impl = (HcfCipherDesGeneratorSpiOpensslImpl *)self;
274     FreeCipherData(&(impl->cipherData));
275     HcfFree(impl);
276 }
277 
GetDesCipherSpecString(HcfCipherGeneratorSpi * self,CipherSpecItem item,char ** returnString)278 static HcfResult GetDesCipherSpecString(HcfCipherGeneratorSpi *self, CipherSpecItem item, char **returnString)
279 {
280     (void)self;
281     (void)item;
282     (void)returnString;
283     return HCF_NOT_SUPPORT;
284 }
285 
GetDesCipherSpecUint8Array(HcfCipherGeneratorSpi * self,CipherSpecItem item,HcfBlob * returnUint8Array)286 static HcfResult GetDesCipherSpecUint8Array(HcfCipherGeneratorSpi *self, CipherSpecItem item, HcfBlob *returnUint8Array)
287 {
288     (void)self;
289     (void)item;
290     (void)returnUint8Array;
291     return HCF_NOT_SUPPORT;
292 }
293 
SetDesCipherSpecUint8Array(HcfCipherGeneratorSpi * self,CipherSpecItem item,HcfBlob blob)294 static HcfResult SetDesCipherSpecUint8Array(HcfCipherGeneratorSpi *self, CipherSpecItem item, HcfBlob blob)
295 {
296     (void)self;
297     (void)item;
298     (void)blob;
299     return HCF_NOT_SUPPORT;
300 }
301 
HcfCipherDesGeneratorSpiCreate(CipherAttr * attr,HcfCipherGeneratorSpi ** generator)302 HcfResult HcfCipherDesGeneratorSpiCreate(CipherAttr *attr, HcfCipherGeneratorSpi **generator)
303 {
304     if ((attr == NULL) || (generator == NULL)) {
305         LOGE("Invalid input parameter.");
306         return HCF_INVALID_PARAMS;
307     }
308     HcfCipherDesGeneratorSpiOpensslImpl *returnImpl = (HcfCipherDesGeneratorSpiOpensslImpl *)HcfMalloc(
309         sizeof(HcfCipherDesGeneratorSpiOpensslImpl), 0);
310     if (returnImpl == NULL) {
311         LOGE("Failed to allocate returnImpl memroy.");
312         return HCF_ERR_MALLOC;
313     }
314     (void)memcpy_s(&returnImpl->attr, sizeof(CipherAttr), attr, sizeof(CipherAttr));
315     returnImpl->base.init = EngineCipherInit;
316     returnImpl->base.update = EngineUpdate;
317     returnImpl->base.doFinal = EngineDoFinal;
318     returnImpl->base.getCipherSpecString = GetDesCipherSpecString;
319     returnImpl->base.getCipherSpecUint8Array = GetDesCipherSpecUint8Array;
320     returnImpl->base.setCipherSpecUint8Array = SetDesCipherSpecUint8Array;
321     returnImpl->base.base.destroy = EngineDesGeneratorDestroy;
322     returnImpl->base.base.getClass = GetDesGeneratorClass;
323 
324     *generator = (HcfCipherGeneratorSpi *)returnImpl;
325     return HCF_SUCCESS;
326 }
327