diff --git a/bundle.json b/bundle.json index 08cfb6817ac9adfb55fea1a4753f9f3795b49ec1..0d88430333c474ffc62b91f055364523a0719825 100644 --- a/bundle.json +++ b/bundle.json @@ -40,7 +40,9 @@ "appverify", "init", "openssl", - "fsverity-utils" + "fsverity-utils", + "screenlock_mgr", + "common_event_service" ], "third_party": [] }, diff --git a/services/key_enable/src/key_enable.rs b/services/key_enable/src/key_enable.rs index 37fbd1ef683bdee67ef027f2aa9b014eee023389..5eebc3a17f8530e970cc124fbfbfddcaa7d6ab84 100644 --- a/services/key_enable/src/key_enable.rs +++ b/services/key_enable/src/key_enable.rs @@ -14,6 +14,7 @@ */ use super::cert_chain_utils::PemCollection; +use super::cert_path_utils::TrustCertPath; use super::cert_utils::{get_cert_path, get_trusted_certs}; use super::cs_hisysevent; use super::profile_utils::add_profile_cert_path; @@ -24,6 +25,7 @@ use std::fs::File; use std::io::{BufRead, BufReader}; use std::option::Option; use std::ptr; +use std::thread; const LOG_LABEL: HiLogLabel = HiLogLabel { log_type: LogType::LogCore, @@ -55,6 +57,7 @@ extern "C" { type_name: *const u8, restriction: *const u8, ) -> KeySerial; + fn CheckUserUnlock() -> bool; } fn print_openssl_error_stack(error_stack: ErrorStack) { @@ -161,6 +164,27 @@ fn enable_trusted_keys(key_id: KeySerial, root_cert: &PemCollection) { } } +// start cert path ops thread add trusted cert & developer cert +fn add_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."); + } + info!(LOG_LABEL, "Finished cert path adding."); + }) +} + // enable local key from local code sign SA fn enable_local_key(key_id: KeySerial) { if let Some(cert_data) = get_local_key() { @@ -181,29 +205,37 @@ fn restrict_keys(key_id: KeySerial) { } } +fn enable_keys_after_user_unlock(key_id: KeySerial) { + if !unsafe { CheckUserUnlock() } { + restrict_keys(key_id); + return; + } + + // enable local code sign key + enable_local_key(key_id); + restrict_keys(key_id); +} + /// enable trusted and local keys, and then restrict keyring pub fn enable_all_keys() { let key_id = match get_keyring_id() { Ok(id) => id, - Err(_) => return, + Err(_) => { + error!(LOG_LABEL, "Failed to get keyring ID."); + return; + }, }; let root_cert = get_trusted_certs(); // enable device keys and authed source enable_trusted_keys(key_id, &root_cert); let cert_paths = get_cert_path(); - if cert_paths.add_cert_paths().is_err() { - error!(LOG_LABEL, "Add trusted cert path err"); - } + let cert_thread = add_cert_path_thread(root_cert, cert_paths); + enable_keys_after_user_unlock(key_id); - // enable developer cert - if add_profile_cert_path(&root_cert, &cert_paths).is_err() { - error!(LOG_LABEL, "Add cert path from local profile"); + if let Err(e) = cert_thread.join() { + error!(LOG_LABEL, "add cert path thread panicked: {:?}", e); } - // enable local code sign key - enable_local_key(key_id); - restrict_keys(key_id); - info!(LOG_LABEL, "Fnished enable all keys."); } diff --git a/services/key_enable/utils/BUILD.gn b/services/key_enable/utils/BUILD.gn index 7400f6ea5f917dbbfd2484676443253fda8c40b0..6977888b1e01e19494dcd92a812c7520f169fa22 100644 --- a/services/key_enable/utils/BUILD.gn +++ b/services/key_enable/utils/BUILD.gn @@ -17,8 +17,9 @@ import("../../../code_signature.gni") ohos_static_library("libkey_enable_utils") { sources = [ "src/cert_path.cpp", + "src/key_enable_adapter.cpp", "src/key_utils.cpp", - "src/local_code_sign_utils.cpp", + "src/unlock_event_helper.cpp", ] include_dirs = [ "include", @@ -31,9 +32,13 @@ ohos_static_library("libkey_enable_utils") { configs = [ "${code_signature_root_dir}:common_utils_config" ] external_deps = [ + "ability_base:want", "c_utils:utils", + "common_event_service:cesfwk_innerkits", "hilog:libhilog", "init:libbegetutil", + "samgr:samgr_proxy", + "screenlock_mgr:screenlock_client", ] subsystem_name = "security" part_name = "code_signature" diff --git a/services/key_enable/utils/include/key_enable_adapter.h b/services/key_enable/utils/include/key_enable_adapter.h new file mode 100644 index 0000000000000000000000000000000000000000..fe61509942c255a64c64dd10ee00456eeedecf60 --- /dev/null +++ b/services/key_enable/utils/include/key_enable_adapter.h @@ -0,0 +1,34 @@ +/* + * 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 CODE_SIGN_KEY_ENABLE_ADAPTER_H +#define CODE_SIGN_KEY_ENABLE_ADAPTER_H + +#ifndef LOG_RUST +#define LOG_RUST +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif +int32_t InitLocalCertificate(uint8_t *cert, uint32_t *certSize); +bool CheckUserUnlock(); +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/services/key_enable/utils/include/unlock_event_helper.h b/services/key_enable/utils/include/unlock_event_helper.h new file mode 100644 index 0000000000000000000000000000000000000000..ddc245c295588cb191422b4e4842c6dd0581f421 --- /dev/null +++ b/services/key_enable/utils/include/unlock_event_helper.h @@ -0,0 +1,67 @@ +/* + * 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 CODE_SIGN_UNLOCK_EVENT_HELPER_H +#define CODE_SIGN_UNLOCK_EVENT_HELPER_H + +#include +#include +#include + +#include "common_event_manager.h" +#include "common_event_support.h" +#include "iservice_registry.h" + +#ifndef LOG_RUST +#define LOG_RUST +#endif + +namespace OHOS { +namespace Security { +namespace CodeSign { +class UnlockEventHelper { +public: + static UnlockEventHelper &GetInstance(); + + bool StartWaitingUnlock(); + void FinishWaiting(); + bool CheckUserUnlockByScreenLockManager(); + +private: + class UnlockEventSubscriber : public OHOS::EventFwk::CommonEventSubscriber { + public: + UnlockEventSubscriber(const OHOS::EventFwk::CommonEventSubscribeInfo& info) : CommonEventSubscriber(info) {} + ~UnlockEventSubscriber() override = default; + void OnReceiveEvent(const OHOS::EventFwk::CommonEventData& event) override; + }; + + UnlockEventHelper() {}; + ~UnlockEventHelper() = default; + void InitUnlockEventSubscriber(); + bool RegisterEvent(); + void UnregisterEvent(); + bool WaitForCommonEventManager(); + + bool hasRegistered_ = false; + bool hasInited_ = false; + bool hasUnLocked_ = false; + std::mutex unlockMutex_; + std::condition_variable unlockConVar_; + std::shared_ptr unlockEventSubscriber_; +}; +} +} +} +#endif \ No newline at end of file diff --git a/services/key_enable/utils/src/local_code_sign_utils.cpp b/services/key_enable/utils/src/key_enable_adapter.cpp similarity index 34% rename from services/key_enable/utils/src/local_code_sign_utils.cpp rename to services/key_enable/utils/src/key_enable_adapter.cpp index db6cc55832299feeb34e6013bb00837c8e710856..13365d7874f5f2197a192ee51df4383f234211ab 100644 --- a/services/key_enable/utils/src/local_code_sign_utils.cpp +++ b/services/key_enable/utils/src/key_enable_adapter.cpp @@ -1,99 +1,56 @@ -/* - * Copyright (c) 2023-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 "local_code_sign_utils.h" - -#include -#include - -#include "byte_buffer.h" -#include "local_code_sign_kit.h" -#include "log.h" -#include "thread_ex.h" - -using namespace OHOS::Security::CodeSign; - -namespace OHOS { -namespace Security { -namespace CodeSign { -constexpr uint32_t INIT_LOCAL_CERT_TIMEOUT_MS = 300 * 1000; // 5min -constexpr uint32_t INIT_LOCAL_CERT_SLEEP_US = 1000 * 1000; // 1s -const std::string INIT_LOCAL_CERT_THREAD_NAME = "init_local_cert"; - -static std::condition_variable g_condition; - -class InitLocalCertThread : public OHOS::Thread { -public: - InitLocalCertThread() {} - ~InitLocalCertThread() {} - - int GetRet() - { - return initResult_; - } - - ByteBuffer& GetCert() - { - return cert_; - } - -protected: - bool Run() - { - initResult_ = LocalCodeSignKit::InitLocalCertificate(cert_); - if (initResult_ == CS_ERR_SA_GET_PROXY) { - usleep(INIT_LOCAL_CERT_SLEEP_US); - return true; - } else { - g_condition.notify_one(); - return false; - } - } - -private: - int32_t initResult_ = -1; - ByteBuffer cert_; -}; -} -} -} - -int32_t InitLocalCertificate(uint8_t *certData, uint32_t *certSize) -{ - std::unique_ptr thread = std::make_unique(); - OHOS::ThreadStatus status = thread->Start(INIT_LOCAL_CERT_THREAD_NAME); - if (status != OHOS::ThreadStatus::OK) { - LOG_ERROR(LABEL, "initing local cert thread not start."); - return CS_ERR_INIT_LOCAL_CERT; - } - - std::mutex mtx; - std::unique_lock lock(mtx); - g_condition.wait_for(lock, std::chrono::milliseconds(INIT_LOCAL_CERT_TIMEOUT_MS)); - thread->NotifyExitSync(); - - int ret = thread->GetRet(); - if (ret != CS_SUCCESS) { - LOG_ERROR(LABEL, "init local cert timeout or error, ret = %{public}d", ret); - return ret; - } - - ByteBuffer &cert = thread->GetCert(); - if (memcpy_s(certData, *certSize, cert.GetBuffer(), cert.GetSize()) != EOK) { - return CS_ERR_MEMORY; - } - *certSize = cert.GetSize(); - return ret; +/* + * 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 "key_enable_adapter.h" + +#include "byte_buffer.h" +#include "common_event_data.h" +#include "local_code_sign_kit.h" +#include "unlock_event_helper.h" + +using namespace OHOS::Security::CodeSign; + +int32_t InitLocalCertificate(uint8_t *certData, uint32_t *certSize) +{ + ByteBuffer cert; + int32_t ret = LocalCodeSignKit::InitLocalCertificate(cert); + if (ret != CS_SUCCESS) { + return ret; + } + if (memcpy_s(certData, *certSize, cert.GetBuffer(), cert.GetSize()) != EOK) { + return CS_ERR_MEMORY; + } + *certSize = cert.GetSize(); + return CS_SUCCESS; +} + +bool CheckUserUnlock() +{ + // check whether unlocked at current + if (UnlockEventHelper::GetInstance().CheckUserUnlockByScreenLockManager()) { + return true; + } + + // waiting for user unlock + if (UnlockEventHelper::GetInstance(). StartWaitingUnlock()) { + return true; + } + + // if some error occours, check again at current + if (UnlockEventHelper::GetInstance().CheckUserUnlockByScreenLockManager()) { + return true; + } + return false; } \ No newline at end of file diff --git a/services/key_enable/utils/src/unlock_event_helper.cpp b/services/key_enable/utils/src/unlock_event_helper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2693d1d456c24c84b5e556336c0a947b27437614 --- /dev/null +++ b/services/key_enable/utils/src/unlock_event_helper.cpp @@ -0,0 +1,161 @@ +/* + * 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 "unlock_event_helper.h" + +#include + +#include "datetime_ex.h" +#include "log.h" +#include "screenlock_manager.h" + +namespace OHOS { +namespace Security { +namespace CodeSign { +constexpr int32_t SEELP_TIME_FOR_COMMON_EVENT_MGR = 500 * 1000; // 500 ms +constexpr int32_t SEELP_TIME_FOR_COMMON_EVENT_MGR_TIME_OUT = 10 * 60; // 10 min +constexpr int32_t COMMON_EVENT_MANAGER_ID = 3299; + +void UnlockEventHelper::UnlockEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData& event) +{ + const auto want = event.GetWant(); + const auto action = want.GetAction(); + if (action == EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_UNLOCKED) { + LOG_INFO(LABEL, "receive unlocked event"); + UnlockEventHelper::GetInstance().FinishWaiting(); + return; + } +} + +UnlockEventHelper &UnlockEventHelper::GetInstance() +{ + static UnlockEventHelper singleUnlockEventHelper; + return singleUnlockEventHelper; +} + +bool UnlockEventHelper::CheckUserUnlockByScreenLockManager() +{ + std::lock_guard lock(unlockMutex_); + if (hasUnLocked_) { + return true; + } + bool lockStatus = false; + if (ScreenLock::ScreenLockManager::GetInstance()->IsLocked(lockStatus) == ScreenLock::E_SCREENLOCK_OK) { + LOG_INFO(LABEL, "screen locked status = %{private}d", lockStatus); + hasUnLocked_ = !lockStatus; + } else { + LOG_ERROR(LABEL, "unable get lock screen status"); + } + return hasUnLocked_; +} + +void UnlockEventHelper::InitUnlockEventSubscriber() +{ + if (hasInited_) { + return; + } + EventFwk::MatchingSkills matchingSkill; + // use COMMON_EVENT_USER_UNLOCKED if only for device with PIN + matchingSkill.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_UNLOCKED); + EventFwk::CommonEventSubscribeInfo eventInfo(matchingSkill); + unlockEventSubscriber_ = std::make_shared(eventInfo); + hasInited_ = true; + LOG_INFO(LABEL, "Init subscriber success."); +} + +bool UnlockEventHelper::RegisterEvent() +{ + LOG_INFO(LABEL, "RegisterEvent start"); + if (hasRegistered_) { + LOG_DEBUG(LABEL, "status observer already registered"); + return false; + } + InitUnlockEventSubscriber(); + const auto result = EventFwk::CommonEventManager::SubscribeCommonEvent( + unlockEventSubscriber_); + if (!result) { + LOG_ERROR(LABEL, "RegisterEvent result is err"); + return false; + } + hasRegistered_ = true; + return true; +} + +void UnlockEventHelper::UnregisterEvent() +{ + LOG_INFO(LABEL, "UnregisterEvent start"); + const auto result = EventFwk::CommonEventManager::UnSubscribeCommonEvent( + unlockEventSubscriber_); + if (!result) { + LOG_ERROR(LABEL, "UnregisterEvent result is err"); + return; + } + hasRegistered_ = false; +} + +bool UnlockEventHelper::WaitForCommonEventManager() +{ + struct tm doingTime = {0}; + struct tm startTime = {0}; + int64_t seconds = 0; + bool ret = false; + if (!OHOS::GetSystemCurrentTime(&startTime)) { + return false; + } + while (seconds <= SEELP_TIME_FOR_COMMON_EVENT_MGR_TIME_OUT) { + sptr samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (samgr != nullptr && + samgr->CheckSystemAbility(COMMON_EVENT_MANAGER_ID) != nullptr) { + ret = true; + LOG_INFO(LABEL, "Common event manager is loaded."); + break; + } + LOG_DEBUG(LABEL, "Get common event manager failed."); + usleep(SEELP_TIME_FOR_COMMON_EVENT_MGR); + if (OHOS::GetSystemCurrentTime(&doingTime)) { + seconds = OHOS::GetSecondsBetween(startTime, doingTime); + } + } + return ret; +} + +bool UnlockEventHelper::StartWaitingUnlock() +{ + std::unique_lock lock(unlockMutex_); + if (hasUnLocked_) { + return true; + } + if (!WaitForCommonEventManager()) { + return false; + } + if (!RegisterEvent()) { + return false; + } + unlockConVar_.wait(lock, [this]() { return this->hasUnLocked_; }); + LOG_INFO(LABEL, "thread is wake up"); + // only listening the first unlock event + UnregisterEvent(); + return true; +} + +void UnlockEventHelper::FinishWaiting() +{ + std::lock_guard lock(unlockMutex_); + hasUnLocked_ = true; + unlockConVar_.notify_one(); +} +} +} +} \ No newline at end of file diff --git a/services/local_code_sign/local_code_sign.cfg b/services/local_code_sign/local_code_sign.cfg index 153b0adbc54ca525baebb66908dee66b05128833..8697c37d3aac2b92be28f1d6fe9af08baab40c4d 100644 --- a/services/local_code_sign/local_code_sign.cfg +++ b/services/local_code_sign/local_code_sign.cfg @@ -1,11 +1,4 @@ { - "jobs" : [{ - "name" : "early-boot", - "cmds" : [ - "start local_code_sign" - ] - } - ], "services" : [{ "name" : "local_code_sign", "path" : ["/system/bin/sa_main", "/system/profile/local_code_sign.json"], diff --git a/test/unittest/local_code_sign_test.cpp b/test/unittest/local_code_sign_test.cpp index 71dbbe0e87c6937d3db2ecc7eb0fd4e92c44c1df..d945fdaf727c339a15f8b0b54d79a87fe3bea892 100644 --- a/test/unittest/local_code_sign_test.cpp +++ b/test/unittest/local_code_sign_test.cpp @@ -23,8 +23,9 @@ #include "local_code_sign_client.h" #include "local_code_sign_kit.h" #include "local_code_sign_load_callback.h" -#include "signer_info.h" +#include "local_key_helper.h" #include "log.h" +#include "signer_info.h" using namespace OHOS::Security::CodeSign; using namespace testing::ext; @@ -93,7 +94,7 @@ HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0003, TestSize.Level0) EXPECT_EQ(ret, CS_ERR_NO_OWNER_ID); EXPECT_EQ(retOwnerID, ""); ret = CodeSignUtils::EnforceCodeSignForFile(DEMO_AN_PATH, sig); - EXPECT_EQ(ret, CS_SUCCESS); + EXPECT_EQ(ret, GetEnforceFileResult()); } /** @@ -197,7 +198,7 @@ HWTEST_F(LocalCodeSignTest, LocalCodeSignTest_0010, TestSize.Level0) ret = CodeSignUtils::ParseOwnerIdFromSignature(sig, retOwnerID); EXPECT_EQ(ownerID, retOwnerID); ret = CodeSignUtils::EnforceCodeSignForFile(DEMO_AN_PATH2, sig); - EXPECT_EQ(ret, CS_SUCCESS); + EXPECT_EQ(ret, GetEnforceFileResult()); } /** diff --git a/test/unittest/multi_thread_local_sign_test.cpp b/test/unittest/multi_thread_local_sign_test.cpp index f6d27b9b7e8a484cd6a8fb62340136984982ce00..84699151bfd292f28d4a7ef1dca3e96a7c7c5094 100644 --- a/test/unittest/multi_thread_local_sign_test.cpp +++ b/test/unittest/multi_thread_local_sign_test.cpp @@ -23,6 +23,7 @@ #include "byte_buffer.h" #include "code_sign_utils.h" #include "local_code_sign_kit.h" +#include "local_key_helper.h" #include "log.h" using namespace OHOS::Security::CodeSign; @@ -94,7 +95,7 @@ void LocalCodeSignAndEnforce() NativeTokenReset(selfTokenId); EXPECT_EQ(ret, CS_SUCCESS); ret = CodeSignUtils::EnforceCodeSignForFile(tmpFileName, sig); - EXPECT_EQ(ret, CS_SUCCESS); + EXPECT_EQ(ret, GetEnforceFileResult()); } void LocalCodeSignAndEnforceWithOwnerID() @@ -112,7 +113,7 @@ void LocalCodeSignAndEnforceWithOwnerID() NativeTokenReset(selfTokenId); EXPECT_EQ(ret, CS_SUCCESS); ret = CodeSignUtils::EnforceCodeSignForFile(tmpFileName, sig); - EXPECT_EQ(ret, CS_SUCCESS); + EXPECT_EQ(ret, GetEnforceFileResult()); } class MultiThreadLocalSignTest : public testing::Test { diff --git a/test/unittest/resources/ohos_test.xml b/test/unittest/resources/ohos_test.xml index 22db761f53aa41030cf4300014aac28b2a77d048..b189ee4beff6a414fd9ad43ebb022e51b7d8cc40 100644 --- a/test/unittest/resources/ohos_test.xml +++ b/test/unittest/resources/ohos_test.xml @@ -80,6 +80,9 @@