diff --git a/OAT.xml b/OAT.xml
index de43b3a52772cf67f1af61d8603165a9dd0837a4..20a119eccd893c3a0806a1a0e7aecd445897cab3 100644
--- a/OAT.xml
+++ b/OAT.xml
@@ -49,8 +49,14 @@
+
+
+
-
+
+
+
+
diff --git a/interfaces/innerkits/common/include/errcode.h b/interfaces/innerkits/common/include/errcode.h
index 1145993eb5a8222ab66783924d388fd1201f6eaf..ad3c25026ed4bebe45bf20ef7ed2932e74c6335b 100644
--- a/interfaces/innerkits/common/include/errcode.h
+++ b/interfaces/innerkits/common/include/errcode.h
@@ -96,6 +96,7 @@ enum SignBlockErrCode {
CS_ERR_SIGN_EXTENSION_OFFSET_ALIGN = -0x622,
CS_ERR_TARGET_FILE_PATH = -0x623,
CS_ERR_INVALID_OWNER_ID = -0x624,
+ CS_CODE_SIGN_NOT_EXISTS = -0x625,
};
}
}
diff --git a/services/key_enable/utils/BUILD.gn b/services/key_enable/utils/BUILD.gn
index c8c22abf6bb82c4c0c4a207505f1034fa90464b6..8bcde1a5980e940a76ab6d2bb6b6713bb6304551 100644
--- a/services/key_enable/utils/BUILD.gn
+++ b/services/key_enable/utils/BUILD.gn
@@ -16,7 +16,7 @@ import("../../../code_signature.gni")
ohos_static_library("libkey_enable_utils") {
sources = [
- "src/cert_utils.cpp",
+ "src/cert_path.cpp",
"src/key_utils.cpp",
"src/local_code_sign_utils.cpp",
]
diff --git a/services/key_enable/utils/include/cert_utils.h b/services/key_enable/utils/include/cert_path.h
similarity index 100%
rename from services/key_enable/utils/include/cert_utils.h
rename to services/key_enable/utils/include/cert_path.h
diff --git a/services/key_enable/utils/src/cert_utils.cpp b/services/key_enable/utils/src/cert_path.cpp
similarity index 98%
rename from services/key_enable/utils/src/cert_utils.cpp
rename to services/key_enable/utils/src/cert_path.cpp
index 3feacbd6f0bfdf44e4b472079ce88d057a5ce2aa..35e6ffd09f48b5419a3cbce76a490543e940df7a 100644
--- a/services/key_enable/utils/src/cert_utils.cpp
+++ b/services/key_enable/utils/src/cert_path.cpp
@@ -21,7 +21,7 @@
#include
#include "log.h"
#include "errcode.h"
-#include "cert_utils.h"
+#include "cert_path.h"
using namespace OHOS::Security::CodeSign;
diff --git a/test/fuzztest/local_code_sign_stub/signlocalcodestub_fuzzer/signlocalcodestub_fuzzer.cpp b/test/fuzztest/local_code_sign_stub/signlocalcodestub_fuzzer/signlocalcodestub_fuzzer.cpp
index 8ed4e3734cd88814a7748a3530c85ad7e3604534..ccd998a2bd5b4e1b3677bd29fbec498c31affdab 100644
--- a/test/fuzztest/local_code_sign_stub/signlocalcodestub_fuzzer/signlocalcodestub_fuzzer.cpp
+++ b/test/fuzztest/local_code_sign_stub/signlocalcodestub_fuzzer/signlocalcodestub_fuzzer.cpp
@@ -41,7 +41,6 @@ namespace OHOS {
SetSelfTokenID(tokenId);
}
-
bool SignLocalCodeStubFuzzTest(const uint8_t *data, size_t size)
{
if ((data == nullptr) || (size == 0)) {
diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn
index d4d216af80aea12b66ade7d2003a867666c48af7..c1e76fbbe1b93089901f8d9b70b2cdc49f470a12 100644
--- a/test/unittest/BUILD.gn
+++ b/test/unittest/BUILD.gn
@@ -14,9 +14,27 @@
import("//build/test.gni")
import("../../code_signature.gni")
-ohos_unittest("code_sign_ioctl_unittest") {
+ohos_source_set("key_enable_src_set") {
+ sources = [
+ "${code_signature_root_dir}/services/key_enable/utils/src/cert_path.cpp",
+ "utils/src/enable_key_utils.cpp",
+ ]
+ include_dirs = [
+ "utils/include",
+ "${code_signature_root_dir}/services/key_enable/utils/include",
+ ]
+ configs = [
+ "${code_signature_root_dir}:common_utils_config",
+ "${code_signature_root_dir}:common_public_config",
+ ]
+ external_deps = [ "hilog:libhilog" ]
+ part_name = "code_signature"
+ subsystem_name = "security"
+}
+
+ohos_unittest("add_cert_path_unittest") {
module_out_path = "security/code_signature"
- sources = [ "code_sign_ioctl_test.cpp" ]
+ sources = [ "add_cert_path_test.cpp" ]
deps = [ "${googletest_dir}:gtest" ]
}
@@ -27,11 +45,13 @@ ohos_unittest("code_sign_utils_unittest") {
sources = [ "code_sign_utils_test.cpp" ]
deps = [
+ ":key_enable_src_set",
"${code_signature_root_dir}/interfaces/innerkits/code_sign_utils:libcode_sign_utils",
"${googletest_dir}:gtest",
]
include_dirs = [
+ "utils/include",
"${code_signature_root_dir}/interfaces/innerkits/code_sign_utils/include",
"${code_signature_root_dir}/utils/include",
]
@@ -165,12 +185,33 @@ ohos_rust_unittest("rust_key_enable_unittest") {
part_name = "code_signature"
}
+ohos_unittest("enable_verity_ioctl_unittest") {
+ module_out_path = "security/code_signature"
+ resource_config_file = "resources/ohos_test.xml"
+ sources = [ "enable_verity_test.cpp" ]
+
+ include_dirs = [ "utils/include" ]
+ configs = [
+ "${code_signature_root_dir}:common_utils_config",
+ "${code_signature_root_dir}:common_public_config",
+ ]
+ deps = [
+ ":key_enable_src_set",
+ "${googletest_dir}:gtest",
+ ]
+ external_deps = [
+ "c_utils:utils",
+ "hilog:libhilog",
+ ]
+}
+
group("unittest_group") {
testonly = true
if (!defined(ohos_lite)) {
deps = [
- ":code_sign_ioctl_unittest",
+ ":add_cert_path_unittest",
":code_sign_utils_unittest",
+ ":enable_verity_ioctl_unittest",
":local_code_sign_unittest",
":multi_thread_local_sign_unittest",
":rust_key_enable_unittest",
diff --git a/test/unittest/code_sign_ioctl_test.cpp b/test/unittest/add_cert_path_test.cpp
similarity index 83%
rename from test/unittest/code_sign_ioctl_test.cpp
rename to test/unittest/add_cert_path_test.cpp
index 848c05ec56e8211581a98b39eedad115a75c48ed..17c0ed4a3f98add000867be9b932a9af40f4b2de 100644
--- a/test/unittest/code_sign_ioctl_test.cpp
+++ b/test/unittest/add_cert_path_test.cpp
@@ -46,6 +46,16 @@ static const string DEV_NAME = "/dev/code_sign";
static const string TEST_SUBJECT = "OpenHarmony Application Release";
static const string TEST_ISSUER = "OpenHarmony Application CA";
+class AddCertPathTest : public testing::Test {
+public:
+ AddCertPathTest() {};
+ virtual ~AddCertPathTest() {};
+ static void SetUpTestCase() {};
+ static void TearDownTestCase() {};
+ void SetUp() {};
+ void TearDown() {};
+};
+
static bool CallIoctl(const char *signing, const char *issuer, uint32_t max_cert_chain)
{
int fd = open(DEV_NAME.c_str(), O_WRONLY);
@@ -63,47 +73,37 @@ static bool CallIoctl(const char *signing, const char *issuer, uint32_t max_cert
return ret;
}
-class CodeSignIoctlTest : public testing::Test {
-public:
- CodeSignIoctlTest() {};
- virtual ~CodeSignIoctlTest() {};
- static void SetUpTestCase() {};
- static void TearDownTestCase() {};
- void SetUp() {};
- void TearDown() {};
-};
-
/**
- * @tc.name: CodeSignIoctlTest_0001
+ * @tc.name: AddCertPathTest_0001
* @tc.desc: successfully called interface
* @tc.type: Func
* @tc.require:
*/
-HWTEST_F(CodeSignIoctlTest, CodeSignIoctlTest_0001, TestSize.Level0)
+HWTEST_F(AddCertPathTest, AddCertPathTest_0001, TestSize.Level0)
{
int ret = CallIoctl(TEST_SUBJECT.c_str(), TEST_ISSUER.c_str(), MAX_CERT_CHAIN);
EXPECT_EQ(ret, 0);
}
/**
- * @tc.name: CodeSignIoctlTest_0002
+ * @tc.name: AddCertPathTest_0002
* @tc.desc: calling interface with greater than path len
* @tc.type: Func
* @tc.require:
*/
-HWTEST_F(CodeSignIoctlTest, CodeSignIoctlTest_0002, TestSize.Level0)
+HWTEST_F(AddCertPathTest, AddCertPathTest_0002, TestSize.Level0)
{
int ret = CallIoctl(TEST_SUBJECT.c_str(), TEST_ISSUER.c_str(), GREATER_THAN_MAX_CERT_CHAIN);
EXPECT_NE(ret, 0);
}
/**
- * @tc.name: CodeSignIoctlTest_0003
+ * @tc.name: AddCertPathTest_0003
* @tc.desc: calling interface with invalid path len
* @tc.type: Func
* @tc.require:
*/
-HWTEST_F(CodeSignIoctlTest, CodeSignIoctlTest_0003, TestSize.Level0)
+HWTEST_F(AddCertPathTest, AddCertPathTest_0003, TestSize.Level0)
{
int ret = CallIoctl(TEST_SUBJECT.c_str(), TEST_ISSUER.c_str(), LESS_THAN_MIN_CERT_CHAIN);
EXPECT_NE(ret, 0);
diff --git a/test/unittest/code_sign_utils_test.cpp b/test/unittest/code_sign_utils_test.cpp
index 22b191df605d1977055df0f7030d7c013b04c309..67ad295afa93bcb61ea8c58ac1893b5325f1626d 100644
--- a/test/unittest/code_sign_utils_test.cpp
+++ b/test/unittest/code_sign_utils_test.cpp
@@ -23,6 +23,7 @@
#include "code_sign_utils.h"
#include "code_sign_block.h"
+#include "enable_key_utils.h"
namespace OHOS {
namespace Security {
@@ -30,22 +31,9 @@ namespace CodeSign {
using namespace testing::ext;
using namespace std;
-struct cert_chain_info {
- uint32_t signing_length;
- uint32_t issuer_length;
- uint64_t signing;
- uint64_t issuer;
- uint32_t max_cert_chain;
- uint8_t reserved[36];
-};
-
-#define WRITE_CERT_CHAIN _IOW('k', 1, cert_chain_info)
-
-static const uint32_t MAX_CERT_CHAIN = 3;
static const std::string TMP_BASE_PATH = "/data/service/el1/public/bms/bundle_manager_service/tmp";
static const std::string TEST_APP_DTAT_DIR = "/data/app/el1/bundle/public/com.example.codesignaturetest";
static const std::string APP_BASE_PATH = "/data/app/el1/bundle/public/tmp";
-static const string DEV_NAME = "/dev/code_sign";
static const string SUBJECT = "Huawei: HarmonyOS Application Code Signature";
static const string ISSUER = "Huawei CBG Software Signing Service CA Test";
static const string OH_SUBJECT = "OpenHarmony Application Release";
@@ -127,29 +115,16 @@ class CodeSignUtilsTest : public testing::Test {
public:
CodeSignUtilsTest() {};
virtual ~CodeSignUtilsTest() {};
- static void SetUpTestCase() {};
+ static void SetUpTestCase()
+ {
+ EXPECT_EQ(EnableTestKey(SUBJECT.c_str(), ISSUER.c_str()), 0);
+ EXPECT_EQ(EnableTestKey(OH_SUBJECT.c_str(), OH_ISSUER.c_str()), 0);
+ };
static void TearDownTestCase() {};
void SetUp() {};
void TearDown() {};
};
-static bool CallIoctl(const char *signing, const char *issuer, uint32_t max_cert_chain)
-{
- int fd = open(DEV_NAME.c_str(), O_WRONLY);
- EXPECT_GE(fd, 0);
-
- cert_chain_info arg = { 0 };
- arg.signing = reinterpret_cast(signing);
- arg.issuer = reinterpret_cast(issuer);
- arg.signing_length = strlen(signing) + 1;
- arg.issuer_length = strlen(issuer) + 1;
- arg.max_cert_chain = max_cert_chain;
- int ret = ioctl(fd, WRITE_CERT_CHAIN, &arg);
-
- close(fd);
- return ret;
-}
-
static bool ReadSignatureFromFile(const std::string &path, ByteBuffer &data)
{
FILE *file = fopen(path.c_str(), "rb");
@@ -341,14 +316,11 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0010, TestSize.Level0)
*/
HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0011, TestSize.Level0)
{
- int ret = CallIoctl(SUBJECT.c_str(), ISSUER.c_str(), MAX_CERT_CHAIN);
- EXPECT_EQ(ret, 0);
-
ByteBuffer buffer;
bool flag = ReadSignatureFromFile(g_filesigEnablePath, buffer);
EXPECT_EQ(flag, true);
- ret = CodeSignUtils::EnforceCodeSignForFile(g_fileEnableSuc, buffer);
+ int32_t ret = CodeSignUtils::EnforceCodeSignForFile(g_fileEnableSuc, buffer);
EXPECT_EQ(ret, CS_SUCCESS);
}
@@ -360,10 +332,7 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0011, TestSize.Level0)
*/
HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0012, TestSize.Level0)
{
- int ret = CallIoctl(SUBJECT.c_str(), ISSUER.c_str(), MAX_CERT_CHAIN);
- EXPECT_EQ(ret, 0);
-
- ret = CodeSignUtils::EnforceCodeSignForApp(g_hapWithoutLibRetSuc, g_sigWithoutLibRetSucPath);
+ int32_t ret = CodeSignUtils::EnforceCodeSignForApp(g_hapWithoutLibRetSuc, g_sigWithoutLibRetSucPath);
EXPECT_EQ(ret, CS_SUCCESS);
ret = CodeSignUtils::EnforceCodeSignForApp(g_hapWithMultiLibRetSuc, g_sigWithMultiLibRetSucPath);
@@ -500,9 +469,7 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0017, TestSize.Level0)
{
std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/entry-default-signed-debug.hap";
EntryMap entryMap;
- int ret = CallIoctl(OH_SUBJECT.c_str(), OH_ISSUER.c_str(), MAX_CERT_CHAIN);
- EXPECT_EQ(ret, 0);
- ret = CodeSignUtils::EnforceCodeSignForAppWithOwnerId("DEBUG_LIB_ID", hapRealPath, entryMap, FILE_SELF);
+ int32_t ret = CodeSignUtils::EnforceCodeSignForAppWithOwnerId("DEBUG_LIB_ID", hapRealPath, entryMap, FILE_SELF);
EXPECT_EQ(ret, CS_SUCCESS);
}
@@ -516,9 +483,8 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0018, TestSize.Level0)
{
std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/entry-default-signed-release.hap";
EntryMap entryMap;
- int ret = CallIoctl(OH_SUBJECT.c_str(), OH_ISSUER.c_str(), MAX_CERT_CHAIN);
- EXPECT_EQ(ret, 0);
- ret = CodeSignUtils::EnforceCodeSignForAppWithOwnerId("test-app-identifier", hapRealPath, entryMap, FILE_SELF);
+ int32_t ret = CodeSignUtils::EnforceCodeSignForAppWithOwnerId("test-app-identifier",
+ hapRealPath, entryMap, FILE_SELF);
EXPECT_EQ(ret, CS_SUCCESS);
}
@@ -532,9 +498,7 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0019, TestSize.Level0)
{
std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/entry-default-signed-debug.hap";
EntryMap entryMap;
- int ret = CallIoctl(OH_SUBJECT.c_str(), OH_ISSUER.c_str(), MAX_CERT_CHAIN);
- EXPECT_EQ(ret, 0);
- ret = CodeSignUtils::EnforceCodeSignForAppWithOwnerId("INVALID_ID", hapRealPath, entryMap, FILE_SELF);
+ int32_t ret = CodeSignUtils::EnforceCodeSignForAppWithOwnerId("INVALID_ID", hapRealPath, entryMap, FILE_SELF);
EXPECT_EQ(ret, CS_ERR_INVALID_OWNER_ID);
}
@@ -548,9 +512,7 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0020, TestSize.Level0)
{
std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/entry-default-signed-release.hap";
EntryMap entryMap;
- int ret = CallIoctl(OH_SUBJECT.c_str(), OH_ISSUER.c_str(), MAX_CERT_CHAIN);
- EXPECT_EQ(ret, 0);
- ret = CodeSignUtils::EnforceCodeSignForAppWithOwnerId("INVALID_ID", hapRealPath, entryMap, FILE_SELF);
+ int32_t ret = CodeSignUtils::EnforceCodeSignForAppWithOwnerId("INVALID_ID", hapRealPath, entryMap, FILE_SELF);
EXPECT_EQ(ret, CS_ERR_INVALID_OWNER_ID);
}
} // namespace CodeSign
diff --git a/test/unittest/enable_verity_test.cpp b/test/unittest/enable_verity_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1054705ad0b243bf21153adaf039dcb657fe4d06
--- /dev/null
+++ b/test/unittest/enable_verity_test.cpp
@@ -0,0 +1,487 @@
+/*
+ * Copyright (c) 2023 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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "byte_buffer.h"
+#include "directory_ex.h"
+#include "enable_key_utils.h"
+#include "log.h"
+
+using namespace testing::ext;
+
+namespace OHOS {
+namespace Security {
+namespace CodeSign {
+constexpr uint32_t HASH_PAGE_SIZE = 4096;
+constexpr uint32_t BUFFER_LENGTH = 4096;
+
+const std::string TEST_FILES_DIR = "/data/test/tmp/";
+const std::string TEST_FILES_LIST[] = {
+ "file_4K/file_4K",
+ "file_4K_greater/file_4K_greater",
+ "file_4K_less/file_4K_less",
+ "file_4M/file_4M",
+ "file_4M_greater/file_4M_greater",
+ "file_4M_less/file_4M_less"
+};
+const int TEST_FILE_NUM = sizeof(TEST_FILES_LIST) / sizeof(TEST_FILES_LIST[0]);
+const std::string TEST_DEFAULT_FILE = TEST_FILES_DIR + "file_4M_greater/file_4M_greater";
+const std::string FAKE_STRING = "AAAAA";
+
+const std::string TEST_SUBJECT = "OpenHarmony Application Release";
+const std::string TEST_ISSUER = "OpenHarmony Application CA";
+
+class EnableVerityTest : public testing::Test {
+public:
+ EnableVerityTest() {};
+ virtual ~EnableVerityTest() {};
+ static void SetUpTestCase()
+ {
+ EXPECT_EQ(EnableTestKey(TEST_SUBJECT.c_str(), TEST_ISSUER.c_str()), 0);
+ };
+ static void TearDownTestCase() {};
+ void SetUp() {};
+ void TearDown() {};
+};
+
+static size_t GetFileSize(const std::string &path)
+{
+ FILE *file = fopen(path.c_str(), "rb");
+ if (file == nullptr) {
+ return false;
+ }
+ if (fseek(file, 0L, SEEK_END) != 0) {
+ (void)fclose(file);
+ return false;
+ }
+ size_t fileSize = ftell(file);
+ (void)fclose(file);
+ return fileSize;
+}
+
+static bool ReadDataFromFile(const std::string &path, ByteBuffer &data)
+{
+ FILE *file = fopen(path.c_str(), "rb");
+ if (file == nullptr) {
+ return false;
+ }
+ if (fseek(file, 0L, SEEK_END) != 0) {
+ (void)fclose(file);
+ return false;
+ }
+
+ size_t fileSize = ftell(file);
+ if (fileSize == 0) {
+ (void)fclose(file);
+ return true;
+ }
+ rewind(file);
+ if (!data.Resize(fileSize)) {
+ (void)fclose(file);
+ return false;
+ }
+ size_t ret = fread(data.GetBuffer(), 1, fileSize, file);
+ (void)fclose(file);
+ if (ret < fileSize) {
+ LOG_ERROR(LABEL, "Read size (%{public}zu) < file size", ret);
+ return false;
+ }
+ return true;
+}
+
+static void CopyData(const std::string &srcPath, FILE *fout)
+{
+ ByteBuffer data;
+ EXPECT_EQ(ReadDataFromFile(srcPath, data), true);
+ if (data.GetSize() > 0) {
+ int32_t ret = fwrite(data.GetBuffer(), 1, data.GetSize(), fout);
+ EXPECT_EQ(ret, data.GetSize());
+ }
+}
+
+static bool CopyFile(const std::string &srcPath, const std::string &dstPath)
+{
+ FILE *fout = fopen(dstPath.c_str(), "wb");
+ if (fout == nullptr) {
+ return false;
+ }
+ CopyData(srcPath, fout);
+ (void)fclose(fout);
+ return true;
+}
+
+static void CleanFile(const std::string &filePath)
+{
+ EXPECT_EQ(OHOS::RemoveFile(filePath), true);
+}
+
+static bool ExpandFile(const std::string &srcPath, const std::string &expandDataFile,
+ size_t gapSize, const std::string &dstPath)
+{
+ FILE *fout = fopen(dstPath.c_str(), "wb");
+ if (fout == nullptr) {
+ return false;
+ }
+ CopyData(srcPath, fout);
+ uint8_t buffer[BUFFER_LENGTH];
+ (void)memset_s(buffer, BUFFER_LENGTH, 0, BUFFER_LENGTH);
+ size_t writeSize = BUFFER_LENGTH;
+ size_t totalSize = 0;
+ size_t ret;
+ while (totalSize < gapSize) {
+ if (gapSize - totalSize < BUFFER_LENGTH) {
+ writeSize = gapSize - totalSize;
+ }
+ ret = fwrite(buffer, 1, writeSize, fout);
+ if (ret != writeSize) {
+ (void)fclose(fout);
+ return false;
+ }
+ LOG_ERROR(LABEL, "write padding = %{public}zu", writeSize);
+ totalSize += writeSize;
+ }
+ CopyData(expandDataFile, fout);
+ (void)fclose(fout);
+ return true;
+}
+
+static void DropAllCaches()
+{
+ std::fstream fout;
+ fout.open("/proc/sys/vm/drop_caches", std::ios::out);
+ fout << "3";
+ fout.close();
+}
+
+static void CheckEnableSuccess(const std::string &filePath)
+{
+ DropAllCaches();
+ FILE *fout = fopen(filePath.c_str(), "wb");
+ EXPECT_EQ(fout, nullptr);
+
+ ByteBuffer tmp;
+ EXPECT_EQ(ReadDataFromFile(filePath, tmp), true);
+}
+
+static inline size_t GetRoundUp(size_t fileSize)
+{
+ return ceil((double)fileSize / HASH_PAGE_SIZE) * HASH_PAGE_SIZE;
+}
+
+static bool TamperFileTail(const std::string &filePath)
+{
+ FILE *file = fopen(filePath.c_str(), "ab");
+ if (file == nullptr) {
+ return false;
+ }
+ if (fseek(file, 0L, SEEK_END) != 0) {
+ (void)fclose(file);
+ return false;
+ }
+
+ size_t fileSize = ftell(file);
+ if (fseek(file, fileSize - FAKE_STRING.size(), SEEK_SET)) {
+ (void)fclose(file);
+ return false;
+ }
+ int32_t ret = fwrite(FAKE_STRING.c_str(), 1, FAKE_STRING.size(), file);
+ EXPECT_EQ(ret, FAKE_STRING.size());
+ (void)fclose(file);
+ return true;
+}
+
+static bool TamperFileHead(const std::string &filePath)
+{
+ FILE *file = fopen(filePath.c_str(), "ab");
+ if (file == nullptr) {
+ return false;
+ }
+ if (fseek(file, 0L, SEEK_SET) != 0) {
+ (void)fclose(file);
+ return false;
+ }
+
+ int32_t ret = fwrite(FAKE_STRING.c_str(), 1, FAKE_STRING.size(), file);
+ EXPECT_EQ(ret, FAKE_STRING.size());
+ (void)fclose(file);
+ return true;
+}
+
+int32_t EnableVerityOnOneFile(const std::string filePath,
+ struct code_sign_enable_arg *arg)
+{
+ int fd = open(filePath.c_str(), O_RDONLY);
+ int ret = 0;
+
+ int error = ioctl(fd, FS_IOC_ENABLE_CODE_SIGN, arg);
+ if (error < 0) {
+ LOG_ERROR(LABEL, "Enable fs-verity failed, errno = <%{public}d, %{public}s>",
+ errno, strerror(errno));
+ ret = errno;
+ }
+ close(fd);
+ return ret;
+}
+
+static std::string MakeExpandTreeFile(const std::string &filePath,
+ struct code_sign_enable_arg *arg)
+{
+ size_t treeOffset = GetRoundUp(arg->data_size);
+ std::string expandFilePath = filePath + "_expand_tree";
+ EXPECT_EQ(ExpandFile(filePath, filePath + ".tree",
+ treeOffset - arg->data_size, expandFilePath), true);
+ return expandFilePath;
+}
+
+static void FillCommonArgs(const std::string &filePath, bool isInsideTree,
+ struct code_sign_enable_arg *arg, ByteBuffer &signature)
+{
+ bool ret;
+
+ if (isInsideTree) {
+ ret = ReadDataFromFile(filePath + "_inside_tree.sig", signature);
+ } else {
+ ret = ReadDataFromFile(filePath + "_no_tree.sig", signature);
+ }
+ EXPECT_EQ(ret, true);
+
+ size_t fileSize = GetFileSize(filePath);
+ arg->version = 1;
+ arg->cs_version = 1; // version of code signing features
+ arg->hash_algorithm = 1;
+ arg->block_size = HASH_PAGE_SIZE;
+ arg->salt_ptr = 0;
+ arg->salt_size = 0;
+ arg->data_size = fileSize;
+ arg->sig_size = signature.GetSize();
+ arg->sig_ptr = reinterpret_cast(signature.GetBuffer());
+}
+
+static void FillOptional(const std::string &filePath, struct code_sign_enable_arg *arg)
+{
+ ByteBuffer rootHash;
+ EXPECT_EQ(ReadDataFromFile(filePath + ".hash", rootHash), true);
+ arg->flags = 1;
+ arg->tree_offset = GetRoundUp(arg->data_size);
+ arg->root_hash_ptr = reinterpret_cast(rootHash.GetBuffer());
+}
+
+static void EnableExpandedTamperFile(const std::string &filePath,
+ bool (*tamperFileFunc)(const std::string &filePath))
+{
+ struct code_sign_enable_arg arg = {};
+ ByteBuffer signature;
+ FillCommonArgs(filePath, true, &arg, signature);
+ FillOptional(filePath, &arg);
+
+ // tamper file
+ std::string tmpFilePath = filePath + "_tmp";
+ EXPECT_EQ(CopyFile(filePath, tmpFilePath), true);
+ EXPECT_EQ(tamperFileFunc(tmpFilePath), true);
+
+ // expand tampered file
+ std::string treeFile = filePath + ".tree";
+ std::string expandFilePath = filePath + "_expand_tree";
+ size_t treeOffset = GetRoundUp(arg.data_size);
+ EXPECT_EQ(ExpandFile(tmpFilePath, treeFile,
+ treeOffset - arg.data_size, expandFilePath), true);
+
+ // Enable successully but cannot read
+ EXPECT_EQ(EnableVerityOnOneFile(expandFilePath, &arg), 0);
+ ByteBuffer tmp;
+ EXPECT_EQ(ReadDataFromFile(expandFilePath, tmp), false);
+
+ CleanFile(expandFilePath);
+}
+
+/**
+ * @tc.name: CodeSignUtilsTest_0001
+ * @tc.desc: enable all data in file successfully
+ * @tc.type: Func
+ * @tc.require:I8DH28
+ */
+HWTEST_F(EnableVerityTest, EnableVerityTest_0001, TestSize.Level0)
+{
+ for (int i = 0; i < TEST_FILE_NUM; i++) {
+ std::string filePath = TEST_FILES_DIR + TEST_FILES_LIST[i];
+ LOG_INFO(LABEL, "Test on file path = %{public}s", filePath.c_str());
+ struct code_sign_enable_arg arg = {};
+ ByteBuffer signature;
+ FillCommonArgs(filePath, false, &arg, signature);
+ std::string copiedFile = filePath + "_copy";
+ EXPECT_EQ(CopyFile(filePath, copiedFile), true);
+ EXPECT_EQ(EnableVerityOnOneFile(copiedFile, &arg), 0);
+ CheckEnableSuccess(copiedFile);
+ CleanFile(copiedFile);
+ }
+}
+
+/**
+ * @tc.name: CodeSignUtilsTest_0002
+ * @tc.desc: enable orignial file with wrong file size
+ * @tc.type: Func
+ * @tc.require:I8DH28
+ */
+HWTEST_F(EnableVerityTest, EnableVerityTest_0002, TestSize.Level0)
+{
+ std::string filePath = TEST_DEFAULT_FILE;
+
+ struct code_sign_enable_arg arg = {};
+ ByteBuffer signature;
+ FillCommonArgs(filePath, false, &arg, signature);
+
+ std::string copiedFile = filePath + "_copy";
+ EXPECT_EQ(CopyFile(filePath, copiedFile), true);
+
+ uint32_t fileSize = arg.data_size;
+ // size is set to less than file size
+ // descriptor is unmatched, signature verification failed.
+ arg.data_size = fileSize - 1;
+ EXPECT_EQ(EnableVerityOnOneFile(copiedFile, &arg), EKEYREJECTED);
+
+ // size is set to greater than file size
+ // unable to pass parameter check
+ arg.data_size = fileSize + 1;
+ EXPECT_EQ(EnableVerityOnOneFile(copiedFile, &arg), EINVAL);
+
+ CleanFile(copiedFile);
+}
+
+/**
+ * @tc.name: CodeSignUtilsTest_0003
+ * @tc.desc: enable expanded file successfully
+ * @tc.type: Func
+ * @tc.require:I8DH28
+ */
+HWTEST_F(EnableVerityTest, EnableVerityTest_0003, TestSize.Level0)
+{
+ for (int i = 0; i < TEST_FILE_NUM; i++) {
+ std::string filePath = TEST_FILES_DIR + TEST_FILES_LIST[i];
+ struct code_sign_enable_arg arg = {};
+ ByteBuffer signature;
+ FillCommonArgs(filePath, false, &arg, signature);
+
+ std::string expandFilePath = MakeExpandTreeFile(filePath, &arg);
+ EXPECT_EQ(EnableVerityOnOneFile(expandFilePath, &arg), 0);
+ CheckEnableSuccess(expandFilePath);
+ CleanFile(expandFilePath);
+ }
+}
+
+/**
+ * @tc.name: CodeSignUtilsTest_0004
+ * @tc.desc: enable expanded file with inside tree successfully
+ * @tc.type: Func
+ * @tc.require:I8DH28
+ */
+HWTEST_F(EnableVerityTest, EnableVerityTest_0004, TestSize.Level0)
+{
+ for (int i = 0; i < TEST_FILE_NUM; i++) {
+ std::string filePath = TEST_FILES_DIR + TEST_FILES_LIST[i];
+ LOG_INFO(LABEL, "Test on file path = %{public}s", filePath.c_str());
+
+ struct code_sign_enable_arg arg = {};
+ ByteBuffer signature;
+ FillCommonArgs(filePath, true, &arg, signature);
+ FillOptional(filePath, &arg);
+ std::string expandFilePath = MakeExpandTreeFile(filePath, &arg);
+ EXPECT_EQ(EnableVerityOnOneFile(expandFilePath, &arg), 0);
+ CheckEnableSuccess(expandFilePath);
+ CleanFile(expandFilePath);
+ }
+}
+
+/**
+ * @tc.name: CodeSignUtilsTest_0005
+ * @tc.desc: enable expanded file with wrong tree offset
+ * @tc.type: Func
+ * @tc.require:I8DH28
+ */
+HWTEST_F(EnableVerityTest, EnableVerityTest_0005, TestSize.Level0)
+{
+ std::string filePath = TEST_DEFAULT_FILE;
+ struct code_sign_enable_arg arg = {};
+ ByteBuffer signature;
+ FillCommonArgs(filePath, true, &arg, signature);
+ FillOptional(filePath, &arg);
+ std::string expandFilePath = MakeExpandTreeFile(filePath, &arg);
+
+ uint32_t treeOffset = arg.tree_offset;
+ // byte alignment check failed
+ arg.tree_offset = treeOffset + 1;
+ EXPECT_EQ(EnableVerityOnOneFile(expandFilePath, &arg), EINVAL);
+
+ // unmatched fsverity descriptor
+ arg.tree_offset = treeOffset - HASH_PAGE_SIZE;
+ EXPECT_EQ(EnableVerityOnOneFile(expandFilePath, &arg), EKEYREJECTED);
+
+ CleanFile(expandFilePath);
+}
+
+/**
+ * @tc.name: CodeSignUtilsTest_0006
+ * @tc.desc: enable expanded file with wrong root hash
+ * @tc.type: Func
+ * @tc.require:I8DH28
+ */
+HWTEST_F(EnableVerityTest, EnableVerityTest_0006, TestSize.Level0)
+{
+ std::string filePath = TEST_DEFAULT_FILE;
+ struct code_sign_enable_arg arg = {};
+ ByteBuffer signature;
+ FillCommonArgs(filePath, true, &arg, signature);
+ FillOptional(filePath, &arg);
+ std::string expandFilePath = MakeExpandTreeFile(filePath, &arg);
+
+ (void)memcpy_s(reinterpret_cast(arg.root_hash_ptr),
+ FAKE_STRING.size(), FAKE_STRING.c_str(), FAKE_STRING.size());
+
+ EXPECT_EQ(EnableVerityOnOneFile(expandFilePath, &arg), EKEYREJECTED);
+
+ CleanFile(expandFilePath);
+}
+
+/**
+ * @tc.name: CodeSignUtilsTest_0007
+ * @tc.desc: enable expanded file with wrong file
+ * @tc.type: Func
+ * @tc.require:I8DH28
+ */
+HWTEST_F(EnableVerityTest, EnableVerityTest_0007, TestSize.Level0)
+{
+ std::string filePath = TEST_DEFAULT_FILE;
+ EnableExpandedTamperFile(filePath, TamperFileHead);
+
+ EnableExpandedTamperFile(filePath, TamperFileTail);
+}
+} // namespace CodeSign
+} // namespace Security
+} // namespace OHOS
diff --git a/test/unittest/resources/demo_verity/file_4K/file_4K b/test/unittest/resources/demo_verity/file_4K/file_4K
new file mode 100644
index 0000000000000000000000000000000000000000..ef6ce649d71849f425f4152130fd2b656c29065a
Binary files /dev/null and b/test/unittest/resources/demo_verity/file_4K/file_4K differ
diff --git a/test/unittest/resources/demo_verity/file_4K/file_4K.hash b/test/unittest/resources/demo_verity/file_4K/file_4K.hash
new file mode 100644
index 0000000000000000000000000000000000000000..f05da993ebf2dfa7a1e5741f4cf4a37a5bb3fe98
--- /dev/null
+++ b/test/unittest/resources/demo_verity/file_4K/file_4K.hash
@@ -0,0 +1,2 @@
+ׇoK:ki#DxZ
+(=
\ No newline at end of file
diff --git a/test/unittest/resources/demo_verity/file_4K/file_4K.tree b/test/unittest/resources/demo_verity/file_4K/file_4K.tree
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test/unittest/resources/demo_verity/file_4K/file_4K_expand_tree b/test/unittest/resources/demo_verity/file_4K/file_4K_expand_tree
new file mode 100644
index 0000000000000000000000000000000000000000..1020fe35b73cde34ff3c1d9363798a92322049d1
Binary files /dev/null and b/test/unittest/resources/demo_verity/file_4K/file_4K_expand_tree differ
diff --git a/test/unittest/resources/demo_verity/file_4K/file_4K_inside_tree.sig b/test/unittest/resources/demo_verity/file_4K/file_4K_inside_tree.sig
new file mode 100644
index 0000000000000000000000000000000000000000..c721521235d72da8aecdfd1e5b43128bbd34d5cf
Binary files /dev/null and b/test/unittest/resources/demo_verity/file_4K/file_4K_inside_tree.sig differ
diff --git a/test/unittest/resources/demo_verity/file_4K/file_4K_no_tree.sig b/test/unittest/resources/demo_verity/file_4K/file_4K_no_tree.sig
new file mode 100644
index 0000000000000000000000000000000000000000..83677cb396b77a410544b7e5b638d8f9d133ba4c
Binary files /dev/null and b/test/unittest/resources/demo_verity/file_4K/file_4K_no_tree.sig differ
diff --git a/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater b/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater
new file mode 100644
index 0000000000000000000000000000000000000000..688a743d914decba64ff66a70acd835b9cbc00a6
Binary files /dev/null and b/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater differ
diff --git a/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater.hash b/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater.hash
new file mode 100644
index 0000000000000000000000000000000000000000..2f6837f02acbf76ef27f4d52ba914ac1c174830d
--- /dev/null
+++ b/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater.hash
@@ -0,0 +1 @@
+@~&~\ƗL|.|nA
\ No newline at end of file
diff --git a/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater.tree b/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater.tree
new file mode 100644
index 0000000000000000000000000000000000000000..d2246d37a34245caa4a8f02e633c76abd0911479
Binary files /dev/null and b/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater.tree differ
diff --git a/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater_expand_tree b/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater_expand_tree
new file mode 100644
index 0000000000000000000000000000000000000000..109d20e11f56937ea2332ab4ff3c5b84fafe9c80
Binary files /dev/null and b/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater_expand_tree differ
diff --git a/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater_inside_tree.sig b/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater_inside_tree.sig
new file mode 100644
index 0000000000000000000000000000000000000000..3b492e2353921af79194b3c3d77edcac61d7c165
Binary files /dev/null and b/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater_inside_tree.sig differ
diff --git a/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater_no_tree.sig b/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater_no_tree.sig
new file mode 100644
index 0000000000000000000000000000000000000000..b16d5a45d95c8e0cf1243e1c409ad7bcbb496beb
Binary files /dev/null and b/test/unittest/resources/demo_verity/file_4K_greater/file_4K_greater_no_tree.sig differ
diff --git a/test/unittest/resources/demo_verity/file_4K_less/file_4K_less b/test/unittest/resources/demo_verity/file_4K_less/file_4K_less
new file mode 100644
index 0000000000000000000000000000000000000000..bd2259de75f2c2612995f3fab5856c9d09985c35
Binary files /dev/null and b/test/unittest/resources/demo_verity/file_4K_less/file_4K_less differ
diff --git a/test/unittest/resources/demo_verity/file_4K_less/file_4K_less.hash b/test/unittest/resources/demo_verity/file_4K_less/file_4K_less.hash
new file mode 100644
index 0000000000000000000000000000000000000000..aeb395b86a29179022a3a634da8cc4213015f3b2
--- /dev/null
+++ b/test/unittest/resources/demo_verity/file_4K_less/file_4K_less.hash
@@ -0,0 +1 @@
+WǿꨬX
-
+
@@ -119,5 +119,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/unittest/utils/include/enable_key_utils.h b/test/unittest/utils/include/enable_key_utils.h
new file mode 100644
index 0000000000000000000000000000000000000000..799975d49018b4c38c8dbfdfadf7799a5ec7b82b
--- /dev/null
+++ b/test/unittest/utils/include/enable_key_utils.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2023 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.
+ */
+
+#ifndef CODE_SIGN_ENABLE_KEY_UTILS_H
+#define CODE_SIGN_ENABLE_KEY_UTILS_H
+
+namespace OHOS {
+namespace Security {
+namespace CodeSign {
+int EnableTestKey(const char *signing, const char *issuer);
+}
+}
+}
+#endif
\ No newline at end of file
diff --git a/test/unittest/utils/src/enable_key_utils.cpp b/test/unittest/utils/src/enable_key_utils.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5bc055062880b455ea8f5b6bb3c16cae0ec78cb9
--- /dev/null
+++ b/test/unittest/utils/src/enable_key_utils.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2023 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
+#include "cert_path.h"
+#include "enable_key_utils.h"
+
+namespace OHOS {
+namespace Security {
+namespace CodeSign {
+constexpr int DEFUALT_CERT_CHAIN_LEN = 3;
+
+int32_t EnableTestKey(const char *signing, const char *issuer)
+{
+ CertPathInfo arg = { 0 };
+ arg.signing = reinterpret_cast(signing);
+ arg.issuer = reinterpret_cast(issuer);
+ arg.signing_length = strlen(signing) + 1;
+ arg.issuer_length = strlen(issuer) + 1;
+ arg.path_len = DEFUALT_CERT_CHAIN_LEN;
+ return AddCertPath(arg);
+}
+}
+}
+}
\ No newline at end of file
diff --git a/utils/src/code_sign_block.cpp b/utils/src/code_sign_block.cpp
index e781b2b33286d50f4780cd99a14f1f364a3efe00..9e19d53a9e0d6d02aa61423bd768f60ad944c286 100644
--- a/utils/src/code_sign_block.cpp
+++ b/utils/src/code_sign_block.cpp
@@ -183,7 +183,7 @@ int32_t CodeSignBlock::GetCodeSignBlockBuffer(const std::string &path, ReadBuffe
int32_t ret = Verify::ParseHapSignatureInfo(path, signatureInfo_);
if (ret != Verify::VERIFY_SUCCESS) {
LOG_ERROR(LABEL, "find code sign block buffer failed. errno = %{public}d ", ret);
- return CS_ERR_FILE_INVALID;
+ return CS_CODE_SIGN_NOT_EXISTS;
}
for (const auto &value : signatureInfo_.optionBlocks) {
@@ -197,7 +197,7 @@ int32_t CodeSignBlock::GetCodeSignBlockBuffer(const std::string &path, ReadBuffe
}
if ((blobBuffer == nullptr) || (blobSize <= sizeof(PropertyBlobHeader))) {
- return CS_ERR_NO_SIGNATURE;
+ return CS_CODE_SIGN_NOT_EXISTS;
}
size_t length = 0;