1 /*
2 * Copyright (c) 2024 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 "cert_crl_common.h"
19 #include "cf_blob.h"
20 #include "cf_log.h"
21 #include "cf_mock.h"
22 #include "cf_object_base.h"
23 #include "cf_result.h"
24 #include "crypto_x509_test_common.h"
25 #include "memory_mock.h"
26 #include "securec.h"
27 #include "string"
28 #include "x509_cert_chain.h"
29 #include "x509_cert_chain_openssl.h"
30 #include "x509_certificate_openssl.h"
31 #include "x509_distinguished_name.h"
32 #include "x509_distinguished_name_openssl.h"
33 #include "x509_distinguished_name_spi.h"
34
35 using namespace std;
36 using namespace testing::ext;
37 using namespace CFMock;
38
39 using ::testing::_;
40 using ::testing::AnyNumber;
41 using ::testing::Invoke;
42 using ::testing::Return;
43
44 #ifdef __cplusplus
45 extern "C" {
46 #endif
47
48 int __real_ASN1_STRING_length(const ASN1_STRING *x);
49 X509_NAME *__real_X509_NAME_new(void);
50 int __real_OBJ_txt2nid(const char *s);
51
52 #ifdef __cplusplus
53 }
54 #endif
55
56 namespace {
57 #define HCF_X509_DIST_NAME_VALID_CLASS "HcfX509DistinguishedName"
58 #define X509_DISTINGUISHED_NAME_OPENSSL_CLASS "X509DistinguishedNameOpensslClass"
59
60 typedef struct {
61 HcfX509DistinguishedName base;
62 HcfX509DistinguishedNameSpi *spiObj;
63 const char *certType;
64 } HcfX509DistinguishedNameImpl;
65
GetValidX509DistinguishedNameClass(void)66 static const char *GetValidX509DistinguishedNameClass(void)
67 {
68 return HCF_X509_DIST_NAME_VALID_CLASS;
69 }
70
GetX509DistinguishedNameOpensslClass(void)71 static const char *GetX509DistinguishedNameOpensslClass(void)
72 {
73 return X509_DISTINGUISHED_NAME_OPENSSL_CLASS;
74 }
75
76 class X509DistinguishedNameTest : public testing::Test {
77 public:
78 static void SetUpTestCase();
79 static void TearDownTestCase();
80 void SetUp();
81 void TearDown();
82 };
83
84 static HcfX509Certificate *g_x509CertObj = nullptr;
85 static HcfX509DistinguishedName *g_x509Name = nullptr;
86 static HcfX509DistinguishedNameSpi *g_x509NameSpi = nullptr;
87
SetUpTestCase()88 void X509DistinguishedNameTest::SetUpTestCase()
89 {
90 HcfX509Certificate *x509CertObj = nullptr;
91 CfEncodingBlob inStream = { 0 };
92 inStream.data = reinterpret_cast<uint8_t *>(const_cast<char *>(g_testSelfSignedCaCert));
93 inStream.encodingFormat = CF_FORMAT_PEM;
94 inStream.len = strlen(g_testSelfSignedCaCert) + 1;
95 (void)HcfX509CertificateCreate(&inStream, &x509CertObj);
96 ASSERT_NE(x509CertObj, nullptr);
97 g_x509CertObj = x509CertObj;
98
99 CfBlob out = { 0 };
100 CfResult ret = g_x509CertObj->getIssuerName(g_x509CertObj, &out);
101 EXPECT_EQ(ret, CF_SUCCESS);
102 EXPECT_NE(out.data, nullptr);
103
104 HcfX509DistinguishedName *x509Name = nullptr;
105 ret = HcfX509DistinguishedNameCreate(&out, true, &x509Name);
106 EXPECT_EQ(ret, CF_SUCCESS);
107 EXPECT_NE(x509Name, nullptr);
108 g_x509Name = x509Name;
109
110 HcfX509DistinguishedNameImpl *x509NameImpl = (HcfX509DistinguishedNameImpl *)x509Name;
111 g_x509NameSpi = x509NameImpl->spiObj;
112
113 CfBlobDataClearAndFree(&out);
114 }
115
TearDownTestCase()116 void X509DistinguishedNameTest::TearDownTestCase()
117 {
118 // test DestroyX509DistinguishedNameOpenssl failed case
119 g_x509NameSpi->base.destroy(NULL);
120
121 g_x509NameSpi->base.getClass = GetInvalidCertClass;
122 g_x509NameSpi->base.destroy((CfObjectBase *)g_x509NameSpi);
123
124 // restore getClass
125 g_x509NameSpi->base.getClass = GetX509DistinguishedNameOpensslClass;
126
127 CfObjDestroy(g_x509CertObj);
128 CfObjDestroy(g_x509Name);
129 }
130
SetUp()131 void X509DistinguishedNameTest::SetUp() {}
132
TearDown()133 void X509DistinguishedNameTest::TearDown() {}
134
135 HWTEST_F(X509DistinguishedNameTest, HcfX509DistinguishedNameCreateTest001, TestSize.Level0)
136 {
137 CF_LOG_I("HcfX509DistinguishedNameCreateTest001");
138 ASSERT_NE(g_x509CertObj, nullptr);
139
140 CfBlob out = { 0 };
141 CfResult ret = g_x509CertObj->getIssuerName(g_x509CertObj, &out);
142 EXPECT_EQ(ret, CF_SUCCESS);
143 EXPECT_NE(out.data, nullptr);
144
145 HcfX509DistinguishedName *x509Name = nullptr;
146 ret = HcfX509DistinguishedNameCreate(&out, true, &x509Name);
147 EXPECT_EQ(ret, CF_SUCCESS);
148 EXPECT_NE(x509Name, nullptr);
149
150 // test DestroyX509DistinguishedName failed case
151 x509Name->base.destroy(NULL);
152
153 x509Name->base.getClass = GetInvalidCertClass;
154 CfObjDestroy(x509Name);
155
156 // restore getClass
157 x509Name->base.getClass = GetValidX509DistinguishedNameClass;
158 CfObjDestroy(x509Name);
159
160 CfBlobDataClearAndFree(&out);
161 }
162
163 HWTEST_F(X509DistinguishedNameTest, HcfX509DistinguishedNameCreateTest002, TestSize.Level0)
164 {
165 CF_LOG_I("HcfX509DistinguishedNameCreateTest002");
166 ASSERT_NE(g_x509CertObj, nullptr);
167
168 CfBlob out = { 0 };
169 CfResult ret = g_x509CertObj->getIssuerName(g_x509CertObj, &out);
170 EXPECT_EQ(ret, CF_SUCCESS);
171 EXPECT_NE(out.data, nullptr);
172
173 HcfX509DistinguishedName *x509Name = nullptr;
174 ret = HcfX509DistinguishedNameCreate(&out, false, &x509Name);
175 EXPECT_EQ(ret, CF_ERR_CRYPTO_OPERATION);
176
177 ret = HcfX509DistinguishedNameCreate(NULL, true, &x509Name);
178 EXPECT_EQ(ret, CF_INVALID_PARAMS);
179
180 ret = HcfX509DistinguishedNameCreate(&out, true, NULL);
181 EXPECT_EQ(ret, CF_INVALID_PARAMS);
182
183 ret = HcfX509DistinguishedNameCreate(NULL, true, NULL);
184 EXPECT_EQ(ret, CF_INVALID_PARAMS);
185
186 CfBlobDataClearAndFree(&out);
187 }
188
189 HWTEST_F(X509DistinguishedNameTest, OpensslX509DistinguishedNameSpiCreateTest001, TestSize.Level0)
190 {
191 ASSERT_NE(g_x509CertObj, nullptr);
192
193 CfBlob out = { 0 };
194 CfResult ret = g_x509CertObj->getIssuerName(g_x509CertObj, &out);
195 EXPECT_EQ(ret, CF_SUCCESS);
196 EXPECT_NE(out.data, nullptr);
197
198 HcfX509DistinguishedNameSpi *spi = nullptr;
199 ret = OpensslX509DistinguishedNameSpiCreate(&out, true, &spi);
200 EXPECT_EQ(ret, CF_SUCCESS);
201 CfObjDestroy(spi);
202
203 SetMockFlag(true);
204 ret = OpensslX509DistinguishedNameSpiCreate(&out, true, &spi);
205 EXPECT_EQ(ret, CF_ERR_MALLOC);
206 SetMockFlag(false);
207
208 ret = OpensslX509DistinguishedNameSpiCreate(NULL, true, &spi);
209 EXPECT_EQ(ret, CF_INVALID_PARAMS);
210
211 ret = OpensslX509DistinguishedNameSpiCreate(&out, true, NULL);
212 EXPECT_EQ(ret, CF_INVALID_PARAMS);
213
214 ret = OpensslX509DistinguishedNameSpiCreate(NULL, true, NULL);
215 EXPECT_EQ(ret, CF_INVALID_PARAMS);
216
217 // test CollectAndParseName failed case
218 X509OpensslMock::SetMockFlag(true);
219 EXPECT_CALL(X509OpensslMock::GetInstance(), OBJ_txt2nid(_))
220 .WillOnce(Return(NID_undef))
221 .WillRepeatedly(Invoke(__real_OBJ_txt2nid));
222 ret = OpensslX509DistinguishedNameSpiCreate(&out, true, &spi);
223 EXPECT_EQ(ret, CF_SUCCESS);
224 X509OpensslMock::SetMockFlag(false);
225 CfObjDestroy(spi);
226
227 // test ParseName failed case
228 X509OpensslMock::SetMockFlag(true);
229 EXPECT_CALL(X509OpensslMock::GetInstance(), X509_NAME_add_entry_by_NID(_, _, _, _, _, _, _))
230 .Times(AnyNumber())
231 .WillOnce(Return(0));
232 ret = OpensslX509DistinguishedNameSpiCreate(&out, true, &spi);
233 EXPECT_EQ(ret, CF_ERR_CRYPTO_OPERATION);
234 X509OpensslMock::SetMockFlag(false);
235
236 out.data[3] = '+';
237 ret = OpensslX509DistinguishedNameSpiCreate(&out, true, &spi);
238 EXPECT_EQ(ret, CF_SUCCESS);
239 CfObjDestroy(spi);
240
241 out.data[3] = '\\';
242 out.data[4] = '\0';
243 ret = OpensslX509DistinguishedNameSpiCreate(&out, true, &spi);
244 EXPECT_EQ(ret, CF_ERR_CRYPTO_OPERATION);
245
246 out.data[2] = '\0';
247 ret = OpensslX509DistinguishedNameSpiCreate(&out, true, &spi);
248 EXPECT_EQ(ret, CF_ERR_CRYPTO_OPERATION);
249
250 CfBlobDataClearAndFree(&out);
251 }
252
253 HWTEST_F(X509DistinguishedNameTest, OpensslX509DistinguishedNameSpiCreateTest002, TestSize.Level0)
254 {
255 CF_LOG_I("OpensslX509DistinguishedNameSpiCreateTest002");
256 ASSERT_NE(g_x509CertObj, nullptr);
257
258 CfBlob out = { 0 };
259 CfResult ret = g_x509CertObj->getIssuerName(g_x509CertObj, &out);
260 EXPECT_EQ(ret, CF_SUCCESS);
261 EXPECT_NE(out.data, nullptr);
262
263 HcfX509DistinguishedNameSpi *spi = nullptr;
264 ret = OpensslX509DistinguishedNameSpiCreate(&out, true, &spi);
265 EXPECT_EQ(ret, CF_SUCCESS);
266 CfObjDestroy(spi);
267
268 // test ParseName failed case
269 X509OpensslMock::SetMockFlag(true);
270 EXPECT_CALL(X509OpensslMock::GetInstance(), X509_NAME_new())
271 .WillOnce(Return(NULL))
272 .WillRepeatedly(Invoke(__real_X509_NAME_new));
273 ret = OpensslX509DistinguishedNameSpiCreate(&out, true, &spi);
274 EXPECT_EQ(ret, CF_ERR_CRYPTO_OPERATION);
275 X509OpensslMock::SetMockFlag(false);
276
277 // test ParseName failed case
278 X509OpensslMock::SetMockFlag(true);
279 EXPECT_CALL(X509OpensslMock::GetInstance(), CRYPTO_strdup(_, _, _)).WillRepeatedly(Return(NULL));
280 ret = OpensslX509DistinguishedNameSpiCreate(&out, true, &spi);
281 EXPECT_EQ(ret, CF_ERR_CRYPTO_OPERATION);
282 X509OpensslMock::SetMockFlag(false);
283
284 // test ParseName cp != / failed case
285 out.data[0] = 'a';
286 ret = OpensslX509DistinguishedNameSpiCreate(&out, true, &spi);
287 EXPECT_EQ(ret, CF_ERR_CRYPTO_OPERATION);
288
289 CfBlobDataClearAndFree(&out);
290 }
291
292 HWTEST_F(X509DistinguishedNameTest, GetEncodeTest001, TestSize.Level0)
293 {
294 CF_LOG_I("GetEncodeTest001");
295 ASSERT_NE(g_x509Name, nullptr);
296
297 CfEncodingBlob blob = { nullptr, 0, CF_FORMAT_DER };
298 CfResult ret = g_x509Name->getEncode(g_x509Name, &blob);
299 EXPECT_EQ(ret, CF_SUCCESS);
300 CfEncodingBlobDataFree(&blob);
301
302 HcfX509DistinguishedName x509Name;
303 x509Name.base.getClass = GetInvalidCertClass;
304
305 ret = g_x509Name->getEncode(&x509Name, &blob);
306 EXPECT_EQ(ret, CF_INVALID_PARAMS);
307
308 ret = g_x509Name->getEncode(NULL, &blob);
309 EXPECT_EQ(ret, CF_INVALID_PARAMS);
310
311 ret = g_x509Name->getEncode(g_x509Name, NULL);
312 EXPECT_EQ(ret, CF_INVALID_PARAMS);
313
314 ret = g_x509Name->getEncode(NULL, NULL);
315 EXPECT_EQ(ret, CF_INVALID_PARAMS);
316
317 SetMockFlag(true);
318 ret = g_x509Name->getEncode(g_x509Name, &blob);
319 EXPECT_EQ(ret, CF_ERR_MALLOC);
320 SetMockFlag(false);
321
322 X509OpensslMock::SetMockFlag(true);
323 EXPECT_CALL(X509OpensslMock::GetInstance(), X509_NAME_get0_der(_, _, _)).WillRepeatedly(Return(-1));
324 ret = g_x509Name->getEncode(g_x509Name, &blob);
325 EXPECT_EQ(ret, CF_ERR_CRYPTO_OPERATION);
326 X509OpensslMock::SetMockFlag(false);
327 }
328
329 HWTEST_F(X509DistinguishedNameTest, GetNameTest001, TestSize.Level0)
330 {
331 CF_LOG_I("GetNameTest001");
332 ASSERT_NE(g_x509Name, nullptr);
333
334 // PARAM0
335 CfBlob blob = { 0, nullptr };
336 CfResult ret = g_x509Name->getName(g_x509Name, NULL, &blob, NULL);
337 EXPECT_EQ(ret, CF_SUCCESS);
338 CfBlobDataFree(&blob);
339
340 // test GetNameOpenssl failed case
341 X509OpensslMock::SetMockFlag(true);
342 EXPECT_CALL(X509OpensslMock::GetInstance(), X509_NAME_oneline(_, _, _))
343 .Times(AnyNumber())
344 .WillRepeatedly(Return(NULL));
345 ret = g_x509Name->getName(g_x509Name, NULL, &blob, NULL);
346 EXPECT_EQ(ret, CF_ERR_CRYPTO_OPERATION);
347 X509OpensslMock::SetMockFlag(false);
348
349 // PARAM1
350 CfBlob inPara = { 0, nullptr };
351 CfArray outArr = { nullptr, CF_FORMAT_DER, 0 };
352 ret = g_x509Name->getName(g_x509Name, &inPara, NULL, &outArr);
353 EXPECT_EQ(ret, CF_INVALID_PARAMS);
354 CfArrayDataClearAndFree(&outArr);
355
356 inPara.data = (uint8_t *)"emailAddress";
357 inPara.size = strlen("emailAddress") + 1;
358
359 SetMockFlag(true);
360 ret = g_x509Name->getName(g_x509Name, &inPara, NULL, &outArr);
361 EXPECT_EQ(ret, CF_ERR_MALLOC);
362 SetMockFlag(false);
363
364 ret = g_x509Name->getName(g_x509Name, &inPara, NULL, &outArr);
365 EXPECT_EQ(ret, CF_SUCCESS);
366 CfArrayDataClearAndFree(&outArr);
367
368 ret = g_x509Name->getName(g_x509Name, NULL, NULL, NULL);
369 EXPECT_EQ(ret, CF_INVALID_PARAMS);
370
371 ret = g_x509Name->getName(g_x509Name, &inPara, NULL, NULL);
372 EXPECT_EQ(ret, CF_INVALID_PARAMS);
373
374 inPara.data = (uint8_t *)"test";
375 inPara.size = strlen("test") + 1;
376 ret = g_x509Name->getName(g_x509Name, &inPara, NULL, &outArr);
377 EXPECT_EQ(ret, CF_SUCCESS);
378
379 HcfX509DistinguishedName x509Name;
380 x509Name.base.getClass = GetInvalidCertClass;
381
382 ret = g_x509Name->getName(&x509Name, NULL, &blob, NULL);
383 EXPECT_EQ(ret, CF_INVALID_PARAMS);
384
385 ret = g_x509Name->getName(NULL, NULL, &blob, NULL);
386 EXPECT_EQ(ret, CF_INVALID_PARAMS);
387 }
388
389 HWTEST_F(X509DistinguishedNameTest, GetNameTest002, TestSize.Level0)
390 {
391 CF_LOG_I("GetNameTest001");
392 ASSERT_NE(g_x509Name, nullptr);
393
394 CfResult ret;
395 CfBlob inPara = { 0, nullptr };
396 CfArray outArr = { nullptr, CF_FORMAT_DER, 0 };
397
398 inPara.data = (uint8_t *)"emailAddress";
399 inPara.size = strlen("emailAddress") + 1;
400
401 // test GetDataByEntryOpenssl failed case
402 X509OpensslMock::SetMockFlag(true);
403 EXPECT_CALL(X509OpensslMock::GetInstance(), ASN1_STRING_length(_))
404 .WillOnce(Return(-1))
405 .WillRepeatedly(Invoke(__real_ASN1_STRING_length));
406 ret = g_x509Name->getName(g_x509Name, &inPara, NULL, &outArr);
407 EXPECT_EQ(ret, CF_ERR_CRYPTO_OPERATION);
408 X509OpensslMock::SetMockFlag(false);
409
410 X509OpensslMock::SetMockFlag(true);
411 EXPECT_CALL(X509OpensslMock::GetInstance(), DeepCopyDataToOut(_, _, _))
412 .WillRepeatedly(Return(CF_ERR_CRYPTO_OPERATION));
413 ret = g_x509Name->getName(g_x509Name, &inPara, NULL, &outArr);
414 EXPECT_EQ(ret, CF_ERR_CRYPTO_OPERATION);
415 X509OpensslMock::SetMockFlag(false);
416
417 // test GetNameByTypeOpenssl failed case
418 X509OpensslMock::SetMockFlag(true);
419 EXPECT_CALL(X509OpensslMock::GetInstance(), OBJ_nid2sn(_)).Times(AnyNumber()).WillRepeatedly(Return(NULL));
420 ret = g_x509Name->getName(g_x509Name, &inPara, NULL, &outArr);
421 EXPECT_EQ(ret, CF_ERR_CRYPTO_OPERATION);
422 X509OpensslMock::SetMockFlag(false);
423 }
424
425 HWTEST_F(X509DistinguishedNameTest, HcfX509DistinguishedNameSpiEngineGetEncodeTest001, TestSize.Level0)
426 {
427 CF_LOG_I("GetEncodeTest001");
428 ASSERT_NE(g_x509NameSpi, nullptr);
429
430 CfEncodingBlob blob = { nullptr, 0, CF_FORMAT_DER };
431 CfResult ret = g_x509NameSpi->engineGetEncode(g_x509NameSpi, &blob);
432 EXPECT_EQ(ret, CF_SUCCESS);
433 CfEncodingBlobDataFree(&blob);
434
435 HcfX509DistinguishedNameSpi invalidDistinguishedNameSpi;
436 invalidDistinguishedNameSpi.base.getClass = GetInvalidCertClass;
437
438 ret = g_x509NameSpi->engineGetEncode(&invalidDistinguishedNameSpi, &blob);
439 EXPECT_EQ(ret, CF_INVALID_PARAMS);
440
441 ret = g_x509NameSpi->engineGetEncode(NULL, &blob);
442 EXPECT_EQ(ret, CF_INVALID_PARAMS);
443
444 ret = g_x509NameSpi->engineGetEncode(g_x509NameSpi, NULL);
445 EXPECT_EQ(ret, CF_INVALID_PARAMS);
446
447 ret = g_x509NameSpi->engineGetEncode(NULL, NULL);
448 EXPECT_EQ(ret, CF_INVALID_PARAMS);
449 }
450
451 HWTEST_F(X509DistinguishedNameTest, HcfX509DistinguishedNameSpiEngineGetNameTest001, TestSize.Level0)
452 {
453 CF_LOG_I("HcfX509DistinguishedNameSpiEngineGetNameTest001");
454 ASSERT_NE(g_x509NameSpi, nullptr);
455
456 // PARAM0
457 CfBlob blob = { 0, nullptr };
458 CfResult ret = g_x509NameSpi->engineGetName(g_x509NameSpi, NULL, &blob, NULL);
459 EXPECT_EQ(ret, CF_SUCCESS);
460 CfBlobDataFree(&blob);
461
462 // PARAM1
463 CfBlob inPara = { 0, nullptr };
464 CfArray outArr = { nullptr, CF_FORMAT_DER, 0 };
465 ret = g_x509NameSpi->engineGetName(g_x509NameSpi, &inPara, NULL, &outArr);
466 EXPECT_EQ(ret, CF_INVALID_PARAMS);
467 CfArrayDataClearAndFree(&outArr);
468
469 HcfX509DistinguishedNameSpi invalidDistinguishedNameSpi;
470 invalidDistinguishedNameSpi.base.getClass = GetInvalidCertClass;
471
472 ret = g_x509NameSpi->engineGetName(&invalidDistinguishedNameSpi, NULL, &blob, NULL);
473 EXPECT_EQ(ret, CF_INVALID_PARAMS);
474
475 ret = g_x509NameSpi->engineGetName(NULL, NULL, &blob, NULL);
476 EXPECT_EQ(ret, CF_INVALID_PARAMS);
477 }
478
479 } // namespace
480