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