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_rsa_openssl.h"
17 #include "securec.h"
18 #include "openssl/rsa.h"
19 #include "rsa_openssl_common.h"
20 #include "log.h"
21 #include "memory.h"
22 #include "openssl_adapter.h"
23 #include "openssl_class.h"
24 #include "openssl_common.h"
25 #include "stdbool.h"
26 #include "string.h"
27 #include "utils.h"
28 
29 static const char *EngineGetClass(void);
30 
31 typedef struct {
32     HcfCipherGeneratorSpi super;
33 
34     CipherAttr attr;
35 
36     CryptoStatus initFlag;
37 
38     EVP_PKEY_CTX *ctx;
39 
40     HcfBlob pSource;
41 } HcfCipherRsaGeneratorSpiImpl;
42 
CheckCipherInitParams(enum HcfCryptoMode opMode,HcfKey * key)43 static HcfResult CheckCipherInitParams(enum HcfCryptoMode opMode, HcfKey *key)
44 {
45     switch (opMode) {
46         case ENCRYPT_MODE:
47             if (!HcfIsClassMatch((HcfObjectBase *)key, OPENSSL_RSA_PUBKEY_CLASS)) {
48                 LOGE("Class not match");
49                 return HCF_INVALID_PARAMS;
50             }
51             break;
52         case DECRYPT_MODE:
53             if (!HcfIsClassMatch((HcfObjectBase *)key, OPENSSL_RSA_PRIKEY_CLASS)) {
54                 LOGE("Class not match");
55                 return HCF_INVALID_PARAMS;
56             }
57             break;
58         default:
59             LOGE("Invalid opMode %u", opMode);
60             return HCF_INVALID_PARAMS;
61     }
62 
63     return HCF_SUCCESS;
64 }
65 
DuplicateRsaFromKey(HcfKey * key,enum HcfCryptoMode opMode,RSA ** dupRsa)66 static HcfResult DuplicateRsaFromKey(HcfKey *key, enum HcfCryptoMode opMode, RSA **dupRsa)
67 {
68     HcfResult ret = HCF_SUCCESS;
69     if (opMode == ENCRYPT_MODE) {
70         ret = DuplicateRsa(((HcfOpensslRsaPubKey *)key)->pk, false, dupRsa);
71         if (ret != HCF_SUCCESS) {
72             LOGD("[error] dup pub RSA fail.");
73             return ret;
74         }
75     } else if (opMode == DECRYPT_MODE) {
76         // dup will check if rsa is NULL
77         ret = DuplicateRsa(((HcfOpensslRsaPriKey *)key)->sk, true, dupRsa);
78         if (ret != HCF_SUCCESS) {
79             LOGD("[error] dup pri RSA fail.");
80             return ret;
81         }
82     } else {
83         LOGD("[error] OpMode not match.");
84         return HCF_INVALID_PARAMS;
85     }
86     return ret;
87 }
88 
InitEvpPkeyCtx(HcfCipherRsaGeneratorSpiImpl * impl,HcfKey * key,enum HcfCryptoMode opMode)89 static HcfResult InitEvpPkeyCtx(HcfCipherRsaGeneratorSpiImpl *impl, HcfKey *key, enum HcfCryptoMode opMode)
90 {
91     RSA *rsa = NULL;
92     HcfResult ret = HCF_SUCCESS;
93     ret = DuplicateRsaFromKey(key, opMode, &rsa);
94     if (ret != HCF_SUCCESS) {
95         LOGD("[error] DuplicateRsaFromKey fail.");
96         return ret;
97     }
98     EVP_PKEY *pkey = NewEvpPkeyByRsa(rsa, false);
99     if (pkey == NULL) {
100         LOGD("[error] NewEvpPkeyByRsa fail");
101         HcfPrintOpensslError();
102         OpensslRsaFree(rsa);
103         return HCF_ERR_CRYPTO_OPERATION;
104     }
105     impl->ctx = EVP_PKEY_CTX_new(pkey, NULL);
106     if (impl->ctx == NULL) {
107         LOGD("[error] EVP_PKEY_CTX_new fail");
108         HcfPrintOpensslError();
109         OpensslEvpPkeyFree(pkey);
110         return HCF_ERR_CRYPTO_OPERATION;
111     }
112     int32_t sslRet = HCF_OPENSSL_SUCCESS;
113     if (opMode == ENCRYPT_MODE) {
114         sslRet = OpensslEvpPkeyEncryptInit(impl->ctx);
115     } else {
116         sslRet = OpensslEvpPkeyDecryptInit(impl->ctx);
117     }
118     if (sslRet != HCF_OPENSSL_SUCCESS) {
119         LOGD("[error] Init EVP_PKEY fail");
120         HcfPrintOpensslError();
121         OpensslEvpPkeyFree(pkey);
122         OpensslEvpPkeyCtxFree(impl->ctx);
123         impl->ctx = NULL;
124         return HCF_ERR_CRYPTO_OPERATION;
125     }
126     OpensslEvpPkeyFree(pkey);
127     return HCF_SUCCESS;
128 }
129 
SetPsourceFromBlob(HcfBlob pSource,EVP_PKEY_CTX * ctx)130 static HcfResult SetPsourceFromBlob(HcfBlob pSource, EVP_PKEY_CTX *ctx)
131 {
132     // If pSource is NULL or len is 0, the pSource will be cleared.
133     if (pSource.data == NULL || pSource.len == 0) {
134         if (OpensslEvpPkeyCtxSet0RsaOaepLabel(ctx, NULL, 0) != HCF_OPENSSL_SUCCESS) {
135             LOGD("[error] Openssl Set psource fail");
136             HcfPrintOpensslError();
137             return HCF_ERR_CRYPTO_OPERATION;
138         }
139     }
140     // deep copy from pSource
141     uint8_t *opensslPsource = (uint8_t *)HcfMalloc(pSource.len, 0);
142     if (opensslPsource == NULL) {
143         LOGE("Failed to allocate openssl pSource data memory");
144         return HCF_ERR_MALLOC;
145     }
146     (void)memcpy_s(opensslPsource, pSource.len, pSource.data, pSource.len);
147 
148     if (OpensslEvpPkeyCtxSet0RsaOaepLabel(ctx, opensslPsource, pSource.len) != HCF_OPENSSL_SUCCESS) {
149         LOGD("[error] Openssl Set psource fail");
150         HcfPrintOpensslError();
151         HcfFree(opensslPsource);
152         return HCF_ERR_CRYPTO_OPERATION;
153     }
154     return HCF_SUCCESS;
155 }
156 
157 // all parmas have been checked in CheckRsaCipherParams, this function does not need check.
SetDetailParams(HcfCipherRsaGeneratorSpiImpl * impl)158 static HcfResult SetDetailParams(HcfCipherRsaGeneratorSpiImpl *impl)
159 {
160     CipherAttr attr = impl->attr;
161     int32_t opensslPadding = 0;
162     (void)GetOpensslPadding(attr.paddingMode, &opensslPadding);
163     if (OpensslEvpPkeyCtxSetRsaPadding(impl->ctx, opensslPadding) != HCF_OPENSSL_SUCCESS) {
164         LOGD("[error] Cipher set padding fail.");
165         HcfPrintOpensslError();
166         return HCF_ERR_CRYPTO_OPERATION;
167     }
168     if (attr.paddingMode != HCF_OPENSSL_RSA_PKCS1_OAEP_PADDING) {
169         return HCF_SUCCESS;
170     }
171     // pkcs oaep
172     EVP_MD *md = NULL;
173     EVP_MD *mgf1md = NULL;
174     (void)GetOpensslDigestAlg(attr.md, &md);
175     (void)GetOpensslDigestAlg(attr.mgf1md, &mgf1md);
176     // set md and mgf1md
177     if (OpensslEvpPkeyCtxSetRsaOaepMd(impl->ctx, md) != HCF_OPENSSL_SUCCESS ||
178         OpensslEvpPkeyCtxSetRsaMgf1Md(impl->ctx, mgf1md) != HCF_OPENSSL_SUCCESS) {
179         LOGD("[error] Set md or mgf1md fail");
180         HcfPrintOpensslError();
181         return HCF_ERR_CRYPTO_OPERATION;
182     }
183     // default EVP pSource is NULL, need not set.
184     if (impl->pSource.data != NULL && impl->pSource.len > 0) {
185         HcfResult ret = SetPsourceFromBlob(impl->pSource, impl->ctx);
186         if (ret != HCF_SUCCESS) {
187             // check if clean the pSource when init fail at it.
188             HcfFree(impl->pSource.data);
189             impl->pSource.data = NULL;
190             LOGD("[error] Set pSource fail, clean the pSource");
191             return ret;
192         }
193     }
194     return HCF_SUCCESS;
195 }
196 
197 // The EVP_PKEY_CTX_set0_rsa_oaep_label() macro sets the RSA OAEP label to label and its length to len.
198 // https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_CTX_set0_rsa_oaep_label.html
SetRsaCipherSpecUint8Array(HcfCipherGeneratorSpi * self,CipherSpecItem item,HcfBlob pSource)199 static HcfResult SetRsaCipherSpecUint8Array(HcfCipherGeneratorSpi *self, CipherSpecItem item, HcfBlob pSource)
200 {
201     // If pSource is NULL or len is 0, the pSource will be cleared.
202     if (self == NULL) {
203         LOGE("Param is invalid.");
204         return HCF_INVALID_PARAMS;
205     }
206     if (item != OAEP_MGF1_PSRC_UINT8ARR) {
207         LOGE("Invalid cipher spec item");
208         return HCF_INVALID_PARAMS;
209     }
210     if (!HcfIsClassMatch((HcfObjectBase *)self, EngineGetClass())) {
211         LOGE("Class not match");
212         return HCF_INVALID_PARAMS;
213     }
214     HcfCipherRsaGeneratorSpiImpl *impl = (HcfCipherRsaGeneratorSpiImpl *)self;
215     CipherAttr attr = impl->attr;
216     if (attr.paddingMode != HCF_OPENSSL_RSA_PKCS1_OAEP_PADDING) {
217         LOGE("Psource is not supported.");
218         return HCF_INVALID_PARAMS;
219     }
220     // if it has pSource from previous set, it should be free at first;
221     if (impl->pSource.data != NULL) {
222         HcfFree(impl->pSource.data);
223         impl->pSource.data = NULL;
224     }
225     // If pSource is NULL or len is 0, the pSource will be cleared.
226     if (pSource.data == NULL || pSource.len == 0) {
227         impl->pSource.data = NULL;
228         impl->pSource.len = 0;
229     } else {
230         // deep copy two pSource, one for impl struct and one for openssl.
231         impl->pSource.data = (uint8_t *)HcfMalloc(pSource.len, 0);
232         if (impl->pSource.data == NULL) {
233             LOGE("Failed to allocate pSource data memory");
234             return HCF_ERR_MALLOC;
235         }
236         (void)memcpy_s(impl->pSource.data, pSource.len, pSource.data, pSource.len);
237         impl->pSource.len = pSource.len;
238     }
239     // if uninitliszed, pSource should only be stored in the struct.
240     // if initliszed, pSource should have another copy and set the copy to the evp ctx.
241     if (impl->initFlag == INITIALIZED) {
242         HcfResult ret = SetPsourceFromBlob(impl->pSource, impl->ctx);
243         if (ret != HCF_SUCCESS) {
244             LOGE("Set pSource fail");
245             HcfFree(impl->pSource.data);
246             impl->pSource.data = NULL;
247             return ret;
248         }
249     }
250     return HCF_SUCCESS;
251 }
252 
GetRsaCipherSpecUint8Array(HcfCipherGeneratorSpi * self,CipherSpecItem item,HcfBlob * returnPSource)253 static HcfResult GetRsaCipherSpecUint8Array(HcfCipherGeneratorSpi *self, CipherSpecItem item, HcfBlob* returnPSource)
254 {
255     if (self == NULL || returnPSource == NULL) {
256         LOGE("Param is invalid.");
257         return HCF_INVALID_PARAMS;
258     }
259     if (item != OAEP_MGF1_PSRC_UINT8ARR) {
260         LOGE("Invalid cipher spec item");
261         return HCF_INVALID_PARAMS;
262     }
263     if (!HcfIsClassMatch((HcfObjectBase *)self, EngineGetClass())) {
264         LOGE("Class not match");
265         return HCF_INVALID_PARAMS;
266     }
267     HcfCipherRsaGeneratorSpiImpl *impl = (HcfCipherRsaGeneratorSpiImpl *)self;
268     CipherAttr attr = impl->attr;
269     if (attr.paddingMode != HCF_OPENSSL_RSA_PKCS1_OAEP_PADDING) {
270         LOGE("Psource is not supported.");
271         return HCF_INVALID_PARAMS;
272     }
273     // use the pSource from struct at first.
274     if (impl->pSource.data != NULL && impl->pSource.len > 0) {
275         uint8_t *pSource = (uint8_t *)HcfMalloc(impl->pSource.len, 0);
276         if (pSource == NULL) {
277             LOGE("Failed to allocate pSource memory!");
278             return HCF_ERR_MALLOC;
279         }
280         (void)memcpy_s(pSource, impl->pSource.len, impl->pSource.data, impl->pSource.len);
281         returnPSource->data = pSource;
282         returnPSource->len = impl->pSource.len;
283         return HCF_SUCCESS;
284     }
285     // without pSource in the struct, use the default get func of openssl after init.
286     // default situation, the pSource is NULL and len is 0, return fail.
287     return HCF_INVALID_PARAMS;
288 }
289 
GetRsaCipherSpecString(HcfCipherGeneratorSpi * self,CipherSpecItem item,char ** returnString)290 static HcfResult GetRsaCipherSpecString(HcfCipherGeneratorSpi *self, CipherSpecItem item, char **returnString)
291 {
292     if (self == NULL || returnString == NULL) {
293         LOGE("Param is invalid.");
294         return HCF_INVALID_PARAMS;
295     }
296     if (!HcfIsClassMatch((HcfObjectBase *)self, EngineGetClass())) {
297         LOGE("Class not match");
298         return HCF_INVALID_PARAMS;
299     }
300     HcfCipherRsaGeneratorSpiImpl *impl = (HcfCipherRsaGeneratorSpiImpl *)self;
301     CipherAttr attr = impl->attr;
302     if (attr.paddingMode != HCF_OPENSSL_RSA_PKCS1_OAEP_PADDING) {
303         LOGE("cipher spec string is not supported.");
304         return HCF_INVALID_PARAMS;
305     }
306     HcfResult ret = HCF_INVALID_PARAMS;
307     switch (item) {
308         case OAEP_MD_NAME_STR:
309             ret = GetRsaSpecStringMd((const HcfAlgParaValue)(attr.md), returnString);
310             break;
311         case OAEP_MGF_NAME_STR:
312             // only support mgf1
313             ret = GetRsaSpecStringMGF(returnString);
314             break;
315         case OAEP_MGF1_MD_STR:
316             ret = GetRsaSpecStringMd((const HcfAlgParaValue)(attr.mgf1md), returnString);
317             break;
318         default:
319             LOGE("Invalid input cipher spec");
320             return HCF_INVALID_PARAMS;
321     }
322     return ret;
323 }
324 
EngineInit(HcfCipherGeneratorSpi * self,enum HcfCryptoMode opMode,HcfKey * key,HcfParamsSpec * params)325 static HcfResult EngineInit(HcfCipherGeneratorSpi *self, enum HcfCryptoMode opMode,
326     HcfKey *key, HcfParamsSpec *params)
327 {
328     (void)params;
329     if (self == NULL || key == NULL) {
330         LOGE("Param is invalid.");
331         return HCF_INVALID_PARAMS;
332     }
333     if (!HcfIsClassMatch((HcfObjectBase *)self, EngineGetClass())) {
334         LOGE("Class not match");
335         return HCF_INVALID_PARAMS;
336     }
337     HcfCipherRsaGeneratorSpiImpl *impl = (HcfCipherRsaGeneratorSpiImpl *)self;
338     if (impl->initFlag != UNINITIALIZED) {
339         LOGE("The cipher has been initialize, don't init again.");
340         return HCF_INVALID_PARAMS;
341     }
342 
343     // check opMode is matched with Key
344     if (CheckCipherInitParams(opMode, key) != HCF_SUCCESS) {
345         LOGE("OpMode dismatch with keyType.");
346         return HCF_INVALID_PARAMS;
347     }
348     impl->attr.mode = (int32_t)opMode;
349     if (InitEvpPkeyCtx(impl, key, opMode) != HCF_SUCCESS) {
350         LOGD("[error] InitEvpPkeyCtx fail");
351         return HCF_ERR_CRYPTO_OPERATION;
352     }
353 
354     if (SetDetailParams(impl) != HCF_SUCCESS) {
355         OpensslEvpPkeyCtxFree(impl->ctx);
356         impl->ctx = NULL;
357         LOGD("[error] SetDetailParams fail.");
358         return HCF_ERR_CRYPTO_OPERATION;
359     }
360     impl->initFlag = INITIALIZED;
361     return HCF_SUCCESS;
362 }
363 
EngineUpdate(HcfCipherGeneratorSpi * self,HcfBlob * input,HcfBlob * output)364 static HcfResult EngineUpdate(HcfCipherGeneratorSpi *self, HcfBlob *input, HcfBlob *output)
365 {
366     LOGE("Openssl don't support update");
367     (void)self;
368     (void)input;
369     (void)output;
370     return HCF_NOT_SUPPORT;
371 }
372 
DoRsaCrypt(EVP_PKEY_CTX * ctx,HcfBlob * input,HcfBlob * output,int32_t mode)373 static HcfResult DoRsaCrypt(EVP_PKEY_CTX *ctx, HcfBlob *input, HcfBlob *output, int32_t mode)
374 {
375     int32_t ret = HCF_OPENSSL_SUCCESS;
376     if (mode == ENCRYPT_MODE) {
377         ret = OpensslEvpPkeyEncrypt(ctx, output->data, &output->len, input->data, input->len);
378     } else if (mode == DECRYPT_MODE) {
379         ret = OpensslEvpPkeyDecrypt(ctx, output->data, &output->len, input->data, input->len);
380     } else {
381         LOGE("OpMode is invalid.");
382         return HCF_INVALID_PARAMS;
383     }
384     if (ret != HCF_OPENSSL_SUCCESS) {
385         LOGD("[error] RSA openssl error");
386         HcfPrintOpensslError();
387         return HCF_ERR_CRYPTO_OPERATION;
388     }
389     return HCF_SUCCESS;
390 }
391 
EngineDoFinal(HcfCipherGeneratorSpi * self,HcfBlob * input,HcfBlob * output)392 static HcfResult EngineDoFinal(HcfCipherGeneratorSpi *self, HcfBlob *input, HcfBlob *output)
393 {
394     if (self == NULL || !HcfIsBlobValid(input) || output == NULL) {
395         LOGE("Param is invalid.");
396         return HCF_INVALID_PARAMS;
397     }
398     if (!HcfIsClassMatch((HcfObjectBase *)self, EngineGetClass())) {
399         LOGE("Class not match");
400         return HCF_INVALID_PARAMS;
401     }
402     HcfCipherRsaGeneratorSpiImpl *impl = (HcfCipherRsaGeneratorSpiImpl *)self;
403     if (impl->initFlag != INITIALIZED) {
404         LOGE("RSACipher has not been init");
405         return HCF_INVALID_PARAMS;
406     }
407     CipherAttr attr = impl->attr;
408     output->len = 0;
409     output->data = NULL;
410     HcfResult ret = DoRsaCrypt(impl->ctx, input, output, attr.mode);
411     if (ret != HCF_SUCCESS) {
412         LOGD("[error] GetOutLen fail.");
413         return HCF_ERR_CRYPTO_OPERATION;
414     }
415 
416     output->data = (uint8_t *)HcfMalloc(sizeof(uint8_t) * output->len, 0);
417     if (output->data == NULL) {
418         LOGE("failed to allocate memory!");
419         return HCF_ERR_MALLOC;
420     }
421     ret = DoRsaCrypt(impl->ctx, input, output, attr.mode);
422     if (ret != HCF_SUCCESS) {
423         HcfFree(output->data);
424         output->data = NULL;
425         output->len = 0;
426         return HCF_ERR_CRYPTO_OPERATION;
427     }
428     return HCF_SUCCESS;
429 }
430 
EngineDestroySpiImpl(HcfObjectBase * generator)431 static void EngineDestroySpiImpl(HcfObjectBase *generator)
432 {
433     if (generator == NULL) {
434         return;
435     }
436     if (!HcfIsClassMatch((HcfObjectBase *)generator, EngineGetClass())) {
437         LOGE("Class not match");
438         return;
439     }
440     HcfCipherRsaGeneratorSpiImpl *impl = (HcfCipherRsaGeneratorSpiImpl *)generator;
441     OpensslEvpPkeyCtxFree(impl->ctx);
442     impl->ctx = NULL;
443     HcfFree(impl->pSource.data);
444     impl->pSource.data = NULL;
445     HcfFree(impl);
446     impl = NULL;
447 }
448 
EngineGetClass(void)449 static const char *EngineGetClass(void)
450 {
451     return OPENSSL_RSA_CIPHER_CLASS;
452 }
453 
CheckRsaCipherParams(CipherAttr * params)454 static HcfResult CheckRsaCipherParams(CipherAttr *params)
455 {
456     int32_t opensslPadding = 0;
457     if (params->algo != HCF_ALG_RSA) {
458         LOGE("Cipher algo %u is invalid.", params->algo);
459         return HCF_INVALID_PARAMS;
460     }
461     if (GetOpensslPadding(params->paddingMode, &opensslPadding) != HCF_SUCCESS) {
462         LOGE("Cipher create without padding mode");
463         return HCF_INVALID_PARAMS;
464     }
465     // cannot use pss padding mode in RSA cipher.
466     if (opensslPadding == RSA_PKCS1_PSS_PADDING) {
467         LOGE("Cipher cannot use PSS mode");
468         return HCF_INVALID_PARAMS;
469     }
470     if (params->paddingMode == HCF_OPENSSL_RSA_PKCS1_OAEP_PADDING) {
471         EVP_MD *md = NULL;
472         EVP_MD *mgf1md = NULL;
473         (void)GetOpensslDigestAlg(params->md, &md);
474         (void)GetOpensslDigestAlg(params->mgf1md, &mgf1md);
475         if (md == NULL) {
476             LOGE("Use pkcs1_oaep padding, but md is NULL");
477             return HCF_INVALID_PARAMS;
478         }
479         if (mgf1md == NULL) {
480             LOGE("Use pkcs1_oaep padding, but mgf1md is NULL");
481             return HCF_INVALID_PARAMS;
482         }
483     }
484     return HCF_SUCCESS;
485 }
486 
HcfCipherRsaCipherSpiCreate(CipherAttr * params,HcfCipherGeneratorSpi ** generator)487 HcfResult HcfCipherRsaCipherSpiCreate(CipherAttr *params, HcfCipherGeneratorSpi **generator)
488 {
489     if (generator == NULL || params == NULL) {
490         LOGE("Invalid input parameter.");
491         return HCF_INVALID_PARAMS;
492     }
493     HcfCipherRsaGeneratorSpiImpl *returnImpl = (HcfCipherRsaGeneratorSpiImpl *)HcfMalloc(
494         sizeof(HcfCipherRsaGeneratorSpiImpl), 0);
495     if (returnImpl == NULL) {
496         LOGE("Malloc rsa cipher fail.");
497         return HCF_ERR_MALLOC;
498     }
499     (void)memcpy_s(&returnImpl->attr, sizeof(CipherAttr), params, sizeof(CipherAttr));
500 
501     if (CheckRsaCipherParams(&returnImpl->attr) != HCF_SUCCESS) {
502         HcfFree(returnImpl);
503         returnImpl = NULL;
504         return HCF_INVALID_PARAMS;
505     }
506 
507     returnImpl->super.init = EngineInit;
508     returnImpl->super.update = EngineUpdate;
509     returnImpl->super.doFinal = EngineDoFinal;
510     returnImpl->super.setCipherSpecUint8Array = SetRsaCipherSpecUint8Array;
511     returnImpl->super.getCipherSpecString = GetRsaCipherSpecString;
512     returnImpl->super.getCipherSpecUint8Array = GetRsaCipherSpecUint8Array;
513     returnImpl->super.base.destroy = EngineDestroySpiImpl;
514     returnImpl->super.base.getClass = EngineGetClass;
515     returnImpl->initFlag = UNINITIALIZED;
516     *generator = (HcfCipherGeneratorSpi *)returnImpl;
517     return HCF_SUCCESS;
518 }
519