• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 #include "sm4_openssl.h"
16 #include "securec.h"
17 #include "blob.h"
18 #include "log.h"
19 #include "memory.h"
20 #include "result.h"
21 #include "utils.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 MAX_AAD_LEN 2048
29 #define SM4_BLOCK_SIZE 16
30 #define SM4_SIZE_128 16
31 
32 typedef struct {
33     HcfCipherGeneratorSpi base;
34     CipherAttr attr;
35     CipherData *cipherData;
36 } HcfCipherSm4GeneratorSpiOpensslImpl;
37 
GetSm4GeneratorClass(void)38 static const char *GetSm4GeneratorClass(void)
39 {
40     return OPENSSL_SM4_CIPHER_CLASS;
41 }
42 
CipherEcbType(SymKeyImpl * symKey)43 static const EVP_CIPHER *CipherEcbType(SymKeyImpl *symKey)
44 {
45     switch (symKey->keyMaterial.len) {
46         case SM4_SIZE_128:
47             return Openssl_EVP_sm4_ecb();
48         default:
49             break;
50     }
51     return NULL;
52 }
53 
CipherCbcType(SymKeyImpl * symKey)54 static const EVP_CIPHER *CipherCbcType(SymKeyImpl *symKey)
55 {
56     switch (symKey->keyMaterial.len) {
57         case SM4_SIZE_128:
58             return Openssl_EVP_sm4_cbc();
59         default:
60             break;
61     }
62     return NULL;
63 }
64 
CipherCtrType(SymKeyImpl * symKey)65 static const EVP_CIPHER *CipherCtrType(SymKeyImpl *symKey)
66 {
67     switch (symKey->keyMaterial.len) {
68         case SM4_SIZE_128:
69             return Openssl_EVP_sm4_ctr();
70         default:
71             break;
72     }
73     return NULL;
74 }
75 
CipherOfbType(SymKeyImpl * symKey)76 static const EVP_CIPHER *CipherOfbType(SymKeyImpl *symKey)
77 {
78     switch (symKey->keyMaterial.len) {
79         case SM4_SIZE_128:
80             return Openssl_EVP_sm4_ofb();
81         default:
82             break;
83     }
84     return NULL;
85 }
86 
CipherCfbType(SymKeyImpl * symKey)87 static const EVP_CIPHER *CipherCfbType(SymKeyImpl *symKey)
88 {
89     switch (symKey->keyMaterial.len) {
90         case SM4_SIZE_128:
91             return Openssl_EVP_sm4_cfb();
92         default:
93             break;
94     }
95     return NULL;
96 }
97 
CipherCfb128Type(SymKeyImpl * symKey)98 static const EVP_CIPHER *CipherCfb128Type(SymKeyImpl *symKey)
99 {
100     switch (symKey->keyMaterial.len) {
101         case SM4_SIZE_128:
102             return Openssl_EVP_sm4_cfb128();
103         default:
104             break;
105     }
106     return NULL;
107 }
108 
DefaultCipherType(SymKeyImpl * symKey)109 static const EVP_CIPHER *DefaultCipherType(SymKeyImpl *symKey)
110 {
111     return CipherEcbType(symKey);
112 }
113 
GetCipherType(HcfCipherSm4GeneratorSpiOpensslImpl * impl,SymKeyImpl * symKey)114 static const EVP_CIPHER *GetCipherType(HcfCipherSm4GeneratorSpiOpensslImpl *impl, SymKeyImpl *symKey)
115 {
116     switch (impl->attr.mode) {
117         case HCF_ALG_MODE_ECB:
118             return CipherEcbType(symKey);
119         case HCF_ALG_MODE_CBC:
120             return CipherCbcType(symKey);
121         case HCF_ALG_MODE_CTR:
122             return CipherCtrType(symKey);
123         case HCF_ALG_MODE_OFB:
124             return CipherOfbType(symKey);
125         case HCF_ALG_MODE_CFB:
126             return CipherCfbType(symKey);
127         case HCF_ALG_MODE_CFB128:
128             return CipherCfb128Type(symKey);
129         default:
130             break;
131     }
132     return DefaultCipherType(symKey);
133 }
134 
InitCipherData(enum HcfCryptoMode opMode,CipherData ** cipherData)135 static HcfResult InitCipherData(enum HcfCryptoMode opMode, CipherData **cipherData)
136 {
137     HcfResult ret = HCF_ERR_MALLOC;
138     if (cipherData == NULL) {
139         LOGE("invalid cipher data");
140         return HCF_INVALID_PARAMS;
141     }
142 
143     CipherData *data = (CipherData *)HcfMalloc(sizeof(CipherData), 0);
144     if (data == NULL) {
145         LOGE("malloc failed.");
146         return HCF_ERR_MALLOC;
147     }
148 
149     data->enc = opMode;
150     data->ctx = Openssl_EVP_CIPHER_CTX_new();
151     if (data->ctx != NULL) {
152         *cipherData = data;
153         ret = HCF_SUCCESS;
154     } else {
155         HcfPrintOpensslError();
156         HcfFree(data);
157         LOGD("[error] Failed to allocate ctx memroy.");
158     }
159     return ret;
160 }
161 
GetPaddingMode(HcfCipherSm4GeneratorSpiOpensslImpl * cipherImpl)162 static HcfResult GetPaddingMode(HcfCipherSm4GeneratorSpiOpensslImpl* cipherImpl)
163 {
164     switch (cipherImpl->attr.paddingMode) {
165         case HCF_ALG_NOPADDING:
166             break;
167         case HCF_ALG_PADDING_PKCS5:
168             return EVP_PADDING_PKCS7;
169         case HCF_ALG_PADDING_PKCS7:
170             return EVP_PADDING_PKCS7;
171         default:
172             LOGE("No Params!");
173             break;
174     }
175     return HCF_SUCCESS;
176 }
177 
CheckParam(HcfCipherGeneratorSpi * self,enum HcfCryptoMode opMode,HcfKey * key)178 static HcfResult CheckParam(HcfCipherGeneratorSpi* self, enum HcfCryptoMode opMode, HcfKey* key)
179 {
180     if ((self == NULL) || (key == NULL)) {
181         LOGE("Invalid input parameter.");
182         return HCF_INVALID_PARAMS;
183     }
184     if (!IsClassMatch((HcfObjectBase *)self, self->base.getClass())) {
185         LOGE("Class is not match.");
186         return HCF_INVALID_PARAMS;
187     }
188     if (!IsClassMatch((HcfObjectBase *)key, OPENSSL_SYM_KEY_CLASS)) {
189         LOGE("Class is not match.");
190         return HCF_INVALID_PARAMS;
191     }
192     if (opMode != ENCRYPT_MODE && opMode != DECRYPT_MODE) {
193         LOGE("Invalid opMode %d", opMode);
194         return HCF_INVALID_PARAMS;
195     }
196     SymKeyImpl* keyImpl = (SymKeyImpl*)key;
197     if (keyImpl->keyMaterial.len < SM4_SIZE_128) {
198         LOGE("Init failed, the input key size is smaller than keySize specified in cipher.");
199         return HCF_INVALID_PARAMS;
200     }
201     HcfCipherSm4GeneratorSpiOpensslImpl *cipherImpl = (HcfCipherSm4GeneratorSpiOpensslImpl *)self;
202     if (cipherImpl->attr.paddingMode != HCF_ALG_NOPADDING && cipherImpl->attr.paddingMode != HCF_ALG_PADDING_PKCS5
203         && cipherImpl->attr.paddingMode != HCF_ALG_PADDING_PKCS7) {
204         LOGE("Invalid padding mode %u", cipherImpl->attr.paddingMode);
205         return HCF_INVALID_PARAMS;
206     }
207     return HCF_SUCCESS;
208 }
209 
EngineCipherInit(HcfCipherGeneratorSpi * self,enum HcfCryptoMode opMode,HcfKey * key,HcfParamsSpec * params)210 static HcfResult EngineCipherInit(HcfCipherGeneratorSpi* self, enum HcfCryptoMode opMode,
211     HcfKey* key, HcfParamsSpec* params)
212 {
213     if (CheckParam(self, opMode, key) != HCF_SUCCESS) {
214         return HCF_INVALID_PARAMS;
215     }
216     HcfCipherSm4GeneratorSpiOpensslImpl *cipherImpl = (HcfCipherSm4GeneratorSpiOpensslImpl *)self;
217     CipherData* data = NULL;
218     if (InitCipherData(opMode, &data) != HCF_SUCCESS) {
219         LOGE("InitCipherData failed");
220         return HCF_INVALID_PARAMS;
221     }
222     HcfResult ret = HCF_ERR_CRYPTO_OPERATION;
223     int32_t enc = (opMode == ENCRYPT_MODE) ? 1 : 0;
224     SymKeyImpl* keyImpl = (SymKeyImpl*)key;
225     if (Openssl_EVP_CipherInit(data->ctx, GetCipherType(cipherImpl, keyImpl), keyImpl->keyMaterial.data,
226         GetIv(params), enc) != HCF_OPENSSL_SUCCESS) {
227         HcfPrintOpensslError();
228         LOGD("[error] Cipher init key and iv failed.");
229         FreeCipherData(&data);
230         return ret;
231     }
232     if (Openssl_EVP_CIPHER_CTX_set_padding(data->ctx, GetPaddingMode(cipherImpl)) != HCF_OPENSSL_SUCCESS) {
233         HcfPrintOpensslError();
234         LOGD("[error] Set padding failed.");
235         FreeCipherData(&data);
236         return ret;
237     }
238     cipherImpl->cipherData = data;
239     return HCF_SUCCESS;
240 }
241 
AllocateOutput(HcfBlob * input,HcfBlob * output)242 static HcfResult AllocateOutput(HcfBlob* input, HcfBlob* output)
243 {
244     uint32_t outLen = SM4_BLOCK_SIZE;
245     if (IsBlobValid(input)) {
246         outLen += input->len;
247     }
248     output->data = (uint8_t*)HcfMalloc(outLen, 0);
249     if (output->data == NULL) {
250         LOGE("Malloc output failed.");
251         return HCF_ERR_MALLOC;
252     }
253     output->len = outLen;
254     return HCF_SUCCESS;
255 }
256 
EngineUpdate(HcfCipherGeneratorSpi * self,HcfBlob * input,HcfBlob * output)257 static HcfResult EngineUpdate(HcfCipherGeneratorSpi *self, HcfBlob *input, HcfBlob *output)
258 {
259     if ((self == NULL) || (input == NULL) || (output == NULL)) {
260         LOGE("Invalid input parameter!");
261         return HCF_INVALID_PARAMS;
262     }
263     if (!IsClassMatch((HcfObjectBase *)self, self->base.getClass())) {
264         LOGE("Class is not match.");
265         return HCF_INVALID_PARAMS;
266     }
267 
268     HcfCipherSm4GeneratorSpiOpensslImpl *cipherImpl = (HcfCipherSm4GeneratorSpiOpensslImpl *)self;
269     CipherData *data = cipherImpl->cipherData;
270     if (data == NULL) {
271         LOGE("cipherData is null!");
272         return HCF_INVALID_PARAMS;
273     }
274     HcfResult ret = HCF_ERR_CRYPTO_OPERATION;
275     if (AllocateOutput(input, output) == HCF_SUCCESS) {
276         if (Openssl_EVP_CipherUpdate(data->ctx, output->data, (int*)&output->len,
277             input->data, input->len) != HCF_OPENSSL_SUCCESS) {
278             HcfPrintOpensslError();
279             LOGD("[error] Cipher update failed.");
280         } else {
281             ret = HCF_SUCCESS;
282         }
283     }
284     if (ret != HCF_SUCCESS) {
285         HcfBlobDataFree(output);
286         FreeCipherData(&(cipherImpl->cipherData));
287     } else {
288         FreeRedundantOutput(output);
289     }
290     return ret;
291 }
292 
SM4DoFinal(CipherData * data,HcfBlob * input,HcfBlob * output)293 static HcfResult SM4DoFinal(CipherData* data, HcfBlob* input, HcfBlob* output)
294 {
295     int32_t ret;
296     uint32_t len = 0;
297 
298     if (IsBlobValid(input)) {
299         ret = Openssl_EVP_CipherUpdate(data->ctx, output->data, (int*)&output->len,
300             input->data, input->len);
301         if (ret != HCF_OPENSSL_SUCCESS) {
302             HcfPrintOpensslError();
303             LOGD("[error] Cipher update failed.");
304             return HCF_ERR_CRYPTO_OPERATION;
305         }
306         len += output->len;
307     }
308     ret = Openssl_EVP_CipherFinal_ex(data->ctx, output->data + len, (int*)&output->len);
309     if (ret != HCF_OPENSSL_SUCCESS) {
310         HcfPrintOpensslError();
311         LOGD("[error] Cipher final filed.");
312         return HCF_ERR_CRYPTO_OPERATION;
313     }
314     output->len += len;
315     return HCF_SUCCESS;
316 }
317 
EngineDoFinal(HcfCipherGeneratorSpi * self,HcfBlob * input,HcfBlob * output)318 static HcfResult EngineDoFinal(HcfCipherGeneratorSpi* self, HcfBlob* input, HcfBlob* output)
319 {
320     if ((self == NULL) || (output == NULL)) { /* input maybe is null */
321         LOGE("Invalid input parameter.");
322         return HCF_INVALID_PARAMS;
323     }
324     if (!IsClassMatch((HcfObjectBase*)self, self->base.getClass())) {
325         LOGE("Class is not match.");
326         return HCF_INVALID_PARAMS;
327     }
328     HcfCipherSm4GeneratorSpiOpensslImpl* cipherImpl = (HcfCipherSm4GeneratorSpiOpensslImpl*)self;
329     if (cipherImpl->cipherData == NULL) {
330         LOGE("CipherData is null.");
331         return HCF_INVALID_PARAMS;
332     }
333 
334     HcfResult ret = HCF_ERR_CRYPTO_OPERATION;
335     if (AllocateOutput(input, output) == HCF_SUCCESS) {
336         ret = SM4DoFinal(cipherImpl->cipherData, input, output);
337         if (ret != HCF_SUCCESS) {
338             LOGD("[error] DesDoFinal failed.");
339         }
340     }
341     if (ret != HCF_SUCCESS) {
342         HcfBlobDataFree(output);
343     } else {
344         FreeRedundantOutput(output);
345     }
346     FreeCipherData(&(cipherImpl->cipherData));
347     return ret;
348 }
349 
EngineSm4GeneratorDestroy(HcfObjectBase * self)350 static void EngineSm4GeneratorDestroy(HcfObjectBase *self)
351 {
352     if (self == NULL) {
353         return;
354     }
355     if (!IsClassMatch(self, self->getClass())) {
356         LOGE("Class is not match.");
357         return;
358     }
359 
360     HcfCipherSm4GeneratorSpiOpensslImpl *impl = (HcfCipherSm4GeneratorSpiOpensslImpl *)self;
361     FreeCipherData(&(impl->cipherData));
362     HcfFree(impl);
363 }
364 
GetSm4CipherSpecString(HcfCipherGeneratorSpi * self,CipherSpecItem item,char ** returnString)365 static HcfResult GetSm4CipherSpecString(HcfCipherGeneratorSpi *self, CipherSpecItem item, char **returnString)
366 {
367     (void)self;
368     (void)item;
369     (void)returnString;
370     return HCF_NOT_SUPPORT;
371 }
372 
GetSm4CipherSpecUint8Array(HcfCipherGeneratorSpi * self,CipherSpecItem item,HcfBlob * returnUint8Array)373 static HcfResult GetSm4CipherSpecUint8Array(HcfCipherGeneratorSpi *self, CipherSpecItem item, HcfBlob *returnUint8Array)
374 {
375     (void)self;
376     (void)item;
377     (void)returnUint8Array;
378     return HCF_NOT_SUPPORT;
379 }
380 
SetSm4CipherSpecUint8Array(HcfCipherGeneratorSpi * self,CipherSpecItem item,HcfBlob blob)381 static HcfResult SetSm4CipherSpecUint8Array(HcfCipherGeneratorSpi *self, CipherSpecItem item, HcfBlob blob)
382 {
383     (void)self;
384     (void)item;
385     (void)blob;
386     return HCF_NOT_SUPPORT;
387 }
388 
HcfCipherSm4GeneratorSpiCreate(CipherAttr * attr,HcfCipherGeneratorSpi ** generator)389 HcfResult HcfCipherSm4GeneratorSpiCreate(CipherAttr *attr, HcfCipherGeneratorSpi **generator)
390 {
391     if (attr == NULL || generator == NULL) {
392         LOGE("Invalid input parameter.");
393         return HCF_INVALID_PARAMS;
394     }
395     HcfCipherSm4GeneratorSpiOpensslImpl *returnImpl = (HcfCipherSm4GeneratorSpiOpensslImpl *)HcfMalloc(
396         sizeof(HcfCipherSm4GeneratorSpiOpensslImpl), 0);
397     if (returnImpl == NULL) {
398         LOGE("Failed to allocate returnImpl memroy!");
399         return HCF_ERR_MALLOC;
400     }
401     (void)memcpy_s(&returnImpl->attr, sizeof(CipherAttr), attr, sizeof(CipherAttr));
402     returnImpl->base.init = EngineCipherInit;
403     returnImpl->base.update = EngineUpdate;
404     returnImpl->base.doFinal = EngineDoFinal;
405     returnImpl->base.getCipherSpecString = GetSm4CipherSpecString;
406     returnImpl->base.getCipherSpecUint8Array = GetSm4CipherSpecUint8Array;
407     returnImpl->base.setCipherSpecUint8Array = SetSm4CipherSpecUint8Array;
408     returnImpl->base.base.destroy = EngineSm4GeneratorDestroy;
409     returnImpl->base.base.getClass = GetSm4GeneratorClass;
410 
411     *generator = (HcfCipherGeneratorSpi *)returnImpl;
412     return HCF_SUCCESS;
413 }
414