• 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     if (info_.templateIdList.empty()) {
59         return;
60     }
61     info_.parameters->SetUint64ArrayValue(Attributes::ATTR_TEMPLATE_ID_LIST, info_.templateIdList);
62     if (info_.templateIdList.size() == 1) {
63         info_.parameters->SetUint64Value(Attributes::ATTR_TEMPLATE_ID, *info_.templateIdList.begin());
64     }
65 }
66 
GetScheduleId() const67 uint64_t ScheduleNodeImpl::GetScheduleId() const
68 {
69     return info_.scheduleId;
70 }
71 
GetContextId() const72 uint64_t ScheduleNodeImpl::GetContextId() const
73 {
74     return info_.contextId;
75 }
76 
GetAuthType() const77 AuthType ScheduleNodeImpl::GetAuthType() const
78 {
79     return info_.authType;
80 }
81 
GetExecutorMatcher() const82 uint64_t ScheduleNodeImpl::GetExecutorMatcher() const
83 {
84     return info_.executorMatcher;
85 }
86 
GetScheduleMode() const87 ScheduleMode ScheduleNodeImpl::GetScheduleMode() const
88 {
89     return info_.scheduleMode;
90 }
91 
GetCollectorExecutor() const92 std::weak_ptr<ResourceNode> ScheduleNodeImpl::GetCollectorExecutor() const
93 {
94     return info_.collector;
95 }
96 
GetVerifyExecutor() const97 std::weak_ptr<ResourceNode> ScheduleNodeImpl::GetVerifyExecutor() const
98 {
99     return info_.verifier;
100 }
101 
GetTemplateIdList() const102 std::optional<std::vector<uint64_t>> ScheduleNodeImpl::GetTemplateIdList() const
103 {
104     if (info_.templateIdList.empty()) {
105         return std::nullopt;
106     }
107     return info_.templateIdList;
108 }
109 
GetCurrentScheduleState() const110 ScheduleNode::State ScheduleNodeImpl::GetCurrentScheduleState() const
111 {
112     if (machine_ == nullptr) {
113         return S_INIT;
114     }
115     return static_cast<State>(machine_->GetCurrentState());
116 }
117 
StartSchedule()118 bool ScheduleNodeImpl::StartSchedule()
119 {
120     iamHitraceHelper_ = Common::MakeShared<IamHitraceHelper>(GetDescription());
121     {
122         std::lock_guard<std::mutex> lock(mutex_);
123         if (!TryKickMachine(E_START_AUTH)) {
124             return false;
125         }
126     }
127     StartTimer();
128     return true;
129 }
130 
StopSchedule()131 bool ScheduleNodeImpl::StopSchedule()
132 {
133     std::lock_guard<std::mutex> lock(mutex_);
134 
135     SetFwkResultCode(CANCELED);
136     return TryKickMachine(E_STOP_AUTH);
137 }
138 
ContinueSchedule(ExecutorRole srcRole,ExecutorRole dstRole,uint64_t transNum,const std::vector<uint8_t> & msg)139 bool ScheduleNodeImpl::ContinueSchedule(ExecutorRole srcRole, ExecutorRole dstRole, uint64_t transNum,
140     const std::vector<uint8_t> &msg)
141 {
142     if (dstRole != SCHEDULER) {
143         IAM_LOGE("not supported yet");
144         return false;
145     }
146 
147     if (info_.callback) {
148         info_.callback->OnScheduleProcessed(srcRole, GetAuthType(), msg);
149     }
150 
151     return true;
152 }
153 
ContinueSchedule(ResultCode resultCode,const std::shared_ptr<Attributes> & finalResult)154 bool ScheduleNodeImpl::ContinueSchedule(ResultCode resultCode, const std::shared_ptr<Attributes> &finalResult)
155 {
156     std::lock_guard<std::mutex> lock(mutex_);
157     SetExecutorResultCode(resultCode);
158     SetScheduleResult(finalResult);
159     return TryKickMachine(E_SCHEDULE_RESULT_RECEIVED);
160 }
161 
MakeFiniteStateMachine()162 std::shared_ptr<FiniteStateMachine> ScheduleNodeImpl::MakeFiniteStateMachine()
163 {
164     auto builder = FiniteStateMachine::Builder::New(GetDescription(), S_INIT);
165     if (builder == nullptr) {
166         return nullptr;
167     }
168     // S_INIT
169     builder->MakeTransition(S_INIT, E_START_AUTH, S_VERIFY_STARING,
170         [this](FiniteStateMachine &machine, uint32_t event) { ProcessBeginVerifier(machine, event); });
171 
172     // S_VERIFY_STARING
173     builder->MakeTransition(S_VERIFY_STARING, E_VERIFY_STARTED_SUCCESS, S_COLLECT_STARING,
174         [this](FiniteStateMachine &machine, uint32_t event) { ProcessBeginCollector(machine, event); });
175     builder->MakeTransition(S_VERIFY_STARING, E_VERIFY_STARTED_FAILED, S_END,
176         [this](FiniteStateMachine &machine, uint32_t event) { ProcessVerifierBeginFailed(machine, event); });
177     builder->MakeTransition(S_VERIFY_STARING, E_SCHEDULE_RESULT_RECEIVED, S_END);
178     builder->MakeTransition(S_VERIFY_STARING, E_STOP_AUTH, S_END);
179     builder->MakeTransition(S_VERIFY_STARING, E_TIME_OUT, S_END);
180 
181     // S_COLLECT_STARING
182     builder->MakeTransition(S_COLLECT_STARING, E_COLLECT_STARTED_SUCCESS, S_AUTH_PROCESSING);
183     builder->MakeTransition(S_COLLECT_STARING, E_SCHEDULE_RESULT_RECEIVED, S_END);
184 
185     // S_AUTH_PROCESSING
186     builder->MakeTransition(S_AUTH_PROCESSING, E_SCHEDULE_RESULT_RECEIVED, S_END);
187     builder->MakeTransition(S_AUTH_PROCESSING, E_STOP_AUTH, S_COLLECT_STOPPING,
188         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndCollector(machine, event); });
189     builder->MakeTransition(S_AUTH_PROCESSING, E_TIME_OUT, S_COLLECT_STOPPING,
190         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndCollector(machine, event); });
191 
192     // S_COLLECT_STOPPING
193     builder->MakeTransition(S_COLLECT_STOPPING, E_SCHEDULE_RESULT_RECEIVED, S_END);
194     builder->MakeTransition(S_COLLECT_STOPPING, E_COLLECT_STOPPED_SUCCESS, S_VERIFY_STOPPING,
195         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndVerifier(machine, event); });
196     builder->MakeTransition(S_COLLECT_STOPPING, E_COLLECT_STOPPED_FAILED, S_VERIFY_STOPPING,
197         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndVerifier(machine, event); });
198     builder->MakeTransition(S_COLLECT_STOPPING, E_TIME_OUT, S_VERIFY_STOPPING,
199         [this](FiniteStateMachine &machine, uint32_t event) { ProcessEndVerifier(machine, event); });
200 
201     // S_VERIFY_STOPPING
202     builder->MakeTransition(S_VERIFY_STOPPING, E_SCHEDULE_RESULT_RECEIVED, S_END);
203     builder->MakeTransition(S_VERIFY_STOPPING, E_VERIFY_STOPPED_SUCCESS, S_END);
204     builder->MakeTransition(S_VERIFY_STOPPING, E_VERIFY_STOPPED_FAILED, S_END);
205     builder->MakeTransition(S_VERIFY_STOPPING, E_TIME_OUT, S_END);
206 
207     // ENTERS
208     builder->MakeOnStateEnter(S_AUTH_PROCESSING,
209         [this](FiniteStateMachine &machine, uint32_t event) { OnScheduleProcessing(machine, event); });
210     builder->MakeOnStateEnter(S_END,
211         [this](FiniteStateMachine &machine, uint32_t event) { OnScheduleFinished(machine, event); });
212     return builder->Build();
213 }
214 
GetDescription() const215 std::string ScheduleNodeImpl::GetDescription() const
216 {
217     std::stringstream stream;
218     std::string name;
219 
220     auto verifier = info_.verifier.lock();
221     stream << "schedule type:" << (verifier ? Common::AuthTypeToStr(verifier->GetAuthType()) : "nullptr") <<
222         " id:******" << std::hex << static_cast<uint16_t>(GetScheduleId());
223     stream >> name;
224     return name;
225 }
226 
TryKickMachine(Event event)227 bool ScheduleNodeImpl::TryKickMachine(Event event)
228 {
229     if (machine_ == nullptr) {
230         return false;
231     }
232     machine_->Schedule(event);
233     return true;
234 }
235 
SetFwkResultCode(int32_t resultCode)236 void ScheduleNodeImpl::SetFwkResultCode(int32_t resultCode)
237 {
238     fwkResultCode_ = resultCode;
239 }
240 
SetExecutorResultCode(int32_t resultCode)241 void ScheduleNodeImpl::SetExecutorResultCode(int32_t resultCode)
242 {
243     executorResultCode_ = resultCode;
244 }
245 
SetScheduleResult(const std::shared_ptr<Attributes> & scheduleResult)246 void ScheduleNodeImpl::SetScheduleResult(const std::shared_ptr<Attributes> &scheduleResult)
247 {
248     scheduleResult_ = scheduleResult;
249 }
250 
StartTimer()251 void ScheduleNodeImpl::StartTimer()
252 {
253     std::lock_guard<std::mutex> lock(mutex_);
254     if (info_.expiredTime == 0 || timerId_ != 0) {
255         return;
256     }
257 
258     timerId_ = RelativeTimer::GetInstance().Register(
259         [self = weak_from_this(), this] {
260             if (self.lock()) {
261                 std::lock_guard<std::mutex> lock(mutex_);
262                 SetFwkResultCode(TIMEOUT);
263                 TryKickMachine(E_TIME_OUT);
264             }
265         },
266         info_.expiredTime);
267 }
268 
StopTimer()269 void ScheduleNodeImpl::StopTimer()
270 {
271     std::lock_guard<std::mutex> lock(mutex_);
272     if (timerId_ == 0) {
273         return;
274     }
275     RelativeTimer::GetInstance().Unregister(timerId_);
276     timerId_ = 0;
277 }
278 
ProcessBeginVerifier(FiniteStateMachine & machine,uint32_t event)279 void ScheduleNodeImpl::ProcessBeginVerifier(FiniteStateMachine &machine, uint32_t event)
280 {
281     auto collector = info_.collector.lock();
282     auto verifier = info_.verifier.lock();
283     if (collector == nullptr || verifier == nullptr) {
284         SetFwkResultCode(GENERAL_ERROR);
285         machine.Schedule(E_VERIFY_STARTED_FAILED);
286         IAM_LOGE("invalid resource");
287         return;
288     }
289     auto peerPk = collector->GetExecutorPublicKey();
290 
291     auto result = verifier->BeginExecute(info_.scheduleId, peerPk, *info_.parameters);
292     if (result != SUCCESS) {
293         IAM_LOGE("start verify failed, result = %{public}d", result);
294         SetExecutorResultCode(result);
295         machine.Schedule(E_VERIFY_STARTED_FAILED);
296         return;
297     }
298     IAM_LOGI("start verify success");
299     machine.Schedule(E_VERIFY_STARTED_SUCCESS);
300 }
301 
ProcessBeginCollector(FiniteStateMachine & machine,uint32_t event)302 void ScheduleNodeImpl::ProcessBeginCollector(FiniteStateMachine &machine, uint32_t event)
303 {
304     auto collector = info_.collector.lock();
305     auto verifier = info_.verifier.lock();
306     if (collector == nullptr || verifier == nullptr) {
307         SetFwkResultCode(GENERAL_ERROR);
308         machine.Schedule(E_COLLECT_STARTED_FAILED);
309         IAM_LOGE("invalid resource");
310         return;
311     }
312     if (collector == verifier) {
313         IAM_LOGE("all in one schedule, just wait the result");
314         machine.Schedule(E_COLLECT_STARTED_SUCCESS);
315         return;
316     }
317     IAM_LOGE("distributed auth not supported yet");
318 }
319 
ProcessVerifierBeginFailed(FiniteStateMachine & machine,uint32_t event)320 void ScheduleNodeImpl::ProcessVerifierBeginFailed(FiniteStateMachine &machine, uint32_t event)
321 {
322     // just do nothing
323 }
324 
ProcessCollectorBeginFailed(FiniteStateMachine & machine,uint32_t event)325 void ScheduleNodeImpl::ProcessCollectorBeginFailed(FiniteStateMachine &machine, uint32_t event)
326 {
327     // just do nothing
328 }
329 
ProcessScheduleResultReceived(FiniteStateMachine & machine,uint32_t event) const330 void ScheduleNodeImpl::ProcessScheduleResultReceived(FiniteStateMachine &machine, uint32_t event) const
331 {
332     // just do nothing
333 }
334 
ProcessEndCollector(FiniteStateMachine & machine,uint32_t event)335 void ScheduleNodeImpl::ProcessEndCollector(FiniteStateMachine &machine, uint32_t event)
336 {
337     auto collector = info_.collector.lock();
338     auto verifier = info_.verifier.lock();
339     if (collector == nullptr || verifier == nullptr) {
340         SetFwkResultCode(GENERAL_ERROR);
341         machine.Schedule(E_COLLECT_STOPPED_FAILED);
342         return;
343     }
344     if (collector == verifier) {
345         IAM_LOGE("all in one schedule, just do noting");
346         machine.Schedule(E_COLLECT_STOPPED_SUCCESS);
347         return;
348     }
349     IAM_LOGE("distributed auth not supported yet");
350 }
351 
ProcessEndVerifier(FiniteStateMachine & machine,uint32_t event)352 void ScheduleNodeImpl::ProcessEndVerifier(FiniteStateMachine &machine, uint32_t event)
353 {
354     auto verifier = info_.verifier.lock();
355     if (verifier == nullptr) {
356         SetFwkResultCode(GENERAL_ERROR);
357         machine.Schedule(E_VERIFY_STOPPED_FAILED);
358         return;
359     }
360     Attributes attr;
361     auto result = verifier->EndExecute(info_.scheduleId, attr);
362     if (result != SUCCESS) {
363         IAM_LOGE("end verify failed, result = %{public}d", result);
364         SetExecutorResultCode(result);
365         machine.Schedule(E_VERIFY_STOPPED_FAILED);
366         return;
367     }
368     machine.Schedule(E_VERIFY_STOPPED_SUCCESS);
369 }
370 
OnScheduleProcessing(FiniteStateMachine & machine,uint32_t event) const371 void ScheduleNodeImpl::OnScheduleProcessing(FiniteStateMachine &machine, uint32_t event) const
372 {
373     if (!info_.callback) {
374         return;
375     }
376     info_.callback->OnScheduleStarted();
377 }
378 
OnScheduleFinished(FiniteStateMachine & machine,uint32_t event)379 void ScheduleNodeImpl::OnScheduleFinished(FiniteStateMachine &machine, uint32_t event)
380 {
381     StopTimer();
382     if (!info_.callback) {
383         return;
384     }
385 
386     iamHitraceHelper_ = nullptr;
387 
388     int32_t result = fwkResultCode_.value_or(executorResultCode_);
389     IAM_LOGI("schedule result = %{public}d", result);
390     info_.callback->OnScheduleStoped(result, scheduleResult_);
391     info_.callback = nullptr;
392 }
393 } // namespace UserAuth
394 } // namespace UserIam
395 } // namespace OHOS
396