* 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 <string>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include "access_token_setter.h"
#include "byte_buffer.h"
#include "code_sign_attr_utils.h"
#include "code_sign_test_common.h"
#include "code_sign_utils.h"
#include "local_code_sign_client.h"
#include "local_code_sign_kit.h"
#include "local_code_sign_load_callback.h"
#include "local_key_helper.h"
#include "log.h"
#include "signer_info.h"
using namespace OHOS::Security::CodeSign;
using namespace testing::ext;
using namespace std;
namespace OHOS {
namespace Security {
namespace CodeSign {
static const std::string AN_BASE_PATH = "/data/local/ark-cache/tmp/";
static const std::string DEMO_AN_PATH = AN_BASE_PATH + "demo.an";
static const std::string DEMO_AN_PATH2 = AN_BASE_PATH + "demo2.an";
static const std::string EMPTY_FILE_PATH = AN_BASE_PATH + "empty.an";
class LocalCodeSignTest : public testing::Test {
public:
LocalCodeSignTest() {};
virtual ~LocalCodeSignTest() {};
static void SetUpTestCase() {};
static void TearDownTestCase() {};
void SetUp() {};
void TearDown() {};
};
* @tc.name: LocalCodeSignTest_0001
* @tc.desc: init local certificate successfully
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0001, TestSize.Level0)
{
ByteBuffer cert;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("key_enable"));
int ret = LocalCodeSignKit::InitLocalCertificate(cert);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_SUCCESS);
}
* @tc.name: LocalCodeSignTest_0002
* @tc.desc: init local certificate failed with invalid caller
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0002, TestSize.Level0)
{
ByteBuffer cert;
int ret = LocalCodeSignKit::InitLocalCertificate(cert);
EXPECT_EQ(ret, CS_ERR_NO_PERMISSION);
}
* @tc.name: LocalCodeSignTest_0003
* @tc.desc: sign local code successfully, owner ID is empty
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0003, TestSize.Level0)
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
int ret = LocalCodeSignKit::SignLocalCode(DEMO_AN_PATH, sig);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_SUCCESS);
std::string retOwnerID;
ret = CodeSignUtils::ParseOwnerIdFromSignature(sig, retOwnerID);
EXPECT_EQ(ret, CS_ERR_NO_OWNER_ID);
EXPECT_EQ(retOwnerID, "");
ret = CodeSignUtils::EnforceCodeSignForFile(DEMO_AN_PATH, sig);
EXPECT_EQ(ret, GetEnforceFileResult());
}
* @tc.name: LocalCodeSignTest_0004
* @tc.desc: sign local code failed with invalid caller
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0004, TestSize.Level0)
{
ByteBuffer sig;
int ret = LocalCodeSignKit::SignLocalCode(DEMO_AN_PATH, sig);
EXPECT_EQ(ret, CS_ERR_NO_PERMISSION);
}
* @tc.name: LocalCodeSignTest_0005
* @tc.desc: sign local code failed with wrong path
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0005, TestSize.Level0)
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
int ret = LocalCodeSignKit::SignLocalCode(DEMO_AN_PATH + "invalid", sig);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_ERR_FILE_PATH);
}
* @tc.name: LocalCodeSignTest_0006
* @tc.desc: local codesignsvr died
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0006, TestSize.Level0)
{
LocalCodeSignClient *client = GetLocalCodeSignClient();
EXPECT_NE(client, nullptr);
sptr<ISystemAbilityManager> systemAbilityManager =
SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
EXPECT_NE(systemAbilityManager, nullptr);
sptr<IRemoteObject> remoteObject =
systemAbilityManager->GetSystemAbility(LOCAL_CODE_SIGN_SA_ID);
client->OnRemoteLocalCodeSignSvrDied(remoteObject);
}
* @tc.name: LocalCodeSignTest_0007
* @tc.desc: sign local code with owner ID successfully, parse owner ID from signature success
* @tc.type: Func
* @tc.require: issueI88PPA
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0007, TestSize.Level0)
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
std::string ownerID = "AppName123";
int ret = LocalCodeSignKit::SignLocalCode(ownerID, DEMO_AN_PATH2, sig);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_SUCCESS);
std::string retOwnerID;
ret = CodeSignUtils::ParseOwnerIdFromSignature(sig, retOwnerID);
EXPECT_EQ(ownerID, retOwnerID);
ret = CodeSignUtils::EnforceCodeSignForFile(DEMO_AN_PATH2, sig);
EXPECT_EQ(ret, GetEnforceFileResult());
}
* @tc.name: LocalCodeSignTest_0008
* @tc.desc: sign local code with empty owner ID successfully
* @tc.type: Func
* @tc.require: issueI88PPA
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0008, TestSize.Level0)
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
std::string ownerID = "";
int ret = LocalCodeSignKit::SignLocalCode(ownerID, DEMO_AN_PATH2, sig);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_SUCCESS);
std::string retOwnerID;
ret = CodeSignUtils::ParseOwnerIdFromSignature(sig, retOwnerID);
EXPECT_EQ(ret, CS_ERR_NO_OWNER_ID);
EXPECT_EQ(retOwnerID, "");
}
* @tc.name: LocalCodeSignTest_0009
* @tc.desc: sign local code with owner ID failed, reason = invalid path
* @tc.type: Func
* @tc.require: issueI88PPA
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0009, TestSize.Level0)
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
std::string ownerID = "AppName123";
int ret = LocalCodeSignKit::SignLocalCode(ownerID, DEMO_AN_PATH2 + "invalid", sig);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_ERR_FILE_PATH);
}
* @tc.name: LocalCodeSignTest_0010
* @tc.desc: sign local code failed with invalid caller
* @tc.type: Func
* @tc.require: issueI88PPA
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0010, TestSize.Level0)
{
ByteBuffer sig;
std::string ownerID = "AppName123";
int ret = LocalCodeSignKit::SignLocalCode(ownerID, DEMO_AN_PATH2, sig);
EXPECT_EQ(ret, CS_ERR_NO_PERMISSION);
}
* @tc.name: LocalCodeSignTest_0011
* @tc.desc: sign local code failed with ownerID exceed 128 bytes
* @tc.type: Func
* @tc.require: issueI8FCGF
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0011, TestSize.Level0)
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
std::string ownerID(33, 'a');
int ret = LocalCodeSignKit::SignLocalCode(ownerID, DEMO_AN_PATH2, sig);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_ERR_INVALID_OWNER_ID);
}
* @tc.name: LocalCodeSignTest_0012
* @tc.desc: sign local code failed with ownerID exceed 128 bytes
* @tc.type: Func
* @tc.require: issueI8FCGF
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0012, TestSize.Level0)
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
std::string ownerID = "AppName123";
int ret = LocalCodeSignKit::SignLocalCode(ownerID, DEMO_AN_PATH2, sig);
EXPECT_TRUE(MockTokenId("local_code_sign"));
sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
EXPECT_NE(samgr, nullptr);
ret = samgr->UnloadSystemAbility(LOCAL_CODE_SIGN_SA_ID);
EXPECT_EQ(ret, ERR_OK);
EXPECT_TRUE(MockTokenId("compiler_service"));
LocalCodeSignKit::SignLocalCode(ownerID, DEMO_AN_PATH2, sig);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
}
* @tc.name: LocalCodeSignTest_0013
* @tc.desc: load sa success and return remote object is not null
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0013, TestSize.Level0)
{
LocalCodeSignLoadCallback cb;
cb.OnLoadSystemAbilityFail(LOCAL_CODE_SIGN_SA_ID);
cb.OnLoadSystemAbilitySuccess(LOCAL_CODE_SIGN_SA_ID - 1, nullptr);
cb.OnLoadSystemAbilitySuccess(LOCAL_CODE_SIGN_SA_ID, nullptr);
sptr<ISystemAbilityManager> systemAbilityManager =
SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
EXPECT_NE(systemAbilityManager, nullptr);
sptr<IRemoteObject> remoteObject =
systemAbilityManager->GetSystemAbility(LOCAL_CODE_SIGN_SA_ID);
cb.OnLoadSystemAbilitySuccess(LOCAL_CODE_SIGN_SA_ID, remoteObject);
}
* @tc.name: LocalCodeSignTest_0014
* @tc.desc: sign local code failed with ownerID equals SYSTEM_LIB_ID
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0014, TestSize.Level0)
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
std::string ownerID = OWNERID_SYSTEM_TAG;
int ret = LocalCodeSignKit::SignLocalCode(ownerID, DEMO_AN_PATH2, sig);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_ERR_FORBIDDEN_OWNER_ID);
}
* @tc.name: LocalCodeSignTest_0015
* @tc.desc: sign local code failed with ownerID equals COMPAT_LIB_ID
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0015, TestSize.Level0)
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
std::string ownerID = OWNERID_COMPAT_TAG;
int ret = LocalCodeSignKit::SignLocalCode(ownerID, DEMO_AN_PATH2, sig);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_ERR_FORBIDDEN_OWNER_ID);
}
* @tc.name: LocalCodeSignTest_0016
* @tc.desc: sign local code by fd successfully with empty owner ID
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0016, TestSize.Level0)
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
int fd = open(DEMO_AN_PATH.c_str(), O_RDONLY);
EXPECT_GE(fd, 0);
std::string ownerID;
int ret = LocalCodeSignKit::SignLocalCodeByFd(ownerID, fd, sig);
close(fd);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_SUCCESS);
}
* @tc.name: LocalCodeSignTest_0017
* @tc.desc: sign local code by fd failed with invalid caller
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0017, TestSize.Level0)
{
ByteBuffer sig;
int fd = open(DEMO_AN_PATH.c_str(), O_RDONLY);
EXPECT_GE(fd, 0);
std::string ownerID;
int ret = LocalCodeSignKit::SignLocalCodeByFd(ownerID, fd, sig);
close(fd);
EXPECT_EQ(ret, CS_ERR_NO_PERMISSION);
}
* @tc.name: LocalCodeSignTest_0018
* @tc.desc: sign local code by fd failed with invalid fd (negative)
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0018, TestSize.Level0)
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
std::string ownerID;
int ret = LocalCodeSignKit::SignLocalCodeByFd(ownerID, -1, sig);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_ERR_INVALID_FD);
}
* @tc.name: LocalCodeSignTest_0019
* @tc.desc: sign local code by fd successfully with owner ID, parse owner ID from signature success
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0019, TestSize.Level0)
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
std::string ownerID = "AppName123";
int fd = open(DEMO_AN_PATH2.c_str(), O_RDONLY);
EXPECT_GE(fd, 0);
int ret = LocalCodeSignKit::SignLocalCodeByFd(ownerID, fd, sig);
close(fd);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_SUCCESS);
std::string retOwnerID;
ret = CodeSignUtils::ParseOwnerIdFromSignature(sig, retOwnerID);
EXPECT_EQ(ownerID, retOwnerID);
ret = CodeSignUtils::EnforceCodeSignForFile(DEMO_AN_PATH2, sig);
EXPECT_EQ(ret, GetEnforceFileResult());
}
* @tc.name: LocalCodeSignTest_0021
* @tc.desc: sign local code by fd failed with ownerID exceeding 32 bytes
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0021, TestSize.Level0)
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
std::string ownerID(33, 'a');
int fd = open(DEMO_AN_PATH2.c_str(), O_RDONLY);
EXPECT_GE(fd, 0);
int ret = LocalCodeSignKit::SignLocalCodeByFd(ownerID, fd, sig);
close(fd);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_ERR_INVALID_OWNER_ID);
}
* @tc.name: LocalCodeSignTest_0022
* @tc.desc: sign local code by fd failed with ownerID equals SYSTEM_LIB_ID
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0022, TestSize.Level0)
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
std::string ownerID = OWNERID_SYSTEM_TAG;
int fd = open(DEMO_AN_PATH2.c_str(), O_RDONLY);
EXPECT_GE(fd, 0);
int ret = LocalCodeSignKit::SignLocalCodeByFd(ownerID, fd, sig);
close(fd);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_ERR_FORBIDDEN_OWNER_ID);
}
* @tc.name: LocalCodeSignTest_0023
* @tc.desc: sign local code by fd failed with ownerID equals COMPAT_LIB_ID
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0023, TestSize.Level0)
{
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
std::string ownerID = OWNERID_COMPAT_TAG;
int fd = open(DEMO_AN_PATH2.c_str(), O_RDONLY);
EXPECT_GE(fd, 0);
int ret = LocalCodeSignKit::SignLocalCodeByFd(ownerID, fd, sig);
close(fd);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_ERR_FORBIDDEN_OWNER_ID);
}
* @tc.name: LocalCodeSignTest_0024
* @tc.desc: sign local code by fd with empty file (libfsverity computes digest for size=0, signing succeeds)
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0024, TestSize.Level0)
{
if (GetEnforceFileResult() != CS_SUCCESS) {
GTEST_SKIP() << "Local signing key not provisioned, skipping empty file signing test";
}
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
int fd = open(EMPTY_FILE_PATH.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0644);
EXPECT_GE(fd, 0);
std::string ownerID = "AppName123";
int ret = LocalCodeSignKit::SignLocalCodeByFd(ownerID, fd, sig);
close(fd);
unlink(EMPTY_FILE_PATH.c_str());
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_SUCCESS);
}
* @tc.name: LocalCodeSignTest_0025
* @tc.desc: sign local code by fd with memfd (non-regular file)
* @tc.type: Func
* @tc.require:
*/
HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0025, TestSize.Level0)
{
if (GetEnforceFileResult() != CS_SUCCESS) {
GTEST_SKIP() << "Local signing key not provisioned, skipping memfd signing test";
}
int fd = memfd_create("test_memfd_sign", MFD_ALLOW_SEALING);
ASSERT_GE(fd, 0);
const char data[] = "memfd test data for code signing";
ssize_t written = write(fd, data, sizeof(data));
ASSERT_EQ(written, static_cast<ssize_t>(sizeof(data)));
lseek(fd, 0, SEEK_SET);
ByteBuffer sig;
uint64_t selfTokenId = GetSelfTokenID();
EXPECT_TRUE(MockTokenId("compiler_service"));
std::string ownerID = "MemfdTest";
int ret = LocalCodeSignKit::SignLocalCodeByFd(ownerID, fd, sig);
close(fd);
EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
EXPECT_EQ(ret, CS_SUCCESS);
}
}
}
}