1 /*
2  * Copyright (C) 2022-2023 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 "cipher.h"
17 #include "aes_openssl.h"
18 #include "config.h"
19 #include "securec.h"
20 #include "result.h"
21 #include "string.h"
22 #include "log.h"
23 #include "memory.h"
24 #include "cipher_rsa_openssl.h"
25 #include "cipher_sm2_openssl.h"
26 #include "sm4_openssl.h"
27 #include "utils.h"
28 
29 typedef HcfResult (*HcfCipherGeneratorSpiCreateFunc)(CipherAttr *, HcfCipherGeneratorSpi **);
30 
31 typedef struct {
32     HcfCipher super;
33     HcfCipherGeneratorSpi *spiObj;
34     char algoName[HCF_MAX_ALGO_NAME_LEN];
35 } CipherGenImpl;
36 
37 typedef struct {
38     HcfCipherGeneratorSpiCreateFunc createFunc;
39 } HcfCipherGenFuncSet;
40 
41 typedef struct {
42     HcfAlgValue algo;
43     HcfCipherGenFuncSet funcSet;
44 } HcfCipherGenAbility;
45 
46 static const HcfCipherGenAbility CIPHER_ABILITY_SET[] = {
47     { HCF_ALG_RSA, { HcfCipherRsaCipherSpiCreate } },
48     { HCF_ALG_SM2, { HcfCipherSm2CipherSpiCreate } },
49     { HCF_ALG_AES, { HcfCipherAesGeneratorSpiCreate } },
50     { HCF_ALG_DES, { HcfCipherDesGeneratorSpiCreate } },
51     { HCF_ALG_SM4, { HcfCipherSm4GeneratorSpiCreate } }
52 };
53 
SetKeyType(HcfAlgParaValue value,void * cipher)54 static void SetKeyType(HcfAlgParaValue value, void *cipher)
55 {
56     CipherAttr *cipherAttr = (CipherAttr *)cipher;
57 
58     cipherAttr->keySize = 0;
59 
60     switch (value) {
61         case HCF_ALG_AES_DEFAULT:
62             cipherAttr->algo = HCF_ALG_AES;
63             break;
64         case HCF_ALG_SM4_DEFAULT:
65             cipherAttr->algo = HCF_ALG_SM4;
66             break;
67         case HCF_ALG_3DES_DEFAULT:
68             cipherAttr->algo = HCF_ALG_DES;
69             break;
70         case HCF_ALG_RSA_DEFAULT:
71             cipherAttr->algo = HCF_ALG_RSA;
72             break;
73         case HCF_ALG_SM2_DEFAULT:
74             cipherAttr->algo = HCF_ALG_SM2;
75             break;
76         default:
77             LOGE("Invalid algo %u.", value);
78             break;
79     }
80 }
81 
SetKeyLength(HcfAlgParaValue value,void * cipher)82 static void SetKeyLength(HcfAlgParaValue value, void *cipher)
83 {
84     CipherAttr *cipherAttr = (CipherAttr *)cipher;
85 
86     cipherAttr->keySize = value;
87 
88     switch (value) {
89         case HCF_ALG_AES_128:
90         case HCF_ALG_AES_192:
91         case HCF_ALG_AES_256:
92             cipherAttr->algo = HCF_ALG_AES;
93             break;
94         case HCF_ALG_SM4_128:
95             cipherAttr->algo = HCF_ALG_SM4;
96             break;
97         case HCF_ALG_3DES_192:
98             cipherAttr->algo = HCF_ALG_DES;
99             break;
100         case HCF_OPENSSL_RSA_512:
101         case HCF_OPENSSL_RSA_768:
102         case HCF_OPENSSL_RSA_1024:
103         case HCF_OPENSSL_RSA_2048:
104         case HCF_OPENSSL_RSA_3072:
105         case HCF_OPENSSL_RSA_4096:
106         case HCF_OPENSSL_RSA_8192:
107             cipherAttr->algo = HCF_ALG_RSA;
108             break;
109         case HCF_ALG_SM2_256:
110             cipherAttr->algo = HCF_ALG_SM2;
111             break;
112         default:
113             LOGE("Invalid algo %u.", value);
114             break;
115     }
116 }
117 
SetMode(HcfAlgParaValue value,void * cipher)118 static void SetMode(HcfAlgParaValue value, void *cipher)
119 {
120     CipherAttr *cipherAttr = (CipherAttr *)cipher;
121     cipherAttr->mode = value ;
122 }
123 
SetPadding(HcfAlgParaValue value,void * cipher)124 static void SetPadding(HcfAlgParaValue value, void *cipher)
125 {
126     CipherAttr *cipherAttr = (CipherAttr *)cipher;
127     cipherAttr->paddingMode = value;
128 }
129 
SetDigest(HcfAlgParaValue value,CipherAttr * cipher)130 static void SetDigest(HcfAlgParaValue value, CipherAttr *cipher)
131 {
132     cipher->md = value;
133 }
134 
SetMgf1Digest(HcfAlgParaValue value,CipherAttr * cipher)135 static void SetMgf1Digest(HcfAlgParaValue value, CipherAttr *cipher)
136 {
137     cipher->mgf1md = value;
138 }
139 
OnSetParameter(const HcfParaConfig * config,void * cipher)140 static HcfResult OnSetParameter(const HcfParaConfig *config, void *cipher)
141 {
142     if ((config == NULL) || (cipher == NULL)) {
143         LOGE("Invalid cipher params");
144         return HCF_INVALID_PARAMS;
145     }
146     HcfResult ret = HCF_SUCCESS;
147     LOGD("Set Parameter:%s", config->tag);
148     switch (config->paraType) {
149         case HCF_ALG_TYPE:
150             SetKeyType(config->paraValue, cipher);
151             break;
152         case HCF_ALG_KEY_TYPE:
153             SetKeyLength(config->paraValue, cipher);
154             break;
155         case HCF_ALG_MODE:
156             SetMode(config->paraValue, cipher);
157             break;
158         case HCF_ALG_PADDING_TYPE:
159             SetPadding(config->paraValue, cipher);
160             break;
161         case HCF_ALG_DIGEST:
162             SetDigest(config->paraValue, cipher);
163             break;
164         case HCF_ALG_MGF1_DIGEST:
165             SetMgf1Digest(config->paraValue, cipher);
166             break;
167         case HCF_ALG_TEXT_FORMAT:
168             if (config->paraValue == HCF_ALG_TEXT_FORMAT_C1C2C3) {
169                 LOGE("Not Support C1C2C3 Format");
170                 ret = HCF_INVALID_PARAMS;
171             }
172             break;
173         default:
174             ret = HCF_INVALID_PARAMS;
175             break;
176     }
177     return ret;
178 }
179 
GetCipherGeneratorClass(void)180 static const char *GetCipherGeneratorClass(void)
181 {
182     return "HcfCipherGenerator";
183 }
184 
GetAlgorithm(HcfCipher * self)185 static const char *GetAlgorithm(HcfCipher *self)
186 {
187     if (self == NULL) {
188         LOGE("The input self ptr is NULL!");
189         return NULL;
190     }
191     if (!HcfIsClassMatch((HcfObjectBase *)self, GetCipherGeneratorClass())) {
192         LOGE("Class is not match.");
193         return NULL;
194     }
195     return ((CipherGenImpl *)self)->algoName;
196 }
197 
CipherDestroy(HcfObjectBase * self)198 static void CipherDestroy(HcfObjectBase *self)
199 {
200     if (self == NULL) {
201         return;
202     }
203     if (!HcfIsClassMatch(self, GetCipherGeneratorClass())) {
204         LOGE("Class not match.");
205         return;
206     }
207     CipherGenImpl *impl = (CipherGenImpl *)self;
208     HcfObjDestroy(impl->spiObj);
209     impl->spiObj = NULL;
210     HcfFree(impl);
211 }
212 
SetCipherSpecUint8Array(HcfCipher * self,CipherSpecItem item,HcfBlob pSource)213 static HcfResult SetCipherSpecUint8Array(HcfCipher *self, CipherSpecItem item, HcfBlob pSource)
214 {
215     // only implemented for OAEP_MGF1_PSRC_UINT8ARR
216     // if pSource == NULL or len == 0, it means cleaning the pSource
217     if (self == NULL) {
218         LOGE("Invalid input parameter.");
219         return HCF_INVALID_PARAMS;
220     }
221     if (item != OAEP_MGF1_PSRC_UINT8ARR) {
222         LOGE("Spec item not support.");
223         return HCF_INVALID_PARAMS;
224     }
225     if (!HcfIsClassMatch((HcfObjectBase *)self, GetCipherGeneratorClass())) {
226         LOGE("Class not match.");
227         return HCF_INVALID_PARAMS;
228     }
229     CipherGenImpl *impl = (CipherGenImpl *)self;
230     return impl->spiObj->setCipherSpecUint8Array(impl->spiObj, item, pSource);
231 }
232 
CheckCipherSpecString(CipherSpecItem item)233 static bool CheckCipherSpecString(CipherSpecItem item)
234 {
235     return ((item == OAEP_MD_NAME_STR) || (item == OAEP_MGF_NAME_STR) ||
236         (item == OAEP_MGF1_MD_STR) || (item == SM2_MD_NAME_STR));
237 }
238 
GetCipherSpecString(HcfCipher * self,CipherSpecItem item,char ** returnString)239 static HcfResult GetCipherSpecString(HcfCipher *self, CipherSpecItem item, char **returnString)
240 {
241     if (self == NULL || returnString == NULL) {
242         LOGE("Invalid input parameter.");
243         return HCF_INVALID_PARAMS;
244     }
245     if (!CheckCipherSpecString(item)) {
246         LOGE("Spec item not support.");
247         return HCF_INVALID_PARAMS;
248     }
249     if (!HcfIsClassMatch((HcfObjectBase *)self, GetCipherGeneratorClass())) {
250         LOGE("Class not match.");
251         return HCF_INVALID_PARAMS;
252     }
253     CipherGenImpl *impl = (CipherGenImpl *)self;
254     return impl->spiObj->getCipherSpecString(impl->spiObj, item, returnString);
255 }
256 
GetCipherSpecUint8Array(HcfCipher * self,CipherSpecItem item,HcfBlob * returnUint8Array)257 static HcfResult GetCipherSpecUint8Array(HcfCipher *self, CipherSpecItem item, HcfBlob *returnUint8Array)
258 {
259     if (self == NULL || returnUint8Array == NULL) {
260         LOGE("Invalid input parameter.");
261         return HCF_INVALID_PARAMS;
262     }
263     if (item != OAEP_MGF1_PSRC_UINT8ARR) {
264         LOGE("Spec item not support.");
265         return HCF_INVALID_PARAMS;
266     }
267     if (!HcfIsClassMatch((HcfObjectBase *)self, GetCipherGeneratorClass())) {
268         LOGE("Class not match.");
269         return HCF_INVALID_PARAMS;
270     }
271     CipherGenImpl *impl = (CipherGenImpl *)self;
272     return impl->spiObj->getCipherSpecUint8Array(impl->spiObj, item, returnUint8Array);
273 }
274 
CipherInit(HcfCipher * self,enum HcfCryptoMode opMode,HcfKey * key,HcfParamsSpec * params)275 static HcfResult CipherInit(HcfCipher *self, enum HcfCryptoMode opMode,
276     HcfKey *key, HcfParamsSpec *params)
277 {
278     if (self == NULL || key == NULL) { /* params maybe is NULL */
279         LOGE("Invalid input parameter.");
280         return HCF_INVALID_PARAMS;
281     }
282     if (!HcfIsClassMatch((HcfObjectBase *)self, GetCipherGeneratorClass())) {
283         LOGE("Class is not match.");
284         return HCF_INVALID_PARAMS;
285     }
286     CipherGenImpl *impl = (CipherGenImpl *)self;
287     return impl->spiObj->init(impl->spiObj, opMode, key, params);
288 }
289 
CipherUpdate(HcfCipher * self,HcfBlob * input,HcfBlob * output)290 static HcfResult CipherUpdate(HcfCipher *self, HcfBlob *input, HcfBlob *output)
291 {
292     if ((self == NULL) || (input == NULL) || (output == NULL)) {
293         LOGE("Invalid input parameter.");
294         return HCF_INVALID_PARAMS;
295     }
296     if (!HcfIsClassMatch((HcfObjectBase *)self, GetCipherGeneratorClass())) {
297         LOGE("Class is not match.");
298         return HCF_INVALID_PARAMS;
299     }
300     CipherGenImpl *impl = (CipherGenImpl *)self;
301     return impl->spiObj->update(impl->spiObj, input, output);
302 }
303 
CipherFinal(HcfCipher * self,HcfBlob * input,HcfBlob * output)304 static HcfResult CipherFinal(HcfCipher *self, HcfBlob *input, HcfBlob *output)
305 {
306     if ((self == NULL) || (output == NULL)) {
307         LOGE("Invalid input parameter!");
308         return HCF_INVALID_PARAMS;
309     }
310     if (!HcfIsClassMatch((HcfObjectBase *)self, GetCipherGeneratorClass())) {
311         LOGE("Class is not match.");
312         return HCF_INVALID_PARAMS;
313     }
314     CipherGenImpl *impl = (CipherGenImpl *)self;
315     return impl->spiObj->doFinal(impl->spiObj, input, output);
316 }
317 
InitCipher(HcfCipherGeneratorSpi * spiObj,CipherGenImpl * cipher)318 static void InitCipher(HcfCipherGeneratorSpi *spiObj, CipherGenImpl *cipher)
319 {
320     cipher->super.init = CipherInit;
321     cipher->super.update = CipherUpdate;
322     cipher->super.doFinal = CipherFinal;
323     cipher->super.getAlgorithm = GetAlgorithm;
324     cipher->super.base.destroy = CipherDestroy;
325     cipher->super.base.getClass = GetCipherGeneratorClass;
326     cipher->super.getCipherSpecString = GetCipherSpecString;
327     cipher->super.getCipherSpecUint8Array = GetCipherSpecUint8Array;
328     cipher->super.setCipherSpecUint8Array = SetCipherSpecUint8Array;
329 }
330 
FindAbility(CipherAttr * attr)331 static const HcfCipherGenFuncSet *FindAbility(CipherAttr *attr)
332 {
333     if (attr == NULL) {
334         return NULL;
335     }
336     for (uint32_t i = 0; i < sizeof(CIPHER_ABILITY_SET) / sizeof(HcfCipherGenAbility); i++) {
337         if (CIPHER_ABILITY_SET[i].algo == attr->algo) {
338             return &(CIPHER_ABILITY_SET[i].funcSet);
339         }
340     }
341     LOGE("Algo not support! [Algo]: %d", attr->algo);
342     return NULL;
343 }
344 
HcfCipherCreate(const char * transformation,HcfCipher ** returnObj)345 HcfResult HcfCipherCreate(const char *transformation, HcfCipher **returnObj)
346 {
347     CipherAttr attr = {0};
348     if (!HcfIsStrValid(transformation, HCF_MAX_ALGO_NAME_LEN) || (returnObj == NULL)) {
349         LOGE("Invalid input params while creating cipher!");
350         return HCF_INVALID_PARAMS;
351     }
352     if (ParseAndSetParameter(transformation, (void *)&attr, OnSetParameter) != HCF_SUCCESS) {
353         LOGE("ParseAndSetParameter failed!");
354         return HCF_NOT_SUPPORT;
355     }
356 
357     const HcfCipherGenFuncSet *funcSet = FindAbility(&attr);
358     if (funcSet == NULL) {
359         LOGE("FindAbility failed!");
360         return HCF_NOT_SUPPORT;
361     }
362     CipherGenImpl *returnGenerator = (CipherGenImpl *)HcfMalloc(sizeof(CipherGenImpl), 0);
363     if (returnGenerator == NULL) {
364         LOGE("failed to allocate returnGenerator memory!");
365         return HCF_ERR_MALLOC;
366     }
367     if (strcpy_s(returnGenerator->algoName, HCF_MAX_ALGO_NAME_LEN, transformation) != EOK) {
368         LOGE("Failed to copy algoName!");
369         HcfFree(returnGenerator);
370         return HCF_INVALID_PARAMS;
371     }
372     HcfCipherGeneratorSpi *spiObj = NULL;
373     HcfResult res = funcSet->createFunc(&attr, &spiObj);
374     if (res != HCF_SUCCESS) {
375         LOGE("Failed to create spi object!");
376         HcfFree(returnGenerator);
377         return res;
378     }
379     returnGenerator->spiObj = spiObj;
380     InitCipher(spiObj, returnGenerator);
381 
382     *returnObj = (HcfCipher *)returnGenerator;
383     return res;
384 }
385