1 /*
2  * Copyright (C) 2022 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 "ecdsa_openssl.h"
17 
18 #include <openssl/bio.h>
19 #include <openssl/err.h>
20 
21 #include "algorithm_parameter.h"
22 #include "openssl_adapter.h"
23 #include "openssl_class.h"
24 #include "openssl_common.h"
25 #include "log.h"
26 #include "memory.h"
27 #include "utils.h"
28 
29 #define OPENSSL_ECC_SIGN_CLASS "OPENSSL.ECC.SIGN"
30 #define OPENSSL_ECC_VERIFY_CLASS "OPENSSL.ECC.VERIFY"
31 
32 typedef struct {
33     HcfSignSpi base;
34 
35     const EVP_MD *digestAlg;
36 
37     EVP_MD_CTX *ctx;
38 
39     CryptoStatus status;
40 } HcfSignSpiEcdsaOpensslImpl;
41 
42 typedef struct {
43     HcfVerifySpi base;
44 
45     const EVP_MD *digestAlg;
46 
47     EVP_MD_CTX *ctx;
48 
49     CryptoStatus status;
50 } HcfVerifySpiEcdsaOpensslImpl;
51 
IsDigestAlgValid(uint32_t alg)52 static bool IsDigestAlgValid(uint32_t alg)
53 {
54     if ((alg == HCF_OPENSSL_DIGEST_SHA1) || (alg == HCF_OPENSSL_DIGEST_SHA224) ||
55         (alg == HCF_OPENSSL_DIGEST_SHA256) ||(alg == HCF_OPENSSL_DIGEST_SHA384) ||
56         (alg == HCF_OPENSSL_DIGEST_SHA512)) {
57         return true;
58     } else {
59         LOGE("Invalid digest num is %u.", alg);
60         return false;
61     }
62 }
63 
IsBrainPoolDigestAlgValid(uint32_t alg)64 static bool IsBrainPoolDigestAlgValid(uint32_t alg)
65 {
66     if ((alg == HCF_OPENSSL_DIGEST_SHA1) || (alg == HCF_OPENSSL_DIGEST_SHA224) ||
67         (alg == HCF_OPENSSL_DIGEST_SHA256) || (alg == HCF_OPENSSL_DIGEST_SHA384) ||
68         (alg == HCF_OPENSSL_DIGEST_SHA512) || (alg == HCF_OPENSSL_DIGEST_MD5)) {
69         return true;
70     } else {
71         LOGE("Invalid digest num is %u.", alg);
72         return false;
73     }
74 }
75 
76 // export interfaces
GetEcdsaSignClass(void)77 static const char *GetEcdsaSignClass(void)
78 {
79     return OPENSSL_ECC_SIGN_CLASS;
80 }
81 
GetEcdsaVerifyClass(void)82 static const char *GetEcdsaVerifyClass(void)
83 {
84     return OPENSSL_ECC_VERIFY_CLASS;
85 }
86 
DestroyEcdsaSign(HcfObjectBase * self)87 static void DestroyEcdsaSign(HcfObjectBase *self)
88 {
89     if (self == NULL) {
90         LOGE("Class is null.");
91         return;
92     }
93     if (!HcfIsClassMatch(self, GetEcdsaSignClass())) {
94         LOGE("Class not match.");
95         return;
96     }
97     HcfSignSpiEcdsaOpensslImpl *impl = (HcfSignSpiEcdsaOpensslImpl *)self;
98     OpensslEvpMdCtxFree(impl->ctx);
99     impl->ctx = NULL;
100     HcfFree(impl);
101 }
102 
DestroyEcdsaVerify(HcfObjectBase * self)103 static void DestroyEcdsaVerify(HcfObjectBase *self)
104 {
105     if (self == NULL) {
106         LOGE("Class is null.");
107         return;
108     }
109     if (!HcfIsClassMatch(self, GetEcdsaVerifyClass())) {
110         LOGE("Class not match.");
111         return;
112     }
113     HcfVerifySpiEcdsaOpensslImpl *impl = (HcfVerifySpiEcdsaOpensslImpl *)self;
114     OpensslEvpMdCtxFree(impl->ctx);
115     impl->ctx = NULL;
116     HcfFree(impl);
117 }
118 
EngineSignInit(HcfSignSpi * self,HcfParamsSpec * params,HcfPriKey * privateKey)119 static HcfResult EngineSignInit(HcfSignSpi *self, HcfParamsSpec *params, HcfPriKey *privateKey)
120 {
121     (void)params;
122     if ((self == NULL) || (privateKey == NULL)) {
123         LOGE("Invalid input parameter.");
124         return HCF_INVALID_PARAMS;
125     }
126     if ((!HcfIsClassMatch((HcfObjectBase *)self, GetEcdsaSignClass())) ||
127         (!HcfIsClassMatch((HcfObjectBase *)privateKey, HCF_OPENSSL_ECC_PRI_KEY_CLASS))) {
128         LOGE("Class not match.");
129         return HCF_INVALID_PARAMS;
130     }
131 
132     HcfSignSpiEcdsaOpensslImpl *impl = (HcfSignSpiEcdsaOpensslImpl *)self;
133     if (impl->status != UNINITIALIZED) {
134         LOGE("Repeated initialization is not allowed.");
135         return HCF_INVALID_PARAMS;
136     }
137     // dup will check if ecKey is NULL
138     EC_KEY *ecKey = OpensslEcKeyDup(((HcfOpensslEccPriKey *)privateKey)->ecKey);
139     if (ecKey == NULL) {
140         HcfPrintOpensslError();
141         LOGD("[error] Dup ecKey failed.");
142         return HCF_ERR_CRYPTO_OPERATION;
143     }
144     EVP_PKEY *pKey = OpensslEvpPkeyNew();
145     if (pKey == NULL) {
146         HcfPrintOpensslError();
147         LOGD("[error] Dup pKey failed.");
148         OpensslEcKeyFree(ecKey);
149         return HCF_ERR_CRYPTO_OPERATION;
150     }
151     if (OpensslEvpPkeyAssignEcKey(pKey, ecKey) != HCF_OPENSSL_SUCCESS) {
152         HcfPrintOpensslError();
153         LOGD("[error] EVP_PKEY_assign_EC_KEY failed.");
154         OpensslEcKeyFree(ecKey);
155         OpensslEvpPkeyFree(pKey);
156         return HCF_ERR_CRYPTO_OPERATION;
157     }
158     if (OpensslEvpDigestSignInit(impl->ctx, NULL, impl->digestAlg, NULL, pKey) != HCF_OPENSSL_SUCCESS) {
159         HcfPrintOpensslError();
160         LOGD("[error] EVP_DigestSignInit failed.");
161         OpensslEvpPkeyFree(pKey);
162         return HCF_ERR_CRYPTO_OPERATION;
163     }
164     OpensslEvpPkeyFree(pKey);
165     impl->status = INITIALIZED;
166     return HCF_SUCCESS;
167 }
168 
EngineSignUpdate(HcfSignSpi * self,HcfBlob * data)169 static HcfResult EngineSignUpdate(HcfSignSpi *self, HcfBlob *data)
170 {
171     if ((self == NULL) || (!HcfIsBlobValid(data))) {
172         LOGE("Invalid input parameter.");
173         return HCF_INVALID_PARAMS;
174     }
175     if (!HcfIsClassMatch((HcfObjectBase *)self, GetEcdsaSignClass())) {
176         LOGE("Class not match.");
177         return HCF_INVALID_PARAMS;
178     }
179     HcfSignSpiEcdsaOpensslImpl *impl = (HcfSignSpiEcdsaOpensslImpl *)self;
180     if (impl->status == UNINITIALIZED) {
181         LOGE("Sign object has not been initialized.");
182         return HCF_INVALID_PARAMS;
183     }
184     if (OpensslEvpDigestSignUpdate(impl->ctx, data->data, data->len) != HCF_OPENSSL_SUCCESS) {
185         HcfPrintOpensslError();
186         LOGD("[error] EVP_DigestSignUpdate failed.");
187         return HCF_ERR_CRYPTO_OPERATION;
188     }
189     impl->status = READY;
190     return HCF_SUCCESS;
191 }
192 
EngineSignDoFinal(HcfSignSpi * self,HcfBlob * data,HcfBlob * returnSignatureData)193 static HcfResult EngineSignDoFinal(HcfSignSpi *self, HcfBlob *data, HcfBlob *returnSignatureData)
194 {
195     if ((self == NULL) || (returnSignatureData == NULL)) {
196         LOGE("Invalid input parameter.");
197         return HCF_INVALID_PARAMS;
198     }
199     if (!HcfIsClassMatch((HcfObjectBase *)self, GetEcdsaSignClass())) {
200         LOGE("Class not match.");
201         return HCF_INVALID_PARAMS;
202     }
203 
204     HcfSignSpiEcdsaOpensslImpl *impl = (HcfSignSpiEcdsaOpensslImpl *)self;
205     if (HcfIsBlobValid(data)) {
206         if (OpensslEvpDigestSignUpdate(impl->ctx, data->data, data->len) != HCF_OPENSSL_SUCCESS) {
207             HcfPrintOpensslError();
208             LOGD("[error] EVP_DigestSignUpdate failed.");
209             return HCF_ERR_CRYPTO_OPERATION;
210         }
211         impl->status = READY;
212     }
213     if (impl->status != READY) {
214         LOGE("The message has not been transferred.");
215         return HCF_INVALID_PARAMS;
216     }
217     size_t maxLen;
218     if (OpensslEvpDigestSignFinal(impl->ctx, NULL, &maxLen) != HCF_OPENSSL_SUCCESS) {
219         HcfPrintOpensslError();
220         LOGD("[error] EVP_DigestSignFinal failed.");
221         return HCF_ERR_CRYPTO_OPERATION;
222     }
223     uint8_t *outData = (uint8_t *)HcfMalloc(maxLen, 0);
224     if (outData == NULL) {
225         LOGE("Failed to allocate outData memory!");
226         return HCF_ERR_MALLOC;
227     }
228 
229     if (OpensslEvpDigestSignFinal(impl->ctx, outData, &maxLen) != HCF_OPENSSL_SUCCESS) {
230         HcfPrintOpensslError();
231         LOGD("[error] EVP_DigestSignFinal failed.");
232         HcfFree(outData);
233         return HCF_ERR_CRYPTO_OPERATION;
234     }
235 
236     returnSignatureData->data = outData;
237     returnSignatureData->len = (uint32_t)maxLen;
238     return HCF_SUCCESS;
239 }
240 
EngineVerifyInit(HcfVerifySpi * self,HcfParamsSpec * params,HcfPubKey * publicKey)241 static HcfResult EngineVerifyInit(HcfVerifySpi *self, HcfParamsSpec *params, HcfPubKey *publicKey)
242 {
243     (void)params;
244     if ((self == NULL) || (publicKey == NULL)) {
245         LOGE("Invalid input parameter.");
246         return HCF_INVALID_PARAMS;
247     }
248     if ((!HcfIsClassMatch((HcfObjectBase *)self, GetEcdsaVerifyClass())) ||
249         (!HcfIsClassMatch((HcfObjectBase *)publicKey, HCF_OPENSSL_ECC_PUB_KEY_CLASS))) {
250         LOGE("Class not match.");
251         return HCF_INVALID_PARAMS;
252     }
253 
254     HcfVerifySpiEcdsaOpensslImpl *impl = (HcfVerifySpiEcdsaOpensslImpl *)self;
255     if (impl->status != UNINITIALIZED) {
256         LOGE("Repeated initialization is not allowed.");
257         return HCF_INVALID_PARAMS;
258     }
259     EC_KEY *ecKey = OpensslEcKeyDup(((HcfOpensslEccPubKey *)publicKey)->ecKey);
260     if (ecKey == NULL) {
261         HcfPrintOpensslError();
262         LOGD("[error] Dup ecKey failed.");
263         return HCF_ERR_CRYPTO_OPERATION;
264     }
265     EVP_PKEY *pKey = OpensslEvpPkeyNew();
266     if (pKey == NULL) {
267         HcfPrintOpensslError();
268         LOGD("[error] New pKey failed.");
269         OpensslEcKeyFree(ecKey);
270         return HCF_ERR_CRYPTO_OPERATION;
271     }
272     if (OpensslEvpPkeyAssignEcKey(pKey, ecKey) != HCF_OPENSSL_SUCCESS) {
273         HcfPrintOpensslError();
274         LOGD("[error] EVP_PKEY_assign_EC_KEY failed.");
275         OpensslEcKeyFree(ecKey);
276         OpensslEvpPkeyFree(pKey);
277         return HCF_ERR_CRYPTO_OPERATION;
278     }
279     if (OpensslEvpDigestVerifyInit(impl->ctx, NULL, impl->digestAlg, NULL, pKey) != HCF_OPENSSL_SUCCESS) {
280         HcfPrintOpensslError();
281         LOGD("[error] EVP_DigestVerifyInit failed.");
282         OpensslEvpPkeyFree(pKey);
283         return HCF_ERR_CRYPTO_OPERATION;
284     }
285     OpensslEvpPkeyFree(pKey);
286     impl->status = INITIALIZED;
287     return HCF_SUCCESS;
288 }
289 
EngineVerifyUpdate(HcfVerifySpi * self,HcfBlob * data)290 static HcfResult EngineVerifyUpdate(HcfVerifySpi *self, HcfBlob *data)
291 {
292     if ((self == NULL) || (!HcfIsBlobValid(data))) {
293         LOGE("Invalid input parameter.");
294         return HCF_INVALID_PARAMS;
295     }
296     if (!HcfIsClassMatch((HcfObjectBase *)self, GetEcdsaVerifyClass())) {
297         LOGE("Class not match.");
298         return HCF_INVALID_PARAMS;
299     }
300 
301     HcfVerifySpiEcdsaOpensslImpl *impl = (HcfVerifySpiEcdsaOpensslImpl *)self;
302     if (impl->status == UNINITIALIZED) {
303         LOGE("Verify object has not been initialized.");
304         return HCF_INVALID_PARAMS;
305     }
306     if (OpensslEvpDigestVerifyUpdate(impl->ctx, data->data, data->len) != HCF_OPENSSL_SUCCESS) {
307         HcfPrintOpensslError();
308         LOGD("[error] EVP_DigestVerifyUpdate failed.");
309         return HCF_ERR_CRYPTO_OPERATION;
310     }
311     impl->status = READY;
312     return HCF_SUCCESS;
313 }
314 
EngineVerifyDoFinal(HcfVerifySpi * self,HcfBlob * data,HcfBlob * signatureData)315 static bool EngineVerifyDoFinal(HcfVerifySpi *self, HcfBlob *data, HcfBlob *signatureData)
316 {
317     if ((self == NULL) || (!HcfIsBlobValid(signatureData))) {
318         LOGE("Invalid input parameter.");
319         return false;
320     }
321     if (!HcfIsClassMatch((HcfObjectBase *)self, GetEcdsaVerifyClass())) {
322         LOGE("Class not match.");
323         return false;
324     }
325 
326     HcfVerifySpiEcdsaOpensslImpl *impl = (HcfVerifySpiEcdsaOpensslImpl *)self;
327     if (HcfIsBlobValid(data)) {
328         if (OpensslEvpDigestVerifyUpdate(impl->ctx, data->data, data->len) != HCF_OPENSSL_SUCCESS) {
329             HcfPrintOpensslError();
330             LOGD("[error] EVP_DigestVerifyUpdate failed.");
331             return false;
332         }
333         impl->status = READY;
334     }
335     if (impl->status != READY) {
336         LOGE("The message has not been transferred.");
337         return false;
338     }
339     if (OpensslEvpDigestVerifyFinal(impl->ctx, signatureData->data, signatureData->len) != HCF_OPENSSL_SUCCESS) {
340         HcfPrintOpensslError();
341         LOGD("[error] EVP_DigestVerifyFinal failed.");
342         return false;
343     }
344     return true;
345 }
346 
EngineSetSignEcdsaSpecInt(HcfSignSpi * self,SignSpecItem item,int32_t saltLen)347 static HcfResult EngineSetSignEcdsaSpecInt(HcfSignSpi *self, SignSpecItem item, int32_t saltLen)
348 {
349     (void)self;
350     (void)item;
351     (void)saltLen;
352     return HCF_NOT_SUPPORT;
353 }
354 
EngineSetVerifyEcdsaSpecInt(HcfVerifySpi * self,SignSpecItem item,int32_t saltLen)355 static HcfResult EngineSetVerifyEcdsaSpecInt(HcfVerifySpi *self, SignSpecItem item, int32_t saltLen)
356 {
357     (void)self;
358     (void)item;
359     (void)saltLen;
360     return HCF_NOT_SUPPORT;
361 }
362 
EngineGetSignEcdsaSpecInt(HcfSignSpi * self,SignSpecItem item,int32_t * returnInt)363 static HcfResult EngineGetSignEcdsaSpecInt(HcfSignSpi *self, SignSpecItem item, int32_t *returnInt)
364 {
365     (void)self;
366     (void)item;
367     (void)returnInt;
368     return HCF_NOT_SUPPORT;
369 }
370 
EngineGetVerifyEcdsaSpecInt(HcfVerifySpi * self,SignSpecItem item,int32_t * returnInt)371 static HcfResult EngineGetVerifyEcdsaSpecInt(HcfVerifySpi *self, SignSpecItem item, int32_t *returnInt)
372 {
373     (void)self;
374     (void)item;
375     (void)returnInt;
376     return HCF_NOT_SUPPORT;
377 }
378 
EngineGetSignEcdsaSpecString(HcfSignSpi * self,SignSpecItem item,char ** returnString)379 static HcfResult EngineGetSignEcdsaSpecString(HcfSignSpi *self, SignSpecItem item, char **returnString)
380 {
381     (void)self;
382     (void)item;
383     (void)returnString;
384     return HCF_NOT_SUPPORT;
385 }
386 
EngineSetSignEcdsaSpecUint8Array(HcfSignSpi * self,SignSpecItem item,HcfBlob blob)387 static HcfResult EngineSetSignEcdsaSpecUint8Array(HcfSignSpi *self, SignSpecItem item, HcfBlob blob)
388 {
389     (void)self;
390     (void)item;
391     (void)blob;
392     return HCF_NOT_SUPPORT;
393 }
394 
EngineGetVerifyEcdsaSpecString(HcfVerifySpi * self,SignSpecItem item,char ** returnString)395 static HcfResult EngineGetVerifyEcdsaSpecString(HcfVerifySpi *self, SignSpecItem item, char **returnString)
396 {
397     (void)self;
398     (void)item;
399     (void)returnString;
400     return HCF_NOT_SUPPORT;
401 }
402 
EngineSetVerifyEcdsaSpecUint8Array(HcfVerifySpi * self,SignSpecItem item,HcfBlob blob)403 static HcfResult EngineSetVerifyEcdsaSpecUint8Array(HcfVerifySpi *self, SignSpecItem item, HcfBlob blob)
404 {
405     (void)self;
406     (void)item;
407     (void)blob;
408     return HCF_NOT_SUPPORT;
409 }
410 
HcfSignSpiEcdsaCreate(HcfSignatureParams * params,HcfSignSpi ** returnObj)411 HcfResult HcfSignSpiEcdsaCreate(HcfSignatureParams *params, HcfSignSpi **returnObj)
412 {
413     if ((params == NULL) || (returnObj == NULL)) {
414         LOGE("Invalid input parameter.");
415         return HCF_INVALID_PARAMS;
416     }
417     if (params->algo == HCF_ALG_ECC_BRAINPOOL) {
418         if (!IsBrainPoolDigestAlgValid(params->md)) {
419             LOGE("Invalid md.");
420             return HCF_INVALID_PARAMS;
421         }
422     } else {
423         if (!IsDigestAlgValid(params->md)) {
424             LOGE("Invalid md.");
425             return HCF_INVALID_PARAMS;
426         }
427     }
428     EVP_MD *opensslAlg = NULL;
429     int32_t ret = GetOpensslDigestAlg(params->md, &opensslAlg);
430     if (ret != HCF_SUCCESS || opensslAlg == NULL) {
431         LOGE("Failed to Invalid digest!");
432         return HCF_INVALID_PARAMS;
433     }
434 
435     HcfSignSpiEcdsaOpensslImpl *returnImpl = (HcfSignSpiEcdsaOpensslImpl *)HcfMalloc(
436         sizeof(HcfSignSpiEcdsaOpensslImpl), 0);
437     if (returnImpl == NULL) {
438         LOGE("Failed to allocate returnImpl memroy!");
439         return HCF_ERR_MALLOC;
440     }
441     returnImpl->base.base.getClass = GetEcdsaSignClass;
442     returnImpl->base.base.destroy = DestroyEcdsaSign;
443     returnImpl->base.engineInit = EngineSignInit;
444     returnImpl->base.engineUpdate = EngineSignUpdate;
445     returnImpl->base.engineSign = EngineSignDoFinal;
446     returnImpl->base.engineSetSignSpecInt = EngineSetSignEcdsaSpecInt;
447     returnImpl->base.engineGetSignSpecInt = EngineGetSignEcdsaSpecInt;
448     returnImpl->base.engineGetSignSpecString = EngineGetSignEcdsaSpecString;
449     returnImpl->base.engineSetSignSpecUint8Array = EngineSetSignEcdsaSpecUint8Array;
450     returnImpl->digestAlg = opensslAlg;
451     returnImpl->status = UNINITIALIZED;
452     returnImpl->ctx = OpensslEvpMdCtxNew();
453     if (returnImpl->ctx == NULL) {
454         LOGE("Failed to allocate ctx memory!");
455         HcfFree(returnImpl);
456         return HCF_ERR_MALLOC;
457     }
458 
459     *returnObj = (HcfSignSpi *)returnImpl;
460     return HCF_SUCCESS;
461 }
462 
HcfVerifySpiEcdsaCreate(HcfSignatureParams * params,HcfVerifySpi ** returnObj)463 HcfResult HcfVerifySpiEcdsaCreate(HcfSignatureParams *params, HcfVerifySpi **returnObj)
464 {
465     if ((params == NULL) || (returnObj == NULL)) {
466         LOGE("Invalid input parameter.");
467         return HCF_INVALID_PARAMS;
468     }
469     if (params->algo == HCF_ALG_ECC_BRAINPOOL) {
470         if (!IsBrainPoolDigestAlgValid(params->md)) {
471             LOGE("Invalid md.");
472             return HCF_INVALID_PARAMS;
473         }
474     } else {
475         if (!IsDigestAlgValid(params->md)) {
476             LOGE("Invalid md.");
477             return HCF_INVALID_PARAMS;
478         }
479     }
480     EVP_MD *opensslAlg = NULL;
481     int32_t ret = GetOpensslDigestAlg(params->md, &opensslAlg);
482     if (ret != HCF_SUCCESS || opensslAlg == NULL) {
483         LOGE("Failed to Invalid digest!");
484         return HCF_INVALID_PARAMS;
485     }
486 
487     HcfVerifySpiEcdsaOpensslImpl *returnImpl = (HcfVerifySpiEcdsaOpensslImpl *)HcfMalloc(
488         sizeof(HcfVerifySpiEcdsaOpensslImpl), 0);
489     if (returnImpl == NULL) {
490         LOGE("Failed to allocate returnImpl memroy!");
491         return HCF_ERR_MALLOC;
492     }
493     returnImpl->base.base.getClass = GetEcdsaVerifyClass;
494     returnImpl->base.base.destroy = DestroyEcdsaVerify;
495     returnImpl->base.engineInit = EngineVerifyInit;
496     returnImpl->base.engineUpdate = EngineVerifyUpdate;
497     returnImpl->base.engineVerify = EngineVerifyDoFinal;
498     returnImpl->base.engineSetVerifySpecInt = EngineSetVerifyEcdsaSpecInt;
499     returnImpl->base.engineGetVerifySpecInt = EngineGetVerifyEcdsaSpecInt;
500     returnImpl->base.engineGetVerifySpecString = EngineGetVerifyEcdsaSpecString;
501     returnImpl->base.engineSetVerifySpecUint8Array = EngineSetVerifyEcdsaSpecUint8Array;
502     returnImpl->digestAlg = opensslAlg;
503     returnImpl->status = UNINITIALIZED;
504     returnImpl->ctx = OpensslEvpMdCtxNew();
505     if (returnImpl->ctx == NULL) {
506         LOGE("Failed to allocate ctx memory!");
507         HcfFree(returnImpl);
508         return HCF_ERR_MALLOC;
509     }
510 
511     *returnObj = (HcfVerifySpi *)returnImpl;
512     return HCF_SUCCESS;
513 }
514