• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "schedule_node_impl.h"
16 
17 #include <mutex>
18 #include <sstream>
19 
20 #include "nocopyable.h"
21 
22 #include "attributes.h"
23 #include "hdi_wrapper.h"
24 #include "iam_check.h"
25 #include "iam_logger.h"
26 #include "iam_ptr.h"
27 #include "iam_para2str.h"
28 #include "iam_common_defines.h"
29 #include "relative_timer.h"
30 #include "schedule_resource_node_listener.h"
31 
32 #define LOG_TAG "USER_AUTH_SA"
33 
34 namespace OHOS {
35 namespace UserIam {
36 namespace UserAuth {
ScheduleNodeImpl(ScheduleInfo & info)37 ScheduleNodeImpl::ScheduleNodeImpl(ScheduleInfo &info) : info_(std::move(info))
38 {
39     machine_ = MakeFiniteStateMachine();
40     if (machine_ && info_.threadHandler == nullptr) {
41         info_.threadHandler = ThreadHandler::GetSingleThreadInstance();
42         machine_->SetThreadHandler(info_.threadHandler);
43     }
44 }
45 
~ScheduleNodeImpl()46 ScheduleNodeImpl::~ScheduleNodeImpl()
47 {
48     if (resourceNodePoolListener_ != nullptr) {
49         ResourceNodePool::Instance().DeregisterResourceNodePoolListener(resourceNodePoolListener_);
50     }
51 }
52 
GetScheduleAttribute(bool isVerifier,Attributes & attribute) const53 void ScheduleNodeImpl::GetScheduleAttribute(bool isVerifier, Attributes &attribute) const
54 {
55     attribute.SetInt32Value(Attributes::ATTR_SCHEDULE_MODE, info_.scheduleMode);
56 
57     if (info_.tokenId.has_value()) {
58         attribute.SetUint32Value(Attributes::ATTR_ACCESS_TOKEN_ID, info_.tokenId.value());
59     }
60 
61     if (info_.pinSubType != 0) {
62         attribute.SetInt32Value(Attributes::ATTR_PIN_SUB_TYPE, info_.pinSubType);
63     }
64 
65     attribute.SetUint32Value(Attributes::ATTR_COLLECTOR_TOKEN_ID, info_.collectorTokenId);
66     attribute.SetBoolValue(Attributes::ATTR_END_AFTER_FIRST_FAIL, info_.endAfterFirstFail);
67     IAM_LOGI("verifier message length = %{public}zu, collector message length = %{public}zu",
68         info_.verifierMessage.size(), info_.collectorMessage.size());
69 
70     if (isVerifier) {
71         attribute.SetInt32Value(Attributes::ATTR_AUTH_INTENTION, info_.authIntent);
72         attribute.SetInt32Value(Attributes::ATTR_USER_ID, info_.userId);
73         attribute.SetUint8ArrayValue(Attributes::ATTR_EXTRA_INFO, info_.verifierMessage);
74     } else {
75         attribute.SetUint8ArrayValue(Attributes::ATTR_EXTRA_INFO, info_.collectorMessage);
76     }
77 
78     if (!info_.templateIdList.empty()) {
79         attribute.SetUint64ArrayValue(Attributes::ATTR_TEMPLATE_ID_LIST, info_.templateIdList);
80         if (info_.templateIdList.size() == 1) {
81             attribute.SetUint64Value(Attributes::ATTR_TEMPLATE_ID, *info_.templateIdList.begin());
82         }
83     }
84 }
85 
GetScheduleId() const86 uint64_t ScheduleNodeImpl::GetScheduleId() const
87 {
88     return info_.scheduleId;
89 }
90 
GetContextId() const91 uint64_t ScheduleNodeImpl::GetContextId() const
92 {
93     return info_.contextId;
94 }
95 
GetAuthType() const96 AuthType ScheduleNodeImpl::GetAuthType() const
97 {
98     return info_.authType;
99 }
100 
GetExecutorMatcher() const101 uint64_t ScheduleNodeImpl::GetExecutorMatcher() const
102 {
103     return info_.executorMatcher;
104 }
105 
GetScheduleMode() const106 ScheduleMode ScheduleNodeImpl::GetScheduleMode() const
107 {
108     return info_.scheduleMode;
109 }
110 
GetCollectorExecutor() const111 std::weak_ptr<ResourceNode> ScheduleNodeImpl::GetCollectorExecutor() const
112 {
113     return info_.collector;
114 }
115 
GetVerifyExecutor() const116 std::weak_ptr<ResourceNode> ScheduleNodeImpl::GetVerifyExecutor() const
117 {
118     return info_.verifier;
119 }
120 
GetTemplateIdList() const121 std::optional<std::vector<uint64_t>> ScheduleNodeImpl::GetTemplateIdList() const
122 {
123     if (info_.templateIdList.empty()) {
124         return std::nullopt;
125     }
126     return info_.templateIdList;
127 }
128 
GetCurrentScheduleState() const129 ScheduleNode::State ScheduleNodeImpl::GetCurrentScheduleState() const
130 {
131     if (machine_ == nullptr) {
132         return S_INIT;
133     }
134     return static_cast<State>(machine_->GetCurrentState());
135 }
136 
GetScheduleCallback()137 std::shared_ptr<ScheduleNodeCallback> ScheduleNodeImpl::GetScheduleCallback()
138 {
139     std::lock_guard<std::mutex> lock(mutex_);
140     return info_.callback;
141 }
142 
ClearScheduleCallback()143 void ScheduleNodeImpl::ClearScheduleCallback()
144 {
145     std::lock_guard<std::mutex> lock(mutex_);
146     info_.callback = nullptr;
147 }
148 
StartSchedule()149 bool ScheduleNodeImpl::StartSchedule()
150 {
151     iamHitraceHelper_ = Common::MakeShared<IamHitraceHelper>(GetDescription());
152     {
153         std::lock_guard<std::mutex> lock(mutex_);
154         resourceNodePoolListener_ = Common::MakeShared<ScheduleResourceNodeListener>(weak_from_this());
155         IF_FALSE_LOGE_AND_RETURN_VAL(resourceNodePoolListener_ != nullptr, false);
156         bool registerRet = ResourceNodePool::Instance().RegisterResourceNodePoolListener(resourceNodePoolListener_);
157         IF_FALSE_LOGE_AND_RETURN_VAL(registerRet, false);
158         if (!TryKickMachine(E_START_AUTH)) {
159             return false;
160         }
161     }
162     StartTimer();
163     return true;
164 }
165 
StopSchedule()166 bool ScheduleNodeImpl::StopSchedule()
167 {
168     return StopSchedule(CANCELED);
169 }
170 
StopSchedule(ResultCode errorCode)171 bool ScheduleNodeImpl::StopSchedule(ResultCode errorCode)
172 {
173     std::lock_guard<std::mutex> lock(mutex_);
174 
175     SetFwkResultCode(errorCode);
176     IAM_LOGI("stop schedule %{public}s, error code %{public}d", GET_MASKED_STRING(info_.scheduleId).c_str(),
177         errorCode);
178     return TryKickMachine(E_STOP_AUTH);
179 }
180 
SendMessage(ExecutorRole dstRole,const std::vector<uint8_t> & msg)181 bool ScheduleNodeImpl::SendMessage(ExecutorRole dstRole, const std::vector<uint8_t> &msg)
182 {
183     Attributes attr(msg);
184     if (dstRole == SCHEDULER) {
185         int32_t tip;
186         if (attr.GetInt32Value(Attributes::ATTR_TIP_INFO, tip)) {
187             std::shared_ptr<ScheduleNodeCallback> callback = GetScheduleCallback();
188             IF_FALSE_LOGE_AND_RETURN_VAL(callback != nullptr, false);
189             callback->OnScheduleProcessed(dstRole, GetAuthType(), msg);
190             return true;
191         } else {
192             int srcRole;
193             std::vector<uint8_t> message;
194             bool getAcquireRet = attr.GetInt32Value(Attributes::ATTR_SRC_ROLE, srcRole);
195             IF_FALSE_LOGE_AND_RETURN_VAL(getAcquireRet, false);
196             bool getExtraInfoRet = attr.GetUint8ArrayValue(Attributes::ATTR_EXTRA_INFO, message);
197             IF_FALSE_LOGE_AND_RETURN_VAL(getExtraInfoRet, false);
198             auto hdi = HdiWrapper::GetHdiInstance();
199             IF_FALSE_LOGE_AND_RETURN_VAL(hdi != nullptr, false);
200             int sendMsgRet = hdi->SendMessage(GetScheduleId(), srcRole, message);
201             IF_FALSE_LOGE_AND_RETURN_VAL(sendMsgRet == HDF_SUCCESS, false);
202             return true;
203         }
204     }
205 
206     std::shared_ptr<ResourceNode> node = nullptr;
207     if (dstRole == ALL_IN_ONE || dstRole == VERIFIER) {
208         node = info_.verifier.lock();
209     } else if (dstRole == COLLECTOR) {
210         node = info_.collector.lock();
211     }
212 
213     IF_FALSE_LOGE_AND_RETURN_VAL(node != nullptr, false);
214     node->SendData(GetScheduleId(), attr);
215     return true;
216 }
217 
ContinueSchedule(ResultCode resultCode,const std::shared_ptr<Attributes> & finalResult)218 bool ScheduleNodeImpl::ContinueSchedule(ResultCode resultCode, const std::shared_ptr<Attributes> &finalResult)
219 {
220     std::lock_guard<std::mutex> lock(mutex_);
221     SetExecutorResultCode(resultCode);
222     SetScheduleResult(finalResult);
223     return TryKickMachine(E_SCHEDULE_RESULT_RECEIVED);
224 }
225 
MakeFiniteStateMachine()226 std::shared_ptr<FiniteStateMachine> ScheduleNodeImpl::MakeFiniteStateMachine()
227 {
228     auto builder = FiniteStateMachine::Builder::New(GetDescription(), S_INIT);
229     if (builder == nullptr) {
230         return nullptr;
231     }
232     // S_INIT
233     builder->MakeTransition(S_INIT, E_START_AUTH, S_VERIFY_STARING,
234         [this](FiniteStateMachine &machine, uint32_t event) { ProcessBeginVerifier(machine, event); });
235 
236     // S_VERIFY_STARING
237     builder->MakeTransition(S_VERIFY_STARING, E_VERIFY_STARTED_SUCCESS, S_COLLECT_STARING,
238         [this](FiniteStateMachine &machine, uint32_t event) { ProcessBeginCollector(machine, event); });
239     builder->MakeTransition(S_VERIFY_STARING, E_VERIFY_STARTED_FAILED, S_END,
240         [this](FiniteStateMachine &machine, uint32_t event) { ProcessVerifierBeginFailed(machine, event); });
241     builder->MakeTransition(S_VERIFY_STARING, E_SCHEDULE_RESULT_RECEIVED, S_END);
242     builder->MakeTransition(S_VERIFY_STARING, E_STOP_AUTH, S_VERIFY_STOPPING,
243         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndVerifier(machine, event); });
244     builder->MakeTransition(S_VERIFY_STARING, E_TIME_OUT, S_VERIFY_STOPPING,
245         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndVerifier(machine, event); });
246 
247     // S_COLLECT_STARING
248     builder->MakeTransition(S_COLLECT_STARING, E_COLLECT_STARTED_SUCCESS, S_AUTH_PROCESSING);
249     builder->MakeTransition(S_COLLECT_STARING, E_SCHEDULE_RESULT_RECEIVED, S_END);
250     builder->MakeTransition(S_COLLECT_STARING, E_STOP_AUTH, S_COLLECT_STOPPING,
251         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndCollector(machine, event); });
252 
253     // S_AUTH_PROCESSING
254     builder->MakeTransition(S_AUTH_PROCESSING, E_SCHEDULE_RESULT_RECEIVED, S_END);
255     builder->MakeTransition(S_AUTH_PROCESSING, E_STOP_AUTH, S_COLLECT_STOPPING,
256         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndCollector(machine, event); });
257     builder->MakeTransition(S_AUTH_PROCESSING, E_TIME_OUT, S_COLLECT_STOPPING,
258         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndCollector(machine, event); });
259 
260     // S_COLLECT_STOPPING
261     builder->MakeTransition(S_COLLECT_STOPPING, E_SCHEDULE_RESULT_RECEIVED, S_END);
262     builder->MakeTransition(S_COLLECT_STOPPING, E_COLLECT_STOPPED_SUCCESS, S_VERIFY_STOPPING,
263         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndVerifier(machine, event); });
264     builder->MakeTransition(S_COLLECT_STOPPING, E_COLLECT_STOPPED_FAILED, S_VERIFY_STOPPING,
265         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndVerifier(machine, event); });
266     builder->MakeTransition(S_COLLECT_STOPPING, E_TIME_OUT, S_VERIFY_STOPPING,
267         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndVerifier(machine, event); });
268 
269     // S_VERIFY_STOPPING
270     builder->MakeTransition(S_VERIFY_STOPPING, E_SCHEDULE_RESULT_RECEIVED, S_END);
271     builder->MakeTransition(S_VERIFY_STOPPING, E_VERIFY_STOPPED_SUCCESS, S_END);
272     builder->MakeTransition(S_VERIFY_STOPPING, E_VERIFY_STOPPED_FAILED, S_END);
273     builder->MakeTransition(S_VERIFY_STOPPING, E_TIME_OUT, S_END);
274 
275     // ENTERS
276     builder->MakeOnStateEnter(S_AUTH_PROCESSING,
277         [this](FiniteStateMachine &machine, uint32_t event) { OnScheduleProcessing(machine, event); });
278     builder->MakeOnStateEnter(S_END,
279         [this](FiniteStateMachine &machine, uint32_t event) { OnScheduleFinished(machine, event); });
280     return builder->Build();
281 }
282 
GetDescription() const283 std::string ScheduleNodeImpl::GetDescription() const
284 {
285     std::ostringstream ss;
286 
287     auto verifier = info_.verifier.lock();
288     ss << "schedule type:" << (verifier ? Common::AuthTypeToStr(verifier->GetAuthType()) : "nullptr") <<
289         " id:******" << std::hex << static_cast<uint16_t>(GetScheduleId());
290     return ss.str();
291 }
292 
TryKickMachine(Event event)293 bool ScheduleNodeImpl::TryKickMachine(Event event)
294 {
295     if (machine_ == nullptr) {
296         return false;
297     }
298     machine_->Schedule(event);
299     return true;
300 }
301 
SetFwkResultCode(int32_t resultCode)302 void ScheduleNodeImpl::SetFwkResultCode(int32_t resultCode)
303 {
304     fwkResultCode_ = resultCode;
305 }
306 
SetExecutorResultCode(int32_t resultCode)307 void ScheduleNodeImpl::SetExecutorResultCode(int32_t resultCode)
308 {
309     executorResultCode_ = resultCode;
310 }
311 
SetScheduleResult(const std::shared_ptr<Attributes> & scheduleResult)312 void ScheduleNodeImpl::SetScheduleResult(const std::shared_ptr<Attributes> &scheduleResult)
313 {
314     scheduleResult_ = scheduleResult;
315 }
316 
StartTimer()317 void ScheduleNodeImpl::StartTimer()
318 {
319     std::lock_guard<std::mutex> lock(mutex_);
320     if (info_.expiredTime == 0 || timerId_ != 0) {
321         return;
322     }
323 
324     timerId_ = RelativeTimer::GetInstance().Register(
325         [self = weak_from_this(), this] {
326             if (self.lock()) {
327                 std::lock_guard<std::mutex> lock(mutex_);
328                 SetFwkResultCode(TIMEOUT);
329                 TryKickMachine(E_TIME_OUT);
330             }
331         },
332         info_.expiredTime);
333 }
334 
StopTimer()335 void ScheduleNodeImpl::StopTimer()
336 {
337     std::lock_guard<std::mutex> lock(mutex_);
338     if (timerId_ == 0) {
339         return;
340     }
341     RelativeTimer::GetInstance().Unregister(timerId_);
342     timerId_ = 0;
343 }
344 
ProcessBeginVerifier(FiniteStateMachine & machine,uint32_t event)345 void ScheduleNodeImpl::ProcessBeginVerifier(FiniteStateMachine &machine, uint32_t event)
346 {
347     auto collector = info_.collector.lock();
348     auto verifier = info_.verifier.lock();
349     if (collector == nullptr || verifier == nullptr) {
350         SetFwkResultCode(GENERAL_ERROR);
351         machine.Schedule(E_VERIFY_STARTED_FAILED);
352         IAM_LOGE("invalid resource");
353         return;
354     }
355     auto peerPk = collector->GetExecutorPublicKey();
356     Attributes attr;
357     GetScheduleAttribute(true, attr);
358     auto result = verifier->BeginExecute(info_.scheduleId, peerPk, attr);
359     if (result != SUCCESS) {
360         IAM_LOGE("start verify failed, result = %{public}d", result);
361         SetExecutorResultCode(result);
362         machine.Schedule(E_VERIFY_STARTED_FAILED);
363         return;
364     }
365     IAM_LOGI("start verify success");
366     machine.Schedule(E_VERIFY_STARTED_SUCCESS);
367 }
368 
ProcessBeginCollector(FiniteStateMachine & machine,uint32_t event)369 void ScheduleNodeImpl::ProcessBeginCollector(FiniteStateMachine &machine, uint32_t event)
370 {
371     auto collector = info_.collector.lock();
372     auto verifier = info_.verifier.lock();
373     if (collector == nullptr || verifier == nullptr) {
374         SetFwkResultCode(GENERAL_ERROR);
375         machine.Schedule(E_COLLECT_STARTED_FAILED);
376         IAM_LOGE("invalid resource");
377         return;
378     }
379     if (collector == verifier) {
380         IAM_LOGI("all in one schedule, just wait the result");
381         machine.Schedule(E_COLLECT_STARTED_SUCCESS);
382         return;
383     }
384 
385     auto peerPk = collector->GetExecutorPublicKey();
386     Attributes attr;
387     GetScheduleAttribute(false, attr);
388     auto result = collector->BeginExecute(info_.scheduleId, peerPk, attr);
389     if (result != SUCCESS) {
390         IAM_LOGE("start collect failed, result = %{public}d", result);
391         SetExecutorResultCode(result);
392         machine.Schedule(E_COLLECT_STARTED_FAILED);
393         return;
394     }
395     IAM_LOGI("start collect success");
396     machine.Schedule(E_COLLECT_STARTED_SUCCESS);
397     NotifyCollectorReady();
398 }
399 
NotifyCollectorReady()400 void ScheduleNodeImpl::NotifyCollectorReady()
401 {
402     auto verifier = info_.verifier.lock();
403     if (verifier == nullptr) {
404         return;
405     }
406 
407     Attributes attr;
408     bool setPropertyModeRet = attr.SetInt32Value(Attributes::ATTR_PROPERTY_MODE, PROPERTY_MODE_NOTIFY_COLLECTOR_READY);
409     IF_FALSE_LOGE_AND_RETURN(setPropertyModeRet);
410     bool setScheduleIdRet = attr.SetUint64Value(Attributes::ATTR_SCHEDULE_ID, GetScheduleId());
411     IF_FALSE_LOGE_AND_RETURN(setScheduleIdRet);
412 
413     int32_t ret = verifier->SetProperty(attr);
414     if (ret != SUCCESS) {
415         IAM_LOGE("notify collector ready failed, result = %{public}d", ret);
416     }
417 }
418 
ProcessVerifierBeginFailed(FiniteStateMachine & machine,uint32_t event)419 void ScheduleNodeImpl::ProcessVerifierBeginFailed(FiniteStateMachine &machine, uint32_t event)
420 {
421     // just do nothing
422 }
423 
ProcessCollectorBeginFailed(FiniteStateMachine & machine,uint32_t event)424 void ScheduleNodeImpl::ProcessCollectorBeginFailed(FiniteStateMachine &machine, uint32_t event)
425 {
426     // just do nothing
427 }
428 
ProcessScheduleResultReceived(FiniteStateMachine & machine,uint32_t event) const429 void ScheduleNodeImpl::ProcessScheduleResultReceived(FiniteStateMachine &machine, uint32_t event) const
430 {
431     // just do nothing
432 }
433 
ProcessEndCollector(FiniteStateMachine & machine,uint32_t event)434 void ScheduleNodeImpl::ProcessEndCollector(FiniteStateMachine &machine, uint32_t event)
435 {
436     auto collector = info_.collector.lock();
437     auto verifier = info_.verifier.lock();
438     if (collector == nullptr || verifier == nullptr) {
439         SetFwkResultCode(GENERAL_ERROR);
440         machine.Schedule(E_COLLECT_STOPPED_FAILED);
441         return;
442     }
443     if (collector == verifier) {
444         IAM_LOGE("all in one schedule, just do noting");
445         machine.Schedule(E_COLLECT_STOPPED_SUCCESS);
446         return;
447     }
448     Attributes attr;
449     auto result = collector->EndExecute(info_.scheduleId, attr);
450     if (result != SUCCESS) {
451         IAM_LOGE("end verify failed, result = %{public}d", result);
452         SetExecutorResultCode(result);
453         machine.Schedule(E_COLLECT_STOPPED_FAILED);
454         return;
455     }
456     machine.Schedule(E_COLLECT_STOPPED_SUCCESS);
457 }
458 
ProcessEndVerifier(FiniteStateMachine & machine,uint32_t event)459 void ScheduleNodeImpl::ProcessEndVerifier(FiniteStateMachine &machine, uint32_t event)
460 {
461     auto verifier = info_.verifier.lock();
462     if (verifier == nullptr) {
463         SetFwkResultCode(GENERAL_ERROR);
464         machine.Schedule(E_VERIFY_STOPPED_FAILED);
465         return;
466     }
467     Attributes attr;
468     auto result = verifier->EndExecute(info_.scheduleId, attr);
469     if (result != SUCCESS) {
470         IAM_LOGE("end verify failed, result = %{public}d", result);
471         SetExecutorResultCode(result);
472         machine.Schedule(E_VERIFY_STOPPED_FAILED);
473         return;
474     }
475     machine.Schedule(E_VERIFY_STOPPED_SUCCESS);
476 }
477 
OnScheduleProcessing(FiniteStateMachine & machine,uint32_t event)478 void ScheduleNodeImpl::OnScheduleProcessing(FiniteStateMachine &machine, uint32_t event)
479 {
480     std::shared_ptr<ScheduleNodeCallback> callback = GetScheduleCallback();
481     if (!callback) {
482         return;
483     }
484     callback->OnScheduleStarted();
485 }
486 
OnScheduleFinished(FiniteStateMachine & machine,uint32_t event)487 void ScheduleNodeImpl::OnScheduleFinished(FiniteStateMachine &machine, uint32_t event)
488 {
489     StopTimer();
490     std::shared_ptr<ScheduleNodeCallback> callback = GetScheduleCallback();
491     if (!callback) {
492         return;
493     }
494 
495     iamHitraceHelper_ = nullptr;
496 
497     int32_t result = fwkResultCode_.value_or(executorResultCode_);
498     IAM_LOGI("schedule result = %{public}d", result);
499     callback->OnScheduleStoped(result, scheduleResult_);
500     ClearScheduleCallback();
501 }
502 } // namespace UserAuth
503 } // namespace UserIam
504 } // namespace OHOS
505