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 <thread>
18 #include <unistd.h>
19 
20 #include "file_ex.h"
21 #include "hks_api.h"
22 #include "hks_log.h"
23 #include "hks_mem.h"
24 #include "hks_param.h"
25 #include "hks_template.h"
26 
27 #include "securec.h"
28 
29 using namespace testing::ext;
30 namespace Unittest::HksThreeStageMultiThreadTest {
31 class HksThreeStageMultiThreadTest : public testing::Test {
32 public:
33     static void SetUpTestCase(void);
34 
35     static void TearDownTestCase(void);
36 
37     void SetUp();
38 
39     void TearDown();
40 };
41 
SetUpTestCase(void)42 void HksThreeStageMultiThreadTest::SetUpTestCase(void)
43 {
44 }
45 
TearDownTestCase(void)46 void HksThreeStageMultiThreadTest::TearDownTestCase(void)
47 {
48 }
49 
SetUp()50 void HksThreeStageMultiThreadTest::SetUp()
51 {
52 }
53 
TearDown()54 void HksThreeStageMultiThreadTest::TearDown()
55 {
56 }
57 
58 const uint32_t THREADS_NUM = 10;
59 static const uint32_t HKS_SM4_IV_SIZE = 16;
60 
61 static uint8_t g_hksSm4TestIv[HKS_SM4_IV_SIZE] = {0};
62 
63 static struct HksParam g_genParams[] = {
64     {
65         .tag = HKS_TAG_ALGORITHM,
66         .uint32Param = HKS_ALG_SM4
67     }, {
68         .tag = HKS_TAG_IV,
69         .blob = {
70             .size = HKS_SM4_IV_SIZE,
71             .data = static_cast<uint8_t *>(g_hksSm4TestIv)
72         }
73     }, {
74         .tag = HKS_TAG_PURPOSE,
75         .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT
76     }, {
77         .tag = HKS_TAG_PADDING,
78         .uint32Param = HKS_PADDING_PKCS7
79     }, {
80         .tag = HKS_TAG_KEY_SIZE,
81         .uint32Param = HKS_SM4_KEY_SIZE_128
82     }, {
83         .tag = HKS_TAG_BLOCK_MODE,
84         .uint32Param = HKS_MODE_CBC
85     },
86 };
87 
InitParamSet(struct HksParamSet ** paramSet,const struct HksParam * params,uint32_t paramcount)88 static int32_t InitParamSet(struct HksParamSet **paramSet, const struct HksParam *params, uint32_t paramcount)
89 {
90     int32_t ret = HksInitParamSet(paramSet);
91     if (ret != HKS_SUCCESS) {
92         HKS_LOG_E("HksInitParamSet failed");
93         return ret;
94     }
95 
96     ret = HksAddParams(*paramSet, params, paramcount);
97     if (ret != HKS_SUCCESS) {
98         HksFreeParamSet(paramSet);
99         HKS_LOG_E("HksAddParams failed");
100         return ret;
101     }
102 
103     ret = HksBuildParamSet(paramSet);
104     if (ret != HKS_SUCCESS) {
105         HksFreeParamSet(paramSet);
106         HKS_LOG_E("HksBuildParamSet failed!");
107         return ret;
108     }
109 
110     return ret;
111 }
112 
GenerateKeyTest(const char * tmpKeyAlias)113 static int32_t GenerateKeyTest(const char *tmpKeyAlias)
114 {
115     struct HksBlob keyAlias = { strlen(tmpKeyAlias),
116         const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(tmpKeyAlias)) };
117 
118     struct HksParamSet *genParamSet = nullptr;
119     int32_t ret = InitParamSet(&genParamSet, g_genParams, sizeof(g_genParams) / sizeof(HksParam));
120     EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet(gen) failed.";
121 
122     ret = HksGenerateKey(&keyAlias, genParamSet, nullptr);
123     EXPECT_EQ(ret, HKS_SUCCESS) << "GenerateKey failed.";
124 
125     HksFreeParamSet(&genParamSet);
126     return ret;
127 }
128 
DeleteKeyTest(const char * tmpKeyAlias)129 static int32_t DeleteKeyTest(const char *tmpKeyAlias)
130 {
131     struct HksBlob keyAlias = { strlen(tmpKeyAlias),
132         const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(tmpKeyAlias)) };
133     return HksDeleteKey(&keyAlias, nullptr);
134 }
135 
136 static struct HksParam g_encryptParams[] = {
137     {
138         .tag = HKS_TAG_ALGORITHM,
139         .uint32Param = HKS_ALG_SM4
140     }, {
141         .tag = HKS_TAG_PURPOSE,
142         .uint32Param = HKS_KEY_PURPOSE_ENCRYPT
143     }, {
144         .tag = HKS_TAG_IV,
145         .blob = {
146             .size = HKS_SM4_IV_SIZE,
147             .data = static_cast<uint8_t *>(g_hksSm4TestIv)
148         }
149     }, {
150         .tag = HKS_TAG_PADDING,
151         .uint32Param = HKS_PADDING_PKCS7
152     }, {
153         .tag = HKS_TAG_KEY_SIZE,
154         .uint32Param = HKS_SM4_KEY_SIZE_128
155     }, {
156         .tag = HKS_TAG_BLOCK_MODE,
157         .uint32Param = HKS_MODE_CBC
158     },
159 };
160 
InitSessionTest(const char * tmpKeyAlias,struct HksBlob * handle)161 static int32_t InitSessionTest(const char *tmpKeyAlias, struct HksBlob *handle)
162 {
163     struct HksBlob keyAlias = { strlen(tmpKeyAlias),
164         const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(tmpKeyAlias)) };
165     struct HksParamSet *encryptParamSet = nullptr;
166     int32_t ret = InitParamSet(&encryptParamSet, g_encryptParams, sizeof(g_encryptParams) / sizeof(HksParam));
167     EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet(encrypt) failed.";
168     ret = HksInit(&keyAlias, encryptParamSet, handle, nullptr);
169     EXPECT_EQ(ret, HKS_SUCCESS) << "HksInit failed.";
170     HksFreeParamSet(&encryptParamSet);
171     return ret;
172 }
173 
UpdateSessionTest(struct HksBlob * handle)174 static int32_t UpdateSessionTest(struct HksBlob *handle)
175 {
176     struct HksParamSet *encryptParamSet = nullptr;
177     int32_t ret = InitParamSet(&encryptParamSet, g_encryptParams, sizeof(g_encryptParams) / sizeof(HksParam));
178     EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet(encrypt) failed.";
179 
180     uint32_t indataSize = 8192;
181     uint32_t outdataSize = 8208;
182     uint8_t *indata = static_cast<uint8_t *>(HksMalloc(indataSize));
183     struct HksBlob indataBlob = { indataSize, indata };
184     uint8_t *outdata = static_cast<uint8_t *>(HksMalloc(outdataSize));
185     struct HksBlob outdataBlob = { outdataSize, outdata };
186     ret = HksUpdate(handle, encryptParamSet, &indataBlob, &outdataBlob);
187     HKS_IF_NOT_SUCC_LOGE(ret, "HksUpdate failed.")
188     HksFreeParamSet(&encryptParamSet);
189     HKS_FREE(indata);
190     HKS_FREE(outdata);
191     return ret;
192 }
193 
FinishSessionTest(struct HksBlob * handle)194 static int32_t FinishSessionTest(struct HksBlob *handle)
195 {
196     struct HksParamSet *encryptParamSet = nullptr;
197     int32_t ret = InitParamSet(&encryptParamSet, g_encryptParams, sizeof(g_encryptParams) / sizeof(HksParam));
198     EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet(encrypt) failed.";
199 
200     uint32_t indataSize = 8192;
201     uint8_t *indata = static_cast<uint8_t *>(HksMalloc(indataSize));
202     struct HksBlob indataBlob = { indataSize, indata };
203     uint32_t outdataSize = 8208;
204     uint8_t *outdata = static_cast<uint8_t *>(HksMalloc(outdataSize));
205     struct HksBlob outdataBlob = { outdataSize, outdata };
206     ret = HksFinish(handle, encryptParamSet, &indataBlob, &outdataBlob);
207     HKS_IF_NOT_SUCC_LOGE(ret, "HksFinish failed.")
208     HksFreeParamSet(&encryptParamSet);
209     HKS_FREE(indata);
210     HKS_FREE(outdata);
211     return ret;
212 }
213 
AbortSessionTest(struct HksBlob * handle)214 static int32_t AbortSessionTest(struct HksBlob *handle)
215 {
216     struct HksParamSet *encryptParamSet = nullptr;
217     int32_t ret = InitParamSet(&encryptParamSet, g_encryptParams, sizeof(g_encryptParams) / sizeof(HksParam));
218     EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet(encrypt) failed.";
219     ret = HksAbort(handle, encryptParamSet);
220     HKS_IF_NOT_SUCC_LOGE(ret, "HksAbort failed.")
221     HksFreeParamSet(&encryptParamSet);
222     return ret;
223 }
224 
ThreeStageTest(uint32_t testIndex)225 static void ThreeStageTest(uint32_t testIndex)
226 {
227     char alias[20];
228     (void)sprintf_s(alias, sizeof(alias), "%s%u", "test_three_stage", testIndex);
229     uint8_t handleE[sizeof(uint64_t)] = { 0 };
230     struct HksBlob handleBlob = { sizeof(uint64_t), handleE };
231     int32_t ret = GenerateKeyTest(alias);
232     EXPECT_EQ(ret, HKS_SUCCESS) << "GenerateKeyTest failed.";
233     ret = InitSessionTest(alias, &handleBlob);
234     EXPECT_EQ(ret, HKS_SUCCESS) << "InitSessionTest failed.";
235 
236     std::vector<std::thread> threads;
237     srand(time(nullptr));
238     uint32_t finishPos = static_cast<uint32_t>(rand() / RAND_MAX) * THREADS_NUM;
239 
240     for (uint32_t i = 0; i < THREADS_NUM; i++) {
241         if (finishPos == i) {
242             threads.emplace_back(std::thread(AbortSessionTest, &handleBlob));
243         } else {
244             threads.emplace_back(std::thread(UpdateSessionTest, &handleBlob));
245         }
246     }
247 
248     for (auto &t : threads) {
249         t.join();
250     }
251 
252     EXPECT_EQ(ret, HKS_SUCCESS) << "InitSessionTest failed.";
253 
254     std::vector<std::thread> threads2;
255     ret = InitSessionTest(alias, &handleBlob);
256     threads2.emplace_back(std::thread(FinishSessionTest, &handleBlob));
257     threads2.emplace_back(std::thread(AbortSessionTest, &handleBlob));
258 
259     for (auto &t : threads2) {
260         t.join();
261     }
262 
263     ret = DeleteKeyTest(alias);
264     EXPECT_EQ(ret, HKS_SUCCESS) << "DeleteKeyTest failed.";
265 }
266 
267 /**
268  * @tc.name: HksThreeStageMultiThreadTest.HksThreeStageMultiThreadTest001
269  * @tc.desc: test three stage multi thread test
270  * @tc.type: FUNC
271  */
272 HWTEST_F(HksThreeStageMultiThreadTest, HksThreeStageMultiThreadTest001, TestSize.Level0)
273 {
274     HKS_LOG_I("enter HksThreeStageMultiThreadTest001");
275     std::vector<std::thread> threads;
276 
277     for (uint32_t i = 0; i < THREADS_NUM; i++) {
278         threads.emplace_back(std::thread(&ThreeStageTest, i));
279     }
280 
281     for (auto &t : threads) {
282         t.join();
283     }
284     int32_t ret = HksInitialize();
285     ASSERT_TRUE(ret == HKS_SUCCESS);
286 }
287 }