• 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 "iam_logger.h"
23 #include "iam_ptr.h"
24 #include "iam_para2str.h"
25 #include "iam_common_defines.h"
26 #include "relative_timer.h"
27 
28 #define LOG_LABEL UserIam::Common::LABEL_USER_AUTH_SA
29 
30 namespace OHOS {
31 namespace UserIam {
32 namespace UserAuth {
ScheduleNodeImpl(ScheduleInfo & info)33 ScheduleNodeImpl::ScheduleNodeImpl(ScheduleInfo &info) : info_(std::move(info))
34 {
35     machine_ = MakeFiniteStateMachine();
36     if (machine_ && info_.threadHandler == nullptr) {
37         info_.threadHandler = ThreadHandler::GetSingleThreadInstance();
38         machine_->SetThreadHandler(info_.threadHandler);
39     }
40     if (info_.parameters == nullptr) {
41         info_.parameters = Common::MakeShared<Attributes>();
42     }
43 
44     if (info_.parameters == nullptr) {
45         return;
46     }
47 
48     info_.parameters->SetInt32Value(Attributes::ATTR_SCHEDULE_MODE, info_.scheduleMode);
49 
50     if (info_.tokenId.has_value()) {
51         info_.parameters->SetUint32Value(Attributes::ATTR_ACCESS_TOKEN_ID, info_.tokenId.value());
52     }
53 
54     if (info_.pinSubType != 0) {
55         info_.parameters->SetInt32Value(Attributes::ATTR_PIN_SUB_TYPE, info_.pinSubType);
56     }
57 
58     info_.parameters->SetBoolValue(Attributes::ATTR_END_AFTER_FIRST_FAIL, info_.endAfterFirstFail);
59     info_.parameters->SetUint8ArrayValue(Attributes::ATTR_EXTRA_INFO, info_.extraInfo);
60 
61     if (info_.templateIdList.empty()) {
62         return;
63     }
64 
65     info_.parameters->SetUint64ArrayValue(Attributes::ATTR_TEMPLATE_ID_LIST, info_.templateIdList);
66     if (info_.templateIdList.size() == 1) {
67         info_.parameters->SetUint64Value(Attributes::ATTR_TEMPLATE_ID, *info_.templateIdList.begin());
68     }
69 }
70 
GetScheduleId() const71 uint64_t ScheduleNodeImpl::GetScheduleId() const
72 {
73     return info_.scheduleId;
74 }
75 
GetContextId() const76 uint64_t ScheduleNodeImpl::GetContextId() const
77 {
78     return info_.contextId;
79 }
80 
GetAuthType() const81 AuthType ScheduleNodeImpl::GetAuthType() const
82 {
83     return info_.authType;
84 }
85 
GetExecutorMatcher() const86 uint64_t ScheduleNodeImpl::GetExecutorMatcher() const
87 {
88     return info_.executorMatcher;
89 }
90 
GetScheduleMode() const91 ScheduleMode ScheduleNodeImpl::GetScheduleMode() const
92 {
93     return info_.scheduleMode;
94 }
95 
GetCollectorExecutor() const96 std::weak_ptr<ResourceNode> ScheduleNodeImpl::GetCollectorExecutor() const
97 {
98     return info_.collector;
99 }
100 
GetVerifyExecutor() const101 std::weak_ptr<ResourceNode> ScheduleNodeImpl::GetVerifyExecutor() const
102 {
103     return info_.verifier;
104 }
105 
GetTemplateIdList() const106 std::optional<std::vector<uint64_t>> ScheduleNodeImpl::GetTemplateIdList() const
107 {
108     if (info_.templateIdList.empty()) {
109         return std::nullopt;
110     }
111     return info_.templateIdList;
112 }
113 
GetCurrentScheduleState() const114 ScheduleNode::State ScheduleNodeImpl::GetCurrentScheduleState() const
115 {
116     if (machine_ == nullptr) {
117         return S_INIT;
118     }
119     return static_cast<State>(machine_->GetCurrentState());
120 }
121 
GetScheduleCallback()122 std::shared_ptr<ScheduleNodeCallback> ScheduleNodeImpl::GetScheduleCallback()
123 {
124     std::lock_guard<std::mutex> lock(mutex_);
125     return info_.callback;
126 }
127 
ClearScheduleCallback()128 void ScheduleNodeImpl::ClearScheduleCallback()
129 {
130     std::lock_guard<std::mutex> lock(mutex_);
131     info_.callback = nullptr;
132 }
133 
StartSchedule()134 bool ScheduleNodeImpl::StartSchedule()
135 {
136     iamHitraceHelper_ = Common::MakeShared<IamHitraceHelper>(GetDescription());
137     {
138         std::lock_guard<std::mutex> lock(mutex_);
139         if (!TryKickMachine(E_START_AUTH)) {
140             return false;
141         }
142     }
143     StartTimer();
144     return true;
145 }
146 
StopSchedule()147 bool ScheduleNodeImpl::StopSchedule()
148 {
149     std::lock_guard<std::mutex> lock(mutex_);
150 
151     SetFwkResultCode(CANCELED);
152     return TryKickMachine(E_STOP_AUTH);
153 }
154 
ContinueSchedule(ExecutorRole srcRole,ExecutorRole dstRole,uint64_t transNum,const std::vector<uint8_t> & msg)155 bool ScheduleNodeImpl::ContinueSchedule(ExecutorRole srcRole, ExecutorRole dstRole, uint64_t transNum,
156     const std::vector<uint8_t> &msg)
157 {
158     if (dstRole != SCHEDULER) {
159         IAM_LOGE("not supported yet");
160         return false;
161     }
162 
163     std::shared_ptr<ScheduleNodeCallback> callback = GetScheduleCallback();
164     if (callback) {
165         callback->OnScheduleProcessed(srcRole, GetAuthType(), msg);
166     }
167 
168     return true;
169 }
170 
ContinueSchedule(ResultCode resultCode,const std::shared_ptr<Attributes> & finalResult)171 bool ScheduleNodeImpl::ContinueSchedule(ResultCode resultCode, const std::shared_ptr<Attributes> &finalResult)
172 {
173     std::lock_guard<std::mutex> lock(mutex_);
174     SetExecutorResultCode(resultCode);
175     SetScheduleResult(finalResult);
176     return TryKickMachine(E_SCHEDULE_RESULT_RECEIVED);
177 }
178 
MakeFiniteStateMachine()179 std::shared_ptr<FiniteStateMachine> ScheduleNodeImpl::MakeFiniteStateMachine()
180 {
181     auto builder = FiniteStateMachine::Builder::New(GetDescription(), S_INIT);
182     if (builder == nullptr) {
183         return nullptr;
184     }
185     // S_INIT
186     builder->MakeTransition(S_INIT, E_START_AUTH, S_VERIFY_STARING,
187         [this](FiniteStateMachine &machine, uint32_t event) { ProcessBeginVerifier(machine, event); });
188 
189     // S_VERIFY_STARING
190     builder->MakeTransition(S_VERIFY_STARING, E_VERIFY_STARTED_SUCCESS, S_COLLECT_STARING,
191         [this](FiniteStateMachine &machine, uint32_t event) { ProcessBeginCollector(machine, event); });
192     builder->MakeTransition(S_VERIFY_STARING, E_VERIFY_STARTED_FAILED, S_END,
193         [this](FiniteStateMachine &machine, uint32_t event) { ProcessVerifierBeginFailed(machine, event); });
194     builder->MakeTransition(S_VERIFY_STARING, E_SCHEDULE_RESULT_RECEIVED, S_END);
195     builder->MakeTransition(S_VERIFY_STARING, E_STOP_AUTH, S_VERIFY_STOPPING,
196         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndVerifier(machine, event); });
197     builder->MakeTransition(S_VERIFY_STARING, E_TIME_OUT, S_VERIFY_STOPPING,
198         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndVerifier(machine, event); });
199 
200     // S_COLLECT_STARING
201     builder->MakeTransition(S_COLLECT_STARING, E_COLLECT_STARTED_SUCCESS, S_AUTH_PROCESSING);
202     builder->MakeTransition(S_COLLECT_STARING, E_SCHEDULE_RESULT_RECEIVED, S_END);
203     builder->MakeTransition(S_COLLECT_STARING, E_STOP_AUTH, S_COLLECT_STOPPING,
204         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndCollector(machine, event); });
205 
206     // S_AUTH_PROCESSING
207     builder->MakeTransition(S_AUTH_PROCESSING, E_SCHEDULE_RESULT_RECEIVED, S_END);
208     builder->MakeTransition(S_AUTH_PROCESSING, E_STOP_AUTH, S_COLLECT_STOPPING,
209         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndCollector(machine, event); });
210     builder->MakeTransition(S_AUTH_PROCESSING, E_TIME_OUT, S_COLLECT_STOPPING,
211         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndCollector(machine, event); });
212 
213     // S_COLLECT_STOPPING
214     builder->MakeTransition(S_COLLECT_STOPPING, E_SCHEDULE_RESULT_RECEIVED, S_END);
215     builder->MakeTransition(S_COLLECT_STOPPING, E_COLLECT_STOPPED_SUCCESS, S_VERIFY_STOPPING,
216         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndVerifier(machine, event); });
217     builder->MakeTransition(S_COLLECT_STOPPING, E_COLLECT_STOPPED_FAILED, S_VERIFY_STOPPING,
218         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndVerifier(machine, event); });
219     builder->MakeTransition(S_COLLECT_STOPPING, E_TIME_OUT, S_VERIFY_STOPPING,
220         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndVerifier(machine, event); });
221 
222     // S_VERIFY_STOPPING
223     builder->MakeTransition(S_VERIFY_STOPPING, E_SCHEDULE_RESULT_RECEIVED, S_END);
224     builder->MakeTransition(S_VERIFY_STOPPING, E_VERIFY_STOPPED_SUCCESS, S_END);
225     builder->MakeTransition(S_VERIFY_STOPPING, E_VERIFY_STOPPED_FAILED, S_END);
226     builder->MakeTransition(S_VERIFY_STOPPING, E_TIME_OUT, S_END);
227 
228     // ENTERS
229     builder->MakeOnStateEnter(S_AUTH_PROCESSING,
230         [this](FiniteStateMachine &machine, uint32_t event) { OnScheduleProcessing(machine, event); });
231     builder->MakeOnStateEnter(S_END,
232         [this](FiniteStateMachine &machine, uint32_t event) { OnScheduleFinished(machine, event); });
233     return builder->Build();
234 }
235 
GetDescription() const236 std::string ScheduleNodeImpl::GetDescription() const
237 {
238     std::ostringstream ss;
239 
240     auto verifier = info_.verifier.lock();
241     ss << "schedule type:" << (verifier ? Common::AuthTypeToStr(verifier->GetAuthType()) : "nullptr") <<
242         " id:******" << std::hex << static_cast<uint16_t>(GetScheduleId());
243     return ss.str();
244 }
245 
TryKickMachine(Event event)246 bool ScheduleNodeImpl::TryKickMachine(Event event)
247 {
248     if (machine_ == nullptr) {
249         return false;
250     }
251     machine_->Schedule(event);
252     return true;
253 }
254 
SetFwkResultCode(int32_t resultCode)255 void ScheduleNodeImpl::SetFwkResultCode(int32_t resultCode)
256 {
257     fwkResultCode_ = resultCode;
258 }
259 
SetExecutorResultCode(int32_t resultCode)260 void ScheduleNodeImpl::SetExecutorResultCode(int32_t resultCode)
261 {
262     executorResultCode_ = resultCode;
263 }
264 
SetScheduleResult(const std::shared_ptr<Attributes> & scheduleResult)265 void ScheduleNodeImpl::SetScheduleResult(const std::shared_ptr<Attributes> &scheduleResult)
266 {
267     scheduleResult_ = scheduleResult;
268 }
269 
StartTimer()270 void ScheduleNodeImpl::StartTimer()
271 {
272     std::lock_guard<std::mutex> lock(mutex_);
273     if (info_.expiredTime == 0 || timerId_ != 0) {
274         return;
275     }
276 
277     timerId_ = RelativeTimer::GetInstance().Register(
278         [self = weak_from_this(), this] {
279             if (self.lock()) {
280                 std::lock_guard<std::mutex> lock(mutex_);
281                 SetFwkResultCode(TIMEOUT);
282                 TryKickMachine(E_TIME_OUT);
283             }
284         },
285         info_.expiredTime);
286 }
287 
StopTimer()288 void ScheduleNodeImpl::StopTimer()
289 {
290     std::lock_guard<std::mutex> lock(mutex_);
291     if (timerId_ == 0) {
292         return;
293     }
294     RelativeTimer::GetInstance().Unregister(timerId_);
295     timerId_ = 0;
296 }
297 
ProcessBeginVerifier(FiniteStateMachine & machine,uint32_t event)298 void ScheduleNodeImpl::ProcessBeginVerifier(FiniteStateMachine &machine, uint32_t event)
299 {
300     auto collector = info_.collector.lock();
301     auto verifier = info_.verifier.lock();
302     if (collector == nullptr || verifier == nullptr) {
303         SetFwkResultCode(GENERAL_ERROR);
304         machine.Schedule(E_VERIFY_STARTED_FAILED);
305         IAM_LOGE("invalid resource");
306         return;
307     }
308     auto peerPk = collector->GetExecutorPublicKey();
309 
310     auto result = verifier->BeginExecute(info_.scheduleId, peerPk, *info_.parameters);
311     if (result != SUCCESS) {
312         IAM_LOGE("start verify failed, result = %{public}d", result);
313         SetExecutorResultCode(result);
314         machine.Schedule(E_VERIFY_STARTED_FAILED);
315         return;
316     }
317     IAM_LOGI("start verify success");
318     machine.Schedule(E_VERIFY_STARTED_SUCCESS);
319 }
320 
ProcessBeginCollector(FiniteStateMachine & machine,uint32_t event)321 void ScheduleNodeImpl::ProcessBeginCollector(FiniteStateMachine &machine, uint32_t event)
322 {
323     auto collector = info_.collector.lock();
324     auto verifier = info_.verifier.lock();
325     if (collector == nullptr || verifier == nullptr) {
326         SetFwkResultCode(GENERAL_ERROR);
327         machine.Schedule(E_COLLECT_STARTED_FAILED);
328         IAM_LOGE("invalid resource");
329         return;
330     }
331     if (collector == verifier) {
332         IAM_LOGI("all in one schedule, just wait the result");
333         machine.Schedule(E_COLLECT_STARTED_SUCCESS);
334         return;
335     }
336     IAM_LOGE("distributed auth not supported yet");
337 }
338 
ProcessVerifierBeginFailed(FiniteStateMachine & machine,uint32_t event)339 void ScheduleNodeImpl::ProcessVerifierBeginFailed(FiniteStateMachine &machine, uint32_t event)
340 {
341     // just do nothing
342 }
343 
ProcessCollectorBeginFailed(FiniteStateMachine & machine,uint32_t event)344 void ScheduleNodeImpl::ProcessCollectorBeginFailed(FiniteStateMachine &machine, uint32_t event)
345 {
346     // just do nothing
347 }
348 
ProcessScheduleResultReceived(FiniteStateMachine & machine,uint32_t event) const349 void ScheduleNodeImpl::ProcessScheduleResultReceived(FiniteStateMachine &machine, uint32_t event) const
350 {
351     // just do nothing
352 }
353 
ProcessEndCollector(FiniteStateMachine & machine,uint32_t event)354 void ScheduleNodeImpl::ProcessEndCollector(FiniteStateMachine &machine, uint32_t event)
355 {
356     auto collector = info_.collector.lock();
357     auto verifier = info_.verifier.lock();
358     if (collector == nullptr || verifier == nullptr) {
359         SetFwkResultCode(GENERAL_ERROR);
360         machine.Schedule(E_COLLECT_STOPPED_FAILED);
361         return;
362     }
363     if (collector == verifier) {
364         IAM_LOGE("all in one schedule, just do noting");
365         machine.Schedule(E_COLLECT_STOPPED_SUCCESS);
366         return;
367     }
368     IAM_LOGE("distributed auth not supported yet");
369 }
370 
ProcessEndVerifier(FiniteStateMachine & machine,uint32_t event)371 void ScheduleNodeImpl::ProcessEndVerifier(FiniteStateMachine &machine, uint32_t event)
372 {
373     auto verifier = info_.verifier.lock();
374     if (verifier == nullptr) {
375         SetFwkResultCode(GENERAL_ERROR);
376         machine.Schedule(E_VERIFY_STOPPED_FAILED);
377         return;
378     }
379     Attributes attr;
380     auto result = verifier->EndExecute(info_.scheduleId, attr);
381     if (result != SUCCESS) {
382         IAM_LOGE("end verify failed, result = %{public}d", result);
383         SetExecutorResultCode(result);
384         machine.Schedule(E_VERIFY_STOPPED_FAILED);
385         return;
386     }
387     machine.Schedule(E_VERIFY_STOPPED_SUCCESS);
388 }
389 
OnScheduleProcessing(FiniteStateMachine & machine,uint32_t event)390 void ScheduleNodeImpl::OnScheduleProcessing(FiniteStateMachine &machine, uint32_t event)
391 {
392     std::shared_ptr<ScheduleNodeCallback> callback = GetScheduleCallback();
393     if (!callback) {
394         return;
395     }
396     callback->OnScheduleStarted();
397 }
398 
OnScheduleFinished(FiniteStateMachine & machine,uint32_t event)399 void ScheduleNodeImpl::OnScheduleFinished(FiniteStateMachine &machine, uint32_t event)
400 {
401     StopTimer();
402     std::shared_ptr<ScheduleNodeCallback> callback = GetScheduleCallback();
403     if (!callback) {
404         return;
405     }
406 
407     iamHitraceHelper_ = nullptr;
408 
409     int32_t result = fwkResultCode_.value_or(executorResultCode_);
410     IAM_LOGI("schedule result = %{public}d", result);
411     callback->OnScheduleStoped(result, scheduleResult_);
412     ClearScheduleCallback();
413 }
414 } // namespace UserAuth
415 } // namespace UserIam
416 } // namespace OHOS
417