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, ¶mSpec);
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(¶ms, 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 }