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