1 /*
2  * Copyright (c) 2022-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 "pin_auth_all_in_one_hdi.h"
17 
18 #include <map>
19 
20 #include "hdf_base.h"
21 
22 #include "iam_check.h"
23 #include "iam_defines.h"
24 #include "iam_logger.h"
25 #include "pin_auth_executor_callback_hdi.h"
26 #include "pin_auth_executor_hdi_common.h"
27 
28 #define LOG_TAG "PIN_AUTH_SA"
29 
30 namespace OHOS {
31 namespace UserIam {
32 namespace PinAuth {
PinAuthAllInOneHdi(const sptr<IAllInOneExecutor> & allInOneProxy)33 PinAuthAllInOneHdi::PinAuthAllInOneHdi(const sptr<IAllInOneExecutor> &allInOneProxy)
34     : allInOneProxy_(allInOneProxy)
35 {
36 }
37 
GetExecutorInfo(UserAuth::ExecutorInfo & info)38 UserAuth::ResultCode PinAuthAllInOneHdi::GetExecutorInfo(UserAuth::ExecutorInfo &info)
39 {
40     if (allInOneProxy_ == nullptr) {
41         IAM_LOGE("allInOneProxy is null");
42         return UserAuth::ResultCode::GENERAL_ERROR;
43     }
44 
45     ExecutorInfo localInfo = { };
46     int32_t status = allInOneProxy_->GetExecutorInfo(localInfo);
47     UserAuth::ResultCode result = ConvertHdiResultCode(status);
48     if (result != UserAuth::ResultCode::SUCCESS) {
49         IAM_LOGE("GetExecutorInfo fail ret=%{public}d", result);
50         return result;
51     }
52     SetAuthType(localInfo.authType);
53     int32_t ret = MoveHdiExecutorInfo(localInfo, info);
54     if (ret != UserAuth::ResultCode::SUCCESS) {
55         IAM_LOGE("MoveHdiExecutorInfo fail ret=%{public}d", ret);
56         return UserAuth::ResultCode::GENERAL_ERROR;
57     }
58     return UserAuth::ResultCode::SUCCESS;
59 }
60 
OnRegisterFinish(const std::vector<uint64_t> & templateIdList,const std::vector<uint8_t> & frameworkPublicKey,const std::vector<uint8_t> & extraInfo)61 UserAuth::ResultCode PinAuthAllInOneHdi::OnRegisterFinish(const std::vector<uint64_t> &templateIdList,
62     const std::vector<uint8_t> &frameworkPublicKey, const std::vector<uint8_t> &extraInfo)
63 {
64     if (allInOneProxy_ == nullptr) {
65         IAM_LOGE("allInOneProxy is null");
66         return UserAuth::ResultCode::GENERAL_ERROR;
67     }
68     int32_t status = allInOneProxy_->OnRegisterFinish(templateIdList, frameworkPublicKey, extraInfo);
69     UserAuth::ResultCode result = ConvertHdiResultCode(status);
70     if (result != UserAuth::ResultCode::SUCCESS) {
71         IAM_LOGE("OnRegisterFinish fail result %{public}d", result);
72         return result;
73     }
74 
75     return UserAuth::ResultCode::SUCCESS;
76 }
77 
SendMessage(uint64_t scheduleId,int32_t srcRole,const std::vector<uint8_t> & msg)78 UserAuth::ResultCode PinAuthAllInOneHdi::SendMessage(
79     uint64_t scheduleId, int32_t srcRole, const std::vector<uint8_t> &msg)
80 {
81     if (allInOneProxy_ == nullptr) {
82         IAM_LOGE("allInOneProxy is null");
83         return UserAuth::ResultCode::GENERAL_ERROR;
84     }
85     int32_t status = allInOneProxy_->SendMessage(scheduleId, srcRole, msg);
86     UserAuth::ResultCode result = ConvertHdiResultCode(status);
87     if (result != UserAuth::ResultCode::SUCCESS) {
88         IAM_LOGE("SendMessage fail result %{public}d", result);
89         return result;
90     }
91     return UserAuth::ResultCode::SUCCESS;
92 }
93 
OnSetData(uint64_t scheduleId,uint64_t authSubType,const std::vector<uint8_t> & data,int32_t errorCode)94 UserAuth::ResultCode PinAuthAllInOneHdi::OnSetData(uint64_t scheduleId, uint64_t authSubType,
95     const std::vector<uint8_t> &data, int32_t errorCode)
96 {
97     if (allInOneProxy_ == nullptr) {
98         IAM_LOGE("allInOneProxy is null");
99         return UserAuth::ResultCode::GENERAL_ERROR;
100     }
101     int32_t status = allInOneProxy_->SetData(scheduleId, authSubType, data, errorCode);
102     UserAuth::ResultCode result = ConvertHdiResultCode(status);
103     if (result != UserAuth::ResultCode::SUCCESS) {
104         IAM_LOGE("OnSetData fail ret=%{public}d", result);
105         return result;
106     }
107     return UserAuth::ResultCode::SUCCESS;
108 }
109 
Enroll(uint64_t scheduleId,const UserAuth::EnrollParam & param,const std::shared_ptr<UserAuth::IExecuteCallback> & callbackObj)110 UserAuth::ResultCode PinAuthAllInOneHdi::Enroll(uint64_t scheduleId, const UserAuth::EnrollParam &param,
111     const std::shared_ptr<UserAuth::IExecuteCallback> &callbackObj)
112 {
113     if (allInOneProxy_ == nullptr) {
114         IAM_LOGE("allInOneProxy is null");
115         return UserAuth::ResultCode::GENERAL_ERROR;
116     }
117     if (callbackObj == nullptr) {
118         IAM_LOGE("callbackObj is null");
119         return UserAuth::ResultCode::GENERAL_ERROR;
120     }
121     if (!GetAuthType().has_value()) {
122         IAM_LOGE("authType is error");
123         return UserAuth::ResultCode::GENERAL_ERROR;
124     }
125     GetDataMode mode = GET_DATA_MODE_NONE;
126     if (GetAuthType().value() == AuthType::PIN) {
127         mode = GET_DATA_MODE_ALL_IN_ONE_PIN_ENROLL;
128     } else {
129         mode = GET_DATA_MODE_ALL_IN_ONE_PRIVATE_PIN_ENROLL;
130     }
131     UserAuth::ExecutorParam executorParam = {
132         .tokenId = param.tokenId,
133         .scheduleId = scheduleId,
134         .userId = param.userId,
135     };
136     auto callback = sptr<IExecutorCallback>(new (std::nothrow) PinAuthExecutorCallbackHdi(callbackObj,
137         shared_from_this(), executorParam, mode));
138     if (callback == nullptr) {
139         IAM_LOGE("callback is null");
140         return UserAuth::ResultCode::GENERAL_ERROR;
141     }
142     int32_t status = allInOneProxy_->Enroll(scheduleId, param.extraInfo, callback);
143     UserAuth::ResultCode result = ConvertHdiResultCode(status);
144     if (result != UserAuth::ResultCode::SUCCESS) {
145         IAM_LOGE("Enroll fail ret=%{public}d", result);
146         return result;
147     }
148     return UserAuth::ResultCode::SUCCESS;
149 }
150 
Authenticate(uint64_t scheduleId,const UserAuth::AuthenticateParam & param,const std::shared_ptr<UserAuth::IExecuteCallback> & callbackObj)151 UserAuth::ResultCode PinAuthAllInOneHdi::Authenticate(
152     uint64_t scheduleId, const UserAuth::AuthenticateParam &param,
153     const std::shared_ptr<UserAuth::IExecuteCallback> &callbackObj)
154 {
155     if (allInOneProxy_ == nullptr) {
156         IAM_LOGE("allInOneProxy is null");
157         return UserAuth::ResultCode::GENERAL_ERROR;
158     }
159     if (callbackObj == nullptr) {
160         IAM_LOGE("callbackObj is null");
161         return UserAuth::ResultCode::GENERAL_ERROR;
162     }
163     if (!GetAuthType().has_value()) {
164         IAM_LOGE("authType is error");
165         return UserAuth::ResultCode::GENERAL_ERROR;
166     }
167     GetDataMode mode = GET_DATA_MODE_NONE;
168     if (GetAuthType().value() == AuthType::PIN) {
169         mode = GET_DATA_MODE_ALL_IN_ONE_PIN_AUTH;
170     } else {
171         mode = GET_DATA_MODE_ALL_IN_ONE_PRIVATE_PIN_AUTH;
172     }
173     UserAuth::ExecutorParam executorParam = {
174         .tokenId = param.tokenId,
175         .authIntent = param.authIntent,
176         .scheduleId = scheduleId,
177         .userId = param.userId,
178     };
179     auto callback = sptr<IExecutorCallback>(new (std::nothrow) PinAuthExecutorCallbackHdi(callbackObj,
180             shared_from_this(), executorParam, mode));
181     if (callback == nullptr) {
182         IAM_LOGE("callback is null");
183         return UserAuth::ResultCode::GENERAL_ERROR;
184     }
185     if (param.templateIdList.size() == 0) {
186         IAM_LOGE("Error param");
187         return UserAuth::ResultCode::GENERAL_ERROR;
188     }
189     int32_t status = allInOneProxy_->Authenticate(scheduleId, param.templateIdList,
190         param.extraInfo, callback);
191     UserAuth::ResultCode result = ConvertHdiResultCode(status);
192     if (result != UserAuth::ResultCode::SUCCESS) {
193         IAM_LOGE("Authenticate fail ret=%{public}d", result);
194         return result;
195     }
196     return UserAuth::ResultCode::SUCCESS;
197 }
198 
Delete(const std::vector<uint64_t> & templateIdList)199 UserAuth::ResultCode PinAuthAllInOneHdi::Delete(const std::vector<uint64_t> &templateIdList)
200 {
201     if (allInOneProxy_ == nullptr) {
202         IAM_LOGE("allInOneProxy is null");
203         return UserAuth::ResultCode::GENERAL_ERROR;
204     }
205     if (templateIdList.empty()) {
206         IAM_LOGE("templateIdList is empty");
207         return UserAuth::ResultCode::GENERAL_ERROR;
208     }
209     int32_t status = allInOneProxy_->Delete(templateIdList[0]);
210     UserAuth::ResultCode result = ConvertHdiResultCode(status);
211     if (result != UserAuth::ResultCode::SUCCESS) {
212         IAM_LOGE("Delete fail ret=%{public}d", result);
213         return result;
214     }
215     return UserAuth::ResultCode::SUCCESS;
216 }
217 
Cancel(uint64_t scheduleId)218 UserAuth::ResultCode PinAuthAllInOneHdi::Cancel(uint64_t scheduleId)
219 {
220     if (allInOneProxy_ == nullptr) {
221         IAM_LOGE("allInOneProxy is null");
222         return UserAuth::ResultCode::GENERAL_ERROR;
223     }
224     int32_t status = allInOneProxy_->Cancel(scheduleId);
225     UserAuth::ResultCode result = ConvertHdiResultCode(status);
226     if (result != UserAuth::ResultCode::SUCCESS) {
227         IAM_LOGE("Cancel fail ret=%{public}d", result);
228         return result;
229     }
230     return UserAuth::ResultCode::SUCCESS;
231 }
232 
GetProperty(const std::vector<uint64_t> & templateIdList,const std::vector<UserAuth::Attributes::AttributeKey> & keys,UserAuth::Property & property)233 UserAuth::ResultCode PinAuthAllInOneHdi::GetProperty(const std::vector<uint64_t> &templateIdList,
234     const std::vector<UserAuth::Attributes::AttributeKey> &keys, UserAuth::Property &property)
235 {
236     IF_FALSE_LOGE_AND_RETURN_VAL(allInOneProxy_ != nullptr, UserAuth::ResultCode::GENERAL_ERROR);
237 
238     std::vector<int32_t> propertyTypes;
239     UserAuth::ResultCode result = ConvertAttributeKeyVectorToPropertyType(keys, propertyTypes);
240     IF_FALSE_LOGE_AND_RETURN_VAL(result == UserAuth::ResultCode::SUCCESS, UserAuth::ResultCode::GENERAL_ERROR);
241 
242     Property hdiProperty;
243     int32_t status = allInOneProxy_->GetProperty(templateIdList, propertyTypes, hdiProperty);
244     result = ConvertHdiResultCode(status);
245     if (result != UserAuth::ResultCode::SUCCESS) {
246         IAM_LOGE("SendCommand fail result %{public}d", result);
247         return result;
248     }
249     MoveHdiProperty(hdiProperty, property);
250     return UserAuth::ResultCode::SUCCESS;
251 }
252 
MoveHdiProperty(Property & in,UserAuth::Property & out)253 void PinAuthAllInOneHdi::MoveHdiProperty(Property &in, UserAuth::Property &out)
254 {
255     out.authSubType = in.authSubType;
256     out.lockoutDuration = in.lockoutDuration;
257     out.remainAttempts = in.remainAttempts;
258     out.nextFailLockoutDuration = in.nextFailLockoutDuration;
259 }
260 
ConvertAttributeKeyVectorToPropertyType(const std::vector<UserAuth::Attributes::AttributeKey> inItems,std::vector<int32_t> & outItems)261 UserAuth::ResultCode PinAuthAllInOneHdi::ConvertAttributeKeyVectorToPropertyType(
262     const std::vector<UserAuth::Attributes::AttributeKey> inItems, std::vector<int32_t> &outItems)
263 {
264     outItems.clear();
265     for (auto &inItem : inItems) {
266         if (inItem == UserAuth::Attributes::ATTR_ENROLL_PROGRESS ||
267             inItem == UserAuth::Attributes::ATTR_SENSOR_INFO) {
268             continue;
269         }
270         int32_t outItem;
271         UserAuth::ResultCode result = ConvertAttributeKeyToPropertyType(inItem, outItem);
272         IF_FALSE_LOGE_AND_RETURN_VAL(result == UserAuth::ResultCode::SUCCESS, UserAuth::ResultCode::GENERAL_ERROR);
273         outItems.push_back(outItem);
274     }
275 
276     return UserAuth::ResultCode::SUCCESS;
277 }
278 
ConvertAttributeKeyToPropertyType(const UserAuth::Attributes::AttributeKey in,int32_t & out)279 UserAuth::ResultCode PinAuthAllInOneHdi::ConvertAttributeKeyToPropertyType(const UserAuth::Attributes::AttributeKey in,
280     int32_t &out)
281 {
282     static const std::map<UserAuth::Attributes::AttributeKey, GetPropertyType> data = {
283         { UserAuth::Attributes::ATTR_PIN_SUB_TYPE, GetPropertyType::AUTH_SUB_TYPE },
284         { UserAuth::Attributes::ATTR_FREEZING_TIME, GetPropertyType::LOCKOUT_DURATION },
285         { UserAuth::Attributes::ATTR_REMAIN_TIMES, GetPropertyType::REMAIN_ATTEMPTS },
286         { UserAuth::Attributes::ATTR_NEXT_FAIL_LOCKOUT_DURATION, GetPropertyType::NEXT_FAIL_LOCKOUT_DURATION },
287     };
288 
289     auto iter = data.find(in);
290     if (iter == data.end()) {
291         IAM_LOGE("attribute %{public}d is invalid", in);
292         return UserAuth::ResultCode::GENERAL_ERROR;
293     } else {
294         out = static_cast<int32_t>(iter->second);
295     }
296     IAM_LOGI("covert hdi result code %{public}d to framework result code %{public}d", in, out);
297     return UserAuth::ResultCode::SUCCESS;
298 }
299 
SetAuthType(int32_t authType)300 void PinAuthAllInOneHdi::SetAuthType(int32_t authType)
301 {
302     std::lock_guard<std::mutex> lock(mutex_);
303     switch (authType) {
304         case AuthType::PIN:
305             IAM_LOGI("set authType is pin");
306             authType_ = authType;
307             break;
308         case AuthType::PRIVATE_PIN:
309             IAM_LOGI("set authType is private pin");
310             authType_ = authType;
311             break;
312         default:
313             IAM_LOGE("authType value is error, set failed");
314     }
315 }
316 
GetAuthType()317 std::optional<int32_t> PinAuthAllInOneHdi::GetAuthType()
318 {
319     std::lock_guard<std::mutex> lock(mutex_);
320     if (!authType_.has_value()) {
321         IAM_LOGE("authType_ not assigned a value");
322         return std::nullopt;
323     }
324 
325     return authType_;
326 }
327 
328 } // namespace PinAuth
329 } // namespace UserIam
330 } // namespace OHOS
331