diff --git a/interfaces/innerkits/code_sign_attr_utils/BUILD.gn b/interfaces/innerkits/code_sign_attr_utils/BUILD.gn index 5a53cfb6afd9e9ee4de47a9929b94a97f07bc607..342b0085d43c3ab733dc9ebea750595627d99289 100755 --- a/interfaces/innerkits/code_sign_attr_utils/BUILD.gn +++ b/interfaces/innerkits/code_sign_attr_utils/BUILD.gn @@ -19,7 +19,10 @@ config("public_attr_utils_configs") { } ohos_static_library("libcode_sign_attr_utils") { - sources = [ "src/code_sign_attr_utils.c" ] + sources = [ + "src/code_sign_attr_utils.c", + "src/ownerid_utils.cpp", + ] configs = [ ":public_attr_utils_configs", diff --git a/interfaces/innerkits/code_sign_attr_utils/include/code_sign_attr_utils.h b/interfaces/innerkits/code_sign_attr_utils/include/code_sign_attr_utils.h index da944949fee52a9ec4a74ce8843513ef8a60f9e1..5e54a34cbf045ac056499d49d858010445e8ad0c 100755 --- a/interfaces/innerkits/code_sign_attr_utils/include/code_sign_attr_utils.h +++ b/interfaces/innerkits/code_sign_attr_utils/include/code_sign_attr_utils.h @@ -46,6 +46,7 @@ enum FileOwneridType { FILE_OWNERID_DEBUG_PLATFORM, // 7 FILE_OWNERID_PLATFORM, // 8 FILE_OWNERID_NWEB, // 9 + FILE_OWNERID_APP_TEMP_ALLOW, // 10 FILE_OWNERID_MAX }; @@ -61,6 +62,7 @@ enum ProcessOwneridType { PROCESS_OWNERID_DEBUG_PLATFORM, // 7 PROCESS_OWNERID_PLATFORM, // 8 PROCESS_OWNERID_NWEB, // 9 + PROCESS_OWNERID_APP_TEMP_ALLOW, // 10 PROCESS_OWNERID_MAX }; diff --git a/interfaces/innerkits/code_sign_attr_utils/include/ownerid_utils.h b/interfaces/innerkits/code_sign_attr_utils/include/ownerid_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..e992eff86e74c5aa28b9a36fb0fdeb61c2ad9033 --- /dev/null +++ b/interfaces/innerkits/code_sign_attr_utils/include/ownerid_utils.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 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 OWNERID_UTILS_H +#define OWNERID_UTILS_H +#include +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t ConvertIdType(int idType, const char *ownerId); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/interfaces/innerkits/code_sign_attr_utils/src/code_sign_attr_utils.c b/interfaces/innerkits/code_sign_attr_utils/src/code_sign_attr_utils.c index c518d9583da131853285f0f871c281d761f7469e..04a39fbacd9bae3309c3dd66d965e6dd27ed6e24 100755 --- a/interfaces/innerkits/code_sign_attr_utils/src/code_sign_attr_utils.c +++ b/interfaces/innerkits/code_sign_attr_utils/src/code_sign_attr_utils.c @@ -14,6 +14,7 @@ */ #include "code_sign_attr_utils.h" +#include "ownerid_utils.h" #include #include @@ -86,6 +87,7 @@ int InitXpm(int enableJitFort, uint32_t idType, const char *ownerId) // set owner id int ret = CS_SUCCESS; if (idType != PROCESS_OWNERID_UNINIT) { + idType = ConvertIdType(idType, ownerId); ret = DoSetXpmOwnerId(fd, idType, ownerId); } diff --git a/interfaces/innerkits/code_sign_attr_utils/src/ownerid_utils.cpp b/interfaces/innerkits/code_sign_attr_utils/src/ownerid_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c70ef1b49ff2ba416cbf6cf9c4f1b7b5a54576da --- /dev/null +++ b/interfaces/innerkits/code_sign_attr_utils/src/ownerid_utils.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2024 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 "ownerid_utils.h" +#include "code_sign_attr_utils.h" +#include "log.h" + +#include +#include + +// the list will be removed before 930 +static const std::unordered_set g_tempAllowList; + +uint32_t ConvertIdType(int idType, const char *ownerId) +{ + if (idType != PROCESS_OWNERID_APP || ownerId == nullptr) { + return idType; + } + std::string ownerIdStr(ownerId); + if (g_tempAllowList.count(ownerIdStr) != 0) { + LOG_INFO("Xpm: app in temporary allow list"); + return PROCESS_OWNERID_APP_TEMP_ALLOW; + } + return idType; +} \ No newline at end of file diff --git a/interfaces/innerkits/code_sign_utils/include/code_sign_enable_multi_task.h b/interfaces/innerkits/code_sign_utils/include/code_sign_enable_multi_task.h index 64ef9b0a699b1356cf75cad7fed4319de04ae232..46f504a05051fefe01bb1d8c64281431d8704777 100644 --- a/interfaces/innerkits/code_sign_utils/include/code_sign_enable_multi_task.h +++ b/interfaces/innerkits/code_sign_utils/include/code_sign_enable_multi_task.h @@ -43,15 +43,21 @@ public: void AddTaskData(const std::string &targetFile, const struct code_sign_enable_arg &arg); /** * @brief Execute code signature addition task - * @param taskRet Returned execution results * @param ownerId app-identifier of the signature * @param path hap real path on disk * @param func Callback enable function - * @return Timed out or not + * @return err code, see err_code.h */ - bool ExecuteEnableCodeSignTask(int32_t &taskRet, const std::string &ownerId, + int32_t ExecuteEnableCodeSignTask(const std::string &ownerId, const std::string &path, CallbackFunc &func); + /** + * @brief Check whether file is verity enabled by fd + * @param fd file descriptor + * @return err code, see err_code.h + */ + static int32_t IsFsVerityEnabled(int fd); private: + static int32_t IsFsVerityEnabled(const std::string &path); void SortTaskData(); void ExecuteEnableCodeSignTask(uint32_t &index, int32_t &taskRet, const std::string &ownerId, const std::string &path, CallbackFunc &func); diff --git a/interfaces/innerkits/code_sign_utils/include/code_sign_helper.h b/interfaces/innerkits/code_sign_utils/include/code_sign_helper.h index aa4ddeb51080ff40aa1d385372e7e9614254632b..9f9dfd704aff0a0046ba82c6c5818115287a0a63 100644 --- a/interfaces/innerkits/code_sign_utils/include/code_sign_helper.h +++ b/interfaces/innerkits/code_sign_utils/include/code_sign_helper.h @@ -43,7 +43,7 @@ public: int32_t ProcessMultiTask(const std::string &ownerId, const std::string &path, CallbackFunc &func); private: int32_t ProcessOneFile(); - int32_t ExecuteMultiTask(int32_t ret, const std::string &ownerId, const std::string &path, CallbackFunc &func); + int32_t ExecuteMultiTask(const std::string &ownerId, const std::string &path, CallbackFunc &func); void ShowCodeSignInfo(const std::string &path, const struct code_sign_enable_arg &arg); private: CodeSignBlock codeSignBlock_; diff --git a/interfaces/innerkits/code_sign_utils/include/code_sign_utils.h b/interfaces/innerkits/code_sign_utils/include/code_sign_utils.h index 822aef7b2fc6dfb9a4660719bc628ef9805f5b68..6f06b68476ab8849c9d3c62a45a1d9fce8eafcd1 100644 --- a/interfaces/innerkits/code_sign_utils/include/code_sign_utils.h +++ b/interfaces/innerkits/code_sign_utils/include/code_sign_utils.h @@ -123,7 +123,6 @@ public: */ static int32_t IsSupportFsVerity(const std::string &path); private: - static int32_t IsFsVerityEnabled(int fd); static int32_t EnableCodeSignForFile(const std::string &path, const struct code_sign_enable_arg &arg); int32_t ProcessCodeSignBlock(const std::string &ownerId, const std::string &path, FileType type); int32_t HandleCodeSignBlockFailure(const std::string &realPath, int32_t ret); diff --git a/interfaces/innerkits/code_sign_utils/src/code_sign_enable_multi_task.cpp b/interfaces/innerkits/code_sign_utils/src/code_sign_enable_multi_task.cpp index 3e3d7d9423ea6eab719d09774b7cb681ddecba47..ee125829e06378d5c27282f3487736ee72465d74 100644 --- a/interfaces/innerkits/code_sign_utils/src/code_sign_enable_multi_task.cpp +++ b/interfaces/innerkits/code_sign_utils/src/code_sign_enable_multi_task.cpp @@ -15,11 +15,19 @@ #include "code_sign_enable_multi_task.h" +#include +#include +#include +#include +#include +#include + #include "byte_buffer.h" #include "cs_hisysevent.h" #include "errcode.h" #include "log.h" #include "signer_info.h" +#include "stat_utils.h" namespace OHOS { namespace Security { @@ -29,11 +37,13 @@ constexpr uint32_t DEFAULT_THREADS_NUM = 8; CodeSignEnableMultiTask::CodeSignEnableMultiTask(): enableCodeSignTaskWorker_("EnableCodeSign"), taskCallBack_(0) { + LOG_INFO("Tasks init."); enableCodeSignTaskWorker_.Start(DEFAULT_THREADS_NUM); } CodeSignEnableMultiTask::~CodeSignEnableMultiTask() { + LOG_INFO("Tasks finish."); enableCodeSignTaskWorker_.Stop(); } @@ -42,11 +52,44 @@ void CodeSignEnableMultiTask::AddTaskData(const std::string &targetFile, const s enableData_.push_back(std::pair(targetFile, arg)); } -bool CodeSignEnableMultiTask::ExecuteEnableCodeSignTask(int32_t &taskRet, const std::string &ownerId, +int32_t CodeSignEnableMultiTask::IsFsVerityEnabled(int fd) +{ + unsigned int flags; + int ret = ioctl(fd, FS_IOC_GETFLAGS, &flags); + if (ret < 0) { + LOG_ERROR("Get verity flags by ioctl failed. errno = <%{public}d, %{public}s>", + errno, strerror(errno)); + return CS_ERR_FILE_INVALID; + } + if (flags & FS_VERITY_FL) { + return CS_SUCCESS; + } + return CS_ERR_FSVERITY_NOT_ENABLED; +} + +int32_t CodeSignEnableMultiTask::IsFsVerityEnabled(const std::string &path) +{ + int32_t fd = open(path.c_str(), O_RDONLY); + if (fd < 0) { + LOG_ERROR("Open file failed, path = %{public}s, errno = <%{public}d, %{public}s>", + path.c_str(), errno, strerror(errno)); + return CS_ERR_FILE_OPEN; + } + int32_t ret = IsFsVerityEnabled(fd); + if (ret != CS_SUCCESS) { + LOG_INFO("Fs-verity is not enable for file = %{public}s.", path.c_str()); + } + close(fd); + return ret; +} + +int32_t CodeSignEnableMultiTask::ExecuteEnableCodeSignTask(const std::string &ownerId, const std::string &path, CallbackFunc &func) { SortTaskData(); + LOG_INFO("Tasks num = %{public}zu", enableData_.size()); + int32_t taskRet = CS_SUCCESS; for (uint32_t i = 0; i < enableData_.size(); i++) { LOG_DEBUG("index: %{public}d, name:%{public}s, %{public}lld", i, enableData_[i].first.c_str(), enableData_[i].second.data_size); @@ -56,7 +99,22 @@ bool CodeSignEnableMultiTask::ExecuteEnableCodeSignTask(int32_t &taskRet, const std::unique_lock lock(cvLock_); auto waitStatus = taskfinish_.wait_for(lock, std::chrono::milliseconds(CODE_SIGN_TASK_TIMEOUT_MS), [this]() { return this->enableData_.size() == this->taskCallBack_; }); - return waitStatus; + if (!waitStatus) { + LOG_ERROR("enable code sign timeout, finished tasks = %{public}u", taskCallBack_); + return CS_ERR_ENABLE_TIMEOUT; + } + if (taskRet != CS_SUCCESS) { + return taskRet; + } + int32_t ret = CS_SUCCESS; + for (auto &data : enableData_) { + const std::string &filePath = data.first; + if (IsFsVerityEnabled(filePath) != CS_SUCCESS) { + ret = CS_ERR_FSVERITY_NOT_ENABLED; + ReportEnableError(filePath, ret); + } + } + return ret; } void CodeSignEnableMultiTask::SortTaskData() diff --git a/interfaces/innerkits/code_sign_utils/src/code_sign_helper.cpp b/interfaces/innerkits/code_sign_utils/src/code_sign_helper.cpp index e21bd681cb6f03ed929de7c46573aeab4fee4656..6b2cce5e64a4faeff9bc22e74d2fac240c54d022 100644 --- a/interfaces/innerkits/code_sign_utils/src/code_sign_helper.cpp +++ b/interfaces/innerkits/code_sign_utils/src/code_sign_helper.cpp @@ -41,7 +41,7 @@ int32_t CodeSignHelper::ProcessMultiTask(const std::string &ownerId, const std:: return ret; } } while (ret == CS_SUCCESS); - return ExecuteMultiTask(ret, ownerId, path, func); + return ExecuteMultiTask(ownerId, path, func); } int32_t CodeSignHelper::ProcessOneFile() @@ -64,15 +64,10 @@ int32_t CodeSignHelper::ProcessOneFile() return ret; } -int32_t CodeSignHelper::ExecuteMultiTask(int32_t ret, const std::string &ownerId, +int32_t CodeSignHelper::ExecuteMultiTask(const std::string &ownerId, const std::string &path, CallbackFunc &func) { - bool waitStatus = multiTask_.ExecuteEnableCodeSignTask(ret, ownerId, path, func); - if (!waitStatus) { - LOG_ERROR("enable code sign timeout"); - return CS_ERR_ENABLE_TIMEOUT; - } - return ret; + return multiTask_.ExecuteEnableCodeSignTask(ownerId, path, func); } void CodeSignHelper::ShowCodeSignInfo(const std::string &path, const struct code_sign_enable_arg &arg) @@ -80,7 +75,8 @@ void CodeSignHelper::ShowCodeSignInfo(const std::string &path, const struct code uint8_t *salt = reinterpret_cast(arg.salt_ptr); uint8_t rootHash[64] = {0}; uint8_t *rootHashPtr = rootHash; - if (arg.flags & CodeSignBlock::CSB_SIGN_INFO_MERKLE_TREE) { + if (arg.flags & CodeSignBlock::CSB_SIGN_INFO_MERKLE_TREE + && reinterpret_cast(arg.root_hash_ptr) != nullptr) { rootHashPtr = reinterpret_cast(arg.root_hash_ptr); } @@ -88,10 +84,11 @@ void CodeSignHelper::ShowCodeSignInfo(const std::string &path, const struct code "file:%{public}s version:%{public}d hash_algorithm:%{public}d block_size:%{public}d sig_size:%{public}d " "data_size:%{public}lld salt_size:%{public}d salt:[%{public}d, ..., %{public}d, ..., %{public}d] " "flags:%{public}d tree_offset:%{public}lld root_hash:[%{public}d, %{public}d, %{public}d, ..., %{public}d, " - "..., %{public}d] }", + "..., %{public}d] pgtypeinfo_size:%{public}d pgtypeinfo_off:%{public}lld }", path.c_str(), arg.cs_version, arg.hash_algorithm, arg.block_size, arg.sig_size, arg.data_size, arg.salt_size, salt[0], salt[16], salt[31], arg.flags, arg.tree_offset, // 16, 31 data index - rootHashPtr[0], rootHashPtr[1], rootHashPtr[2], rootHashPtr[32], rootHashPtr[63]); // 2, 32, 63 data index + rootHashPtr[0], rootHashPtr[1], rootHashPtr[2], rootHashPtr[32], rootHashPtr[63], // 2, 32, 63 data index + arg.pgtypeinfo_size, arg.pgtypeinfo_off); } } } diff --git a/interfaces/innerkits/code_sign_utils/src/code_sign_utils.cpp b/interfaces/innerkits/code_sign_utils/src/code_sign_utils.cpp index dc5eeb961531b83e98cd2a6e324ee40a929abd60..9a4a3316b8d585b22be446099de92c6713a56115 100644 --- a/interfaces/innerkits/code_sign_utils/src/code_sign_utils.cpp +++ b/interfaces/innerkits/code_sign_utils/src/code_sign_utils.cpp @@ -122,21 +122,6 @@ int32_t CodeSignUtils::IsSupportFsVerity(const std::string &path) return CS_ERR_FSVREITY_NOT_SUPPORTED; } -int32_t CodeSignUtils::IsFsVerityEnabled(int fd) -{ - unsigned int flags; - int ret = ioctl(fd, FS_IOC_GETFLAGS, &flags); - if (ret < 0) { - LOG_ERROR("Get verity flags by ioctl failed. errno = <%{public}d, %{public}s>", - errno, strerror(errno)); - return CS_ERR_FILE_INVALID; - } - if (flags & FS_VERITY_FL) { - return CS_SUCCESS; - } - return CS_ERR_FSVERITY_NOT_ENABLED; -} - int32_t CodeSignUtils::EnforceCodeSignForFile(const std::string &path, const ByteBuffer &signature) { return EnforceCodeSignForFile(path, signature.GetBuffer(), signature.GetSize()); @@ -154,7 +139,7 @@ int32_t CodeSignUtils::EnableCodeSignForFile(const std::string &path, const stru } do { - ret = IsFsVerityEnabled(fd); + ret = CodeSignEnableMultiTask::IsFsVerityEnabled(fd); if (ret == CS_SUCCESS) { LOG_INFO("Fs-verity has been enabled."); break; @@ -179,7 +164,7 @@ int32_t CodeSignUtils::EnableCodeSignForFile(const std::string &path, const stru ret = CS_SUCCESS; } while (0); close(fd); - LOG_INFO("Enforcing file complete and ret = %{public}d", ret); + LOG_INFO("Enforcing file complete, path = %{public}s, ret = %{public}d", path.c_str(), ret); return ret; } @@ -226,7 +211,15 @@ int32_t CodeSignUtils::EnforceCodeSignForAppWithOwnerId(const std::string &owner } else if (type >= FILE_TYPE_MAX) { return CS_ERR_PARAM_INVALID; } - return ProcessCodeSignBlock(ownerId, path, type); + std::lock_guard lock(storedEntryMapLock_); + int ret = ProcessCodeSignBlock(ownerId, path, type); + if (ret != CS_SUCCESS) { + // retry once to make sure stability + ret = ProcessCodeSignBlock(ownerId, path, type); + } + storedEntryMap_.clear(); + LOG_INFO("Enforcing done, ret = %{public}d", ret); + return ret; } int32_t CodeSignUtils::ProcessCodeSignBlock(const std::string &ownerId, const std::string &path, FileType type) @@ -237,15 +230,12 @@ int32_t CodeSignUtils::ProcessCodeSignBlock(const std::string &ownerId, const st } int32_t ret; CodeSignHelper codeSignHelper; - { - std::lock_guard lock(storedEntryMapLock_); - ret = codeSignHelper.ParseCodeSignBlock(realPath, storedEntryMap_, type); - storedEntryMap_.clear(); - } + ret = codeSignHelper.ParseCodeSignBlock(realPath, storedEntryMap_, type); if (ret != CS_SUCCESS) { return HandleCodeSignBlockFailure(realPath, ret); } - return codeSignHelper.ProcessMultiTask(ownerId, path, EnableCodeSignForFile); + ret = codeSignHelper.ProcessMultiTask(ownerId, path, EnableCodeSignForFile); + return ret; } int32_t CodeSignUtils::HandleCodeSignBlockFailure(const std::string &realPath, int32_t ret) @@ -269,7 +259,7 @@ int32_t CodeSignUtils::EnableKeyInProfile(const std::string &bundleName, const B if (ret == CS_SUCCESS) { return ret; } - LOG_ERROR("Enable key in profile failed. errno = <%{public}d, %{public}s>", errno, strerror(errno)); + LOG_ERROR("Enable key in profile failed. ret = %{public}d", ret); return CS_ERR_PROFILE; } @@ -279,7 +269,7 @@ int32_t CodeSignUtils::RemoveKeyInProfile(const std::string &bundleName) if (ret == CS_SUCCESS) { return ret; } - LOG_ERROR("Remove key in profile failed. errno = <%{public}d, %{public}s>", errno, strerror(errno)); + LOG_ERROR("Remove key in profile failed. ret = %{public}d", ret); return CS_ERR_PROFILE; } diff --git a/interfaces/innerkits/common/include/errcode.h b/interfaces/innerkits/common/include/errcode.h index 3086f943a14a3fea4539e84a6ee09602dcd17d6d..541be0e7454ba5b842b96e5b67c373c36a588fe2 100644 --- a/interfaces/innerkits/common/include/errcode.h +++ b/interfaces/innerkits/common/include/errcode.h @@ -58,7 +58,8 @@ enum VerifyErrCode { CS_ERR_INVALID_OWNER_ID = -0x303, CS_CODE_SIGN_NOT_EXISTS = -0x304, CS_ERR_PROFILE = -0x305, - CS_ERR_ENABLE_TIMEOUT = -0x306 + CS_ERR_ENABLE_TIMEOUT = -0x306, + CS_ERR_FSVREITY_NOT_ENABLED = -0x307, }; enum IPCErrCode { @@ -96,7 +97,9 @@ enum SignBlockErrCode { CS_ERR_SO_SIGN_OFFSET = -0x619, CS_ERR_SO_SIGN_SIZE = -0x620, CS_ERR_SIGN_ADDR_ALIGN = -0x621, - CS_ERR_SIGN_EXTENSION_OFFSET_ALIGN = -0x622, + CS_ERR_INVALID_EXTENSION_OFFSET = -0x622, + CS_ERR_INVALID_PAGE_INFO_EXTENSION = -0x623, + CS_ERR_EXTENSION_SIGN_SIZE = -0x624, }; enum JitCodeSignErrCode { diff --git a/interfaces/innerkits/jit_code_sign/include/jit_buffer_integrity.h b/interfaces/innerkits/jit_code_sign/include/jit_buffer_integrity.h index 2520846f00ac9103fee5e494a35b899cecce025a..5b61c48f545a577c3ad6c53c9b97f9726bd8ae61 100644 --- a/interfaces/innerkits/jit_code_sign/include/jit_buffer_integrity.h +++ b/interfaces/innerkits/jit_code_sign/include/jit_buffer_integrity.h @@ -54,7 +54,7 @@ static inline JitCodeSignerBase *CreateJitCodeSigner(JitBufferIntegrityLevel lev */ static bool IsSupportJitCodeSigner() { - return JitCodeSignerFactory::GetInstance().IsSupportJitCodeSigner(); + return IsSupportPACFeature(); } /** diff --git a/interfaces/innerkits/jit_code_sign/include/jit_code_signer_factory.h b/interfaces/innerkits/jit_code_sign/include/jit_code_signer_factory.h index 38986f28ebb6596cbbb750e90adb4d8ba1235428..1edff6bb5c16d5de8f0acc1d41b6bd37e5f5640b 100644 --- a/interfaces/innerkits/jit_code_sign/include/jit_code_signer_factory.h +++ b/interfaces/innerkits/jit_code_sign/include/jit_code_signer_factory.h @@ -34,12 +34,9 @@ public: JitCodeSignerBase *CreateJitCodeSigner( JitBufferIntegrityLevel level = JitBufferIntegrityLevel::Level0); - bool IsSupportJitCodeSigner(); - private: JitCodeSignerFactory(); ~JitCodeSignerFactory() = default; - bool isSupport_; }; } } diff --git a/interfaces/innerkits/jit_code_sign/include/jit_fort_helper.h b/interfaces/innerkits/jit_code_sign/include/jit_fort_helper.h index 6343c3834392a767e310a29cda23ab364da6f0af..40e704d587a0b2b3d06828362f596ec97c8b70b9 100644 --- a/interfaces/innerkits/jit_code_sign/include/jit_fort_helper.h +++ b/interfaces/innerkits/jit_code_sign/include/jit_fort_helper.h @@ -19,6 +19,12 @@ #include #include #include +#ifdef __aarch64__ +#include +#include +#endif + +#include "errcode.h" namespace OHOS { namespace Security { @@ -26,6 +32,7 @@ namespace CodeSign { #define JITFORT_PRCTL_OPTION 0x6a6974 #define JITFORT_SWITCH_IN 3 #define JITFORT_SWITCH_OUT 4 +#define JITFORT_CPU_FEATURES 7 __attribute__((always_inline)) static inline long Syscall( unsigned long n, unsigned long a, unsigned long b, @@ -46,7 +53,7 @@ __attribute__((always_inline)) static inline long Syscall( #endif } -__attribute__((always_inline)) static int inline PrctlWrapper( +__attribute__((always_inline)) static int inline PrctlWrapper( int op, unsigned long a, unsigned long b = 0) { #ifdef __aarch64__ @@ -55,6 +62,18 @@ __attribute__((always_inline)) static int inline PrctlWrapper( return CS_ERR_UNSUPPORT; #endif } + +__attribute__((always_inline)) static inline bool IsSupportPACFeature() +{ +#ifdef __aarch64__ + unsigned long hwcaps = static_cast(PrctlWrapper( + JITFORT_PRCTL_OPTION, JITFORT_CPU_FEATURES, 0)); + if ((hwcaps & HWCAP_PACA) && (hwcaps & HWCAP_PACG)) { + return true; + } +#endif + return false; +} } } } diff --git a/interfaces/innerkits/jit_code_sign/src/jit_code_signer_factory.cpp b/interfaces/innerkits/jit_code_sign/src/jit_code_signer_factory.cpp index 6d9c28c09ea352b2a6e9979540f0f2869782c762..a0d952cfb05fa87a9e674022d8e564fbebd79146 100644 --- a/interfaces/innerkits/jit_code_sign/src/jit_code_signer_factory.cpp +++ b/interfaces/innerkits/jit_code_sign/src/jit_code_signer_factory.cpp @@ -15,11 +15,8 @@ #include "jit_code_signer_factory.h" +#include "jit_fort_helper.h" #ifdef JIT_CODE_SIGN_ENABLE -#include -#include -#include - #include "jit_code_signer_hybrid.h" #include "jit_code_signer_single.h" #include "log.h" @@ -29,17 +26,7 @@ namespace OHOS { namespace Security { namespace CodeSign { -JitCodeSignerFactory::JitCodeSignerFactory():isSupport_(false) -{ -#ifdef JIT_CODE_SIGN_ENABLE - unsigned long hwcaps = getauxval(AT_HWCAP); - if ((hwcaps & HWCAP_PACA) && (hwcaps & HWCAP_PACG)) { - isSupport_ = true; - } else { - isSupport_ = false; - } -#endif -} +JitCodeSignerFactory::JitCodeSignerFactory() {} JitCodeSignerFactory &JitCodeSignerFactory::GetInstance() { @@ -47,16 +34,11 @@ JitCodeSignerFactory &JitCodeSignerFactory::GetInstance() return singleJitCodeSignerFactory; } -bool JitCodeSignerFactory::IsSupportJitCodeSigner() -{ - return isSupport_; -} - #ifdef JIT_CODE_SIGN_ENABLE JitCodeSignerBase *JitCodeSignerFactory::CreateJitCodeSigner( JitBufferIntegrityLevel level) { - if (!IsSupportJitCodeSigner()) { + if (!IsSupportPACFeature()) { return nullptr; } switch (level) { diff --git a/interfaces/innerkits/local_code_sign/BUILD.gn b/interfaces/innerkits/local_code_sign/BUILD.gn index 6257623dd6601f372a1ef32d9eacb86023d02b6b..eeb2f965d352962283d87c12bd25f05e26774da9 100644 --- a/interfaces/innerkits/local_code_sign/BUILD.gn +++ b/interfaces/innerkits/local_code_sign/BUILD.gn @@ -44,6 +44,9 @@ ohos_shared_library("liblocal_code_sign_sdk") { if (build_variant == "root") { defines += [ "CODE_SIGNATURE_DEBUGGABLE" ] } + if (code_signature_support_oh_code_sign) { + defines += [ "VERIFY_KEY_ATTEST_CERTCHAIN" ] + } external_deps = [ "c_utils:utils", diff --git a/interfaces/innerkits/local_code_sign/include/local_code_sign_client.h b/interfaces/innerkits/local_code_sign/include/local_code_sign_client.h index a20e60915f240a934d53668276394acd8ae8a4d5..b5552e0232c5b3da363acf6eb30298790fea0b19 100644 --- a/interfaces/innerkits/local_code_sign/include/local_code_sign_client.h +++ b/interfaces/innerkits/local_code_sign/include/local_code_sign_client.h @@ -49,7 +49,7 @@ private: }; LocalCodeSignClient(); - ~LocalCodeSignClient() = default; + ~LocalCodeSignClient(); LocalCodeSignClient(const LocalCodeSignClient &source) = delete; LocalCodeSignClient &operator = (const LocalCodeSignClient &source) = delete; diff --git a/interfaces/innerkits/local_code_sign/src/local_code_sign_client.cpp b/interfaces/innerkits/local_code_sign/src/local_code_sign_client.cpp index 10abb5b077e93795f5274ba2ca85d68e866ae69a..b599ece85d5154d17274e8f88cdcbd9833a90f4c 100644 --- a/interfaces/innerkits/local_code_sign/src/local_code_sign_client.cpp +++ b/interfaces/innerkits/local_code_sign/src/local_code_sign_client.cpp @@ -36,6 +36,15 @@ LocalCodeSignClient::LocalCodeSignClient() } } +LocalCodeSignClient::~LocalCodeSignClient() +{ + std::lock_guard lock(proxyMutex_); + if (localCodeSignProxy_ != nullptr && localCodeSignSvrRecipient_ != nullptr) { + localCodeSignProxy_->AsObject()->RemoveDeathRecipient(localCodeSignSvrRecipient_); + } + localCodeSignSvrRecipient_ = nullptr; +} + void LocalCodeSignClient::LocalCodeSignSvrRecipient::OnRemoteDied(const wptr &remote) { if (remote == nullptr) { diff --git a/services/key_enable/BUILD.gn b/services/key_enable/BUILD.gn index 7792a3d9f24f14d8ca8ca7053990689a8a38ba7b..31887f5aa0a2317cdc042cdc9d0c2bcfcbd91f6a 100644 --- a/services/key_enable/BUILD.gn +++ b/services/key_enable/BUILD.gn @@ -33,6 +33,7 @@ ohos_rust_executable("key_enable") { deps += [ "${rust_openssl_dir}/openssl:lib", "//third_party/rust/crates/cxx:lib", + "//third_party/rust/crates/lazy-static.rs:lib", ] external_deps += [ "c_utils:utils_rust" ] } @@ -61,6 +62,7 @@ ohos_rust_shared_ffi("key_enable_lib") { deps += [ "${rust_openssl_dir}/openssl:lib", "//third_party/rust/crates/cxx:lib", + "//third_party/rust/crates/lazy-static.rs:lib", ] external_deps += [ "c_utils:utils_rust" ] } diff --git a/services/key_enable/cfg/disable_xpm/key_enable.cfg b/services/key_enable/cfg/disable_xpm/key_enable.cfg index ff934d49ee56a61ae88b746be1cde7214de9ee48..32a8fb391eca665373739157d3ccc811bccf0cdf 100644 --- a/services/key_enable/cfg/disable_xpm/key_enable.cfg +++ b/services/key_enable/cfg/disable_xpm/key_enable.cfg @@ -3,12 +3,12 @@ "name" : "post-fs-data", "cmds" : [ "write /proc/sys/fs/verity/require_signatures 1", - "mkdir /data/service/el1/profiles 0655 installs installs", - "mkdir /data/service/el1/profiles/release 0655 installs installs", - "mkdir /data/service/el1/profiles/debug 0655 installs installs" + "mkdir /data/service/el1/public/profiles 0655 installs installs", + "mkdir /data/service/el1/public/profiles/release 0655 installs installs", + "mkdir /data/service/el1/public/profiles/debug 0655 installs installs" ] }, { - "name" : "late-fs", + "name" : "init", "cmds" : [ "start key_enable" ] diff --git a/services/key_enable/cfg/enable_xpm/level1/key_enable.cfg b/services/key_enable/cfg/enable_xpm/level1/key_enable.cfg index 3d0685a770321d8b90b4d21478b1482ba4519793..c96ac7c8bf2bd1f6ff14813c5d27862015697cbc 100644 --- a/services/key_enable/cfg/enable_xpm/level1/key_enable.cfg +++ b/services/key_enable/cfg/enable_xpm/level1/key_enable.cfg @@ -3,12 +3,12 @@ "name" : "post-fs-data", "cmds" : [ "write /proc/sys/fs/verity/require_signatures 1", - "mkdir /data/service/el1/profiles 0655 installs installs", - "mkdir /data/service/el1/profiles/release 0655 installs installs", - "mkdir /data/service/el1/profiles/debug 0655 installs installs" + "mkdir /data/service/el1/public/profiles 0655 installs installs", + "mkdir /data/service/el1/public/profiles/release 0655 installs installs", + "mkdir /data/service/el1/public/profiles/debug 0655 installs installs" ] }, { - "name" : "late-fs", + "name" : "init", "cmds" : [ "start key_enable" ] diff --git a/services/key_enable/cfg/enable_xpm/level2/key_enable.cfg b/services/key_enable/cfg/enable_xpm/level2/key_enable.cfg index 8cd2cf51206cd3592fdccd7a12c8bbb4873ae529..68da39fbd155a5100d97c5d6911982172dbfccaa 100644 --- a/services/key_enable/cfg/enable_xpm/level2/key_enable.cfg +++ b/services/key_enable/cfg/enable_xpm/level2/key_enable.cfg @@ -3,12 +3,12 @@ "name" : "post-fs-data", "cmds" : [ "write /proc/sys/fs/verity/require_signatures 1", - "mkdir /data/service/el1/profiles 0655 installs installs", - "mkdir /data/service/el1/profiles/release 0655 installs installs", - "mkdir /data/service/el1/profiles/debug 0655 installs installs" + "mkdir /data/service/el1/public/profiles 0655 installs installs", + "mkdir /data/service/el1/public/profiles/release 0655 installs installs", + "mkdir /data/service/el1/public/profiles/debug 0655 installs installs" ] }, { - "name" : "late-fs", + "name" : "init", "cmds" : [ "start key_enable" ] diff --git a/services/key_enable/cfg/enable_xpm/level3/key_enable.cfg b/services/key_enable/cfg/enable_xpm/level3/key_enable.cfg index 086faea23fcb920d01305f5685ee35b778a5d2b0..4d5fb6f69113a9440e2a48f26373b5c36c720882 100644 --- a/services/key_enable/cfg/enable_xpm/level3/key_enable.cfg +++ b/services/key_enable/cfg/enable_xpm/level3/key_enable.cfg @@ -3,12 +3,12 @@ "name" : "post-fs-data", "cmds" : [ "write /proc/sys/fs/verity/require_signatures 1", - "mkdir /data/service/el1/profiles 0655 installs installs", - "mkdir /data/service/el1/profiles/release 0655 installs installs", - "mkdir /data/service/el1/profiles/debug 0655 installs installs" + "mkdir /data/service/el1/public/profiles 0655 installs installs", + "mkdir /data/service/el1/public/profiles/release 0655 installs installs", + "mkdir /data/service/el1/public/profiles/debug 0655 installs installs" ] }, { - "name" : "late-fs", + "name" : "init", "cmds" : [ "start key_enable" ] diff --git a/services/key_enable/cfg/enable_xpm/level4/key_enable.cfg b/services/key_enable/cfg/enable_xpm/level4/key_enable.cfg index 2a8c20d6ea0d3842cdcf0cbb0231d1aea548ba78..86babbf7bf542a843fccf5d4a576741f7bda0878 100644 --- a/services/key_enable/cfg/enable_xpm/level4/key_enable.cfg +++ b/services/key_enable/cfg/enable_xpm/level4/key_enable.cfg @@ -3,12 +3,12 @@ "name" : "post-fs-data", "cmds" : [ "write /proc/sys/fs/verity/require_signatures 1", - "mkdir /data/service/el1/profiles 0655 installs installs", - "mkdir /data/service/el1/profiles/release 0655 installs installs", - "mkdir /data/service/el1/profiles/debug 0655 installs installs" + "mkdir /data/service/el1/public/profiles 0655 installs installs", + "mkdir /data/service/el1/public/profiles/release 0655 installs installs", + "mkdir /data/service/el1/public/profiles/debug 0655 installs installs" ] }, { - "name" : "late-fs", + "name" : "init", "cmds" : [ "start key_enable" ] diff --git a/services/key_enable/cfg/enable_xpm/level5/key_enable.cfg b/services/key_enable/cfg/enable_xpm/level5/key_enable.cfg index d4615d7b241154aafc81894f7668c74d6efe7ba9..6eb075e359578443d1b0ce107b4bb51f75e50766 100644 --- a/services/key_enable/cfg/enable_xpm/level5/key_enable.cfg +++ b/services/key_enable/cfg/enable_xpm/level5/key_enable.cfg @@ -3,12 +3,12 @@ "name" : "post-fs-data", "cmds" : [ "write /proc/sys/fs/verity/require_signatures 1", - "mkdir /data/service/el1/profiles 0655 installs installs", - "mkdir /data/service/el1/profiles/release 0655 installs installs", - "mkdir /data/service/el1/profiles/debug 0655 installs installs" + "mkdir /data/service/el1/public/profiles 0655 installs installs", + "mkdir /data/service/el1/public/profiles/release 0655 installs installs", + "mkdir /data/service/el1/public/profiles/debug 0655 installs installs" ] }, { - "name" : "late-fs", + "name" : "init", "cmds" : [ "start key_enable" ] diff --git a/services/key_enable/src/key_enable.rs b/services/key_enable/src/key_enable.rs index 5eebc3a17f8530e970cc124fbfbfddcaa7d6ab84..dfae09109225b4666f6152fc22b58c72df945829 100644 --- a/services/key_enable/src/key_enable.rs +++ b/services/key_enable/src/key_enable.rs @@ -26,6 +26,8 @@ use std::io::{BufRead, BufReader}; use std::option::Option; use std::ptr; use std::thread; +use std::time::{Duration, Instant}; +use std::path::Path; const LOG_LABEL: HiLogLabel = HiLogLabel { log_type: LogType::LogCore, @@ -39,6 +41,9 @@ const KEYRING_TYPE: &str = "keyring"; const FSVERITY_KEYRING_NAME: &str = ".fs-verity"; const LOCAL_KEY_NAME: &str = "local_key"; const CODE_SIGN_KEY_NAME_PREFIX: &str = "fs_verity_key"; +const PROFILE_STORE_EL1: &str = "/data/service/el1/public/profiles"; +const PROFILE_SEARCH_SLEEP_TIME: u64 = 200; +const PROFILE_SEARCH_SLEEP_OUT_TIME: u64 = 600; const SUCCESS: i32 = 0; type KeySerial = i32; @@ -164,24 +169,37 @@ fn enable_trusted_keys(key_id: KeySerial, root_cert: &PemCollection) { } } +fn check_and_add_cert_path(root_cert: &PemCollection, cert_paths: &TrustCertPath) -> bool { + if Path::new(PROFILE_STORE_EL1).exists() { + if add_profile_cert_path(root_cert, cert_paths).is_err() { + error!(LOG_LABEL, "Add cert path from local profile err."); + } + info!(LOG_LABEL, "Finished cert path adding."); + true + } else { + false + } +} + // start cert path ops thread add trusted cert & developer cert -fn add_cert_path_thread( +fn add_profile_cert_path_thread( root_cert: PemCollection, cert_paths: TrustCertPath, ) -> std::thread::JoinHandle<()> { thread::spawn(move || { - // enable trusted cert in prebuilt config - info!(LOG_LABEL, "Starting enable trusted cert."); - if cert_paths.add_cert_paths().is_err() { - error!(LOG_LABEL, "Add trusted cert path err."); - } - // enable developer certs info!(LOG_LABEL, "Starting enable developer cert."); - if add_profile_cert_path(&root_cert, &cert_paths).is_err() { - error!(LOG_LABEL, "Add cert path from local profile err."); + let start_time = Instant::now(); + loop { + if check_and_add_cert_path(&root_cert, &cert_paths) { + break; + } else if start_time.elapsed() >= Duration::from_secs(PROFILE_SEARCH_SLEEP_OUT_TIME) { + error!(LOG_LABEL, "Timeout while waiting for PROFILE_STORE_EL1."); + break; + } else { + thread::sleep(Duration::from_millis(PROFILE_SEARCH_SLEEP_TIME)); + } } - info!(LOG_LABEL, "Finished cert path adding."); }) } @@ -230,12 +248,16 @@ pub fn enable_all_keys() { enable_trusted_keys(key_id, &root_cert); let cert_paths = get_cert_path(); - let cert_thread = add_cert_path_thread(root_cert, cert_paths); + // enable trusted cert in prebuilt config + if cert_paths.add_cert_paths().is_err() { + error!(LOG_LABEL, "Add trusted cert path err."); + } + + let cert_thread = add_profile_cert_path_thread(root_cert, cert_paths); enable_keys_after_user_unlock(key_id); if let Err(e) = cert_thread.join() { error!(LOG_LABEL, "add cert path thread panicked: {:?}", e); } - info!(LOG_LABEL, "Fnished enable all keys."); } diff --git a/services/key_enable/src/lib.rs b/services/key_enable/src/lib.rs index 34596134f0172469f8f7739aa64bf4d83578681f..97c078d33a7978c169835751af144b6e23e52c13 100644 --- a/services/key_enable/src/lib.rs +++ b/services/key_enable/src/lib.rs @@ -14,7 +14,7 @@ */ //!crate key_enable - +extern crate lazy_static; /// module contains cert chain func pub mod cert_chain_utils; /// module contains cert path func diff --git a/services/key_enable/src/profile_utils.rs b/services/key_enable/src/profile_utils.rs index b0d2d628ba5f5beb17516f53169c4059809cad57..2053d4627cfe82e16b2078bd0993730a3418b19e 100644 --- a/services/key_enable/src/profile_utils.rs +++ b/services/key_enable/src/profile_utils.rs @@ -13,6 +13,7 @@ * limitations under the License. */ +use lazy_static::lazy_static; use super::cert_chain_utils::PemCollection; use super::cert_path_utils::{ add_cert_path_info, remove_cert_path_info, common_format_fabricate_name, @@ -42,8 +43,10 @@ const LOG_LABEL: HiLogLabel = HiLogLabel { }; const PROFILE_STORE_EL0_PREFIX: &str = "/data/service/el0/profiles/developer"; const PROFILE_STORE_EL1_PREFIX: &str = "/data/service/el1/profiles/release"; +const PROFILE_STORE_EL1_PUBLIC_PREFIX: &str = "/data/service/el1/public/profiles/release"; const DEBUG_PROFILE_STORE_EL0_PREFIX: &str = "/data/service/el0/profiles/debug"; const DEBUG_PROFILE_STORE_EL1_PREFIX: &str = "/data/service/el1/profiles/debug"; +const DEBUG_PROFILE_STORE_EL1_PUBLIC_PREFIX: &str = "/data/service/el1/public/profiles/debug"; const PROFILE_STORE_TAIL: &str = "profile.p7b"; const PROFILE_TYPE_KEY: &str = "type"; const PROFILE_DEVICE_ID_TYPE_KEY: &str = "device-id-type"; @@ -52,9 +55,15 @@ const PROFILE_DEVICE_IDS_KEY: &str = "device-ids"; const PROFILE_BUNDLE_INFO_KEY: &str = "bundle-info"; const PROFILE_BUNDLE_INFO_RELEASE_KEY: &str = "distribution-certificate"; const PROFILE_BUNDLE_INFO_DEBUG_KEY: &str = "development-certificate"; +const PROFILE_APP_DISTRIBUTION_TYPE_KEY: &str = "app-distribution-type"; +const APP_DISTRIBUTION_TYPE_INTERNALTESTING: &str = "internaltesting"; +const APP_DISTRIBUTION_TYPE_ENTERPRISE: &str = "enterprise"; +const APP_DISTRIBUTION_TYPE_ENTERPRISE_NORMAL: &str = "enterprise_normal"; +const APP_DISTRIBUTION_TYPE_ENTERPRISE_MDM: &str = "enterprise_mdm"; const DEFAULT_MAX_CERT_PATH_LEN: u32 = 3; const PROFILE_RELEASE_TYPE: &str = "release"; const PROFILE_DEBUG_TYPE: &str = "debug"; + /// profile error pub enum ProfileError { /// add cert path error @@ -105,48 +114,91 @@ fn parse_pkcs7_data( flags: Pkcs7Flags, check_udid: bool, ) -> Result<(String, String, u32), Box> { - let stack_of_certs = Stack::::new()?; + let profile = verify_pkcs7_signature(pkcs7, root_store, flags)?; + let profile_json = parse_and_validate_profile(profile, check_udid)?; + get_cert_details(&profile_json) +} +fn verify_pkcs7_signature( + pkcs7: &Pkcs7, + root_store: &X509Store, + flags: Pkcs7Flags, +) -> Result, Box> { + let stack_of_certs = Stack::::new()?; let mut profile = Vec::new(); - if pkcs7.verify(&stack_of_certs, root_store, None, Some(&mut profile), flags).is_err() { - error!(LOG_LABEL, "pkcs7 verify failed."); - return Err("pkcs7 verify failed.".into()); + pkcs7.verify(&stack_of_certs, root_store, None, Some(&mut profile), flags)?; + Ok(profile) +} + +/// validate bundle info and debug info +pub fn validate_bundle_and_distribution_type( + profile_json: &JsonValue, + check_udid: bool, +) -> Result<(), Box> { + let bundle_type = profile_json[PROFILE_TYPE_KEY].try_as_string()?.as_str(); + match bundle_type { + PROFILE_DEBUG_TYPE => { + if check_udid && verify_udid(profile_json).is_err() { + return Err("Invalid UDID.".into()); + } + }, + PROFILE_RELEASE_TYPE => { + let distribution_type = profile_json[PROFILE_APP_DISTRIBUTION_TYPE_KEY].try_as_string()?.as_str(); + match distribution_type { + APP_DISTRIBUTION_TYPE_INTERNALTESTING => { + if check_udid && verify_udid(profile_json).is_err() { + return Err("Invalid UDID.".into()); + } + }, + APP_DISTRIBUTION_TYPE_ENTERPRISE | + APP_DISTRIBUTION_TYPE_ENTERPRISE_NORMAL | + APP_DISTRIBUTION_TYPE_ENTERPRISE_MDM => { + }, + _ => { + return Err("Invalid app distribution type.".into()); + } + } + } + _ => { + return Err("Invalid bundle type.".into()); + }, } + Ok(()) +} + +fn parse_and_validate_profile( + profile: Vec, + check_udid: bool, +) -> Result> { let profile_json = JsonValue::from_text(profile)?; - let bundle_type = profile_json[PROFILE_TYPE_KEY].try_as_string()?.as_str(); + validate_bundle_and_distribution_type(&profile_json, check_udid)?; + Ok(profile_json) +} - if bundle_type == PROFILE_DEBUG_TYPE && check_udid && verify_udid(&profile_json).is_err() { - error!(LOG_LABEL, "udid verify failed."); - return Err("Invalid udid .".into()); - } +fn get_cert_details(profile_json: &JsonValue) -> Result<(String, String, u32), Box> { + let bundle_type = profile_json[PROFILE_TYPE_KEY].try_as_string()?.as_str(); let profile_type = match bundle_type { PROFILE_DEBUG_TYPE => DebugCertPathType::Developer as u32, PROFILE_RELEASE_TYPE => ReleaseCertPathType::Developer as u32, - _ => { - error!(LOG_LABEL, "pkcs7 verify failed."); - return Err("Invalid bundle type.".into()); - } + _ => return Err("Invalid bundle type.".into()), }; let signed_cert = match bundle_type { - PROFILE_DEBUG_TYPE => { - profile_json[PROFILE_BUNDLE_INFO_KEY][PROFILE_BUNDLE_INFO_DEBUG_KEY].try_as_string()? - } - PROFILE_RELEASE_TYPE => profile_json[PROFILE_BUNDLE_INFO_KEY] - [PROFILE_BUNDLE_INFO_RELEASE_KEY] - .try_as_string()?, - _ => { - error!(LOG_LABEL, "pkcs7 verify failed."); - return Err("Invalid bundle type.".into()); - } + PROFILE_DEBUG_TYPE => profile_json[PROFILE_BUNDLE_INFO_KEY][PROFILE_BUNDLE_INFO_DEBUG_KEY].try_as_string()?, + PROFILE_RELEASE_TYPE => profile_json[PROFILE_BUNDLE_INFO_KEY][PROFILE_BUNDLE_INFO_RELEASE_KEY].try_as_string()?, + _ => return Err("Invalid bundle type.".into()), }; let signed_pem = X509::from_pem(signed_cert.as_bytes())?; let subject = format_x509_fabricate_name(signed_pem.subject_name()); let issuer = format_x509_fabricate_name(signed_pem.issuer_name()); - Ok((subject, issuer, profile_type)) } -fn get_udid() -> Result { +lazy_static! { + /// global udid + pub static ref UDID: Result = init_udid(); +} + +fn init_udid() -> Result { let mut udid: Vec = vec![0; 128]; let result = unsafe { CodeSignGetUdid(udid.as_mut_ptr()) }; @@ -164,6 +216,12 @@ fn get_udid() -> Result { } } +/// get device udid +pub fn get_udid() -> Result { + UDID.clone() +} + + fn verify_signers( pkcs7: &Pkcs7, profile_signer: &[(&String, &String)], @@ -220,8 +278,8 @@ fn format_x509_fabricate_name(name: &X509NameRef) -> String { fn get_profile_paths(is_debug: bool) -> Vec { let mut paths = Vec::new(); let profile_prefixes = match is_debug { - false => vec![PROFILE_STORE_EL0_PREFIX, PROFILE_STORE_EL1_PREFIX], - true => vec![DEBUG_PROFILE_STORE_EL0_PREFIX, DEBUG_PROFILE_STORE_EL1_PREFIX], + false => vec![PROFILE_STORE_EL0_PREFIX, PROFILE_STORE_EL1_PREFIX, PROFILE_STORE_EL1_PUBLIC_PREFIX], + true => vec![DEBUG_PROFILE_STORE_EL0_PREFIX, DEBUG_PROFILE_STORE_EL1_PREFIX, DEBUG_PROFILE_STORE_EL1_PUBLIC_PREFIX], }; for profile_prefix in profile_prefixes { paths.extend(get_paths_from_prefix(profile_prefix)); @@ -287,8 +345,9 @@ fn process_profile( let (subject, issuer, profile_type) = match parse_pkcs7_data(&pkcs7, x509_store, Pkcs7Flags::empty(), check_udid) { Ok(tuple) => tuple, - Err(_) => { - error!(LOG_LABEL, "Failed to parse profile file {}", @public(path)); + Err(e) => { + error!(LOG_LABEL, "Error parsing PKCS7 data: {}, profile file {}", + @public(e), @public(path)); report_parse_profile_err(&path, HisyseventProfileError::ParsePkcs7 as i32); continue; } @@ -375,10 +434,10 @@ fn process_data(profile_data: &[u8]) -> Result<(String, String, u32), ()> { fn create_bundle_path(bundle_name: &str, profile_type: u32) -> Result { let bundle_path = match profile_type { value if value == DebugCertPathType::Developer as u32 => { - fmt_store_path(DEBUG_PROFILE_STORE_EL1_PREFIX, bundle_name) + fmt_store_path(DEBUG_PROFILE_STORE_EL1_PUBLIC_PREFIX, bundle_name) } value if value == ReleaseCertPathType::Developer as u32 => { - fmt_store_path(PROFILE_STORE_EL1_PREFIX, bundle_name) + fmt_store_path(PROFILE_STORE_EL1_PUBLIC_PREFIX, bundle_name) } _ => { error!(LOG_LABEL, "invalid profile type"); @@ -422,24 +481,16 @@ fn enable_key_in_profile_internal( Ok(()) } -fn remove_key_in_profile_internal(bundle_name: *const c_char) -> Result<(), ()> { - let _bundle_name = c_char_to_string(bundle_name); - if _bundle_name.is_empty() { - error!(LOG_LABEL, "Invalid bundle name"); +fn process_remove_bundle( + prefix: &str, + bundle_name: &str, +) -> Result<(), ()> { + let bundle_path = fmt_store_path(prefix, bundle_name); + + if !file_exists(&bundle_path) { return Err(()); } - let debug_bundle_path = fmt_store_path(DEBUG_PROFILE_STORE_EL1_PREFIX, &_bundle_name); - let release_bundle_path = fmt_store_path(PROFILE_STORE_EL1_PREFIX, &_bundle_name); - - let bundle_path = if file_exists(&debug_bundle_path) { - debug_bundle_path - } else if file_exists(&release_bundle_path) { - release_bundle_path - } else { - error!(LOG_LABEL, "bundle path does not exists!"); - return Err(()); - }; let filename = fmt_store_path(&bundle_path, PROFILE_STORE_TAIL); let mut profile_data = Vec::new(); if load_bytes_from_file(&filename, &mut profile_data).is_err() { @@ -452,19 +503,48 @@ fn remove_key_in_profile_internal(bundle_name: *const c_char) -> Result<(), ()> error!(LOG_LABEL, "remove profile data error!"); return Err(()); } + info!(LOG_LABEL, "remove bundle_path path {}!", @public(bundle_path)); - if unsafe { !IsDeveloperModeOn() } && profile_type == DebugCertPathType::Developer as u32 { - info!(LOG_LABEL, "not remove profile_type:{} when development off", @public(profile_type)); - return Ok(()); - } + if remove_cert_path_info(subject, issuer, profile_type, DEFAULT_MAX_CERT_PATH_LEN).is_err() { error!(LOG_LABEL, "remove profile data error!"); return Err(()); } + info!(LOG_LABEL, "finish remove cert path in ioctl!"); Ok(()) } +fn remove_key_in_profile_internal(bundle_name: *const c_char) -> Result<(), ()> { + let _bundle_name = c_char_to_string(bundle_name); + if _bundle_name.is_empty() { + error!(LOG_LABEL, "Invalid bundle name"); + return Err(()); + } + + let profile_prefix = vec![ + DEBUG_PROFILE_STORE_EL0_PREFIX, + PROFILE_STORE_EL0_PREFIX, + DEBUG_PROFILE_STORE_EL1_PREFIX, + PROFILE_STORE_EL1_PREFIX, + DEBUG_PROFILE_STORE_EL1_PUBLIC_PREFIX, + PROFILE_STORE_EL1_PUBLIC_PREFIX, + ]; + + let mut rm_succ = false; + for prefix in profile_prefix { + if process_remove_bundle(prefix, &_bundle_name).is_ok() { + rm_succ = true; + } + } + if rm_succ { + Ok(()) + } else { + error!(LOG_LABEL, "Failed to remove bundle profile info, bundleName: {}.", @public(_bundle_name)); + Err(()) + } +} + fn c_char_to_string(c_str: *const c_char) -> String { unsafe { if c_str.is_null() { diff --git a/services/local_code_sign/src/local_sign_key.cpp b/services/local_code_sign/src/local_sign_key.cpp index 24412ec72e306ad4619b720fb23ccc2a2835b21f..bc17c5a27e56161646bc37249df8bacabbc4a4b1 100644 --- a/services/local_code_sign/src/local_sign_key.cpp +++ b/services/local_code_sign/src/local_sign_key.cpp @@ -297,7 +297,7 @@ bool LocalSignKey::SignByHUKS(const struct HksBlob *inData, struct HksBlob *outD if (ret != HKS_SUCCESS) { LOG_ERROR("HksUpdate Failed."); free(tmpOutData.data); - return CS_ERR_PARAM_INVALID; + return false; } // third stage: finish, get signature from HUKS diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 3f223fd0d8d159fb1bc631c801069022451cf92d..abdcf5117bae25fb60e83cc8c477e2a889398a37 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -37,7 +37,21 @@ ohos_source_set("key_enable_src_set") { ohos_unittest("add_cert_path_unittest") { module_out_path = "security/code_signature" - sources = [ "add_cert_path_test.cpp" ] + sources = [ + "${code_signature_root_dir}/services/key_enable/utils/src/cert_path.cpp", + "add_cert_path_test.cpp", + ] + include_dirs = + [ "${code_signature_root_dir}/services/key_enable/utils/include" ] + configs = [ + "${code_signature_root_dir}:common_utils_config", + "${code_signature_root_dir}:common_public_config", + ] + deps = [ "${selinux_dir}:libselinux" ] + external_deps = [ + "hilog:libhilog", + "init:libbegetutil", + ] } ohos_unittest("code_sign_utils_unittest") { @@ -50,6 +64,10 @@ ohos_unittest("code_sign_utils_unittest") { "${code_signature_root_dir}/interfaces/innerkits/code_sign_utils:libcode_sign_utils", ] + if (!is_asan && !use_clang_coverage) { + defines = [ "NO_USE_CLANG_COVERAGE" ] + } + include_dirs = [ "utils/include", "${code_signature_root_dir}/interfaces/innerkits/code_sign_utils/include", @@ -63,6 +81,24 @@ ohos_unittest("code_sign_utils_unittest") { ] } +ohos_unittest("code_sign_attr_utils_unittest") { + module_out_path = "security/code_signature" + sources = [ "code_sign_attr_utils_test.cpp" ] + + deps = [ "${code_signature_root_dir}/interfaces/innerkits/code_sign_attr_utils:libcode_sign_attr_utils" ] + + include_dirs = [ + "utils/include", + "${code_signature_root_dir}/interfaces/innerkits/common/include", + "${code_signature_root_dir}/utils/include", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] +} + ohos_unittest("code_sign_utils_in_c_unittest") { module_out_path = "security/code_signature" resource_config_file = "resources/ohos_test.xml" @@ -144,6 +180,37 @@ ohos_unittest("local_code_sign_utils_unittest") { ] } +ohos_unittest("local_code_sign_utils_mock_unittest") { + module_out_path = "security/code_signature" + resource_config_file = "resources/ohos_test.xml" + sources = [ + "${code_signature_root_dir}/services/key_enable/utils/src/cert_path.cpp", + "${code_signature_root_dir}/services/local_code_sign/src/local_sign_key.cpp", + "${code_signature_root_dir}/utils/src/cert_utils.cpp", + "local_code_sign_utils_mock_test.cpp", + "mock/src/hks_api_mock_helper.cpp", + "mock/src/hks_api_mock_test.cpp", + ] + deps = [ "${code_signature_root_dir}/interfaces/innerkits/code_sign_utils:libcode_sign_utils" ] + + include_dirs = [ + "mock/include", + "utils/include", + "${code_signature_root_dir}/services/local_code_sign/include", + "${code_signature_root_dir}/services/key_enable/utils/include", + ] + + configs = [ "${code_signature_root_dir}:common_utils_config" ] + external_deps = [ + "c_utils:utils", + "fsverity-utils:libfsverity_utils", + "hilog:libhilog", + "huks:libhukssdk", + "init:libbegetutil", + "openssl:libcrypto_shared", + ] +} + ohos_unittest("sign_and_enforce_unittest") { module_out_path = "security/code_signature" resource_config_file = "resources/ohos_test.xml" @@ -208,6 +275,7 @@ ohos_rust_static_library("rust_key_enable_lib") { "${code_signature_root_dir}/services/key_enable/utils:libkey_enable_utils", "${rust_openssl_dir}/openssl:lib", "//third_party/rust/crates/cxx:lib", + "//third_party/rust/crates/lazy-static.rs:lib", ] external_deps = [ "c_utils:utils_rust", @@ -237,6 +305,7 @@ ohos_rust_unittest("rust_key_enable_unittest") { resource_config_file = "resources/ohos_test.xml" crate_root = "./rust_key_enable_test.rs" sources = [ "./rust_key_enable_test.rs" ] + external_deps = [ "ylong_json:lib" ] deps = [ ":rust_key_enable_lib" ] subsystem_name = "security" part_name = "code_signature" @@ -299,15 +368,49 @@ ohos_unittest("key_enable_utils_unittest") { ] } +ohos_unittest("cert_chain_verifier_unittest") { + module_out_path = "security/code_signature" + sources = [ + "${code_signature_root_dir}/utils/src/cert_utils.cpp", + "${code_signature_root_dir}/utils/src/huks_attest_verifier.cpp", + "${code_signature_root_dir}/utils/src/openssl_utils.cpp", + "cert_chain_verifier_test.cpp", + ] + include_dirs = [ "utils/include" ] + configs = [ + "${code_signature_root_dir}:common_utils_config", + "${code_signature_root_dir}:common_public_config", + ] + defines = [ "CODE_SIGNATURE_DEBUGGABLE" ] + if (code_signature_support_oh_release_app) { + defines += [ "CODE_SIGNATURE_OH_ROOT_CA" ] + } + deps = [ + "${code_signature_root_dir}/services/key_enable/utils:libkey_enable_utils", + ] + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "hilog:libhilog", + "huks:libhukssdk", + "openssl:libcrypto_shared", + ] +} + group("unittest_group") { testonly = true if (!defined(ohos_lite)) { deps = [ ":add_cert_path_unittest", + ":cert_chain_verifier_unittest", + ":code_sign_attr_utils_unittest", ":code_sign_utils_in_c_unittest", ":code_sign_utils_unittest", ":enable_verity_ioctl_unittest", ":local_code_sign_unittest", + ":local_code_sign_utils_mock_unittest", ":local_code_sign_utils_unittest", ":multi_thread_local_sign_unittest", ":sign_and_enforce_unittest", diff --git a/test/unittest/add_cert_path_test.cpp b/test/unittest/add_cert_path_test.cpp index f2ee68bea29f7e8ca7a826cec4202c17eaa208a4..c010ecaab47501bfffb3164e25a27fe19cf64014 100644 --- a/test/unittest/add_cert_path_test.cpp +++ b/test/unittest/add_cert_path_test.cpp @@ -19,26 +19,18 @@ #include #include #include +#include #include +#include "cert_path.h" +#include "selinux/selinux.h" + namespace OHOS { namespace Security { namespace CodeSign { using namespace std; using namespace testing::ext; -struct cert_chain_info { - uint32_t signing_length; - uint32_t issuer_length; - uint64_t signing; - uint64_t issuer; - uint32_t max_cert_chain; - uint32_t cert_path_type; - uint8_t reserved[32]; -}; - -#define WRITE_CERT_CHAIN _IOW('k', 1, cert_chain_info) - static const uint32_t MAX_CERT_CHAIN = 3; static const uint32_t CERT_PATH_TYPE = 0x103; static const uint32_t GREATER_THAN_MAX_CERT_CHAIN = 4; @@ -47,6 +39,11 @@ static const uint32_t LESS_THAN_MIN_CERT_CHAIN = -1; static const string DEV_NAME = "/dev/code_sign"; static const string TEST_SUBJECT = "OpenHarmony Application Release"; static const string TEST_ISSUER = "OpenHarmony Application CA"; +static const string KEY_ENABLE_CTX = "u:r:key_enable:s0"; +static const string FAKE_SUBJECT = "Fake subject"; +static const string FAKE_ISSUER = "Fake issuer"; +static const string SUBJECT_AS_SYSTEM_TYPE = "System subject"; +static const string ISSUER_AS_SYSTEM_TYPE = "System issuer"; class AddCertPathTest : public testing::Test { public: @@ -58,58 +55,80 @@ public: void TearDown() {}; }; -static bool CallIoctl(const char *signing, const char *issuer, uint32_t max_cert_chain, uint32_t cert_path_type) +static CertPathInfo MakeCertPathInfo(const char *signing, const char *issuer, + uint32_t max_cert_chain, uint32_t cert_path_type) { - int fd = open(DEV_NAME.c_str(), O_WRONLY); - EXPECT_GE(fd, 0); - - cert_chain_info arg = { 0 }; + 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.max_cert_chain = max_cert_chain; - arg.cert_path_type = cert_path_type; - int ret = ioctl(fd, WRITE_CERT_CHAIN, &arg); - - close(fd); - return ret; + arg.signing_length = strlen(signing); + arg.issuer_length = strlen(issuer); + arg.path_len = max_cert_chain; + arg.path_type = cert_path_type; + return arg; } /** * @tc.name: AddCertPathTest_0001 - * @tc.desc: successfully called interface + * @tc.desc: calling interface with greater than path len * @tc.type: Func * @tc.require: */ HWTEST_F(AddCertPathTest, AddCertPathTest_0001, TestSize.Level0) { - int ret = CallIoctl(TEST_SUBJECT.c_str(), TEST_ISSUER.c_str(), MAX_CERT_CHAIN, CERT_PATH_TYPE); - EXPECT_GE(ret, 0); + CertPathInfo certPathInfo = MakeCertPathInfo(TEST_SUBJECT.c_str(), TEST_ISSUER.c_str(), + GREATER_THAN_MAX_CERT_CHAIN, CERT_PATH_TYPE); + EXPECT_NE(AddCertPath(certPathInfo), 0); } /** * @tc.name: AddCertPathTest_0002 - * @tc.desc: calling interface with greater than path len + * @tc.desc: calling interface with invalid path len * @tc.type: Func * @tc.require: */ HWTEST_F(AddCertPathTest, AddCertPathTest_0002, TestSize.Level0) { - int ret = CallIoctl(TEST_SUBJECT.c_str(), TEST_ISSUER.c_str(), GREATER_THAN_MAX_CERT_CHAIN, CERT_PATH_TYPE); - EXPECT_NE(ret, 0); + CertPathInfo certPathInfo = MakeCertPathInfo(TEST_SUBJECT.c_str(), TEST_ISSUER.c_str(), + LESS_THAN_MIN_CERT_CHAIN, CERT_PATH_TYPE); + EXPECT_NE(AddCertPath(certPathInfo), 0); } /** * @tc.name: AddCertPathTest_0003 - * @tc.desc: calling interface with invalid path len + * @tc.desc: add cert path success * @tc.type: Func * @tc.require: */ HWTEST_F(AddCertPathTest, AddCertPathTest_0003, TestSize.Level0) { - int ret = CallIoctl(TEST_SUBJECT.c_str(), TEST_ISSUER.c_str(), LESS_THAN_MIN_CERT_CHAIN, CERT_PATH_TYPE); - EXPECT_NE(ret, 0); + // type = developer in release + CertPathInfo certPathInfo = MakeCertPathInfo(FAKE_SUBJECT.c_str(), FAKE_ISSUER.c_str(), MAX_CERT_CHAIN, 0x3); + EXPECT_EQ(AddCertPath(certPathInfo), 0); + EXPECT_EQ(RemoveCertPath(certPathInfo), 0); + + // type = developer in debug + certPathInfo = MakeCertPathInfo(FAKE_SUBJECT.c_str(), FAKE_ISSUER.c_str(), MAX_CERT_CHAIN, 0x103); + EXPECT_EQ(AddCertPath(certPathInfo), 0); + EXPECT_EQ(RemoveCertPath(certPathInfo), 0); + + // remove unexists + EXPECT_NE(RemoveCertPath(certPathInfo), 0); +} + +/** + * @tc.name: AddCertPathTest_0004 + * @tc.desc: cannot add system cert except key_enable + * @tc.type: Func + * @tc.require: + */ +HWTEST_F(AddCertPathTest, AddCertPathTest_0004, TestSize.Level0) +{ + // release + CertPathInfo certPathInfo = MakeCertPathInfo(SUBJECT_AS_SYSTEM_TYPE.c_str(), + ISSUER_AS_SYSTEM_TYPE.c_str(), MAX_CERT_CHAIN, 1); + // cannot add except key_enable + EXPECT_NE(AddCertPath(certPathInfo), 0); } } // namespace CodeSign } // namespace Security diff --git a/test/unittest/cert_chain_verifier_test.cpp b/test/unittest/cert_chain_verifier_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6d4357b77b5a9c6c8c4ea95e85ac6310c5485b1d --- /dev/null +++ b/test/unittest/cert_chain_verifier_test.cpp @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2024-2024 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 "access_token_setter.h" +#include "byte_buffer.h" +#include "huks_attest_verifier.h" +#include "log.h" + +using namespace OHOS::Security::CodeSign; +using namespace std; +using namespace testing::ext; + +namespace OHOS { +namespace Security { +namespace CodeSign { +const std::string SIGNING_CERT_CHAIN_PEM = +"-----BEGIN CERTIFICATE-----\n" \ +"MIIDgzCCAm2gAwIBAgIBATALBgkqhkiG9w0BAQswfzELMAkGA1UEBhMCQ04xEzAR\n" \ +"BgNVBAgMCmhlbGxvd29ybGQxEzARBgNVBAoMCmhlbGxvd29ybGQxEzARBgNVBAsM\n" \ +"CmhlbGxvd29ybGQxFjAUBgNVBAMMDWhlbGxvd29ybGQxMTExGTAXBgkqhkiG9w0B\n" \ +"CQEWCmhlbGxvd29ybGQwHhcNMjQwODA5MDkzMDEyWhcNMzQwODA5MDkzMDEyWjAa\n" \ +"MRgwFgYDVQQDEw9BIEtleW1hc3RlciBLZXkwWTATBgcqhkjOPQIBBggqhkjOPQMB\n" \ +"BwNCAATJqTRIhGKhLmXuJbPI311/5gEljqPbpJpXNp6oe8dOmnyJ9SQQZmMomB5u\n" \ +"lC5aZIoNrCuKHTAgY1PpNNcFSBBpo4IBPDCCATgwCwYDVR0PBAQDAgeAMAgGA1Ud\n" \ +"HwQBADCCAR0GDCsGAQQBj1sCgngBAwSCAQswggEHAgEAMDQCAQAGDSsGAQQBj1sC\n" \ +"gngCAQQEIOIC9EG2Dn3zqle0WWjiHwk2CIP3hJuPjjQwi7z4FaFFMCICAQIGDSsG\n" \ +"AQQBj1sCgngCAQIEDkxPQ0FMX1NJR05fS0VZMFwCAQIGDSsGAQQBj1sCgngCAQMw\n" \ +"SAYOKwYBBAGPWwKCeAIBAwEENnsicHJvY2Vzc05hbWUiOiJsb2NhbF9jb2RlX3Np\n" \ +"Z24iLCJBUEwiOiJzeXN0ZW1fYmFzaWMifTAYAgECBg0rBgEEAY9bAoJ4AgELBAQA\n" \ +"AAAAMBgCAQIGDSsGAQQBj1sCgngCAQUEBAIAAAAwFgIBAgYOKwYBBAGPWwKCeAIE\n" \ +"AQUBAf8wCwYJKoZIhvcNAQELA4IBAQB8zqqeaXux3qkQF0GFax7I4YWtTpoeQeJU\n" \ +"BjyMk/eGmeX+ZD9absOQDzH/wH6MddzPLjoaIuoR+oxDXn2yqQ5xyGQp6uN0E8IB\n" \ +"OFCjeTbRBR86A+CulTGuitszOpfyKF7SvmzfGx+ij2OtQnZ7QZp+I2YEr1Jc4ESr\n" \ +"xXXt0zPslidnf7qso+f09C6U9YOnaxISfjxEqFn25+yWX2tXBJ62L6R7+zpKU3ee\n" \ +"0ljf4jYtlza7s5mYJ2+OHlwdXuF38cpS59cG48UpsL0DAqywqjs5uaGthkrWo2YB\n" \ +"FlAL4bVfBj2FmcqNhz+j3dgLTNA3VczwkNbj/FIY1T+FDTqnsCED\n" \ +"-----END CERTIFICATE-----"; + +const std::string ISSUER_CERT_CHAIN_PEM = +"-----BEGIN CERTIFICATE-----\n" \ +"MIIDyzCCArOgAwIBAgIBAzANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJDTjET\n" \ +"MBEGA1UECAwKaGVsbG93b3JsZDETMBEGA1UECgwKaGVsbG93b3JsZDETMBEGA1UE\n" \ +"CwwKaGVsbG93b3JsZDEVMBMGA1UEAwwMaGVsbG93b3JsZDExMRkwFwYJKoZIhvcN\n" \ +"AQkBFgpoZWxsb3dvcmxkMB4XDTIyMDEyMjA5MjUzM1oXDTMyMDEyMDA5MjUzM1ow\n" \ +"fzELMAkGA1UEBhMCQ04xEzARBgNVBAgMCmhlbGxvd29ybGQxEzARBgNVBAoMCmhl\n" \ +"bGxvd29ybGQxEzARBgNVBAsMCmhlbGxvd29ybGQxFjAUBgNVBAMMDWhlbGxvd29y\n" \ +"bGQxMTExGTAXBgkqhkiG9w0BCQEWCmhlbGxvd29ybGQwggEiMA0GCSqGSIb3DQEB\n" \ +"AQUAA4IBDwAwggEKAoIBAQC8HHhVEbY3uuriW3wAcAMFwIUd+VImAUKnWAYlsiHL\n" \ +"Ps3BhpHHb67kjzP3rcQbZ2l1LSMWjoV8jXckVMOFqOlTlrYlGM3G80bVaWcEgw4c\n" \ +"+nkSk+ApGmNUa69HK3h+5vfz81fVmJL1zX0VaYiA+wCzrFc1w5aGKhsFIcIY8FUo\n" \ +"i15xrwAURQ+/EylzeF302qGwkCHYy4zQqn3ohku25rPLUOyOp6gJNs/3BVh76b9/\n" \ +"1iTyP7ldDD7VV4UQCTDppFtrDQY/UrBhe9sPn0+6GWBfkkjz5n1aGE7JP2vmB3qM\n" \ +"gxIpEkmVLVIxh6dwBOmtr+sT7xJ+UzmTWbbhNGCkzSPxAgMBAAGjUzBRMB0GA1Ud\n" \ +"DgQWBBSDTqp6QOdxk9zF2H+7IGOckq/A1DAfBgNVHSMEGDAWgBRNYAEJlwxPOj5F\n" \ +"B7M4mTsMpokRLzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB4\n" \ +"CkKbJQWuC2pj0cS+zb4v8fRq8OPjRVPylqjHX4IMpmnl2VM0DkNXD0SYPC5IxkK4\n" \ +"bgtglG0Rkr4blYf+PdNenbebWZvw4Y3JUoQgSasfdIA/rJXZtf3mVUNLmPlcRWZC\n" \ +"OtGJmvlntp7/qWl7JCIaiD732baJU1DZchy3am2WWGpchBESBOtoSvdywG+T0xQQ\n" \ +"cXzYQ+mHPsym30JCzChvZCKz+QJlIZUJ3XgoKH7MVviASXGcWLKOBYYUDt3J8/PM\n" \ +"shbsqb+rm+VqU5ohV8Rr/nQ+QLvEFa8rrz7qY6/2QSbUy7QvFCv7MXFD1kCH92FL\n" \ +"GwkmWDavM1kdVMXZmV54\n" \ +"-----END CERTIFICATE-----"; + +const std::string INTER_CA_CHAIN_PEM = +"-----BEGIN CERTIFICATE-----\n" \ +"MIID3zCCAsegAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBkjELMAkGA1UEBhMCQ04x\n" \ +"EzARBgNVBAgMCmhlbGxvd29ybGQxEzARBgNVBAcMCmhlbGxvd29ybGQxEzARBgNV\n" \ +"BAoMCmhlbGxvd29ybGQxEzARBgNVBAsMCmhlbGxvd29ybGQxFDASBgNVBAMMC2hl\n" \ +"bGxvd29ybGQxMRkwFwYJKoZIhvcNAQkBFgpoZWxsb3dvcmxkMB4XDTIyMDEyMjA5\n" \ +"MjM0OFoXDTMyMDEyMDA5MjM0OFowfjELMAkGA1UEBhMCQ04xEzARBgNVBAgMCmhl\n" \ +"bGxvd29ybGQxEzARBgNVBAoMCmhlbGxvd29ybGQxEzARBgNVBAsMCmhlbGxvd29y\n" \ +"bGQxFTATBgNVBAMMDGhlbGxvd29ybGQxMTEZMBcGCSqGSIb3DQEJARYKaGVsbG93\n" \ +"b3JsZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALTJF+SAh/ccmcxF\n" \ +"+le0m8Wx7N9kclMYoUVGyJOPDv0L9kE/1hg9HEavCBWal9ZK69r+i1YiH18Y0F5o\n" \ +"AuqP0teedDByPii8IaDquJKZ1hlMi13vPY1cgUcG77cKzC5TMlmNTLes0ddn9/lY\n" \ +"4ajl4kgUr3bCEXlp4uhBQPYlntujctcjmEdMtcJQmhHpr2Js9cq2kZney59ae5kk\n" \ +"LCzpFqpj7cunz5Rs3RZs1+Njw5oABS18qAy1CEBnecLOi6lIPvIckngBHduwczOM\n" \ +"5YBBXeqOeNk7FWTiIf5MuXlqOSlZ57Wp8SqfDzwS49awwI9dvGpjgyGh3ZQA5TXX\n" \ +"GGIsn5cCAwEAAaNTMFEwHQYDVR0OBBYEFE1gAQmXDE86PkUHsziZOwymiREvMB8G\n" \ +"A1UdIwQYMBaAFJp3c+VFpGlC/r/UiPCozoH1UcgMMA8GA1UdEwEB/wQFMAMBAf8w\n" \ +"DQYJKoZIhvcNAQELBQADggEBAArLbWZWG3cHuCnMBGo28F0KVKctxjLVOCzDhKnH\n" \ +"IusLVqTnZ7AHeUU56NyoRfSRSIEJ2TNXkHO8MyxNN3lP4RapQavOvENLE99s269I\n" \ +"suLPCp3k6znJX1ZW7MIrSp7Bz+6rBTuh2H874H/BcvPXaCZB4X3Npjfu4tRcKEtS\n" \ +"JKdVmIlotjX1qM5eYHY5BDSR0MvRYvSlH7/wA9FEGJ8GHI7vaHxIMxf4+OOz+E4w\n" \ +"qKIZZfYeVBdEpZvfVGHRbS5dEofqc4NthlObTWlwAIhFgTzLqy8y2Y2jDWcJk91/\n" \ +"y9u8F1jQAuoemDCY5BalZ+Bn0eZQQHlXujwyZfoIK+oCuUo=\n" \ +"-----END CERTIFICATE-----"; + +const uint8_t CHALLENGE[] = { + 0xe2, 0x2, 0xf4, 0x41, 0xb6, 0xe, 0x7d, 0xf3, + 0xaa, 0x57, 0xb4, 0x59, 0x68, 0xe2, 0x1f, 0x9, + 0x36, 0x8, 0x83, 0xf7, 0x84, 0x9b, 0x8f, 0x8e, + 0x34, 0x30, 0x8b, 0xbc, 0xf8, 0x15, 0xa1, 0x45 +}; + +static ByteBuffer g_issuerCert; +static ByteBuffer g_signingCert; +static ByteBuffer g_interCA; +static ByteBuffer g_invalidCert; +static ByteBuffer g_rootCA; + +static inline uint8_t *CastToUint8Ptr(uint32_t *ptr) +{ + return reinterpret_cast(ptr); +} + +static X509 *LoadPemString(const std::string &pemData) +{ + BIO *mem = BIO_new_mem_buf(pemData.c_str(), pemData.length()); + if (mem == nullptr) { + return nullptr; + } + + X509 *x509 = PEM_read_bio_X509(mem, nullptr, nullptr, nullptr); + EXPECT_NE(x509, nullptr); + BIO_free(mem); + return x509; +} + +void LoadDerFormPemString(const std::string &pemData, ByteBuffer &certBuffer) +{ + X509 *x509 = LoadPemString(pemData); + uint8_t *derTemp = nullptr; + int32_t derTempLen = i2d_X509(x509, &derTemp); + EXPECT_NE(derTemp, nullptr); + if (derTempLen < 0) { + X509_free(x509); + return; + } + + certBuffer.CopyFrom(derTemp, static_cast(derTempLen)); + + X509_free(x509); + OPENSSL_free(derTemp); +} + +static void FormattedCertChain(const std::vector &certChain, ByteBuffer &buffer) +{ + uint32_t certsCount = certChain.size(); + uint32_t totalLen = sizeof(uint32_t); + for (uint32_t i = 0; i < certsCount; i++) { + totalLen += sizeof(uint32_t) + certChain[i].GetSize(); + } + buffer.Resize(totalLen); + if (!buffer.PutData(0, CastToUint8Ptr(&certsCount), sizeof(uint32_t))) { + return; + } + uint32_t pos = sizeof(uint32_t); + for (uint32_t i = 0; i < certsCount; i++) { + uint32_t size = certChain[i].GetSize(); + if (!buffer.PutData(pos, CastToUint8Ptr(&size), sizeof(uint32_t))) { + return; + } + pos += sizeof(uint32_t); + if (!buffer.PutData(pos, certChain[i].GetBuffer(), certChain[i].GetSize())) { + return; + } + pos += certChain[i].GetSize(); + } +} + +class CertChainVerifierTest : public testing::Test { +public: + CertChainVerifierTest() {}; + virtual ~CertChainVerifierTest() {}; + static void SetUpTestCase() + { + LoadDerFormPemString(SIGNING_CERT_CHAIN_PEM, g_signingCert); + LoadDerFormPemString(ISSUER_CERT_CHAIN_PEM, g_issuerCert); + LoadDerFormPemString(INTER_CA_CHAIN_PEM, g_interCA); + // fake root CA, no use in verifying + uint8_t tmp = 0; + g_rootCA.CopyFrom(&tmp, sizeof(tmp)); + g_invalidCert.CopyFrom(&tmp, sizeof(tmp)); + } + static void TearDownTestCase() {}; + void SetUp() {}; + void TearDown() {}; +}; + +/** + * @tc.name: CertChainVerifierTest_001 + * @tc.desc: Get chain from empty buffer + * @tc.type: Func + * @tc.require: IAJ4QG + */ +HWTEST_F(CertChainVerifierTest, CertChainVerifierTest_001, TestSize.Level0) +{ + ByteBuffer cert, challenge, certBuffer; + EXPECT_EQ(GetVerifiedCert(cert, challenge, certBuffer), false); +} + +/** + * @tc.name: CertChainVerifierTest_0002 + * @tc.desc: Get chain from empty cert chain + * @tc.type: Func + * @tc.require: IAJ4QG + */ +HWTEST_F(CertChainVerifierTest, CertChainVerifierTest_002, TestSize.Level0) +{ + ByteBuffer cert, challenge, certBuffer; + uint32_t count = 0; + cert.CopyFrom(reinterpret_cast(&count), sizeof(count)); + EXPECT_EQ(GetVerifiedCert(cert, challenge, certBuffer), false); +} + + +/** + * @tc.name: CertChainVerifierTest_0003 + * @tc.desc: Get chain from invalid formatted buffer + * @tc.type: Func + * @tc.require: IAJ4QG + */ +HWTEST_F(CertChainVerifierTest, CertChainVerifierTest_003, TestSize.Level0) +{ + ByteBuffer cert, challenge, certBuffer; + std::vector tmpBuffer = {0}; + cert.CopyFrom(reinterpret_cast(tmpBuffer.data()), tmpBuffer.size() * sizeof(uint32_t)); + EXPECT_EQ(GetVerifiedCert(cert, challenge, certBuffer), false); + + // one cert in cert chain, classify as root CA + tmpBuffer[0] = 1; + // load issuer failed + cert.CopyFrom(reinterpret_cast(tmpBuffer.data()), tmpBuffer.size() * sizeof(uint32_t)); + EXPECT_EQ(GetVerifiedCert(cert, challenge, certBuffer), false); + + // two certs in cert chain + tmpBuffer[0] = 2; + // cert size + tmpBuffer.push_back(sizeof(uint32_t)); + cert.CopyFrom(reinterpret_cast(tmpBuffer.data()), tmpBuffer.size() * sizeof(uint32_t)); + // no content to load cert, convert from formatted buffer failed + EXPECT_EQ(GetVerifiedCert(cert, challenge, certBuffer), false); + + // fill issuer + tmpBuffer.push_back(0); + cert.CopyFrom(reinterpret_cast(tmpBuffer.data()), tmpBuffer.size() * sizeof(uint32_t)); + // invalid content, convert content to x509 failed + EXPECT_EQ(GetVerifiedCert(cert, challenge, certBuffer), false); +} + +/** + * @tc.name: CertChainVerifierTest_0004 + * @tc.desc: Get verified failed with invalid issuer format + * @tc.type: Func + * @tc.require: IAJ4QG + */ +HWTEST_F(CertChainVerifierTest, CertChainVerifierTest_004, TestSize.Level0) +{ + ByteBuffer formattedCert, challenge, certBuffer; + std::vector certs; + certs.push_back(g_signingCert); + certs.push_back(g_invalidCert); + certs.push_back(g_interCA); + certs.push_back(g_rootCA); + FormattedCertChain(certs, formattedCert); + EXPECT_EQ(GetVerifiedCert(formattedCert, challenge, certBuffer), false); +} + +/** + * @tc.name: CertChainVerifierTest_0005 + * @tc.desc: Get verified failed with invalid interCA format + * @tc.type: Func + * @tc.require: IAJ4QG + */ +HWTEST_F(CertChainVerifierTest, CertChainVerifierTest_005, TestSize.Level0) +{ + ByteBuffer formattedCert, challenge, certBuffer; + std::vector certs; + certs.push_back(g_signingCert); + certs.push_back(g_issuerCert); + certs.push_back(g_invalidCert); + certs.push_back(g_rootCA); + FormattedCertChain(certs, formattedCert); + EXPECT_EQ(GetVerifiedCert(formattedCert, challenge, certBuffer), false); +} + +/** + * @tc.name: CertChainVerifierTest_0006 + * @tc.desc: verifying issuer cert failed + * @tc.type: Func + * @tc.require: IAJ4QG + */ +HWTEST_F(CertChainVerifierTest, CertChainVerifierTest_006, TestSize.Level0) +{ + ByteBuffer formattedCert, challenge, certBuffer; + std::vector certs; + certs.push_back(g_signingCert); + certs.push_back(g_signingCert); + certs.push_back(g_interCA); + certs.push_back(g_rootCA); + FormattedCertChain(certs, formattedCert); + EXPECT_EQ(GetVerifiedCert(formattedCert, challenge, certBuffer), false); +} + +/** + * @tc.name: CertChainVerifierTest_0007 + * @tc.desc: verify signing cert failed + * @tc.type: Func + * @tc.require: IAJ4QG + */ +HWTEST_F(CertChainVerifierTest, CertChainVerifierTest_007, TestSize.Level0) +{ + ByteBuffer challenge; + //parse pub key of failed + EXPECT_EQ(VerifyCertAndExtension(nullptr, nullptr, challenge), false); + + X509 *signingCert = LoadPemString(SIGNING_CERT_CHAIN_PEM); + X509 *issuerCert = LoadPemString(ISSUER_CERT_CHAIN_PEM); + // verify signature failed + EXPECT_EQ(VerifyCertAndExtension(issuerCert, signingCert, challenge), false); + + // verify extension failed + const char *invalidChallenge = "invalid"; + challenge.CopyFrom(reinterpret_cast(invalidChallenge), + sizeof(invalidChallenge)); + EXPECT_EQ(VerifyCertAndExtension(signingCert, issuerCert, challenge), false); + + // verify extension success + challenge.CopyFrom(CHALLENGE, sizeof(CHALLENGE)); + EXPECT_EQ(VerifyCertAndExtension(signingCert, issuerCert, challenge), true); + X509_free(signingCert); + X509_free(issuerCert); +} + +/** + * @tc.name: CertChainVerifierTest_0008 + * @tc.desc: verifying issuer cert success + * @tc.type: Func + * @tc.require: IAJ4QG + */ +HWTEST_F(CertChainVerifierTest, CertChainVerifierTest_008, TestSize.Level0) +{ + ByteBuffer formattedCert, challenge, certBuffer; + std::vector certs; + certs.push_back(g_signingCert); + certs.push_back(g_issuerCert); + certs.push_back(g_interCA); + certs.push_back(g_rootCA); + FormattedCertChain(certs, formattedCert); + // verify extension success + challenge.CopyFrom(CHALLENGE, sizeof(CHALLENGE)); +#ifdef CODE_SIGNATURE_OH_ROOT_CA + EXPECT_EQ(GetVerifiedCert(formattedCert, challenge, certBuffer), true); +#else + EXPECT_EQ(GetVerifiedCert(formattedCert, challenge, certBuffer), false); +#endif +} + +} // namespace CodeSign +} // namespace Security +} // namespace OHOS \ No newline at end of file diff --git a/test/unittest/code_sign_attr_utils_test.cpp b/test/unittest/code_sign_attr_utils_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b318c325415ecd9c027fe3bbd766c22d48adbb01 --- /dev/null +++ b/test/unittest/code_sign_attr_utils_test.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2024 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 "errcode.h" +#include "code_sign_attr_utils.h" +#include "ownerid_utils.h" + +namespace OHOS { +namespace Security { +namespace CodeSign { +using namespace std; +using namespace testing::ext; +using namespace testing::mt; + +class CodeSignAttrUtilsTest : public testing::Test { +public: + CodeSignAttrUtilsTest() {}; + virtual ~CodeSignAttrUtilsTest() {}; + static void SetUpTestCase() {}; + static void TearDownTestCase() {}; + void SetUp() {}; + void TearDown() {}; +}; + +/** + * @tc.name: CodeSignAttrUtilsTest_0001 + * @tc.desc: test InitXpm with valid param should success + * @tc.type: Func + * @tc.require: IAHWOP + */ +HWTEST_F(CodeSignAttrUtilsTest, CodeSignAttrUtilsTest_0001, TestSize.Level0) +{ + EXPECT_EQ(InitXpm(0, PROCESS_OWNERID_APP, NULL), CS_SUCCESS); + EXPECT_EQ(InitXpm(0, PROCESS_OWNERID_COMPAT, NULL), CS_SUCCESS); + EXPECT_EQ(InitXpm(0, PROCESS_OWNERID_DEBUG, NULL), CS_SUCCESS); + EXPECT_EQ(InitXpm(0, PROCESS_OWNERID_EXTEND, NULL), CS_SUCCESS); + EXPECT_EQ(InitXpm(0, PROCESS_OWNERID_DEBUG_PLATFORM, NULL), CS_SUCCESS); + EXPECT_EQ(InitXpm(0, PROCESS_OWNERID_PLATFORM, NULL), CS_SUCCESS); + EXPECT_EQ(InitXpm(0, PROCESS_OWNERID_NWEB, NULL), CS_SUCCESS); + EXPECT_EQ(InitXpm(0, PROCESS_OWNERID_SHARED, NULL), CS_SUCCESS); + EXPECT_EQ(InitXpm(0, PROCESS_OWNERID_SYSTEM, NULL), CS_SUCCESS); + EXPECT_EQ(InitXpm(0, PROCESS_OWNERID_APP, "test"), CS_SUCCESS); +} + +/** + * @tc.name: CodeSignAttrUtilsTest_0002 + * @tc.desc: test InitXpm with invalid params should fail + * @tc.type: Func + * @tc.require: IAHWOP + */ +HWTEST_F(CodeSignAttrUtilsTest, CodeSignAttrUtilsTest_0002, TestSize.Level0) +{ + // test invalid ownerid type + EXPECT_EQ(InitXpm(0, PROCESS_OWNERID_MAX, NULL), CS_ERR_PARAM_INVALID); + // test invalid ownerid valud + char ownerid[MAX_OWNERID_LEN + 1] = { 0 }; + (void)memset_s(ownerid, MAX_OWNERID_LEN + 1, 'a', MAX_OWNERID_LEN + 1); + EXPECT_EQ(InitXpm(0, PROCESS_OWNERID_APP, ownerid), CS_ERR_MEMORY); +} + +/** + * @tc.name: CodeSignAttrUtilsTest_0003 + * @tc.desc: test ConvertIdType + * @tc.type: Func + * @tc.require: IALFAX + */ +HWTEST_F(CodeSignAttrUtilsTest, CodeSignAttrUtilsTest_0003, TestSize.Level0) +{ + // test non OWNERID_APP, retval is origin idType + EXPECT_EQ(ConvertIdType(PROCESS_OWNERID_DEBUG, nullptr), PROCESS_OWNERID_DEBUG); + // test app not in list, retval is OWNERID_APP + EXPECT_EQ(ConvertIdType(PROCESS_OWNERID_APP, "1"), PROCESS_OWNERID_APP); + // test nullptr + EXPECT_EQ(ConvertIdType(PROCESS_OWNERID_APP, nullptr), PROCESS_OWNERID_APP); +} +} +} +} diff --git a/test/unittest/code_sign_utils_in_c_test.cpp b/test/unittest/code_sign_utils_in_c_test.cpp index 261b1dd1453e1e6225902b2b3e020288798836e0..58e17b9eb4e8113afbe9179215b0dba0ba552285 100644 --- a/test/unittest/code_sign_utils_in_c_test.cpp +++ b/test/unittest/code_sign_utils_in_c_test.cpp @@ -77,6 +77,72 @@ HWTEST_F(CodeSignUtilsInCTest, CodeSignUtilsInCTest_0001, TestSize.Level0) entryMapEntry = nullptr; entryMapEntryData = nullptr; } + +/** + * @tc.name: CodeSignUtilsInCTest_0002 + * @tc.desc: enable code signature for app with the c interface, nullptr + * @tc.type: Func + * @tc.require: + */ +HWTEST_F(CodeSignUtilsInCTest, CodeSignUtilsInCTest_0002, TestSize.Level0) +{ + std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/demo_with_code_sign_block.hap"; + int32_t ret = EnforceCodeSignForApp(nullptr, nullptr, FILE_ALL); + EXPECT_EQ(ret, CS_ERR_PARAM_INVALID); + + ret = EnforceCodeSignForApp(hapRealPath.c_str(), nullptr, FILE_ALL); + EXPECT_EQ(ret, CS_ERR_PARAM_INVALID); +} + +/** + * @tc.name: CodeSignUtilsInCTest_0003 + * @tc.desc: enable code signature for app with the c interface, entryMapEntry is nullptr + * @tc.type: Func + * @tc.require: + */ +HWTEST_F(CodeSignUtilsInCTest, CodeSignUtilsInCTest_0003, TestSize.Level0) +{ + std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/demo_with_code_sign_block.hap"; + std::string filePath1("libs/arm64-v8a/libc++_shared.so"); + std::string targetPath1 = APP_BASE_PATH + "/demo_with_multi_lib/libs/arm64-v8a/code_sign_block/libc++_shared.so"; + std::string filePath2("libs/arm64-v8a/libentry.so"); + std::string targetPath2 = APP_BASE_PATH + "/demo_with_multi_lib/libs/arm64-v8a/code_sign_block/libentry.so"; + + EntryMapEntryData *entryMapEntryData = static_cast(malloc(sizeof(EntryMapEntryData))); + (void)memset_s(entryMapEntryData, sizeof(EntryMapEntryData), 0, sizeof(EntryMapEntryData)); + + int32_t length = sizeof(EntryMapEntry) * ENTRYMAP_COUNT; + EntryMapEntry *entryMapEntry = static_cast(malloc(length)); + (void)memset_s(entryMapEntry, length, 0, length); + + entryMapEntry[0].key = nullptr; + entryMapEntry[0].value = nullptr; + entryMapEntry[1].key = nullptr; + entryMapEntry[1].value = nullptr; + + entryMapEntryData->count = ENTRYMAP_COUNT; + entryMapEntryData->entries = entryMapEntry; + + int32_t ret = EnforceCodeSignForApp(hapRealPath.c_str(), entryMapEntryData, FILE_ALL); + EXPECT_EQ(ret, CS_ERR_PARAM_INVALID); + + entryMapEntry[0].key = const_cast(filePath1.c_str()); + entryMapEntryData->entries = entryMapEntry; + + ret = EnforceCodeSignForApp(hapRealPath.c_str(), entryMapEntryData, FILE_ALL); + EXPECT_EQ(ret, CS_ERR_PARAM_INVALID); + + entryMapEntry[0].value = const_cast(targetPath1.c_str()); + entryMapEntryData->entries = entryMapEntry; + + ret = EnforceCodeSignForApp(hapRealPath.c_str(), entryMapEntryData, FILE_ALL); + EXPECT_EQ(ret, CS_ERR_PARAM_INVALID); + + free(entryMapEntry); + free(entryMapEntryData); + entryMapEntry = nullptr; + entryMapEntryData = nullptr; +} } // namespace CodeSign } // namespace Security } // namespace OHOS diff --git a/test/unittest/code_sign_utils_test.cpp b/test/unittest/code_sign_utils_test.cpp index 478ffc1ed845a444fd8704d7d5befc49605a183b..48569a9f5120e56bbc2183624df693f70387b3f4 100644 --- a/test/unittest/code_sign_utils_test.cpp +++ b/test/unittest/code_sign_utils_test.cpp @@ -537,57 +537,6 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0020, TestSize.Level0) EXPECT_EQ(ret, CS_ERR_INVALID_OWNER_ID); } -/** - * @tc.name: CodeSignUtilsTest_0021 - * @tc.desc: Enable key in profile successfully - * @tc.type: Func - * @tc.require: - */ -HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0021, TestSize.Level0) -{ - std::string profileEnablePath = PROFILE_BASE_PATH + "/demo_cert/pkcs7/verify_test_profile.p7b"; - std::string hapEnablePath = APP_BASE_PATH + "/verify_test_profile.hap"; - ByteBuffer buffer; - bool flag = ReadSignatureFromFile(profileEnablePath, buffer); - EXPECT_EQ(flag, true); - - string bundlName = "CodeSignUtilsTest"; - int32_t ret = CodeSignUtils::EnableKeyInProfile(bundlName, buffer); - EXPECT_EQ(ret, CS_SUCCESS); - - EntryMap entryMap; - CodeSignUtils utils; - ret = utils.EnforceCodeSignForApp(hapEnablePath, entryMap, FILE_SELF); - EXPECT_EQ(ret, CS_SUCCESS); -} - -/** - * @tc.name: CodeSignUtilsTest_0022 - * @tc.desc: Remove key in profile successfully - * @tc.type: Func - * @tc.require: - */ -HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0022, TestSize.Level0) -{ - std::string profileEnablePath = PROFILE_BASE_PATH + "/demo_cert/pkcs7/add_and_remove_profile.p7b"; - ByteBuffer buffer; - bool flag = ReadSignatureFromFile(profileEnablePath, buffer); - EXPECT_EQ(flag, true); - - string bundlName = "CodeSignUtilsTest"; - int32_t ret = CodeSignUtils::EnableKeyInProfile(bundlName, buffer); - EXPECT_EQ(ret, CS_SUCCESS); - - std::string pathOnDisk = "/data/service/el0/profiles/developer/CodeSignUtilsTest/profile.p7b"; - std::string realPath; - EXPECT_EQ(OHOS::PathToRealPath(pathOnDisk, realPath), true); - - ret = CodeSignUtils::RemoveKeyInProfile(bundlName); - EXPECT_EQ(ret, CS_SUCCESS); - - EXPECT_EQ(OHOS::PathToRealPath(pathOnDisk, realPath), false); -} - /** * @tc.name: CodeSignUtilsTest_0023 * @tc.desc: enable code signature for app @@ -682,6 +631,225 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0026, TestSize.Level0) ret = utils.EnforceCodeSignForAppWithOwnerId("test-app-identifier", hapRealPath, entryMap, FILE_ALL); EXPECT_EQ(ret, CS_ERR_NO_SIGNATURE); } + +/** + * @tc.name: CodeSignUtilsTest_0027 + * @tc.desc: test Extension address is beyond the end of the block + * @tc.type: Func + * @tc.require: + */ +HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0027, TestSize.Level0) +{ + CodeSignBlock codeSignBlock; + uintptr_t block[100] = {0}; + uintptr_t blockAddrEnd = reinterpret_cast(block + sizeof(block)); + uintptr_t extensionAddr = blockAddrEnd + 1; + code_sign_enable_arg arg = {}; + + int32_t ret = codeSignBlock.ProcessExtension(extensionAddr, blockAddrEnd, arg); + EXPECT_EQ(ret, CS_ERR_INVALID_EXTENSION_OFFSET); +} + +/** + * @tc.name: CodeSignUtilsTest_0028 + * @tc.desc: test Extension header size exceeds block boundary + * @tc.type: Func + * @tc.require: + */ +HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0028, TestSize.Level0) +{ + CodeSignBlock codeSignBlock; + uintptr_t block[100] = {0}; + uintptr_t blockAddrEnd = reinterpret_cast(block + sizeof(block)); + uintptr_t extensionAddr = blockAddrEnd - sizeof(ExtensionHeader) + 1; + code_sign_enable_arg arg = {}; + + int32_t ret = codeSignBlock.ProcessExtension(extensionAddr, blockAddrEnd, arg); + EXPECT_EQ(ret, CS_ERR_INVALID_EXTENSION_OFFSET); +} + +/** + * @tc.name: CodeSignUtilsTest_0029 + * @tc.desc: test Process Merkle Tree Extension + * @tc.type: Func + * @tc.require: + */ +HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0029, TestSize.Level0) +{ + CodeSignBlock codeSignBlock; + struct { + ExtensionHeader header; + MerkleTreeExtension merkleTree; + } block; + block.header.type = CodeSignBlock::CSB_EXTENSION_TYPE_MERKLE_TREE; + block.header.size = sizeof(MerkleTreeExtension); + block.merkleTree.treeOffset = 123; + + uint8_t fakeRootHash[64] = {0xde, 0xad, 0xbe, 0xef}; + std::copy(std::begin(fakeRootHash), std::end(fakeRootHash), std::begin(block.merkleTree.rootHash)); + + uintptr_t blockAddrEnd = reinterpret_cast(&block + 1); + uintptr_t extensionAddr = reinterpret_cast(&block); + code_sign_enable_arg arg = {}; + + int32_t ret = codeSignBlock.ProcessExtension(extensionAddr, blockAddrEnd, arg); + EXPECT_EQ(ret, CS_SUCCESS); + EXPECT_EQ(arg.tree_offset, 123); + EXPECT_EQ(arg.root_hash_ptr, reinterpret_cast(block.merkleTree.rootHash)); + EXPECT_EQ(arg.flags, CodeSignBlock::CSB_SIGN_INFO_MERKLE_TREE); +} + +/** + * @tc.name: CodeSignUtilsTest_0030 + * @tc.desc: test Process Page Info Extension + * @tc.type: Func + * @tc.require: + */ +HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0030, TestSize.Level0) +{ + CodeSignBlock codeSignBlock; + struct { + ExtensionHeader header; + PageInfoExtension pageInfo; + } block; + block.header.type = CodeSignBlock::CSB_EXTENSION_TYPE_PAGE_INFO; + block.header.size = sizeof(PageInfoExtension) + 50; + block.pageInfo.sign_size = 30; + block.pageInfo.unitSize = 2; + + uint8_t fakeSignature[64] = {0xde, 0xad, 0xbe, 0xef}; + std::copy(std::begin(fakeSignature), std::begin(fakeSignature) + + block.pageInfo.sign_size, block.pageInfo.signature); + + block.pageInfo.mapSize = 100; + block.pageInfo.mapOffset = 200; + + uintptr_t blockAddrEnd = reinterpret_cast(&block + 1); + uintptr_t extensionAddr = reinterpret_cast(&block); + code_sign_enable_arg arg = {}; + + int32_t ret = codeSignBlock.ProcessExtension(extensionAddr, blockAddrEnd, arg); + EXPECT_EQ(ret, CS_SUCCESS); + EXPECT_EQ(arg.sig_size, 30); + EXPECT_EQ(arg.sig_ptr, reinterpret_cast(block.pageInfo.signature)); + EXPECT_EQ(arg.pgtypeinfo_size, 100); + EXPECT_EQ(arg.pgtypeinfo_off, 200); + EXPECT_EQ(arg.cs_version, CodeSignBlock::CSB_EXTENSION_TYPE_PAGE_INFO_VERSION); + EXPECT_EQ(arg.flags, 2 << 1); +} + +/** + * @tc.name: CodeSignUtilsTest_0031 + * @tc.desc: test Invalid Page Info Extension Sign Size + * @tc.type: Func + * @tc.require: + */ +HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0031, TestSize.Level0) +{ + CodeSignBlock codeSignBlock; + struct { + ExtensionHeader header; + PageInfoExtension pageInfo; + } block; + block.header.type = CodeSignBlock::CSB_EXTENSION_TYPE_PAGE_INFO; + block.header.size = sizeof(PageInfoExtension); + block.pageInfo.sign_size = sizeof(PageInfoExtension) + 1; + + uintptr_t blockAddrEnd = reinterpret_cast(&block + 1); + uintptr_t extensionAddr = reinterpret_cast(&block); + code_sign_enable_arg arg = {}; + + int32_t ret = codeSignBlock.ProcessExtension(extensionAddr, blockAddrEnd, arg); + EXPECT_EQ(ret, CS_ERR_EXTENSION_SIGN_SIZE); +} + +/** + * @tc.name: CodeSignUtilsTest_0032 + * @tc.desc: test invalid PageInfoExtension UnitSize + * @tc.type: Func + * @tc.require: + */ +HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0032, TestSize.Level0) +{ + CodeSignBlock codeSignBlock; + struct { + ExtensionHeader header; + PageInfoExtension pageInfo; + } block; + block.header.type = CodeSignBlock::CSB_EXTENSION_TYPE_PAGE_INFO; + block.header.size = sizeof(PageInfoExtension); + block.pageInfo.unitSize = CodeSignBlock::CSB_SIGN_INFO_MAX_PAGEINFO_UNITSIZE + 1; + + uintptr_t blockAddrEnd = reinterpret_cast(&block + 1); + uintptr_t extensionAddr = reinterpret_cast(&block); + code_sign_enable_arg arg = {}; + + int32_t ret = codeSignBlock.ProcessExtension(extensionAddr, blockAddrEnd, arg); + EXPECT_EQ(ret, CS_ERR_INVALID_PAGE_INFO_EXTENSION); +} + +/** + * @tc.name: CodeSignUtilsTest_0033 + * @tc.desc: enable code signature for app, entryPath is nullptr + * @tc.type: Func + * @tc.require: + */ +HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0033, TestSize.Level0) +{ + EntryMap entryPath = {}; + int32_t ret = CodeSignUtils::EnforceCodeSignForApp(entryPath, g_sigWithMultiLibRetSucPath); + EXPECT_EQ(ret, CS_SUCCESS); +} + +/** + * @tc.name: CodeSignUtilsTest_0034 + * @tc.desc: Enable key in profile content data and dump profile buffer + * @tc.type: Func + * @tc.require: + */ +HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0034, TestSize.Level0) +{ + std::string bundleName = ""; + const ByteBuffer profileBuffer; + int32_t ret = CodeSignUtils::EnableKeyInProfile(bundleName, profileBuffer); +#ifdef NO_USE_CLANG_COVERAGE + EXPECT_EQ(ret, CS_ERR_PROFILE); +#else + EXPECT_EQ(ret, CS_SUCCESS); +#endif +} + +/** + * @tc.name: CodeSignUtilsTest_0035 + * @tc.desc: Remove key in profile content data and remove profile + * @tc.type: Func + * @tc.require: + */ +HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0035, TestSize.Level0) +{ + std::string bundleName = ""; + int32_t ret = CodeSignUtils::RemoveKeyInProfile(bundleName); +#ifdef NO_USE_CLANG_COVERAGE + EXPECT_EQ(ret, CS_ERR_PROFILE); +#else + EXPECT_EQ(ret, CS_SUCCESS); +#endif +} + +/** + * @tc.name: CodeSignUtilsTest_0036 + * @tc.desc: enabling code signing for app compiled by oh-sdk + * @tc.type: Func + * @tc.require: + */ +HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0036, TestSize.Level0) +{ +#ifdef SUPPORT_OH_CODE_SIGN + EXPECT_EQ(CodeSignUtils::IsSupportOHCodeSign(), true); +#else + EXPECT_EQ(CodeSignUtils::IsSupportOHCodeSign(), false); +#endif +} } // namespace CodeSign } // namespace Security } // namespace OHOS diff --git a/test/unittest/jit_code_sign_test.cpp b/test/unittest/jit_code_sign_test.cpp index ebdfefd13ef84c4647ede60e7dc7b1e93771be5f..6542fb660ca6829e7080dec41e1fd7dfe2d1ba15 100644 --- a/test/unittest/jit_code_sign_test.cpp +++ b/test/unittest/jit_code_sign_test.cpp @@ -820,6 +820,29 @@ HWTEST_F(JitCodeSignTest, JitCodeSignTest_0023, TestSize.Level0) signer = nullptr; } } + +/** + * @tc.name: JitCodeSignTest_0024 + * @tc.desc: pac sign with auth + * @tc.type: Func + * @tc.require: IAKH9D + */ +HWTEST_F(JitCodeSignTest, JitCodeSignTest_0024, TestSize.Level0) +{ + PACSignCtx signCtx(CTXPurpose::SIGN); + signCtx.InitSalt(); + signCtx.Init(0); + uint32_t signature[INSTRUCTIONS_SET_SIZE]; + int i; + for (i = 0; i < INSTRUCTIONS_SET_SIZE; i++) { + signature[i] = signCtx.Update(g_testInstructionSet[i]); + } + PACSignCtx verifyCtx(CTXPurpose::VERIFY, signCtx.GetSalt()); + verifyCtx.Init(0); + for (i = 0; i < INSTRUCTIONS_SET_SIZE; i++) { + EXPECT_EQ(signature[i], verifyCtx.Update(g_testInstructionSet[i])); + } +} } } } diff --git a/test/unittest/local_code_sign_test.cpp b/test/unittest/local_code_sign_test.cpp index cb1879be5dd24a7dd47f2f8c3257c21463b3f049..93bfe913debe4be7ab689657d7bbc35e351cb5ed 100644 --- a/test/unittest/local_code_sign_test.cpp +++ b/test/unittest/local_code_sign_test.cpp @@ -266,6 +266,48 @@ HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0014, TestSize.Level0) NativeTokenReset(selfTokenId); EXPECT_EQ(ret, CS_ERR_INVALID_OWNER_ID); } + +/** + * @tc.name: LocalCodeSignTest_0015 + * @tc.desc: sign local code failed with ownerID exceed 128 bytes + * @tc.type: Func + * @tc.require: issueI8FCGF + */ +HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0015, TestSize.Level0) +{ + ByteBuffer sig; + uint64_t selfTokenId = NativeTokenSet("compiler_service"); + std::string ownerID = "AppName123"; + + int ret = LocalCodeSignKit::SignLocalCode(ownerID, DEMO_AN_PATH2, sig); + + NativeTokenSet("local_code_sign"); + sptr samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + EXPECT_NE(samgr, nullptr); + + ret = samgr->UnloadSystemAbility(LOCAL_CODE_SIGN_SA_ID); + EXPECT_EQ(ret, ERR_OK); + NativeTokenSet("compiler_service"); + LocalCodeSignKit::SignLocalCode(ownerID, DEMO_AN_PATH2, sig); + NativeTokenReset(selfTokenId); +} + +/** + * @tc.name: LocalCodeSignTest_0016 + * @tc.desc: load sa success and return remote object is not null + * @tc.type: Func + * @tc.require: + */ +HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0016, TestSize.Level0) +{ + LocalCodeSignLoadCallback cb; + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + EXPECT_NE(systemAbilityManager, nullptr); + sptr remoteObject = + systemAbilityManager->GetSystemAbility(LOCAL_CODE_SIGN_SA_ID); + cb.OnLoadSystemAbilitySuccess(LOCAL_CODE_SIGN_SA_ID, remoteObject); +} } // namespace CodeSign } // namespace Security } // namespace OHOS diff --git a/test/unittest/local_code_sign_utils_mock_test.cpp b/test/unittest/local_code_sign_utils_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..baf8d03253c18cc2121aee0bbd2543afcf417f9c --- /dev/null +++ b/test/unittest/local_code_sign_utils_mock_test.cpp @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2024 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 "cert_utils.h" +#include "directory_ex.h" +#include "fsverity_utils_helper.h" +#include "local_sign_key.h" +#include "log.h" +#include "pkcs7_generator.h" +#include "hks_api.h" +#include "byte_buffer.h" +#include "cert_path.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_PATH2 = AN_BASE_PATH + "demo2.an"; +static const std::string DEFAULT_HASH_ALGORITHM = "sha256"; + +class LocalCodeSignUtilsMockTest : public testing::Test { +public: + LocalCodeSignUtilsMockTest() {}; + virtual ~LocalCodeSignUtilsMockTest() {}; + static void SetUpTestCase() {}; + static void TearDownTestCase() {}; + void SetUp() {}; + void TearDown() {}; +}; + +/** + * @tc.name: LocalCodeSignUtilsMockTest_0001 + * @tc.desc: Sign local code successfully, owner ID is empty, and set g_count. + * @tc.type: Func + * @tc.require: issueI8FCGF + */ +HWTEST_F(LocalCodeSignUtilsMockTest, LocalCodeSignUtilsMockTest_0001, TestSize.Level0) +{ + ByteBuffer digest; + std::string realPath; + std::string ownerID = ""; + bool bRet = OHOS::PathToRealPath(DEMO_AN_PATH2, realPath); + EXPECT_EQ(bRet, true); + bRet = FsverityUtilsHelper::GetInstance().GenerateFormattedDigest(realPath.c_str(), digest); + EXPECT_EQ(bRet, true); + + ByteBuffer signature; + g_count = ATTESTKEY; + int ret = PKCS7Generator::GenerateSignature(ownerID, LocalSignKey::GetInstance(), DEFAULT_HASH_ALGORITHM.c_str(), + digest, signature); + EXPECT_EQ(ret, CS_ERR_HUKS_OBTAIN_CERT); + + g_count = INIT; + ret = PKCS7Generator::GenerateSignature(ownerID, LocalSignKey::GetInstance(), DEFAULT_HASH_ALGORITHM.c_str(), + digest, signature); + EXPECT_EQ(ret, CS_ERR_HUKS_SIGN); + + g_count = UPDATE; + ret = PKCS7Generator::GenerateSignature(ownerID, LocalSignKey::GetInstance(), DEFAULT_HASH_ALGORITHM.c_str(), + digest, signature); + EXPECT_EQ(ret, CS_ERR_HUKS_SIGN); + + g_count = FINISH; + ret = PKCS7Generator::GenerateSignature(ownerID, LocalSignKey::GetInstance(), DEFAULT_HASH_ALGORITHM.c_str(), + digest, signature); + EXPECT_EQ(ret, CS_ERR_HUKS_SIGN); +} + +/** + * @tc.name: LocalCodeSignUtilsMockTest_0002 + * @tc.desc: Generate formatted digest failed with wrong path + * @tc.type: Func + * @tc.require: issueI8FCGF + */ +HWTEST_F(LocalCodeSignUtilsMockTest, LocalCodeSignUtilsMockTest_0002, TestSize.Level0) +{ + std::unique_ptr challenge = GetRandomChallenge(); + LocalSignKey &key = LocalSignKey::GetInstance(); + key.SetChallenge(*challenge); + bool bRet = key.InitKey(); + EXPECT_EQ(bRet, true); + + g_count = ERROR; + bRet = key.InitKey(); + EXPECT_EQ(bRet, false); + + g_count = KEYEXIST; + bRet = key.InitKey(); + EXPECT_EQ(bRet, false); + + int32_t iRet = key.GetFormattedCertChain(*challenge); + EXPECT_EQ(iRet, 0); +} + +/** + * @tc.name: LocalCodeSignUtilsMockTest_0003 + * @tc.desc: LocalSignKey GetSignCert test + * @tc.type: Func + * @tc.require: issueI8FCGF + */ +HWTEST_F(LocalCodeSignUtilsMockTest, LocalCodeSignUtilsMockTest_0003, TestSize.Level0) +{ + LocalSignKey &key = LocalSignKey::GetInstance(); + (void)key.GetSignCert(); +} + +/** + * @tc.name: LocalCodeSignUtilsMockTest_0004 + * @tc.desc: cert_utils FreeCertChain certChain is nullptr or certChain->certs is nullptr + * @tc.type: Func + * @tc.require: issueI8FCGF + */ +HWTEST_F(LocalCodeSignUtilsMockTest, LocalCodeSignUtilsMockTest_0004, TestSize.Level0) +{ + struct HksCertChain *certChain = nullptr; + uint32_t pos = 0; + (void)OHOS::Security::CodeSign::FreeCertChain(&certChain, pos); + + certChain = static_cast(malloc(sizeof(struct HksCertChain))); + certChain->certs = nullptr; + (void)OHOS::Security::CodeSign::FreeCertChain(&certChain, pos); +} + +/** + * @tc.name: LocalCodeSignUtilsMockTest_0005 + * @tc.desc: cert_utils CheckChallengeSize func test + * @tc.type: Func + * @tc.require: issueI8FCGF + */ +HWTEST_F(LocalCodeSignUtilsMockTest, LocalCodeSignUtilsMockTest_0005, TestSize.Level0) +{ + uint32_t size = 0; + bool bRet = OHOS::Security::CodeSign::CheckChallengeSize(size); + EXPECT_EQ(bRet, true); + + size = 33; + bRet = OHOS::Security::CodeSign::CheckChallengeSize(size); + EXPECT_EQ(bRet, false); +} + +/** + * @tc.name: LocalCodeSignUtilsMockTest_0006 + * @tc.desc: cert_utils FormattedCertChain func test + * @tc.type: Func + * @tc.require: issueI8FCGF + */ +HWTEST_F(LocalCodeSignUtilsMockTest, LocalCodeSignUtilsMockTest_0006, TestSize.Level0) +{ + const HksCertChain *certChain = LocalSignKey::GetInstance().GetCertChain(); + std::unique_ptr buffer = GetRandomChallenge(); + bool bRet = OHOS::Security::CodeSign::FormattedCertChain(certChain, *buffer); + EXPECT_EQ(bRet, true); +} + +/** + * @tc.name: LocalCodeSignUtilsMockTest_0007 + * @tc.desc: cert_utils GetCertChainFormBuffer func test + * @tc.type: Func + * @tc.require: issueI8FCGF + */ +HWTEST_F(LocalCodeSignUtilsMockTest, LocalCodeSignUtilsMockTest_0007, TestSize.Level0) +{ + ByteBuffer certChainBuffer; + ByteBuffer signCert; + ByteBuffer issuer; + std::vector chain; + bool bRet = OHOS::Security::CodeSign::GetCertChainFormBuffer(certChainBuffer, signCert, issuer, chain); + EXPECT_EQ(bRet, false); +} + +/** + * @tc.name: LocalCodeSignUtilsMockTest_0008 + * @tc.desc: FsverityUtilsHelper GetCertChainFormBuffer func test + * @tc.type: Func + * @tc.require: issueI8FCGF + */ +HWTEST_F(LocalCodeSignUtilsMockTest, LocalCodeSignUtilsMockTest_0008, TestSize.Level0) +{ + (void)FsverityUtilsHelper::GetInstance().ErrorMsgLogCallback(nullptr); +} + +/** + * @tc.name: LocalCodeSignUtilsMockTest_0009 + * @tc.desc: cert_path IsDeveloperModeOn func test + * @tc.type: Func + * @tc.require: issueI8FCGF + */ +HWTEST_F(LocalCodeSignUtilsMockTest, LocalCodeSignUtilsMockTest_0009, TestSize.Level0) +{ + (void)IsDeveloperModeOn(); +} + +/** + * @tc.name: LocalCodeSignUtilsMockTest_0010 + * @tc.desc: cert_path CodeSignGetUdid func test + * @tc.type: Func + * @tc.require: issueI8FCGF + */ +HWTEST_F(LocalCodeSignUtilsMockTest, LocalCodeSignUtilsMockTest_0010, TestSize.Level0) +{ + EXPECT_EQ(CodeSignGetUdid(nullptr), -1); +} +} // namespace CodeSign +} // namespace Security +} // namespace OHOS diff --git a/test/unittest/mock/include/hks_api.h b/test/unittest/mock/include/hks_api.h index fa509f16e7dbaf829d9090d7032b4869d8a9c0ec..a783ee3628ef06e0b4e1bcf99b8e659d94d391ad 100644 --- a/test/unittest/mock/include/hks_api.h +++ b/test/unittest/mock/include/hks_api.h @@ -21,6 +21,16 @@ namespace OHOS { namespace Security { namespace CodeSign { +extern int g_count; +enum HksType { + KEYEXIST = 1, + ATTESTKEY = 2, + GENERATEKEY = 3, + INIT = 4, + UPDATE = 5, + FINISH = 6, + ERROR = 7, +}; int32_t HksKeyExist(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet); int32_t HksAttestKey(const struct HksBlob *keyAlias, diff --git a/test/unittest/mock/src/hks_api_mock_test.cpp b/test/unittest/mock/src/hks_api_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..74df370cdeac3844da8504817b6984b1d3ec7612 --- /dev/null +++ b/test/unittest/mock/src/hks_api_mock_test.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2024 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 "hks_api.h" + +#include "hks_api_mock_helper.h" + +namespace OHOS { +namespace Security { +namespace CodeSign { +int g_count = 0; +int32_t HksKeyExist(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet) +{ + LOG_INFO("Mock HksKeyExist"); + if (g_count == KEYEXIST) { + return -1; + } + if (g_count == ERROR) { + return HKS_ERROR_NOT_EXIST; + } + return HKS_SUCCESS; +} + +int32_t HksAttestKey(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, + struct HksCertChain *certChain) +{ + LOG_INFO("Mock HksAttestKey"); + if (g_count == ATTESTKEY) { + return -1; + } + + bool ret = GetCertInDer(certChain->certs[0].data, certChain->certs[0].size); + if (!ret) { + LOG_ERROR("Failed to convert PEM to DER.\n"); + return HKS_FAILURE; + } + return HKS_SUCCESS; +} + +int32_t HksGenerateKey(const struct HksBlob *keyAlias, + const struct HksParamSet *paramSetIn, struct HksParamSet *paramSetOut) +{ + LOG_INFO("Mock HksGenerateKey"); + if (g_count == GENERATEKEY || g_count == ERROR) { + return -1; + } + return HKS_SUCCESS; +} + +int32_t HksInit(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, + struct HksBlob *handle, struct HksBlob *token) +{ + LOG_INFO("Mock HksInit"); + if (g_count == INIT) { + return -1; + } + return HKS_SUCCESS; +} + + +int32_t HksUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, + const struct HksBlob *inData, struct HksBlob *outData) +{ + LOG_INFO("Mock HksUpdate"); + if (g_count == UPDATE) { + return -1; + } + return HKS_SUCCESS; +} + +int32_t HksFinish(const struct HksBlob *handle, const struct HksParamSet *paramSet, + const struct HksBlob *inData, struct HksBlob *outData) +{ + LOG_INFO("Mock HksFinish"); + if (g_count == FINISH) { + return -1; + } + return HKS_SUCCESS; +} +} +} +} \ No newline at end of file diff --git a/test/unittest/resources/demo_cert/pkcs7/add_and_remove_profile.p7b b/test/unittest/resources/demo_cert/pkcs7/add_and_remove_profile.p7b deleted file mode 100644 index 0be372ddb4521bd17251dc2acd26ac9ad85c06fd..0000000000000000000000000000000000000000 Binary files a/test/unittest/resources/demo_cert/pkcs7/add_and_remove_profile.p7b and /dev/null differ diff --git a/test/unittest/resources/demo_cert/pkcs7/verify_test_profile.hap b/test/unittest/resources/demo_cert/pkcs7/verify_test_profile.hap deleted file mode 100644 index 28b6fc409bd30240f3f2d9e19367237b86788e65..0000000000000000000000000000000000000000 Binary files a/test/unittest/resources/demo_cert/pkcs7/verify_test_profile.hap and /dev/null differ diff --git a/test/unittest/resources/demo_cert/pkcs7/verify_test_profile.p7b b/test/unittest/resources/demo_cert/pkcs7/verify_test_profile.p7b deleted file mode 100644 index d17fdc5cd783dbba61ebcbd8f91645df6631930f..0000000000000000000000000000000000000000 Binary files a/test/unittest/resources/demo_cert/pkcs7/verify_test_profile.p7b and /dev/null differ diff --git a/test/unittest/resources/ohos_test.xml b/test/unittest/resources/ohos_test.xml index 9723e6af58aadeb374875c963783b348bfc1b402..1452baccfe88282ecd03e3df5eaaeb3b607b7a41 100644 --- a/test/unittest/resources/ohos_test.xml +++ b/test/unittest/resources/ohos_test.xml @@ -63,9 +63,6 @@