1 /*
2  * Copyright (c) 2023-2024 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 "local_code_sign_client.h"
17 #include <iservice_registry.h>
18 
19 #include "cert_utils.h"
20 #include "cs_hisysevent.h"
21 #include "huks_attest_verifier.h"
22 #include "local_code_sign_proxy.h"
23 #include "local_code_sign_load_callback.h"
24 #include "log.h"
25 
26 namespace OHOS {
27 namespace Security {
28 namespace CodeSign {
29 constexpr int32_t LOAD_SA_TIMEOUT_MS = 5000;
30 
LocalCodeSignClient()31 LocalCodeSignClient::LocalCodeSignClient()
32 {
33     localCodeSignSvrRecipient_ = new (std::nothrow) LocalCodeSignSvrRecipient();
34     if (localCodeSignSvrRecipient_ == nullptr) {
35         LOG_ERROR("Create LocalCodeSignSvrRecipient failed.");
36     }
37 }
38 
~LocalCodeSignClient()39 LocalCodeSignClient::~LocalCodeSignClient()
40 {
41     std::lock_guard<std::mutex> lock(proxyMutex_);
42     if (localCodeSignProxy_ != nullptr && localCodeSignSvrRecipient_ != nullptr) {
43         localCodeSignProxy_->AsObject()->RemoveDeathRecipient(localCodeSignSvrRecipient_);
44     }
45     localCodeSignSvrRecipient_ = nullptr;
46 }
47 
OnRemoteDied(const wptr<IRemoteObject> & remote)48 void LocalCodeSignClient::LocalCodeSignSvrRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
49 {
50     if (remote == nullptr) {
51         LOG_ERROR("OnRemoteDied remote is nullptr.");
52         return;
53     }
54     LOG_INFO("LocalCodeSignSvrRecipient OnRemoteDied.");
55     LocalCodeSignClient::GetInstance().OnRemoteLocalCodeSignSvrDied(remote);
56 }
57 
StartSA()58 int32_t LocalCodeSignClient::StartSA()
59 {
60     std::unique_lock<std::mutex> lock(proxyMutex_);
61     LOG_DEBUG("Start LocalCodeSignService");
62     sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
63     if (samgr == nullptr) {
64         LOG_ERROR("Get system ability mgr failed.");
65         return CS_ERR_SA_GET_SAMGR;
66     }
67     sptr<LocalCodeSignLoadCallback> loadCallback = new (std::nothrow) LocalCodeSignLoadCallback();
68     if (loadCallback == nullptr) {
69         return CS_ERR_MEMORY;
70     }
71     int32_t ret = samgr->LoadSystemAbility(LOCAL_CODE_SIGN_SA_ID, loadCallback);
72     if (ret != ERR_OK) {
73         LOG_ERROR("Load systemAbility failed, systemAbilityId:%{public}d ret code:%{public}d",
74             LOCAL_CODE_SIGN_SA_ID, ret);
75         return CS_ERR_SA_LOAD_FAILED;
76     }
77     LOG_INFO("To load system ability.");
78     auto waitStatus = proxyConVar_.wait_for(lock, std::chrono::milliseconds(LOAD_SA_TIMEOUT_MS),
79         [this]() { return localCodeSignProxy_ != nullptr; });
80     if (!waitStatus) {
81         LOG_ERROR("code sign load SA timeout");
82         return CS_ERR_SA_LOAD_TIMEOUT;
83     }
84     LOG_INFO("code sign load SA successfully");
85     return CS_SUCCESS;
86 }
87 
FinishStartSA(const sptr<IRemoteObject> & remoteObject)88 void LocalCodeSignClient::FinishStartSA(const sptr<IRemoteObject> &remoteObject)
89 {
90     LOG_DEBUG("LocalCodeSignClient FinishStartSA");
91     std::lock_guard<std::mutex> lock(proxyMutex_);
92     if (localCodeSignSvrRecipient_ == nullptr) {
93         LOG_ERROR("localCodeSignSvrRecipient_ is nullptr.");
94         return;
95     }
96     if (!remoteObject->AddDeathRecipient(localCodeSignSvrRecipient_)) {
97         LOG_ERROR("AddDeathRecipient failed");
98     }
99     localCodeSignProxy_ = iface_cast<LocalCodeSignInterface>(remoteObject);
100     if ((localCodeSignProxy_ == nullptr) || (localCodeSignProxy_->AsObject() == nullptr)) {
101         LOG_ERROR("Get code sign proxy failed.");
102         return;
103     }
104     proxyConVar_.notify_one();
105 }
106 
FailStartSA()107 void LocalCodeSignClient::FailStartSA()
108 {
109     std::lock_guard<std::mutex> lock(proxyMutex_);
110     localCodeSignProxy_ = nullptr;
111     proxyConVar_.notify_one();
112 }
113 
CheckLocalCodeSignProxy()114 void LocalCodeSignClient::CheckLocalCodeSignProxy()
115 {
116     {
117         std::lock_guard<std::mutex> lock(proxyMutex_);
118         if (localCodeSignProxy_ != nullptr) {
119             return;
120         }
121         sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
122         if (samgr == nullptr) {
123             LOG_ERROR("Get system ability mgr failed.");
124             return;
125         }
126         auto remoteObject = samgr->CheckSystemAbility(LOCAL_CODE_SIGN_SA_ID);
127         if (remoteObject != nullptr) {
128             if (!remoteObject->AddDeathRecipient(localCodeSignSvrRecipient_)) {
129                 LOG_ERROR("AddDeathRecipient failed");
130             }
131             localCodeSignProxy_ = iface_cast<LocalCodeSignInterface>(remoteObject);
132             return;
133         }
134     }
135     int32_t ret = StartSA();
136     if (ret != CS_SUCCESS) {
137         ReportLoadSAError(ret);
138     }
139 }
140 
InitLocalCertificate(ByteBuffer & cert)141 int32_t LocalCodeSignClient::InitLocalCertificate(ByteBuffer &cert)
142 {
143     LOG_DEBUG("InitLocalCertificate called");
144     CheckLocalCodeSignProxy();
145     std::lock_guard<std::mutex> lock(proxyMutex_);
146     if (localCodeSignProxy_ == nullptr) {
147         return CS_ERR_SA_GET_PROXY;
148     }
149     ByteBuffer certChainBuffer;
150     std::unique_ptr<ByteBuffer> challenge = GetRandomChallenge();
151     int32_t ret = localCodeSignProxy_->InitLocalCertificate(*challenge, certChainBuffer);
152     if (ret != CS_SUCCESS) {
153         LOG_ERROR("InitLocalCertificate err, error code = %{public}d", ret);
154         return ret;
155     }
156 
157     if (!GetVerifiedCert(certChainBuffer, *challenge, cert)) {
158         ret = CS_ERR_VERIFY_CERT;
159     }
160     return ret;
161 }
162 
SignLocalCode(const std::string & ownerID,const std::string & path,ByteBuffer & signature)163 int32_t LocalCodeSignClient::SignLocalCode(const std::string &ownerID, const std::string &path, ByteBuffer &signature)
164 {
165     LOG_DEBUG("SignLocalCode called");
166     CheckLocalCodeSignProxy();
167     std::lock_guard<std::mutex> lock(proxyMutex_);
168     if (localCodeSignProxy_ == nullptr) {
169         return CS_ERR_SA_GET_PROXY;
170     }
171     int32_t ret = localCodeSignProxy_->SignLocalCode(ownerID, path, signature);
172     if (ret != CS_SUCCESS) {
173         LOG_ERROR("SignLocalCode err, error code = %{public}d", ret);
174         return ret;
175     }
176     LOG_INFO("SignLocalCode successfully");
177     return CS_SUCCESS;
178 }
179 
OnRemoteLocalCodeSignSvrDied(const wptr<IRemoteObject> & remote)180 void LocalCodeSignClient::OnRemoteLocalCodeSignSvrDied(const wptr<IRemoteObject> &remote)
181 {
182     std::lock_guard<std::mutex> lock(proxyMutex_);
183     if (localCodeSignProxy_ == nullptr) {
184         LOG_ERROR("localCodeSignProxy_ is nullptr.");
185         return;
186     }
187     sptr<IRemoteObject> remoteObject = remote.promote();
188     if (remoteObject == nullptr) {
189         LOG_ERROR("OnRemoteDied remote promoted failed");
190         return;
191     }
192 
193     if (localCodeSignProxy_->AsObject() != remoteObject) {
194         LOG_ERROR("OnRemoteLocalCodeSignSvrDied not found remote object.");
195         return;
196     }
197     localCodeSignProxy_->AsObject()->RemoveDeathRecipient(localCodeSignSvrRecipient_);
198     localCodeSignProxy_ = nullptr;
199 }
200 
GetInstance()201 LocalCodeSignClient &LocalCodeSignClient::GetInstance()
202 {
203     static LocalCodeSignClient singleLocalCodeSignClient;
204     return singleLocalCodeSignClient;
205 }
206 
GetLocalCodeSignClient()207 LocalCodeSignClient *GetLocalCodeSignClient()
208 {
209     return &LocalCodeSignClient::GetInstance();
210 }
211 }
212 }
213 }