1 /*
2 * Copyright (c) 2023-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 <cstdlib>
17 #include <fcntl.h>
18 #include <gtest/gtest.h>
19 #include <gtest/hwext/gtest-multithread.h>
20 #include <string>
21
22 #include "access_token_setter.h"
23 #include "byte_buffer.h"
24 #include "code_sign_utils.h"
25 #include "local_code_sign_kit.h"
26 #include "local_key_helper.h"
27 #include "log.h"
28
29 using namespace OHOS::Security::CodeSign;
30 using namespace std;
31 using namespace testing::ext;
32 using namespace testing::mt;
33
34 namespace OHOS {
35 namespace Security {
36 namespace CodeSign {
37 static constexpr uint32_t MULTI_THREAD_NUM = 10;
38 static constexpr int64_t BUFFER_SIZE = 1024;
39 static const std::string AN_BASE_PATH = "/data/local/ark-cache/tmp/multi_thread/";
40 static const std::string ORIGIN_AN_FILE = AN_BASE_PATH + "demo.an";
41 static const std::string DEMO_WITHOWNER_ID = AN_BASE_PATH + "demoWithownerID.an";
42
43 static const char *VALID_CALLER = "compiler_service";
44
GetFileSize(int32_t fd)45 uint64_t GetFileSize(int32_t fd)
46 {
47 struct stat st;
48 if (fstat(fd, &st) != 0) {
49 LOG_ERROR("Stat file failed, errno = <%{public}d, %{public}s>",
50 errno, strerror(errno));
51 return 0;
52 }
53 return st.st_size;
54 }
55
DupFile(const std::string & path)56 static bool DupFile(const std::string &path)
57 {
58 int32_t fin = open(ORIGIN_AN_FILE.c_str(), O_RDONLY);
59 if (fin < 0) {
60 return false;
61 }
62 uint32_t fileSize = GetFileSize(fin);
63 int32_t fout = open(path.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0777);
64 if (fout < 0) {
65 close(fin);
66 return false;
67 }
68 ssize_t curSize = 0;
69 char buffer[BUFFER_SIZE];
70 bool ret = true;
71 while (curSize < fileSize) {
72 ssize_t len = read(fin, buffer, BUFFER_SIZE);
73 if (len <= 0) {
74 break;
75 }
76 curSize += len;
77 write(fout, buffer, len);
78 }
79 close(fin);
80 close(fout);
81 return ret;
82 }
83
LocalCodeSignAndEnforce()84 void LocalCodeSignAndEnforce()
85 {
86 ByteBuffer sig;
87 uint64_t selfTokenId = NativeTokenSet(VALID_CALLER);
88 int ret = LocalCodeSignKit::SignLocalCode(ORIGIN_AN_FILE, sig);
89 std::thread::id thisId = std::this_thread::get_id();
90 std::ostringstream oss;
91 oss << thisId;
92 std::string thisIdStr = oss.str();
93 std::string tmpFileName = AN_BASE_PATH + thisIdStr + ".an";
94 EXPECT_EQ(DupFile(tmpFileName), true);
95 NativeTokenReset(selfTokenId);
96 EXPECT_EQ(ret, CS_SUCCESS);
97 ret = CodeSignUtils::EnforceCodeSignForFile(tmpFileName, sig);
98 EXPECT_EQ(ret, GetEnforceFileResult());
99 }
100
LocalCodeSignAndEnforceWithOwnerID()101 void LocalCodeSignAndEnforceWithOwnerID()
102 {
103 ByteBuffer sig;
104 uint64_t selfTokenId = NativeTokenSet(VALID_CALLER);
105 std::string ownerID = "AppName123";
106 int ret = LocalCodeSignKit::SignLocalCode(ownerID, DEMO_WITHOWNER_ID, sig);
107 std::thread::id thisId = std::this_thread::get_id();
108 std::ostringstream oss;
109 oss << thisId;
110 std::string thisIdStr = oss.str();
111 std::string tmpFileName = AN_BASE_PATH + thisIdStr + "demoWithownerID.an";
112 EXPECT_EQ(DupFile(tmpFileName), true);
113 NativeTokenReset(selfTokenId);
114 EXPECT_EQ(ret, CS_SUCCESS);
115 ret = CodeSignUtils::EnforceCodeSignForFile(tmpFileName, sig);
116 EXPECT_EQ(ret, GetEnforceFileResult());
117 }
118
119 class MultiThreadLocalSignTest : public testing::Test {
120 public:
MultiThreadLocalSignTest()121 MultiThreadLocalSignTest() {};
~MultiThreadLocalSignTest()122 virtual ~MultiThreadLocalSignTest() {};
SetUpTestCase()123 static void SetUpTestCase() {};
TearDownTestCase()124 static void TearDownTestCase() {};
SetUp()125 void SetUp() {};
TearDown()126 void TearDown() {};
127 };
128
129 /**
130 * @tc.name: MultiThreadLocalSignTest_0001
131 * @tc.desc: sign AN files and enforce using multi threads
132 * @tc.type: Func
133 * @tc.require:
134 */
135 HWMTEST_F(MultiThreadLocalSignTest, MultiThreadLocalSignTest_0001, TestSize.Level1, MULTI_THREAD_NUM)
136 {
137 LocalCodeSignAndEnforce();
138 }
139
140 /**
141 * @tc.name: MultiThreadLocalSignTest_0002
142 * @tc.desc: sign AN files with owner ID and enforce using multi threads
143 * @tc.type: Func
144 * @tc.require:
145 */
146 HWMTEST_F(MultiThreadLocalSignTest, MultiThreadLocalSignTest_0002, TestSize.Level1, MULTI_THREAD_NUM)
147 {
148 LocalCodeSignAndEnforceWithOwnerID();
149 }
150 } // namespace CodeSign
151 } // namespace Security
152 } // namespace OHOS