1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "code_sign_enable_multi_task.h"
17
18 #include "byte_buffer.h"
19 #include "cs_hisysevent.h"
20 #include "errcode.h"
21 #include "log.h"
22 #include "signer_info.h"
23
24 namespace OHOS {
25 namespace Security {
26 namespace CodeSign {
27 constexpr uint32_t CODE_SIGN_TASK_TIMEOUT_MS = 300000;
28 constexpr uint32_t DEFAULT_THREADS_NUM = 8;
29
CodeSignEnableMultiTask()30 CodeSignEnableMultiTask::CodeSignEnableMultiTask(): enableCodeSignTaskWorker_("EnableCodeSign"), taskCallBack_(0)
31 {
32 enableCodeSignTaskWorker_.Start(DEFAULT_THREADS_NUM);
33 }
34
~CodeSignEnableMultiTask()35 CodeSignEnableMultiTask::~CodeSignEnableMultiTask()
36 {
37 enableCodeSignTaskWorker_.Stop();
38 }
39
AddTaskData(const std::string & targetFile,const struct code_sign_enable_arg & arg)40 void CodeSignEnableMultiTask::AddTaskData(const std::string &targetFile, const struct code_sign_enable_arg &arg)
41 {
42 enableData_.push_back(std::pair<std::string, code_sign_enable_arg>(targetFile, arg));
43 }
44
ExecuteEnableCodeSignTask(int32_t & taskRet,const std::string & ownerId,const std::string & path,CallbackFunc & func)45 bool CodeSignEnableMultiTask::ExecuteEnableCodeSignTask(int32_t &taskRet, const std::string &ownerId,
46 const std::string &path, CallbackFunc &func)
47 {
48 SortTaskData();
49
50 for (uint32_t i = 0; i < enableData_.size(); i++) {
51 LOG_DEBUG(LABEL, "index: %{public}d, name:%{public}s, %{public}lld",
52 i, enableData_[i].first.c_str(), enableData_[i].second.data_size);
53 ExecuteEnableCodeSignTask(i, taskRet, ownerId, path, func);
54 }
55
56 std::unique_lock<std::mutex> lock(cvLock_);
57 auto waitStatus = taskfinish_.wait_for(lock, std::chrono::milliseconds(CODE_SIGN_TASK_TIMEOUT_MS),
58 [this]() { return this->enableData_.size() == this->taskCallBack_; });
59 return waitStatus;
60 }
61
SortTaskData()62 void CodeSignEnableMultiTask::SortTaskData()
63 {
64 auto compareFileDataSize = [](const std::pair<std::string, code_sign_enable_arg> &a,
65 const std::pair<std::string, code_sign_enable_arg> &b) {
66 return a.second.data_size > b.second.data_size;
67 };
68 sort(enableData_.begin(), enableData_.end(), compareFileDataSize);
69 }
70
ExecuteEnableCodeSignTask(uint32_t & index,int32_t & taskRet,const std::string & ownerId,const std::string & path,CallbackFunc & func)71 void CodeSignEnableMultiTask::ExecuteEnableCodeSignTask(uint32_t &index, int32_t &taskRet,
72 const std::string &ownerId, const std::string &path, CallbackFunc &func)
73 {
74 auto enableCodeSignTask = [this, index, &ownerId, &path, &func, &taskRet]() {
75 LOG_DEBUG(LABEL, "ExecuteEnableCodeSignTask task called");
76 {
77 std::unique_lock<std::mutex> lock(cvLock_);
78 if (taskRet != CS_SUCCESS) {
79 this->taskCallBack_++;
80 if (this->taskCallBack_ == this->enableData_.size()) {
81 this->taskfinish_.notify_one();
82 }
83 return;
84 }
85 }
86
87 int32_t ret = CheckOwnerId(path, ownerId,
88 reinterpret_cast<const uint8_t *>(this->enableData_[index].second.sig_ptr),
89 this->enableData_[index].second.sig_size);
90 if (ret == CS_SUCCESS) {
91 ret = func(this->enableData_[index].first, this->enableData_[index].second);
92 }
93 LOG_DEBUG(LABEL, "Task return info index: %{public}d, ret: %{public}d", index, ret);
94
95 std::unique_lock<std::mutex> lock(cvLock_);
96 if (taskRet == CS_SUCCESS) {
97 taskRet = ret;
98 }
99 this->taskCallBack_++;
100 if (this->taskCallBack_ == this->enableData_.size()) {
101 this->taskfinish_.notify_one();
102 }
103 };
104 enableCodeSignTaskWorker_.AddTask(enableCodeSignTask);
105 }
106
CheckOwnerId(const std::string & path,const std::string & ownerId,const uint8_t * sigPtr,uint32_t sigSize)107 int32_t CodeSignEnableMultiTask::CheckOwnerId(const std::string &path, const std::string &ownerId,
108 const uint8_t *sigPtr, uint32_t sigSize)
109 {
110 if (ownerId.empty()) {
111 return CS_SUCCESS;
112 }
113
114 int32_t ret;
115 ByteBuffer sigBuffer;
116 sigBuffer.CopyFrom(sigPtr, sigSize);
117 std::string retId;
118 ret = SignerInfo::ParseOwnerIdFromSignature(sigBuffer, retId);
119 if (ret != CS_SUCCESS) {
120 ReportInvalidOwner(path, ownerId, "invalid");
121 LOG_ERROR(LABEL, "get ownerId from signature failed, ret %{public}d", ret);
122 } else if (retId != ownerId) {
123 ret = CS_ERR_INVALID_OWNER_ID;
124 ReportInvalidOwner(path, ownerId, retId);
125 LOG_ERROR(LABEL, "invalid ownerId retId %{public}s ownerId %{public}s", retId.c_str(), ownerId.c_str());
126 }
127 return ret;
128 }
129 }
130 }
131 }