* Copyright (c) 2023-2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cstdlib>
#include <fcntl.h>
#include <gtest/gtest.h>
#include <gtest/hwext/gtest-multithread.h>
#include <string>
#include "access_token_setter.h"
#include "byte_buffer.h"
#include "code_sign_test_common.h"
#include "code_sign_utils.h"
#include "local_code_sign_kit.h"
#include "local_key_helper.h"
#include "log.h"
using namespace OHOS::Security::CodeSign;
using namespace std;
using namespace testing::ext;
using namespace testing::mt;
namespace OHOS {
namespace Security {
namespace CodeSign {
static constexpr uint32_t MULTI_THREAD_NUM = 10;
static constexpr int64_t BUFFER_SIZE = 1024;
static const std::string AN_BASE_PATH = "/data/local/ark-cache/tmp/multi_thread/";
static const std::string ORIGIN_AN_FILE = AN_BASE_PATH + "demo.an";
static const std::string DEMO_WITHOWNER_ID = AN_BASE_PATH + "demoWithownerID.an";
static const char *VALID_CALLER = "compiler_service";
uint64_t GetFileSize(int32_t fd)
{
struct stat st;
if (fstat(fd, &st) != 0) {
LOG_ERROR("Stat file failed, errno = <%{public}d, %{public}s>",
errno, strerror(errno));
return 0;
}
return st.st_size;
}
static bool DupFile(const std::string &path)
{
int32_t fin = open(ORIGIN_AN_FILE.c_str(), O_RDONLY);
if (fin < 0) {
return false;
}
uint32_t fileSize = GetFileSize(fin);
int32_t fout = open(path.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0777);
if (fout < 0) {
close(fin);
return false;
}
ssize_t curSize = 0;
char buffer[BUFFER_SIZE];
bool ret = true;
while (curSize < fileSize) {
ssize_t len = read(fin, buffer, BUFFER_SIZE);
if (len <= 0) {
break;
}
curSize += len;
write(fout, buffer, len);
}
close(fin);
close(fout);
return ret;
}
void LocalCodeSignAndEnforce()
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId(VALID_CALLER));
int ret = LocalCodeSignKit::SignLocalCode(ORIGIN_AN_FILE, sig);
std::thread::id thisId = std::this_thread::get_id();
std::ostringstream oss;
oss << thisId;
std::string thisIdStr = oss.str();
std::string tmpFileName = AN_BASE_PATH + thisIdStr + ".an";
EXPECT_EQ(DupFile(tmpFileName), true);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_SUCCESS);
ret = CodeSignUtils::EnforceCodeSignForFile(tmpFileName, sig);
EXPECT_EQ(ret, GetEnforceFileResult());
}
void LocalCodeSignAndEnforceWithOwnerID()
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId(VALID_CALLER));
std::string ownerID = "AppName123";
int ret = LocalCodeSignKit::SignLocalCode(ownerID, DEMO_WITHOWNER_ID, sig);
std::thread::id thisId = std::this_thread::get_id();
std::ostringstream oss;
oss << thisId;
std::string thisIdStr = oss.str();
std::string tmpFileName = AN_BASE_PATH + thisIdStr + "demoWithownerID.an";
EXPECT_EQ(DupFile(tmpFileName), true);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_SUCCESS);
ret = CodeSignUtils::EnforceCodeSignForFile(tmpFileName, sig);
EXPECT_EQ(ret, GetEnforceFileResult());
}
class MultiThreadLocalSignTest : public testing::Test {
public:
MultiThreadLocalSignTest() {};
virtual ~MultiThreadLocalSignTest() {};
static void SetUpTestCase() {};
static void TearDownTestCase() {};
void SetUp() {};
void TearDown() {};
};
* @tc.name: MultiThreadLocalSignTest_0001
* @tc.desc: sign AN files and enforce using multi threads
* @tc.type: Func
* @tc.require:
*/
HWMTEST_F(MultiThreadLocalSignTest, MultiThreadLocalSignTest_0001, TestSize.Level1, MULTI_THREAD_NUM)
{
LocalCodeSignAndEnforce();
}
* @tc.name: MultiThreadLocalSignTest_0002
* @tc.desc: sign AN files with owner ID and enforce using multi threads
* @tc.type: Func
* @tc.require:
*/
HWMTEST_F(MultiThreadLocalSignTest, MultiThreadLocalSignTest_0002, TestSize.Level1, MULTI_THREAD_NUM)
{
LocalCodeSignAndEnforceWithOwnerID();
}
}
}
}