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 %{public}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 %{public}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 outData = NULL;
234 return HCF_ERR_CRYPTO_OPERATION;
235 }
236
237 returnSignatureData->data = outData;
238 returnSignatureData->len = (uint32_t)maxLen;
239 return HCF_SUCCESS;
240 }
241
EngineVerifyInit(HcfVerifySpi * self,HcfParamsSpec * params,HcfPubKey * publicKey)242 static HcfResult EngineVerifyInit(HcfVerifySpi *self, HcfParamsSpec *params, HcfPubKey *publicKey)
243 {
244 (void)params;
245 if ((self == NULL) || (publicKey == NULL)) {
246 LOGE("Invalid input parameter.");
247 return HCF_INVALID_PARAMS;
248 }
249 if ((!HcfIsClassMatch((HcfObjectBase *)self, GetEcdsaVerifyClass())) ||
250 (!HcfIsClassMatch((HcfObjectBase *)publicKey, HCF_OPENSSL_ECC_PUB_KEY_CLASS))) {
251 LOGE("Class not match.");
252 return HCF_INVALID_PARAMS;
253 }
254
255 HcfVerifySpiEcdsaOpensslImpl *impl = (HcfVerifySpiEcdsaOpensslImpl *)self;
256 if (impl->status != UNINITIALIZED) {
257 LOGE("Repeated initialization is not allowed.");
258 return HCF_INVALID_PARAMS;
259 }
260 EC_KEY *ecKey = OpensslEcKeyDup(((HcfOpensslEccPubKey *)publicKey)->ecKey);
261 if (ecKey == NULL) {
262 HcfPrintOpensslError();
263 LOGD("[error] Dup ecKey failed.");
264 return HCF_ERR_CRYPTO_OPERATION;
265 }
266 EVP_PKEY *pKey = OpensslEvpPkeyNew();
267 if (pKey == NULL) {
268 HcfPrintOpensslError();
269 LOGD("[error] New pKey failed.");
270 OpensslEcKeyFree(ecKey);
271 return HCF_ERR_CRYPTO_OPERATION;
272 }
273 if (OpensslEvpPkeyAssignEcKey(pKey, ecKey) != HCF_OPENSSL_SUCCESS) {
274 HcfPrintOpensslError();
275 LOGD("[error] EVP_PKEY_assign_EC_KEY failed.");
276 OpensslEcKeyFree(ecKey);
277 OpensslEvpPkeyFree(pKey);
278 return HCF_ERR_CRYPTO_OPERATION;
279 }
280 if (OpensslEvpDigestVerifyInit(impl->ctx, NULL, impl->digestAlg, NULL, pKey) != HCF_OPENSSL_SUCCESS) {
281 HcfPrintOpensslError();
282 LOGD("[error] EVP_DigestVerifyInit failed.");
283 OpensslEvpPkeyFree(pKey);
284 return HCF_ERR_CRYPTO_OPERATION;
285 }
286 OpensslEvpPkeyFree(pKey);
287 impl->status = INITIALIZED;
288 return HCF_SUCCESS;
289 }
290
EngineVerifyUpdate(HcfVerifySpi * self,HcfBlob * data)291 static HcfResult EngineVerifyUpdate(HcfVerifySpi *self, HcfBlob *data)
292 {
293 if ((self == NULL) || (!HcfIsBlobValid(data))) {
294 LOGE("Invalid input parameter.");
295 return HCF_INVALID_PARAMS;
296 }
297 if (!HcfIsClassMatch((HcfObjectBase *)self, GetEcdsaVerifyClass())) {
298 LOGE("Class not match.");
299 return HCF_INVALID_PARAMS;
300 }
301
302 HcfVerifySpiEcdsaOpensslImpl *impl = (HcfVerifySpiEcdsaOpensslImpl *)self;
303 if (impl->status == UNINITIALIZED) {
304 LOGE("Verify object has not been initialized.");
305 return HCF_INVALID_PARAMS;
306 }
307 if (OpensslEvpDigestVerifyUpdate(impl->ctx, data->data, data->len) != HCF_OPENSSL_SUCCESS) {
308 HcfPrintOpensslError();
309 LOGD("[error] EVP_DigestVerifyUpdate failed.");
310 return HCF_ERR_CRYPTO_OPERATION;
311 }
312 impl->status = READY;
313 return HCF_SUCCESS;
314 }
315
EngineVerifyDoFinal(HcfVerifySpi * self,HcfBlob * data,HcfBlob * signatureData)316 static bool EngineVerifyDoFinal(HcfVerifySpi *self, HcfBlob *data, HcfBlob *signatureData)
317 {
318 if ((self == NULL) || (!HcfIsBlobValid(signatureData))) {
319 LOGE("Invalid input parameter.");
320 return false;
321 }
322 if (!HcfIsClassMatch((HcfObjectBase *)self, GetEcdsaVerifyClass())) {
323 LOGE("Class not match.");
324 return false;
325 }
326
327 HcfVerifySpiEcdsaOpensslImpl *impl = (HcfVerifySpiEcdsaOpensslImpl *)self;
328 if (HcfIsBlobValid(data)) {
329 if (OpensslEvpDigestVerifyUpdate(impl->ctx, data->data, data->len) != HCF_OPENSSL_SUCCESS) {
330 HcfPrintOpensslError();
331 LOGD("[error] EVP_DigestVerifyUpdate failed.");
332 return false;
333 }
334 impl->status = READY;
335 }
336 if (impl->status != READY) {
337 LOGE("The message has not been transferred.");
338 return false;
339 }
340 if (OpensslEvpDigestVerifyFinal(impl->ctx, signatureData->data, signatureData->len) != HCF_OPENSSL_SUCCESS) {
341 HcfPrintOpensslError();
342 LOGD("[error] EVP_DigestVerifyFinal failed.");
343 return false;
344 }
345 return true;
346 }
347
EngineSetSignEcdsaSpecInt(HcfSignSpi * self,SignSpecItem item,int32_t saltLen)348 static HcfResult EngineSetSignEcdsaSpecInt(HcfSignSpi *self, SignSpecItem item, int32_t saltLen)
349 {
350 (void)self;
351 (void)item;
352 (void)saltLen;
353 return HCF_NOT_SUPPORT;
354 }
355
EngineSetVerifyEcdsaSpecInt(HcfVerifySpi * self,SignSpecItem item,int32_t saltLen)356 static HcfResult EngineSetVerifyEcdsaSpecInt(HcfVerifySpi *self, SignSpecItem item, int32_t saltLen)
357 {
358 (void)self;
359 (void)item;
360 (void)saltLen;
361 return HCF_NOT_SUPPORT;
362 }
363
EngineGetSignEcdsaSpecInt(HcfSignSpi * self,SignSpecItem item,int32_t * returnInt)364 static HcfResult EngineGetSignEcdsaSpecInt(HcfSignSpi *self, SignSpecItem item, int32_t *returnInt)
365 {
366 (void)self;
367 (void)item;
368 (void)returnInt;
369 return HCF_NOT_SUPPORT;
370 }
371
EngineGetVerifyEcdsaSpecInt(HcfVerifySpi * self,SignSpecItem item,int32_t * returnInt)372 static HcfResult EngineGetVerifyEcdsaSpecInt(HcfVerifySpi *self, SignSpecItem item, int32_t *returnInt)
373 {
374 (void)self;
375 (void)item;
376 (void)returnInt;
377 return HCF_NOT_SUPPORT;
378 }
379
EngineGetSignEcdsaSpecString(HcfSignSpi * self,SignSpecItem item,char ** returnString)380 static HcfResult EngineGetSignEcdsaSpecString(HcfSignSpi *self, SignSpecItem item, char **returnString)
381 {
382 (void)self;
383 (void)item;
384 (void)returnString;
385 return HCF_NOT_SUPPORT;
386 }
387
EngineSetSignEcdsaSpecUint8Array(HcfSignSpi * self,SignSpecItem item,HcfBlob blob)388 static HcfResult EngineSetSignEcdsaSpecUint8Array(HcfSignSpi *self, SignSpecItem item, HcfBlob blob)
389 {
390 (void)self;
391 (void)item;
392 (void)blob;
393 return HCF_NOT_SUPPORT;
394 }
395
EngineGetVerifyEcdsaSpecString(HcfVerifySpi * self,SignSpecItem item,char ** returnString)396 static HcfResult EngineGetVerifyEcdsaSpecString(HcfVerifySpi *self, SignSpecItem item, char **returnString)
397 {
398 (void)self;
399 (void)item;
400 (void)returnString;
401 return HCF_NOT_SUPPORT;
402 }
403
EngineSetVerifyEcdsaSpecUint8Array(HcfVerifySpi * self,SignSpecItem item,HcfBlob blob)404 static HcfResult EngineSetVerifyEcdsaSpecUint8Array(HcfVerifySpi *self, SignSpecItem item, HcfBlob blob)
405 {
406 (void)self;
407 (void)item;
408 (void)blob;
409 return HCF_NOT_SUPPORT;
410 }
411
HcfSignSpiEcdsaCreate(HcfSignatureParams * params,HcfSignSpi ** returnObj)412 HcfResult HcfSignSpiEcdsaCreate(HcfSignatureParams *params, HcfSignSpi **returnObj)
413 {
414 if ((params == NULL) || (returnObj == NULL)) {
415 LOGE("Invalid input parameter.");
416 return HCF_INVALID_PARAMS;
417 }
418 if (params->algo == HCF_ALG_ECC_BRAINPOOL) {
419 if (!IsBrainPoolDigestAlgValid(params->md)) {
420 LOGE("Invalid md.");
421 return HCF_INVALID_PARAMS;
422 }
423 } else {
424 if (!IsDigestAlgValid(params->md)) {
425 LOGE("Invalid md.");
426 return HCF_INVALID_PARAMS;
427 }
428 }
429 EVP_MD *opensslAlg = NULL;
430 int32_t ret = GetOpensslDigestAlg(params->md, &opensslAlg);
431 if (ret != HCF_SUCCESS || opensslAlg == NULL) {
432 LOGE("Failed to Invalid digest!");
433 return HCF_INVALID_PARAMS;
434 }
435
436 HcfSignSpiEcdsaOpensslImpl *returnImpl = (HcfSignSpiEcdsaOpensslImpl *)HcfMalloc(
437 sizeof(HcfSignSpiEcdsaOpensslImpl), 0);
438 if (returnImpl == NULL) {
439 LOGE("Failed to allocate returnImpl memroy!");
440 return HCF_ERR_MALLOC;
441 }
442 returnImpl->base.base.getClass = GetEcdsaSignClass;
443 returnImpl->base.base.destroy = DestroyEcdsaSign;
444 returnImpl->base.engineInit = EngineSignInit;
445 returnImpl->base.engineUpdate = EngineSignUpdate;
446 returnImpl->base.engineSign = EngineSignDoFinal;
447 returnImpl->base.engineSetSignSpecInt = EngineSetSignEcdsaSpecInt;
448 returnImpl->base.engineGetSignSpecInt = EngineGetSignEcdsaSpecInt;
449 returnImpl->base.engineGetSignSpecString = EngineGetSignEcdsaSpecString;
450 returnImpl->base.engineSetSignSpecUint8Array = EngineSetSignEcdsaSpecUint8Array;
451 returnImpl->digestAlg = opensslAlg;
452 returnImpl->status = UNINITIALIZED;
453 returnImpl->ctx = OpensslEvpMdCtxNew();
454 if (returnImpl->ctx == NULL) {
455 LOGE("Failed to allocate ctx memory!");
456 HcfFree(returnImpl);
457 returnImpl = NULL;
458 return HCF_ERR_MALLOC;
459 }
460
461 *returnObj = (HcfSignSpi *)returnImpl;
462 return HCF_SUCCESS;
463 }
464
HcfVerifySpiEcdsaCreate(HcfSignatureParams * params,HcfVerifySpi ** returnObj)465 HcfResult HcfVerifySpiEcdsaCreate(HcfSignatureParams *params, HcfVerifySpi **returnObj)
466 {
467 if ((params == NULL) || (returnObj == NULL)) {
468 LOGE("Invalid input parameter.");
469 return HCF_INVALID_PARAMS;
470 }
471 if (params->algo == HCF_ALG_ECC_BRAINPOOL) {
472 if (!IsBrainPoolDigestAlgValid(params->md)) {
473 LOGE("Invalid md.");
474 return HCF_INVALID_PARAMS;
475 }
476 } else {
477 if (!IsDigestAlgValid(params->md)) {
478 LOGE("Invalid md.");
479 return HCF_INVALID_PARAMS;
480 }
481 }
482 EVP_MD *opensslAlg = NULL;
483 int32_t ret = GetOpensslDigestAlg(params->md, &opensslAlg);
484 if (ret != HCF_SUCCESS || opensslAlg == NULL) {
485 LOGE("Failed to Invalid digest!");
486 return HCF_INVALID_PARAMS;
487 }
488
489 HcfVerifySpiEcdsaOpensslImpl *returnImpl = (HcfVerifySpiEcdsaOpensslImpl *)HcfMalloc(
490 sizeof(HcfVerifySpiEcdsaOpensslImpl), 0);
491 if (returnImpl == NULL) {
492 LOGE("Failed to allocate returnImpl memroy!");
493 return HCF_ERR_MALLOC;
494 }
495 returnImpl->base.base.getClass = GetEcdsaVerifyClass;
496 returnImpl->base.base.destroy = DestroyEcdsaVerify;
497 returnImpl->base.engineInit = EngineVerifyInit;
498 returnImpl->base.engineUpdate = EngineVerifyUpdate;
499 returnImpl->base.engineVerify = EngineVerifyDoFinal;
500 returnImpl->base.engineSetVerifySpecInt = EngineSetVerifyEcdsaSpecInt;
501 returnImpl->base.engineGetVerifySpecInt = EngineGetVerifyEcdsaSpecInt;
502 returnImpl->base.engineGetVerifySpecString = EngineGetVerifyEcdsaSpecString;
503 returnImpl->base.engineSetVerifySpecUint8Array = EngineSetVerifyEcdsaSpecUint8Array;
504 returnImpl->digestAlg = opensslAlg;
505 returnImpl->status = UNINITIALIZED;
506 returnImpl->ctx = OpensslEvpMdCtxNew();
507 if (returnImpl->ctx == NULL) {
508 LOGE("Failed to allocate ctx memory!");
509 HcfFree(returnImpl);
510 returnImpl = NULL;
511 return HCF_ERR_MALLOC;
512 }
513
514 *returnObj = (HcfVerifySpi *)returnImpl;
515 return HCF_SUCCESS;
516 }
517