• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }