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