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
29typedef HcfResult (*HcfCipherGeneratorSpiCreateFunc)(CipherAttr *, HcfCipherGeneratorSpi **);
30
31typedef struct {
32    HcfCipher super;
33    HcfCipherGeneratorSpi *spiObj;
34    char algoName[HCF_MAX_ALGO_NAME_LEN];
35} CipherGenImpl;
36
37typedef struct {
38    HcfCipherGeneratorSpiCreateFunc createFunc;
39} HcfCipherGenFuncSet;
40
41typedef struct {
42    HcfAlgValue algo;
43    HcfCipherGenFuncSet funcSet;
44} HcfCipherGenAbility;
45
46static 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
54static 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
82static 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
118static void SetMode(HcfAlgParaValue value, void *cipher)
119{
120    CipherAttr *cipherAttr = (CipherAttr *)cipher;
121    cipherAttr->mode = value ;
122}
123
124static void SetPadding(HcfAlgParaValue value, void *cipher)
125{
126    CipherAttr *cipherAttr = (CipherAttr *)cipher;
127    cipherAttr->paddingMode = value;
128}
129
130static void SetDigest(HcfAlgParaValue value, CipherAttr *cipher)
131{
132    cipher->md = value;
133}
134
135static void SetMgf1Digest(HcfAlgParaValue value, CipherAttr *cipher)
136{
137    cipher->mgf1md = value;
138}
139
140static 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
180static const char *GetCipherGeneratorClass(void)
181{
182    return "HcfCipherGenerator";
183}
184
185static 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
198static 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
213static 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
233static 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
239static 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
257static 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
275static 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
290static 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
304static 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
318static 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
331static 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
345HcfResult 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