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