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
16 #include <gtest/gtest.h>
17
18 #include "cf_api.h"
19 #include "cf_param.h"
20 #include "cf_result.h"
21 #include "cf_type.h"
22
23 #include "cf_test_common.h"
24 #include "cf_test_data.h"
25 #include "cf_test_sdk_common.h"
26
27 using namespace testing::ext;
28 using namespace CertframeworkTestData;
29 using namespace CertframeworkTest;
30 using namespace CertframeworkSdkTest;
31
32 namespace {
33 constexpr int32_t DER_FORMAT_INDEX = 0;
34 constexpr int32_t PEM_FORMAT_INDEX = 1;
35 class CfCertTest : public testing::Test {
36 public:
37 static void SetUpTestCase(void);
38
39 static void TearDownTestCase(void);
40
41 void SetUp();
42
43 void TearDown();
44 };
45
SetUpTestCase(void)46 void CfCertTest::SetUpTestCase(void)
47 {
48 }
49
TearDownTestCase(void)50 void CfCertTest::TearDownTestCase(void)
51 {
52 }
53
SetUp()54 void CfCertTest::SetUp()
55 {
56 }
57
TearDown()58 void CfCertTest::TearDown()
59 {
60 }
61
62 const static CfEncodingBlob g_cert[] = {
63 { const_cast<uint8_t *>(g_certData01), sizeof(g_certData01), CF_FORMAT_DER },
64 { reinterpret_cast<uint8_t *>(g_certData02), sizeof(g_certData02), CF_FORMAT_PEM }
65 };
66
67 const static CfBlob g_certTbs = { sizeof(g_certData01TBS), const_cast<uint8_t *>(g_certData01TBS) };
68 const static CfBlob g_certPemTbs = { sizeof(g_certData02TBS), const_cast<uint8_t *>(g_certData02TBS) };
69 const static CfBlob g_certIssueUid = { sizeof(g_certData01IssuerUID), const_cast<uint8_t *>(g_certData01IssuerUID) };
70 const static CfBlob g_certSubUid = { sizeof(g_certData01SubjectUID), const_cast<uint8_t *>(g_certData01SubjectUID) };
71 const static CfBlob g_certExt = { sizeof(g_extensionData01), const_cast<uint8_t *>(g_extensionData01) };
72 const static CfBlob g_certPubKey = { sizeof(g_certData01PubKey), const_cast<uint8_t *>(g_certData01PubKey) };
73
CompareResult(CfItemId id,const CfParamSet * out,enum CfEncodingFormat format)74 static bool CompareResult(CfItemId id, const CfParamSet *out, enum CfEncodingFormat format)
75 {
76 CfParam *resultTypeParam = NULL;
77 int32_t ret = CfGetParam(out, CF_TAG_RESULT_TYPE, &resultTypeParam);
78 if (ret != CF_SUCCESS) {
79 printf("get CF_TAG_RESULT_TYPE failed.\n");
80 return false;
81 }
82
83 if (resultTypeParam->int32Param != CF_TAG_TYPE_BYTES) {
84 printf("result type is not CF_TAG_TYPE_BYTES.\n");
85 return false;
86 }
87
88 CfParam *resultParam = NULL;
89 ret = CfGetParam(out, CF_TAG_RESULT_BYTES, &resultParam);
90 if (ret != CF_SUCCESS) {
91 printf("get CF_TAG_RESULT_BYTES from out failed.\n");
92 return false;
93 }
94
95 switch (id) {
96 case CF_ITEM_TBS:
97 if (format == CF_FORMAT_DER) {
98 return CompareBlob(&resultParam->blob, &g_certTbs);
99 }
100 return CompareBlob(&resultParam->blob, &g_certPemTbs);
101 case CF_ITEM_ISSUER_UNIQUE_ID:
102 return CompareBlob(&resultParam->blob, &g_certIssueUid);
103 case CF_ITEM_SUBJECT_UNIQUE_ID:
104 return CompareBlob(&resultParam->blob, &g_certSubUid);
105 case CF_ITEM_EXTENSIONS:
106 return CompareBlob(&resultParam->blob, &g_certExt);
107 case CF_ITEM_PUBLIC_KEY:
108 return CompareBlob(&resultParam->blob, &g_certPubKey);
109 default:
110 return false;
111 }
112 }
113
CertTest(CfItemId id,const CfEncodingBlob * in)114 static void CertTest(CfItemId id, const CfEncodingBlob *in)
115 {
116 CfParamSet *outParamSet = nullptr;
117 CfParam params[] = {
118 { .tag = CF_TAG_GET_TYPE, .int32Param = CF_GET_TYPE_CERT_ITEM },
119 { .tag = CF_TAG_PARAM0_INT32, .int32Param = id },
120 };
121 int32_t ret = CommonTest(CF_OBJ_TYPE_CERT, in, params, sizeof(params) / sizeof(CfParam), &outParamSet);
122 EXPECT_EQ(ret, CF_SUCCESS);
123 #ifdef TEST_PRINT_DATA
124 (void)GetOutValue(outParamSet);
125 #endif
126 EXPECT_EQ(CompareResult(id, outParamSet, in->encodingFormat), true);
127 CfFreeParamSet(&outParamSet);
128 }
129
130 /**
131 * @tc.name: CfCertTest001
132 * @tc.desc: get tbs
133 * @tc.type: FUNC
134 * @tc.require: AR000HS2RB /SR000HS2Q1
135 */
136 HWTEST_F(CfCertTest, CfCertTest001, TestSize.Level0)
137 {
138 CertTest(CF_ITEM_TBS, &g_cert[DER_FORMAT_INDEX]);
139 }
140
141 /**
142 * @tc.name: CfCertTest002
143 * @tc.desc: get issuer unique id
144 * @tc.type: FUNC
145 * @tc.require: AR000HS2RB /SR000HS2Q1
146 */
147 HWTEST_F(CfCertTest, CfCertTest002, TestSize.Level0)
148 {
149 CertTest(CF_ITEM_ISSUER_UNIQUE_ID, &g_cert[DER_FORMAT_INDEX]);
150 }
151
152 /**
153 * @tc.name: CfCertTest003
154 * @tc.desc: get subject unique id
155 * @tc.type: FUNC
156 * @tc.require: AR000HS2RB /SR000HS2Q1
157 */
158 HWTEST_F(CfCertTest, CfCertTest003, TestSize.Level0)
159 {
160 CertTest(CF_ITEM_SUBJECT_UNIQUE_ID, &g_cert[DER_FORMAT_INDEX]);
161 }
162
163 /**
164 * @tc.name: CfCertTest004
165 * @tc.desc: get public key in der format
166 * @tc.type: FUNC
167 * @tc.require: AR000HS2RB /SR000HS2Q1
168 */
169 HWTEST_F(CfCertTest, CfCertTest004, TestSize.Level0)
170 {
171 CertTest(CF_ITEM_PUBLIC_KEY, &g_cert[DER_FORMAT_INDEX]);
172 }
173
174 /**
175 * @tc.name: CfCertTest005
176 * @tc.desc: get extension
177 * @tc.type: FUNC
178 * @tc.require: AR000HS2RB /SR000HS2Q1
179 */
180 HWTEST_F(CfCertTest, CfCertTest005, TestSize.Level0)
181 {
182 CertTest(CF_ITEM_EXTENSIONS, &g_cert[DER_FORMAT_INDEX]);
183 }
184
185 /**
186 * @tc.name: CfCertTest006
187 * @tc.desc: check func
188 * @tc.type: FUNC
189 * @tc.require: AR000HS2RB /SR000HS2Q1
190 */
191 HWTEST_F(CfCertTest, CfCertTest006, TestSize.Level0)
192 {
193 CfParamSet *outParamSet = nullptr;
194 CfParam params[] = {
195 { .tag = CF_TAG_CHECK_TYPE, .int32Param = 0 }, /* reserve test */
196 };
197 int32_t ret = CommonTest(CF_OBJ_TYPE_CERT, &g_cert[0], params, sizeof(params) / sizeof(CfParam), &outParamSet);
198 EXPECT_EQ(ret, CF_SUCCESS);
199 CfFreeParamSet(&outParamSet);
200 }
201
202 /**
203 * @tc.name: CfCertTest007
204 * @tc.desc: create object
205 * @tc.type: FUNC
206 * @tc.require: AR000HS2RB /SR000HS2Q1
207 */
208 HWTEST_F(CfCertTest, CfCertTest007, TestSize.Level0)
209 {
210 CfObject *object = nullptr;
211 int32_t ret = CfCreate(CF_OBJ_TYPE_CERT, &g_cert[0], &object);
212 ASSERT_EQ(ret, CF_SUCCESS);
213
214 object->destroy(&object);
215 }
216
217 /**
218 * @tc.name: CfCertTest008
219 * @tc.desc: pem format, get tbs
220 * @tc.type: FUNC
221 * @tc.require: AR000HS2RB /SR000HS2Q1
222 */
223 HWTEST_F(CfCertTest, CfCertTest008, TestSize.Level0)
224 {
225 CertTest(CF_ITEM_TBS, &g_cert[PEM_FORMAT_INDEX]);
226 }
227
228 /**
229 * @tc.name: CfCertTest009
230 * @tc.desc: CfCreate: in is nullptr
231 * @tc.type: FUNC
232 * @tc.require: AR000HS2RB /SR000HS2Q1
233 */
234 HWTEST_F(CfCertTest, CfCertTest009, TestSize.Level0)
235 {
236 CfObject *object = nullptr;
237 int32_t ret = CfCreate(CF_OBJ_TYPE_CERT, nullptr, &object); /* in is nullptr */
238 EXPECT_NE(ret, CF_SUCCESS);
239 }
240
241 /**
242 * @tc.name: CfCertTest010
243 * @tc.desc: CfCreate: object is nullptr
244 * @tc.type: FUNC
245 * @tc.require: AR000HS2RB /SR000HS2Q1
246 */
247 HWTEST_F(CfCertTest, CfCertTest010, TestSize.Level0)
248 {
249 int32_t ret = CfCreate(CF_OBJ_TYPE_CERT, &g_cert[DER_FORMAT_INDEX], nullptr); /* object is nullptr */
250 EXPECT_NE(ret, CF_SUCCESS);
251 }
252
253 /**
254 * @tc.name: CfCertTest011
255 * @tc.desc: CfCreate:objType is invalid
256 * @tc.type: FUNC
257 * @tc.require: AR000HS2RB /SR000HS2Q1
258 */
259 HWTEST_F(CfCertTest, CfCertTest011, TestSize.Level0)
260 {
261 CfObject *object = nullptr;
262 int32_t cfObjType = 0xff; /* objType is invalid */
263 int32_t ret = CfCreate(static_cast<CfObjectType>(cfObjType), &g_cert[DER_FORMAT_INDEX], &object);
264 EXPECT_NE(ret, CF_SUCCESS);
265 }
266
267 /**
268 * @tc.name: CfCertTest012
269 * @tc.desc: CfCreate:in's data is invalid create failed
270 * @tc.type: FUNC
271 * @tc.require: AR000HS2RB /SR000HS2Q1
272 */
273 HWTEST_F(CfCertTest, CfCertTest012, TestSize.Level0)
274 {
275 CfObject *object = nullptr;
276 uint8_t invalidData[] = { 0x30, 0x33, 0x44, 0x55, }; /* in's data is invalid create failed */
277 CfEncodingBlob cert = { invalidData, sizeof(invalidData), CF_FORMAT_DER };
278 int32_t ret = CfCreate(CF_OBJ_TYPE_CERT, &cert, &object);
279 EXPECT_NE(ret, CF_SUCCESS);
280 }
281
282 /**
283 * @tc.name: CfCertTest013
284 * @tc.desc: CfCreate:in's data is nullptr
285 * @tc.type: FUNC
286 * @tc.require: AR000HS2RB /SR000HS2Q1
287 */
288 HWTEST_F(CfCertTest, CfCertTest013, TestSize.Level0)
289 {
290 CfObject *object = nullptr;
291 uint8_t invalidData[] = { 0x30, 0x11, 0x22, 0x33, };
292 CfEncodingBlob cert = { nullptr, sizeof(invalidData), CF_FORMAT_DER }; /* in's data is nullptr */
293 int32_t ret = CfCreate(CF_OBJ_TYPE_CERT, &cert, &object);
294 EXPECT_NE(ret, CF_SUCCESS);
295 }
296
297 /**
298 * @tc.name: CfCertTest014
299 * @tc.desc: CfCreate:in's size is 0
300 * @tc.type: FUNC
301 * @tc.require: AR000HS2RB /SR000HS2Q1
302 */
303 HWTEST_F(CfCertTest, CfCertTest014, TestSize.Level0)
304 {
305 CfObject *object = nullptr;
306 uint8_t invalidData[] = { 0x30, 0x01, 0x02, 0x03, };
307 CfEncodingBlob cert = { invalidData, 0, CF_FORMAT_DER }; /* in's size is 0 */
308 int32_t ret = CfCreate(CF_OBJ_TYPE_CERT, &cert, &object);
309 EXPECT_NE(ret, CF_SUCCESS);
310 }
311
312 /**
313 * @tc.name: CfCertTest015
314 * @tc.desc: CfCreate:in's encodingFormat invalid
315 * @tc.type: FUNC
316 * @tc.require: AR000HS2RB /SR000HS2Q1
317 */
318 HWTEST_F(CfCertTest, CfCertTest015, TestSize.Level0)
319 {
320 CfObject *object = nullptr;
321 int32_t format = 0xff;
322 CfEncodingBlob cert = { reinterpret_cast<uint8_t *>(g_certData02), sizeof(g_certData02),
323 static_cast<enum CfEncodingFormat>(format) };
324 int32_t ret = CfCreate(CF_OBJ_TYPE_CERT, &cert, &object);
325 EXPECT_NE(ret, CF_SUCCESS);
326 }
327
328 /**
329 * @tc.name: CfCertTest016
330 * @tc.desc: ->destroy: object is nullptr
331 * @tc.type: FUNC
332 * @tc.require: AR000HS2RB /SR000HS2Q1
333 */
334 HWTEST_F(CfCertTest, CfCertTest016, TestSize.Level0)
335 {
336 CfObject *object = nullptr;
337 int32_t ret = CfCreate(CF_OBJ_TYPE_CERT, &g_cert[DER_FORMAT_INDEX], &object);
338 ASSERT_EQ(ret, CF_SUCCESS);
339
340 object->destroy(nullptr); /* destroy: object is nullptr coverage */
341 object->destroy(&object);
342 }
343
344 /**
345 * @tc.name: CfCertTest017
346 * @tc.desc: ->destroy: *object is nullptr
347 * @tc.type: FUNC
348 * @tc.require: AR000HS2RB /SR000HS2Q1
349 */
350 HWTEST_F(CfCertTest, CfCertTest017, TestSize.Level0)
351 {
352 CfObject *object = nullptr;
353 int32_t ret = CfCreate(CF_OBJ_TYPE_CERT, &g_cert[DER_FORMAT_INDEX], &object);
354 ASSERT_EQ(ret, CF_SUCCESS);
355
356 CfObject *object1 = nullptr;
357 object->destroy(&object1); /* destroy: *object is nullptr coverage */
358 object->destroy(&object);
359 }
360
361 /**
362 * @tc.name: CfCertTest018
363 * @tc.desc: ->get: object is nullptr
364 * @tc.type: FUNC
365 * @tc.require: AR000HS2RB /SR000HS2Q1
366 */
367 HWTEST_F(CfCertTest, CfCertTest018, TestSize.Level0)
368 {
369 CfObject *object = nullptr;
370 int32_t ret = CfCreate(CF_OBJ_TYPE_CERT, &g_cert[DER_FORMAT_INDEX], &object);
371 ASSERT_EQ(ret, CF_SUCCESS);
372
373 CfParamSet *inParamSet = nullptr;
374 EXPECT_EQ(CfInitParamSet(&inParamSet), CF_SUCCESS);
375
376 CfParamSet *outParamSet = nullptr;
377 ret = object->get(nullptr, inParamSet, &outParamSet); /* object is nullptr */
378 EXPECT_NE(ret, CF_SUCCESS);
379
380 object->destroy(&object);
381 CfFreeParamSet(&inParamSet);
382 }
383
384 /**
385 * @tc.name: CfCertTest019
386 * @tc.desc: ->get: in is nullptr
387 * @tc.type: FUNC
388 * @tc.require: AR000HS2RB /SR000HS2Q1
389 */
390 HWTEST_F(CfCertTest, CfCertTest019, TestSize.Level0)
391 {
392 CfObject *object = nullptr;
393 int32_t ret = CfCreate(CF_OBJ_TYPE_CERT, &g_cert[DER_FORMAT_INDEX], &object);
394 ASSERT_EQ(ret, CF_SUCCESS);
395
396 CfParamSet *outParamSet = nullptr;
397 ret = object->get(object, nullptr, &outParamSet); /* inParamSet is nullptr */
398 EXPECT_NE(ret, CF_SUCCESS);
399
400 object->destroy(&object);
401 }
402
403 /**
404 * @tc.name: CfCertTest020
405 * @tc.desc: ->get: out is nullptr
406 * @tc.type: FUNC
407 * @tc.require: AR000HS2RB /SR000HS2Q1
408 */
409 HWTEST_F(CfCertTest, CfCertTest020, TestSize.Level0)
410 {
411 CfObject *object = nullptr;
412 int32_t ret = CfCreate(CF_OBJ_TYPE_CERT, &g_cert[DER_FORMAT_INDEX], &object);
413 ASSERT_EQ(ret, CF_SUCCESS);
414
415 CfParamSet *inParamSet = nullptr;
416 EXPECT_EQ(CfInitParamSet(&inParamSet), CF_SUCCESS);
417
418 ret = object->get(object, inParamSet, nullptr); /* outParamSet is nullptr */
419 EXPECT_NE(ret, CF_SUCCESS);
420
421 object->destroy(&object);
422 CfFreeParamSet(&inParamSet);
423 }
424
425 /**
426 * @tc.name: CfCertTest021
427 * @tc.desc: ->check: object is nullptr
428 * @tc.type: FUNC
429 * @tc.require: AR000HS2RB /SR000HS2Q1
430 */
431 HWTEST_F(CfCertTest, CfCertTest021, TestSize.Level0)
432 {
433 CfObject *object021 = nullptr;
434 int32_t ret = CfCreate(CF_OBJ_TYPE_CERT, &g_cert[DER_FORMAT_INDEX], &object021);
435 ASSERT_EQ(ret, CF_SUCCESS);
436
437 CfParamSet *inParamSet = nullptr;
438 EXPECT_EQ(CfInitParamSet(&inParamSet), CF_SUCCESS);
439
440 CfParamSet *outParamSet = nullptr;
441 ret = object021->check(nullptr, inParamSet, &outParamSet); /* check object is nullptr */
442 EXPECT_NE(ret, CF_SUCCESS);
443
444 object021->destroy(&object021);
445 CfFreeParamSet(&inParamSet);
446 }
447
448 /**
449 * @tc.name: CfCertTest022
450 * @tc.desc: ->check: in is nullptr
451 * @tc.type: FUNC
452 * @tc.require: AR000HS2RB /SR000HS2Q1
453 */
454 HWTEST_F(CfCertTest, CfCertTest022, TestSize.Level0)
455 {
456 CfObject *object022 = nullptr;
457 int32_t ret = CfCreate(CF_OBJ_TYPE_CERT, &g_cert[DER_FORMAT_INDEX], &object022);
458 ASSERT_EQ(ret, CF_SUCCESS);
459
460 CfParamSet *outParamSet = nullptr;
461 ret = object022->check(object022, nullptr, &outParamSet); /* check inParamSet is nullptr */
462 EXPECT_NE(ret, CF_SUCCESS);
463
464 object022->destroy(&object022);
465 }
466
467 /**
468 * @tc.name: CfCertTest023
469 * @tc.desc: ->check: out is nullptr
470 * @tc.type: FUNC
471 * @tc.require: AR000HS2RB /SR000HS2Q1
472 */
473 HWTEST_F(CfCertTest, CfCertTest023, TestSize.Level0)
474 {
475 CfObject *object023 = nullptr;
476 int32_t ret = CfCreate(CF_OBJ_TYPE_CERT, &g_cert[DER_FORMAT_INDEX], &object023);
477 ASSERT_EQ(ret, CF_SUCCESS);
478
479 CfParamSet *inParamSet = nullptr;
480 EXPECT_EQ(CfInitParamSet(&inParamSet), CF_SUCCESS);
481
482 ret = object023->check(object023, inParamSet, nullptr); /* check outParamSet is nullptr */
483 EXPECT_NE(ret, CF_SUCCESS);
484
485 object023->destroy(&object023);
486 CfFreeParamSet(&inParamSet);
487 }
488
489 /**
490 * @tc.name: CfCertTest024
491 * @tc.desc: ->get: inParamSet not set CF_TAG_GET_TYPE
492 * @tc.type: FUNC
493 * @tc.require: AR000HS2RB /SR000HS2Q1
494 */
495 HWTEST_F(CfCertTest, CfCertTest024, TestSize.Level0)
496 {
497 CfParam params[] = { /* inParamSet not set CF_TAG_GET_TYPE */
498 { .tag = CF_TAG_CHECK_TYPE, .int32Param = CF_CHECK_TYPE_EXT_CA },
499 };
500
501 int32_t ret = AbnormalTest(CF_OBJ_TYPE_CERT, &g_cert[DER_FORMAT_INDEX],
502 params, sizeof(params) / sizeof(CfParam), OP_TYPE_GET);
503 EXPECT_EQ(ret, CF_SUCCESS);
504 }
505
506 /**
507 * @tc.name: CfCertTest025
508 * @tc.desc: ->get: inParamSet's CF_TAG_GET_TYPE is not CF_GET_TYPE_CERT_ITEM
509 * @tc.type: FUNC
510 * @tc.require: AR000HS2RB /SR000HS2Q1
511 */
512 HWTEST_F(CfCertTest, CfCertTest025, TestSize.Level0)
513 {
514 CfParam params[] = { /* CF_TAG_GET_TYPE is not CF_GET_TYPE_CERT_ITEM */
515 { .tag = CF_TAG_GET_TYPE, .int32Param = CF_GET_TYPE_EXT_ITEM },
516 };
517
518 int32_t ret = AbnormalTest(CF_OBJ_TYPE_CERT, &g_cert[DER_FORMAT_INDEX],
519 params, sizeof(params) / sizeof(CfParam), OP_TYPE_GET);
520 EXPECT_EQ(ret, CF_SUCCESS);
521 }
522
523 /**
524 * @tc.name: CfCertTest026
525 * @tc.desc: ->get: inParamSet not set CF_TAG_PARAM0_INT32
526 * @tc.type: FUNC
527 * @tc.require: AR000HS2RB /SR000HS2Q1
528 */
529 HWTEST_F(CfCertTest, CfCertTest026, TestSize.Level0)
530 {
531 CfParam params[] = { /* not set CF_TAG_PARAM0_INT32 */
532 { .tag = CF_TAG_GET_TYPE, .int32Param = CF_GET_TYPE_CERT_ITEM },
533 };
534
535 int32_t ret = AbnormalTest(CF_OBJ_TYPE_CERT, &g_cert[DER_FORMAT_INDEX],
536 params, sizeof(params) / sizeof(CfParam), OP_TYPE_GET);
537 EXPECT_EQ(ret, CF_SUCCESS);
538 }
539
540 /**
541 * @tc.name: CfCertTest027
542 * @tc.desc: ->get: inParamSet's CF_TAG_PARAM0_INT32 is not valid
543 * @tc.type: FUNC
544 * @tc.require: AR000HS2RB /SR000HS2Q1
545 */
546 HWTEST_F(CfCertTest, CfCertTest027, TestSize.Level0)
547 {
548 CfParam params[] = { /* CF_TAG_PARAM0_INT32 is not valid */
549 { .tag = CF_TAG_GET_TYPE, .int32Param = CF_GET_TYPE_CERT_ITEM },
550 { .tag = CF_TAG_PARAM0_INT32, .int32Param = CF_ITEM_INVALID },
551 };
552
553 int32_t ret = AbnormalTest(CF_OBJ_TYPE_CERT, &g_cert[DER_FORMAT_INDEX],
554 params, sizeof(params) / sizeof(CfParam), OP_TYPE_GET);
555 EXPECT_EQ(ret, CF_SUCCESS);
556 }
557 }
558
559