1 /*
2  * Copyright (c) 2022 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 "framework_executor_callback.h"
17 
18 #include <mutex>
19 #include <sstream>
20 
21 #include "auth_command.h"
22 #include "collect_command.h"
23 #include "custom_command.h"
24 #include "enroll_command.h"
25 #include "hisysevent_adapter.h"
26 #include "iam_check.h"
27 #include "iam_defines.h"
28 #include "iam_hitrace_helper.h"
29 #include "iam_logger.h"
30 #include "iam_mem.h"
31 #include "iam_para2str.h"
32 #include "iam_ptr.h"
33 #include "identify_command.h"
34 
35 #define LOG_TAG "USER_AUTH_EXECUTOR"
36 
37 namespace OHOS {
38 namespace UserIam {
39 namespace UserAuth {
FrameworkExecutorCallback(std::weak_ptr<Executor> executor)40 FrameworkExecutorCallback::FrameworkExecutorCallback(std::weak_ptr<Executor> executor) : executor_(executor)
41 {
42     uint32_t callbackId = GenerateExecutorCallbackId();
43     std::ostringstream ss;
44     ss << "ExecutorCallback(Id:" << callbackId << ")";
45     description_ = ss.str();
46 }
47 
OnBeginExecute(uint64_t scheduleId,const std::vector<uint8_t> & publicKey,const Attributes & commandAttrs)48 int32_t FrameworkExecutorCallback::OnBeginExecute(uint64_t scheduleId, const std::vector<uint8_t> &publicKey,
49     const Attributes &commandAttrs)
50 {
51     auto pk(publicKey);
52 
53     return OnBeginExecuteInner(scheduleId, pk, commandAttrs);
54 }
55 
OnBeginExecuteInner(uint64_t scheduleId,std::vector<uint8_t> & publicKey,const Attributes & commandAttrs)56 ResultCode FrameworkExecutorCallback::OnBeginExecuteInner(uint64_t scheduleId, std::vector<uint8_t> &publicKey,
57     const Attributes &commandAttrs)
58 {
59     static_cast<void>(publicKey);
60     int32_t commandId = 0;
61     bool getScheduleModeRet =
62         commandAttrs.GetInt32Value(Attributes::ATTR_SCHEDULE_MODE, commandId);
63     IF_FALSE_LOGE_AND_RETURN_VAL(getScheduleModeRet == true, ResultCode::GENERAL_ERROR);
64 
65     IAM_LOGI("%{public}s start process cmd %{public}u", GetDescription(), commandId);
66     ResultCode ret = ResultCode::GENERAL_ERROR;
67     switch (commandId) {
68         case ENROLL:
69             ret = ProcessEnrollCommand(scheduleId, commandAttrs);
70             break;
71         case AUTH:
72             ret = ProcessAuthCommand(scheduleId, commandAttrs);
73             break;
74         case IDENTIFY:
75             ret = ProcessIdentifyCommand(scheduleId, commandAttrs);
76             break;
77         default:
78             IAM_LOGE("command id %{public}u is not supported", commandId);
79     }
80 
81     IAM_LOGI("command id = %{public}u ret = %{public}d", commandId, ret);
82     return ret;
83 }
84 
OnEndExecute(uint64_t scheduleId,const Attributes & commandAttrs)85 int32_t FrameworkExecutorCallback::OnEndExecute(uint64_t scheduleId, const Attributes &commandAttrs)
86 {
87     return OnEndExecuteInner(scheduleId, commandAttrs);
88 }
89 
OnEndExecuteInner(uint64_t scheduleId,const Attributes & consumerAttr)90 ResultCode FrameworkExecutorCallback::OnEndExecuteInner(uint64_t scheduleId, const Attributes &consumerAttr)
91 {
92     ResultCode ret = ProcessCancelCommand(scheduleId);
93     IAM_LOGI("%{public}s cancel scheduleId %{public}s ret %{public}d", GetDescription(),
94         GET_MASKED_STRING(scheduleId).c_str(), ret);
95     return ret;
96 }
97 
OnMessengerReady(const std::shared_ptr<ExecutorMessenger> & messenger,const std::vector<uint8_t> & publicKey,const std::vector<uint64_t> & templateIdList)98 void FrameworkExecutorCallback::OnMessengerReady(const std::shared_ptr<ExecutorMessenger> &messenger,
99     const std::vector<uint8_t> &publicKey, const std::vector<uint64_t> &templateIdList)
100 {
101     IAM_LOGI("%{public}s start", GetDescription());
102     std::lock_guard<std::recursive_mutex> lock(mutex_);
103     auto executor = executor_.lock();
104     if (executor == nullptr) {
105         IAM_LOGE("executor has been released, process failed");
106         return;
107     }
108     auto hdi = executor->GetExecutorHdi();
109     IF_FALSE_LOGE_AND_RETURN(hdi != nullptr);
110     executorMessenger_ = messenger;
111     std::vector<uint8_t> extraInfo;
112     hdi->OnRegisterFinish(templateIdList, publicKey, extraInfo);
113 }
114 
OnSetProperty(const Attributes & properties)115 int32_t FrameworkExecutorCallback::OnSetProperty(const Attributes &properties)
116 {
117     return OnSetPropertyInner(properties);
118 }
119 
OnSetPropertyInner(const Attributes & properties)120 ResultCode FrameworkExecutorCallback::OnSetPropertyInner(const Attributes &properties)
121 {
122     uint32_t commandId = 0;
123     bool getAuthPropertyModeRet =
124         properties.GetUint32Value(Attributes::ATTR_PROPERTY_MODE, commandId);
125     IF_FALSE_LOGE_AND_RETURN_VAL(getAuthPropertyModeRet == true, ResultCode::GENERAL_ERROR);
126     IAM_LOGI("%{public}s start process cmd %{public}u", GetDescription(), commandId);
127     ResultCode ret;
128     if (commandId == PROPERTY_MODE_DEL) {
129         ret = ProcessDeleteTemplateCommand(properties);
130     } else if (commandId == PROPERTY_MODE_SET_CACHED_TEMPLATES) {
131         ret = ProcessSetCachedTemplates(properties);
132     } else if (commandId == PROPERTY_MODE_NOTIFY_COLLECTOR_READY) {
133         ret = ProcessNotifyExecutorReady(properties);
134     } else {
135         ret = ProcessCustomCommand(properties);
136     }
137     IAM_LOGI("command id = %{public}u ret = %{public}d", commandId, ret);
138     return ret;
139 }
140 
OnGetProperty(const Attributes & conditions,Attributes & results)141 int32_t FrameworkExecutorCallback::OnGetProperty(const Attributes &conditions, Attributes &results)
142 {
143     auto cond = Common::MakeShared<Attributes>(conditions.Serialize());
144     auto values = Common::MakeShared<Attributes>(results.Serialize());
145     auto ret = OnGetPropertyInner(cond, values);
146     if (values) {
147         results = std::move(*values);
148     }
149     return ret;
150 }
151 
OnSendData(uint64_t scheduleId,const Attributes & data)152 int32_t FrameworkExecutorCallback::OnSendData(uint64_t scheduleId, const Attributes &data)
153 {
154     int32_t srcRole = 0;
155     bool getDestRoleRet = data.GetInt32Value(Attributes::ATTR_SRC_ROLE, srcRole);
156     IF_FALSE_LOGE_AND_RETURN_VAL(getDestRoleRet == true, ResultCode::GENERAL_ERROR);
157     std::vector<uint8_t> extraInfo;
158     bool getExtraInfoRet = data.GetUint8ArrayValue(Attributes::ATTR_EXTRA_INFO, extraInfo);
159     IF_FALSE_LOGE_AND_RETURN_VAL(getExtraInfoRet == true, ResultCode::GENERAL_ERROR);
160 
161     auto executor = executor_.lock();
162     if (executor == nullptr) {
163         IAM_LOGE("executor has been released, process failed");
164         return ResultCode::GENERAL_ERROR;
165     }
166     auto hdi = executor->GetExecutorHdi();
167     IF_FALSE_LOGE_AND_RETURN_VAL(hdi != nullptr, ResultCode::GENERAL_ERROR);
168     return hdi->SendMessage(scheduleId, srcRole, extraInfo);
169 }
170 
OnGetPropertyInner(std::shared_ptr<Attributes> conditions,std::shared_ptr<Attributes> values)171 ResultCode FrameworkExecutorCallback::OnGetPropertyInner(std::shared_ptr<Attributes> conditions,
172     std::shared_ptr<Attributes> values)
173 {
174     IAM_LOGI("%{public}s start", GetDescription());
175     IF_FALSE_LOGE_AND_RETURN_VAL(conditions != nullptr, ResultCode::GENERAL_ERROR);
176     IF_FALSE_LOGE_AND_RETURN_VAL(values != nullptr, ResultCode::GENERAL_ERROR);
177     uint32_t commandId = 0;
178     bool getAuthPropertyModeRet =
179         conditions->GetUint32Value(Attributes::ATTR_PROPERTY_MODE, commandId);
180     IF_FALSE_LOGE_AND_RETURN_VAL(getAuthPropertyModeRet == true, ResultCode::GENERAL_ERROR);
181     if (commandId != PROPERTY_MODE_GET) {
182         IAM_LOGE("command id not recognised");
183         return ResultCode::GENERAL_ERROR;
184     }
185 
186     ResultCode ret = ProcessGetPropertyCommand(conditions, values);
187     IAM_LOGI("command id = %{public}u ret = %{public}d", commandId, ret);
188     return ret;
189 }
190 
ProcessEnrollCommand(uint64_t scheduleId,const Attributes & properties)191 ResultCode FrameworkExecutorCallback::ProcessEnrollCommand(uint64_t scheduleId, const Attributes &properties)
192 {
193     std::lock_guard<std::recursive_mutex> lock(mutex_);
194     auto command = Common::MakeShared<EnrollCommand>(executor_, scheduleId, properties, executorMessenger_);
195     IF_FALSE_LOGE_AND_RETURN_VAL(command != nullptr, ResultCode::GENERAL_ERROR);
196     return command->StartProcess();
197 }
198 
ProcessAuthCommand(uint64_t scheduleId,const Attributes & properties)199 ResultCode FrameworkExecutorCallback::ProcessAuthCommand(uint64_t scheduleId, const Attributes &properties)
200 {
201     std::lock_guard<std::recursive_mutex> lock(mutex_);
202     auto executor = executor_.lock();
203     if (executor == nullptr) {
204         IAM_LOGE("executor has been released, process failed");
205         return ResultCode::GENERAL_ERROR;
206     }
207 
208     std::shared_ptr<AsyncCommandBase> command = nullptr;
209     if (executor->GetExecutorRole() == COLLECTOR) {
210         command = Common::MakeShared<CollectCommand>(executor_, scheduleId, properties, executorMessenger_);
211     } else {
212         command = Common::MakeShared<AuthCommand>(executor_, scheduleId, properties, executorMessenger_);
213     }
214     IF_FALSE_LOGE_AND_RETURN_VAL(command != nullptr, ResultCode::GENERAL_ERROR);
215     return command->StartProcess();
216 }
217 
ProcessIdentifyCommand(uint64_t scheduleId,const Attributes & properties)218 ResultCode FrameworkExecutorCallback::ProcessIdentifyCommand(uint64_t scheduleId, const Attributes &properties)
219 {
220     std::lock_guard<std::recursive_mutex> lock(mutex_);
221     auto command = Common::MakeShared<IdentifyCommand>(executor_, scheduleId, properties, executorMessenger_);
222     IF_FALSE_LOGE_AND_RETURN_VAL(command != nullptr, ResultCode::GENERAL_ERROR);
223     return command->StartProcess();
224 }
225 
ProcessCancelCommand(uint64_t scheduleId)226 ResultCode FrameworkExecutorCallback::ProcessCancelCommand(uint64_t scheduleId)
227 {
228     auto executor = executor_.lock();
229     if (executor == nullptr) {
230         IAM_LOGE("executor has been released, process failed");
231         return ResultCode::GENERAL_ERROR;
232     }
233     auto hdi = executor->GetExecutorHdi();
234     IF_FALSE_LOGE_AND_RETURN_VAL(hdi != nullptr, ResultCode::GENERAL_ERROR);
235     return hdi->Cancel(scheduleId);
236 }
237 
ProcessDeleteTemplateCommand(const Attributes & properties)238 ResultCode FrameworkExecutorCallback::ProcessDeleteTemplateCommand(const Attributes &properties)
239 {
240     IAM_LOGI("start");
241     auto executor = executor_.lock();
242     if (executor == nullptr) {
243         IAM_LOGE("executor has been released, process failed");
244         return ResultCode::GENERAL_ERROR;
245     }
246     auto hdi = executor->GetExecutorHdi();
247     IF_FALSE_LOGE_AND_RETURN_VAL(hdi != nullptr, ResultCode::GENERAL_ERROR);
248     uint64_t templateId = 0;
249     bool getAuthTemplateIdRet = properties.GetUint64Value(Attributes::ATTR_TEMPLATE_ID, templateId);
250     IF_FALSE_LOGE_AND_RETURN_VAL(getAuthTemplateIdRet == true, ResultCode::GENERAL_ERROR);
251     std::vector<uint64_t> templateIdList;
252 
253     templateIdList.push_back(templateId);
254     IamHitraceHelper traceHelper("hdi Delete");
255     ResultCode ret = hdi->Delete(templateIdList);
256     if (ret == ResultCode::SUCCESS) {
257         TemplateChangeTrace info = {};
258         info.changeType = TRACE_DELETE_CREDENTIAL;
259         std::string templateChangeReason = "";
260         properties.GetStringValue(Attributes::ATTR_TEMPLATE_CHANGE_REASON, templateChangeReason);
261         info.reason = templateChangeReason;
262         info.executorType = executor->GetAuthType();
263         UserIam::UserAuth::ReportSecurityTemplateChange(info);
264     }
265     return ret;
266 }
267 
ProcessSetCachedTemplates(const Attributes & properties)268 ResultCode FrameworkExecutorCallback::ProcessSetCachedTemplates(const Attributes &properties)
269 {
270     IAM_LOGI("start");
271     auto executor = executor_.lock();
272     if (executor == nullptr) {
273         IAM_LOGE("executor has been released, process failed");
274         return ResultCode::GENERAL_ERROR;
275     }
276     auto hdi = executor->GetExecutorHdi();
277     IF_FALSE_LOGE_AND_RETURN_VAL(hdi != nullptr, ResultCode::GENERAL_ERROR);
278 
279     std::vector<uint64_t> templateIdList;
280     bool getTemplateIdListRet = properties.GetUint64ArrayValue(Attributes::ATTR_TEMPLATE_ID_LIST, templateIdList);
281     IF_FALSE_LOGE_AND_RETURN_VAL(getTemplateIdListRet == true, ResultCode::GENERAL_ERROR);
282 
283     return hdi->SetCachedTemplates(templateIdList);
284 }
285 
ProcessNotifyExecutorReady(const Attributes & properties)286 ResultCode FrameworkExecutorCallback::ProcessNotifyExecutorReady(const Attributes &properties)
287 {
288     IAM_LOGI("start");
289     auto executor = executor_.lock();
290     if (executor == nullptr) {
291         IAM_LOGE("executor has been released, process failed");
292         return ResultCode::GENERAL_ERROR;
293     }
294 
295     auto hdi = executor->GetExecutorHdi();
296     IF_FALSE_LOGE_AND_RETURN_VAL(hdi != nullptr, ResultCode::GENERAL_ERROR);
297 
298     uint64_t scheduleId;
299     bool getScheduleIdRet = properties.GetUint64Value(Attributes::ATTR_SCHEDULE_ID, scheduleId);
300     IF_FALSE_LOGE_AND_RETURN_VAL(getScheduleIdRet == true, ResultCode::GENERAL_ERROR);
301 
302     return hdi->NotifyCollectorReady(scheduleId);
303 }
304 
ProcessCustomCommand(const Attributes & properties)305 ResultCode FrameworkExecutorCallback::ProcessCustomCommand(const Attributes &properties)
306 {
307     auto command = Common::MakeShared<CustomCommand>(executor_, properties);
308     IF_FALSE_LOGE_AND_RETURN_VAL(command != nullptr, ResultCode::GENERAL_ERROR);
309     ResultCode ret = command->StartProcess();
310     if (ret != ResultCode::SUCCESS) {
311         IAM_LOGE("start process command fail ret = %{public}d", ret);
312         return ret;
313     }
314 
315     return command->GetResult();
316 }
317 
ProcessGetPropertyCommand(std::shared_ptr<Attributes> conditions,std::shared_ptr<Attributes> values)318 ResultCode FrameworkExecutorCallback::ProcessGetPropertyCommand(std::shared_ptr<Attributes> conditions,
319     std::shared_ptr<Attributes> values)
320 {
321     IAM_LOGI("start");
322     IF_FALSE_LOGE_AND_RETURN_VAL(conditions != nullptr, ResultCode::GENERAL_ERROR);
323     IF_FALSE_LOGE_AND_RETURN_VAL(values != nullptr, ResultCode::GENERAL_ERROR);
324     auto executor = executor_.lock();
325     if (executor == nullptr) {
326         IAM_LOGE("executor has been released, process failed");
327         return ResultCode::GENERAL_ERROR;
328     }
329     auto hdi = executor->GetExecutorHdi();
330     IF_FALSE_LOGE_AND_RETURN_VAL(hdi != nullptr, ResultCode::GENERAL_ERROR);
331 
332     std::vector<uint64_t> templateIdList;
333     bool getTemplateIdListRet = conditions->GetUint64ArrayValue(Attributes::ATTR_TEMPLATE_ID_LIST, templateIdList);
334     IF_FALSE_LOGE_AND_RETURN_VAL(getTemplateIdListRet == true, ResultCode::GENERAL_ERROR);
335 
336     std::vector<uint32_t> uint32KeyList;
337     bool getKeyListRet = conditions->GetUint32ArrayValue(Attributes::ATTR_KEY_LIST, uint32KeyList);
338     IF_FALSE_LOGE_AND_RETURN_VAL(getKeyListRet == true, ResultCode::GENERAL_ERROR);
339 
340     std::vector<Attributes::AttributeKey> keyList;
341     keyList.reserve(uint32KeyList.size());
342     for (auto &uint32Key : uint32KeyList) {
343         keyList.push_back(static_cast<Attributes::AttributeKey>(uint32Key));
344     }
345 
346     Property property = {};
347 
348     ResultCode getPropertyRet = hdi->GetProperty(templateIdList, keyList, property);
349     IF_FALSE_LOGE_AND_RETURN_VAL(getPropertyRet == SUCCESS, ResultCode::GENERAL_ERROR);
350 
351     ResultCode fillAttributeRet = FillPropertyToAttribute(keyList, property, values);
352     IF_FALSE_LOGE_AND_RETURN_VAL(fillAttributeRet == SUCCESS, ResultCode::GENERAL_ERROR);
353 
354     return ResultCode::SUCCESS;
355 }
356 
FillPropertyToAttribute(const std::vector<Attributes::AttributeKey> & keyList,const Property property,std::shared_ptr<Attributes> values)357 ResultCode FrameworkExecutorCallback::FillPropertyToAttribute(const std::vector<Attributes::AttributeKey> &keyList,
358     const Property property, std::shared_ptr<Attributes> values)
359 {
360     for (auto &key : keyList) {
361         switch (key) {
362             case Attributes::ATTR_PIN_SUB_TYPE: {
363                 bool setAuthSubTypeRet = values->SetInt32Value(Attributes::ATTR_PIN_SUB_TYPE, property.authSubType);
364                 IF_FALSE_LOGE_AND_RETURN_VAL(setAuthSubTypeRet == true, ResultCode::GENERAL_ERROR);
365                 break;
366             }
367             case Attributes::ATTR_FREEZING_TIME: {
368                 bool setAuthRemainTimeRet =
369                     values->SetInt32Value(Attributes::ATTR_FREEZING_TIME, property.lockoutDuration);
370                 IF_FALSE_LOGE_AND_RETURN_VAL(setAuthRemainTimeRet == true, ResultCode::GENERAL_ERROR);
371                 break;
372             }
373             case Attributes::ATTR_REMAIN_TIMES: {
374                 bool setAuthRemainCountRet =
375                     values->SetInt32Value(Attributes::ATTR_REMAIN_TIMES, property.remainAttempts);
376                 IF_FALSE_LOGE_AND_RETURN_VAL(setAuthRemainCountRet == true, ResultCode::GENERAL_ERROR);
377                 break;
378             }
379             case Attributes::ATTR_ENROLL_PROGRESS: {
380                 bool setEnrollProgressRet =
381                     values->SetStringValue(Attributes::ATTR_ENROLL_PROGRESS, property.enrollmentProgress);
382                 IF_FALSE_LOGE_AND_RETURN_VAL(setEnrollProgressRet == true, ResultCode::GENERAL_ERROR);
383                 break;
384             }
385             case Attributes::ATTR_SENSOR_INFO: {
386                 bool setSensorInfoRet = values->SetStringValue(Attributes::ATTR_SENSOR_INFO, property.sensorInfo);
387                 IF_FALSE_LOGE_AND_RETURN_VAL(setSensorInfoRet == true, ResultCode::GENERAL_ERROR);
388                 break;
389             }
390             case Attributes::ATTR_NEXT_FAIL_LOCKOUT_DURATION: {
391                 bool setNextFailLockoutDurationRet = values->SetInt32Value(Attributes::ATTR_NEXT_FAIL_LOCKOUT_DURATION,
392                     property.nextFailLockoutDuration);
393                 IF_FALSE_LOGE_AND_RETURN_VAL(setNextFailLockoutDurationRet == true, ResultCode::GENERAL_ERROR);
394                 break;
395             }
396             default:
397                 IAM_LOGE("key %{public}d is not recognized", key);
398                 return ResultCode::GENERAL_ERROR;
399         }
400     }
401 
402     return ResultCode::SUCCESS;
403 }
404 
GenerateExecutorCallbackId()405 uint32_t FrameworkExecutorCallback::GenerateExecutorCallbackId()
406 {
407     static std::mutex mutex;
408     static uint32_t callbackId = 0;
409     std::lock_guard<std::mutex> guard(mutex);
410     // callbackId is only used in log, uint32 overflow or duplicate is ok
411     ++callbackId;
412     return callbackId;
413 }
414 
GetDescription()415 const char *FrameworkExecutorCallback::GetDescription()
416 {
417     return description_.c_str();
418 }
419 } // namespace UserAuth
420 } // namespace UserIam
421 } // namespace OHOS
422