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 #include "securec.h"
18 
19 #include "alg_25519_asy_key_generator_openssl.h"
20 #include "alg_25519_common_param_spec.h"
21 #include "key_agreement.h"
22 #include "params_parser.h"
23 #include "x25519_openssl.h"
24 #include "memory.h"
25 #include "memory_mock.h"
26 #include "openssl_adapter_mock.h"
27 
28 using namespace std;
29 using namespace testing::ext;
30 
31 namespace {
32 class CryptoX25519KeyAgreementTest : public testing::Test {
33 public:
34     static void SetUpTestCase();
35     static void TearDownTestCase();
36     void SetUp();
37     void TearDown();
38 
39     static HcfKeyPair *ed25519KeyPair_;
40     static HcfKeyPair *x25519KeyPair_;
41 };
42 
43 HcfKeyPair *CryptoX25519KeyAgreementTest::ed25519KeyPair_ = nullptr;
44 HcfKeyPair *CryptoX25519KeyAgreementTest::x25519KeyPair_ = nullptr;
45 
46 static string g_ed25519AlgoName = "Ed25519";
47 static string g_x25519AlgoName = "X25519";
48 
SetUp()49 void CryptoX25519KeyAgreementTest::SetUp() {}
TearDown()50 void CryptoX25519KeyAgreementTest::TearDown() {}
51 
GetMockClass(void)52 static const char *GetMockClass(void)
53 {
54     return "HcfSymKeyGenerator";
55 }
56 
57 static HcfObjectBase g_obj = {
58     .getClass = GetMockClass,
59     .destroy = nullptr
60 };
61 
SetUpTestCase()62 void CryptoX25519KeyAgreementTest::SetUpTestCase()
63 {
64     HcfAsyKeyGenerator *ed25519Generator = nullptr;
65     HcfResult ret = TestHcfAsyKeyGeneratorCreate(g_ed25519AlgoName.c_str(), &ed25519Generator);
66     ASSERT_EQ(ret, HCF_SUCCESS);
67 
68     HcfKeyPair *keyPair = nullptr;
69     ret = TestGenerateKeyPair(ed25519Generator, &keyPair);
70     ASSERT_EQ(ret, HCF_SUCCESS);
71     ed25519KeyPair_ = keyPair;
72 
73     HcfAsyKeyGenerator *x25519Generator = nullptr;
74     ret = TestHcfAsyKeyGeneratorCreate(g_x25519AlgoName.c_str(), &x25519Generator);
75     ASSERT_EQ(ret, HCF_SUCCESS);
76 
77     ret = TestGenerateKeyPair(x25519Generator, &keyPair);
78     ASSERT_EQ(ret, HCF_SUCCESS);
79     x25519KeyPair_ = keyPair;
80 
81     HcfObjDestroy(ed25519Generator);
82     HcfObjDestroy(x25519Generator);
83 }
84 
TearDownTestCase()85 void CryptoX25519KeyAgreementTest::TearDownTestCase()
86 {
87     HcfObjDestroy(ed25519KeyPair_);
88     HcfObjDestroy(x25519KeyPair_);
89 }
90 
TestHcfKeyAgreementCreate(const string & algName,HcfKeyAgreement ** keyAgreement)91 static HcfResult TestHcfKeyAgreementCreate(const string &algName, HcfKeyAgreement **keyAgreement)
92 {
93     HcfResult res = HcfKeyAgreementCreate(algName.c_str(), keyAgreement);
94     if (res != HCF_SUCCESS) {
95         return HCF_ERR_CRYPTO_OPERATION;
96     }
97     if (*keyAgreement == nullptr) {
98         return HCF_ERR_CRYPTO_OPERATION;
99     }
100     return HCF_SUCCESS;
101 }
102 
103 HWTEST_F(CryptoX25519KeyAgreementTest, CryptoX25519KeyAgreementTest001, TestSize.Level0)
104 {
105     HcfKeyAgreement *keyAgreement = nullptr;
106     HcfResult res = TestHcfKeyAgreementCreate(g_x25519AlgoName, &keyAgreement);
107     ASSERT_EQ(res, HCF_SUCCESS);
108     HcfObjDestroy(keyAgreement);
109 }
110 
111 HWTEST_F(CryptoX25519KeyAgreementTest, CryptoX25519KeyAgreementTest002, TestSize.Level0)
112 {
113     HcfKeyAgreement *keyAgreement = nullptr;
114     HcfResult res = TestHcfKeyAgreementCreate(g_x25519AlgoName, &keyAgreement);
115     ASSERT_EQ(res, HCF_SUCCESS);
116 
117     const char *className = keyAgreement->base.getClass();
118     ASSERT_NE(className, nullptr);
119     HcfObjDestroy(keyAgreement);
120 }
121 
122 HWTEST_F(CryptoX25519KeyAgreementTest, CryptoX25519KeyAgreementTest003, TestSize.Level0)
123 {
124     HcfKeyAgreement *keyAgreement = nullptr;
125     HcfResult res = TestHcfKeyAgreementCreate(g_x25519AlgoName, &keyAgreement);
126     ASSERT_EQ(res, HCF_SUCCESS);
127     keyAgreement->base.destroy((HcfObjectBase *)keyAgreement);
128 }
129 
130 HWTEST_F(CryptoX25519KeyAgreementTest, CryptoX25519KeyAgreementTest004, TestSize.Level0)
131 {
132     HcfKeyAgreement *keyAgreement = nullptr;
133     HcfResult res = TestHcfKeyAgreementCreate(g_x25519AlgoName, &keyAgreement);
134     ASSERT_EQ(res, HCF_SUCCESS);
135 
136     const char *algName = keyAgreement->getAlgoName(keyAgreement);
137     ASSERT_EQ(algName, g_x25519AlgoName);
138 
139     HcfAsyKeyParamsSpec *paramSpec = nullptr;
140     res = ConstructAlg25519KeyPairParamsSpec(g_x25519AlgoName.c_str(), false, &paramSpec);
141     ASSERT_EQ(res, HCF_SUCCESS);
142     ASSERT_NE(paramSpec, nullptr);
143 
144     HcfAsyKeyGeneratorBySpec *generator = nullptr;
145     res = HcfAsyKeyGeneratorBySpecCreate(paramSpec, &generator);
146     ASSERT_EQ(res, HCF_SUCCESS);
147     ASSERT_NE(generator, nullptr);
148 
149     HcfKeyPair *keyPair = nullptr;
150     res = generator->generateKeyPair(generator, &keyPair);
151     ASSERT_EQ(res, HCF_SUCCESS);
152     ASSERT_NE(keyPair, nullptr);
153 
154     HcfBlob out = { .data = nullptr, .len = 0 };
155     res = keyAgreement->generateSecret(keyAgreement, keyPair->priKey, keyPair->pubKey, &out);
156 
157     ASSERT_EQ(res, HCF_SUCCESS);
158     ASSERT_NE(out.data, nullptr);
159     ASSERT_NE(out.len, (const unsigned int)0);
160 
161     HcfFree(out.data);
162     HcfObjDestroy(keyAgreement);
163     HcfObjDestroy(generator);
164     HcfObjDestroy(keyPair);
165     DestroyAlg25519KeyPairSpec(reinterpret_cast<HcfAlg25519KeyPairParamsSpec *>(paramSpec));
166 }
167 
168 HWTEST_F(CryptoX25519KeyAgreementTest, CryptoX25519KeyAgreementTest005, TestSize.Level0)
169 {
170     HcfKeyAgreement *keyAgreement = nullptr;
171     string algName = "x25519";
172     HcfResult res = TestHcfKeyAgreementCreate(algName, &keyAgreement);
173     ASSERT_NE(res, HCF_SUCCESS);
174     HcfObjDestroy(keyAgreement);
175 }
176 
177 HWTEST_F(CryptoX25519KeyAgreementTest, CryptoX25519KeyAgreementTest006, TestSize.Level0)
178 {
179     HcfKeyAgreement *keyAgreement = nullptr;
180     HcfResult res = TestHcfKeyAgreementCreate(g_x25519AlgoName, &keyAgreement);
181     ASSERT_EQ(res, HCF_SUCCESS);
182     keyAgreement->base.destroy(nullptr);
183     keyAgreement->base.destroy(&g_obj);
184 
185     HcfObjDestroy(keyAgreement);
186 }
187 
188 HWTEST_F(CryptoX25519KeyAgreementTest, CryptoX25519KeyAgreementTest007, TestSize.Level0)
189 {
190     HcfKeyAgreement *keyAgreement = nullptr;
191     HcfResult res = TestHcfKeyAgreementCreate(g_x25519AlgoName, &keyAgreement);
192     ASSERT_EQ(res, HCF_SUCCESS);
193 
194     const char *algName = nullptr;
195     algName = keyAgreement->getAlgoName(nullptr);
196     ASSERT_EQ(algName, nullptr);
197 
198     algName = keyAgreement->getAlgoName((HcfKeyAgreement *)(&g_obj));
199     ASSERT_EQ(algName, nullptr);
200 
201     HcfObjDestroy(keyAgreement);
202 }
203 
204 HWTEST_F(CryptoX25519KeyAgreementTest, CryptoX25519KeyAgreementTest008, TestSize.Level0)
205 {
206     HcfKeyAgreement *keyAgreement = nullptr;
207     HcfResult res = HcfKeyAgreementCreate("X25519", &keyAgreement);
208 
209     ASSERT_EQ(res, HCF_SUCCESS);
210     ASSERT_NE(keyAgreement, nullptr);
211 
212     HcfBlob out = { .data = nullptr, .len = 0 };
213     res = keyAgreement->generateSecret(keyAgreement, x25519KeyPair_->priKey, nullptr, &out);
214     ASSERT_EQ(res, HCF_INVALID_PARAMS);
215     ASSERT_EQ(out.data, nullptr);
216     ASSERT_EQ(out.len, (const unsigned int)0);
217 
218     res = keyAgreement->generateSecret(keyAgreement, nullptr, x25519KeyPair_->pubKey, &out);
219     ASSERT_EQ(res, HCF_INVALID_PARAMS);
220     ASSERT_EQ(out.data, nullptr);
221     ASSERT_EQ(out.len, (const unsigned int)0);
222 
223     res = keyAgreement->generateSecret(keyAgreement, ed25519KeyPair_->priKey, ed25519KeyPair_->pubKey, &out);
224     ASSERT_EQ(res, HCF_ERR_CRYPTO_OPERATION);
225     ASSERT_EQ(out.data, nullptr);
226     ASSERT_EQ(out.len, (const unsigned int)0);
227 
228     res = keyAgreement->generateSecret((HcfKeyAgreement *)&g_obj, ed25519KeyPair_->priKey,
229     ed25519KeyPair_->pubKey, &out);
230     ASSERT_EQ(res, HCF_INVALID_PARAMS);
231     ASSERT_EQ(out.data, nullptr);
232     ASSERT_EQ(out.len, (const unsigned int)0);
233 
234     HcfFree(out.data);
235     HcfObjDestroy(keyAgreement);
236 }
237 
TestHcfKeyAgreementSpiX25519Create(HcfResult result,HcfKeyAgreementSpi ** spiObj)238 static HcfResult TestHcfKeyAgreementSpiX25519Create(HcfResult result, HcfKeyAgreementSpi **spiObj)
239 {
240     HcfKeyAgreementParams params = {
241         .algo = HCF_ALG_X25519,
242     };
243 
244     HcfResult res = HcfKeyAgreementSpiX25519Create(&params, spiObj);
245     if (res != result) {
246         return HCF_ERR_CRYPTO_OPERATION;
247     }
248     return HCF_SUCCESS;
249 }
250 
251 HWTEST_F(CryptoX25519KeyAgreementTest, CryptoX25519KeyAgreementTest009, TestSize.Level0)
252 {
253     HcfResult res = TestHcfKeyAgreementSpiX25519Create(HCF_INVALID_PARAMS, nullptr);
254     ASSERT_EQ(res, HCF_SUCCESS);
255 }
256 
257 HWTEST_F(CryptoX25519KeyAgreementTest, CryptoX25519KeyAgreementTest010, TestSize.Level0)
258 {
259     HcfKeyAgreementSpi *spiObj = nullptr;
260     HcfResult res = TestHcfKeyAgreementSpiX25519Create(HCF_SUCCESS, &spiObj);
261     ASSERT_EQ(res, HCF_SUCCESS);
262     ASSERT_NE(spiObj, nullptr);
263 
264     HcfBlob out = { .data = nullptr, .len = 0 };
265     res = spiObj->engineGenerateSecret((HcfKeyAgreementSpi *)&g_obj, x25519KeyPair_->priKey, x25519KeyPair_->pubKey,
266         &out);
267     ASSERT_EQ(res, HCF_INVALID_PARAMS);
268 
269     res = spiObj->engineGenerateSecret(spiObj, (HcfPriKey *)&g_obj, x25519KeyPair_->pubKey, &out);
270     ASSERT_EQ(res, HCF_INVALID_PARAMS);
271 
272     res = spiObj->engineGenerateSecret(spiObj, x25519KeyPair_->priKey, (HcfPubKey *)&g_obj, &out);
273     ASSERT_EQ(res, HCF_INVALID_PARAMS);
274     HcfFree(out.data);
275     HcfObjDestroy(spiObj);
276 }
277 
278 HWTEST_F(CryptoX25519KeyAgreementTest, CryptoX25519KeyAgreementTest011, TestSize.Level0)
279 {
280     HcfKeyAgreementSpi *spiObj = nullptr;
281     HcfResult res = TestHcfKeyAgreementSpiX25519Create(HCF_SUCCESS, &spiObj);
282     ASSERT_EQ(res, HCF_SUCCESS);
283     ASSERT_NE(spiObj, nullptr);
284 
285     spiObj->base.destroy(nullptr);
286     HcfObjDestroy(spiObj);
287 }
288 
289 HWTEST_F(CryptoX25519KeyAgreementTest, CryptoX25519KeyAgreementTest012, TestSize.Level0)
290 {
291     HcfKeyAgreementSpi *spiObj = nullptr;
292     HcfResult res = TestHcfKeyAgreementSpiX25519Create(HCF_SUCCESS, &spiObj);
293     ASSERT_EQ(res, HCF_SUCCESS);
294 
295     spiObj->base.destroy(&g_obj);
296     HcfObjDestroy(spiObj);
297 }
298 
299 HWTEST_F(CryptoX25519KeyAgreementTest, CryptoX25519KeyAgreementTest013, TestSize.Level0)
300 {
301     StartRecordMallocNum();
302     HcfKeyAgreement *keyAgreement = nullptr;
303 
304     HcfResult res = TestHcfKeyAgreementCreate(g_x25519AlgoName, &keyAgreement);
305     ASSERT_EQ(res, HCF_SUCCESS);
306 
307     HcfBlob out = { .data = nullptr, .len = 0 };
308     res = keyAgreement->generateSecret(keyAgreement, x25519KeyPair_->priKey, x25519KeyPair_->pubKey, &out);
309     ASSERT_EQ(res, HCF_SUCCESS);
310 
311     HcfObjDestroy(keyAgreement);
312     HcfFree(out.data);
313     uint32_t mallocCount = GetMallocNum();
314 
315     for (uint32_t i = 0; i < mallocCount; i++) {
316         ResetRecordMallocNum();
317         SetMockMallocIndex(i);
318         keyAgreement = nullptr;
319         res = HcfKeyAgreementCreate(g_x25519AlgoName.c_str(), &keyAgreement);
320 
321         if (res != HCF_SUCCESS) {
322             continue;
323         }
324 
325         HcfBlob tmpBlob = {
326             .data = nullptr,
327             .len = 0
328         };
329         res = keyAgreement->generateSecret(keyAgreement, x25519KeyPair_->priKey, x25519KeyPair_->pubKey, &tmpBlob);
330 
331         if (res != HCF_SUCCESS) {
332             HcfObjDestroy(keyAgreement);
333             continue;
334         }
335 
336         HcfObjDestroy(keyAgreement);
337         HcfFree(tmpBlob.data);
338     }
339     EndRecordMallocNum();
340 }
341 
342 HWTEST_F(CryptoX25519KeyAgreementTest, CryptoX25519KeyAgreementTest014, TestSize.Level0)
343 {
344     StartRecordOpensslCallNum();
345     HcfKeyAgreement *keyAgreement = nullptr;
346 
347     HcfResult res = TestHcfKeyAgreementCreate(g_x25519AlgoName, &keyAgreement);
348     ASSERT_EQ(res, HCF_SUCCESS);
349 
350     HcfBlob out = { .data = nullptr, .len = 0 };
351     res = keyAgreement->generateSecret(keyAgreement, x25519KeyPair_->priKey, x25519KeyPair_->pubKey, &out);
352     ASSERT_EQ(res, HCF_SUCCESS);
353 
354     HcfObjDestroy(keyAgreement);
355     HcfFree(out.data);
356     uint32_t mallocCount = GetOpensslCallNum();
357 
358     for (uint32_t i = 0; i < mallocCount; i++) {
359         ResetOpensslCallNum();
360         SetOpensslCallMockIndex(i);
361         keyAgreement = nullptr;
362         res = HcfKeyAgreementCreate(g_x25519AlgoName.c_str(), &keyAgreement);
363 
364         if (res != HCF_SUCCESS) {
365             continue;
366         }
367 
368         HcfBlob tmpBlob = {
369             .data = nullptr,
370             .len = 0
371         };
372         res = keyAgreement->generateSecret(keyAgreement, x25519KeyPair_->priKey, x25519KeyPair_->pubKey, &tmpBlob);
373 
374         if (res != HCF_SUCCESS) {
375             HcfObjDestroy(keyAgreement);
376             continue;
377         }
378 
379         HcfObjDestroy(keyAgreement);
380         HcfFree(tmpBlob.data);
381     }
382     EndRecordOpensslCallNum();
383 }
384 
385 HWTEST_F(CryptoX25519KeyAgreementTest, CryptoX25519KeyAgreementTest015, TestSize.Level0)
386 {
387     HcfAsyKeyGenerator *generator = nullptr;
388     HcfResult res = TestHcfAsyKeyGeneratorCreate(g_x25519AlgoName.c_str(), &generator);
389     ASSERT_EQ(res, HCF_SUCCESS);
390 
391     HcfKeyPair *x25519keyPair1 = nullptr;
392     res = TestGenerateKeyPair(generator, &x25519keyPair1);
393     ASSERT_EQ(res, HCF_SUCCESS);
394     HcfKeyPair *x25519keyPair2 = nullptr;
395     res = TestGenerateKeyPair(generator, &x25519keyPair2);
396     ASSERT_EQ(res, HCF_SUCCESS);
397 
398     HcfKeyAgreement *keyAgreement = nullptr;
399     res = TestHcfKeyAgreementCreate(g_x25519AlgoName, &keyAgreement);
400     ASSERT_EQ(res, HCF_SUCCESS);
401 
402     HcfBlob outBlob1 = { .data = nullptr, .len = 0 };
403     res = keyAgreement->generateSecret(keyAgreement, x25519keyPair1->priKey, x25519keyPair2->pubKey, &outBlob1);
404     ASSERT_EQ(res, HCF_SUCCESS);
405 
406     HcfBlob outBlob2 = { .data = nullptr, .len = 0 };
407     res = keyAgreement->generateSecret(keyAgreement, x25519keyPair2->priKey, x25519keyPair1->pubKey, &outBlob2);
408     ASSERT_EQ(res, HCF_SUCCESS);
409 
410     bool flag = true;
411     if (*(outBlob1.data) != *(outBlob2.data)) {
412         flag = false;
413     }
414     EXPECT_EQ(flag, true);
415     ASSERT_EQ(outBlob1.len, outBlob2.len);
416 
417     HcfObjDestroy(keyAgreement);
418     HcfObjDestroy(generator);
419     HcfObjDestroy(x25519keyPair1);
420     HcfObjDestroy(x25519keyPair2);
421     HcfFree(outBlob1.data);
422     HcfFree(outBlob2.data);
423 }
424 }