1 /*
2 * Copyright (c) 2022-2023 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 "executor_impl.h"
17 #include <hdf_base.h>
18 #include <openssl/evp.h>
19 #include <openssl/rand.h>
20 #include <securec.h>
21 #include "defines.h"
22 #include "iam_logger.h"
23 #include "parameter.h"
24 #include "sysparam_errno.h"
25
26 #define LOG_LABEL OHOS::UserIam::Common::LABEL_PIN_AUTH_IMPL
27
28 namespace OHOS {
29 namespace HDI {
30 namespace PinAuth {
31 namespace {
32 constexpr uint32_t EXECUTOR_TYPE = 0;
33 constexpr uint32_t ENROLL_PIN = 0;
34 constexpr uint32_t AUTH_PIN = 1;
35 constexpr uint32_t OPENSSL_SUCCESS = 1;
36 constexpr uint32_t GENERAL_ERROR = 2;
37 constexpr uint32_t SUCCESS = 0;
38 } // namespace
39
ExecutorImpl(std::shared_ptr<OHOS::UserIam::PinAuth::PinAuth> pinHdi)40 ExecutorImpl::ExecutorImpl(std::shared_ptr<OHOS::UserIam::PinAuth::PinAuth> pinHdi)
41 : pinHdi_(pinHdi),
42 threadPool_("pin_async")
43 {
44 threadPool_.Start(1);
45 }
46
~ExecutorImpl()47 ExecutorImpl::~ExecutorImpl()
48 {
49 threadPool_.Stop();
50 }
51
GetExecutorInfo(ExecutorInfo & info)52 int32_t ExecutorImpl::GetExecutorInfo(ExecutorInfo &info)
53 {
54 IAM_LOGI("start");
55 if (pinHdi_ == nullptr) {
56 IAM_LOGE("pinHdi_ is nullptr");
57 return HDF_FAILURE;
58 }
59 constexpr unsigned short SENSOR_ID = 1;
60 info.sensorId = SENSOR_ID;
61 info.executorType = EXECUTOR_TYPE;
62 info.executorRole = ExecutorRole::ALL_IN_ONE;
63 info.authType = AuthType::PIN;
64 uint32_t eslRet = 0;
65 int32_t result = pinHdi_->GetExecutorInfo(info.publicKey, eslRet);
66 if (result != SUCCESS) {
67 IAM_LOGE("Get ExecutorInfo failed, fail code : %{public}d", result);
68 return result;
69 }
70 info.esl = static_cast<ExecutorSecureLevel>(eslRet);
71
72 return HDF_SUCCESS;
73 }
74
GetTemplateInfo(uint64_t templateId,TemplateInfo & info)75 int32_t ExecutorImpl::GetTemplateInfo(uint64_t templateId, TemplateInfo &info)
76 {
77 IAM_LOGI("start");
78 if (pinHdi_ == nullptr) {
79 IAM_LOGE("pinHdi_ is nullptr");
80 return HDF_FAILURE;
81 }
82 OHOS::UserIam::PinAuth::PinCredentialInfo infoRet = {};
83 int32_t result = pinHdi_->QueryPinInfo(templateId, infoRet);
84 if (result != SUCCESS) {
85 IAM_LOGE("Get TemplateInfo failed, fail code : %{public}d", result);
86 return result;
87 }
88 /* subType is stored in extraInfo */
89 info.extraInfo.resize(sizeof(infoRet.subType));
90 if (memcpy_s(&(info.extraInfo[0]), sizeof(infoRet.subType), &(infoRet.subType), sizeof(infoRet.subType)) != EOK) {
91 IAM_LOGE("copy subType to extraInfo fail!");
92 return HDF_FAILURE;
93 }
94
95 info.executorType = EXECUTOR_TYPE;
96 info.remainAttempts = infoRet.remainTimes;
97 info.lockoutDuration = infoRet.freezingTime;
98
99 return HDF_SUCCESS;
100 }
101
OnRegisterFinish(const std::vector<uint64_t> & templateIdList,const std::vector<uint8_t> & frameworkPublicKey,const std::vector<uint8_t> & extraInfo)102 int32_t ExecutorImpl::OnRegisterFinish(const std::vector<uint64_t> &templateIdList,
103 const std::vector<uint8_t> &frameworkPublicKey, const std::vector<uint8_t> &extraInfo)
104 {
105 IAM_LOGI("start");
106 static_cast<void>(frameworkPublicKey);
107 static_cast<void>(extraInfo);
108 if (pinHdi_ == nullptr) {
109 IAM_LOGE("pinHdi_ is nullptr");
110 return HDF_FAILURE;
111 }
112 int32_t result = pinHdi_->VerifyTemplateData(templateIdList);
113 if (result != SUCCESS) {
114 IAM_LOGE("Verify templateData failed");
115 return result;
116 }
117
118 return HDF_SUCCESS;
119 }
120
CallError(const sptr<IExecutorCallback> & callbackObj,uint32_t errorCode)121 void ExecutorImpl::CallError(const sptr<IExecutorCallback> &callbackObj, uint32_t errorCode)
122 {
123 IAM_LOGI("start");
124 std::vector<uint8_t> ret(0);
125 if (callbackObj->OnResult(errorCode, ret) != SUCCESS) {
126 IAM_LOGE("callback failed");
127 }
128 }
129
Enroll(uint64_t scheduleId,const std::vector<uint8_t> & extraInfo,const sptr<IExecutorCallback> & callbackObj)130 int32_t ExecutorImpl::Enroll(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo,
131 const sptr<IExecutorCallback> &callbackObj)
132 {
133 IAM_LOGI("start");
134 if (callbackObj == nullptr) {
135 IAM_LOGE("callbackObj is nullptr");
136 return HDF_ERR_INVALID_PARAM;
137 }
138 static_cast<void>(extraInfo);
139 std::vector<uint8_t> salt;
140 if (NewSalt(salt) != HDF_SUCCESS) {
141 IAM_LOGE("new salt failed");
142 CallError(callbackObj, GENERAL_ERROR);
143 return HDF_SUCCESS;
144 }
145 int32_t result = scheduleMap_.AddScheduleInfo(scheduleId, ENROLL_PIN, callbackObj, 0, salt);
146 if (result != HDF_SUCCESS) {
147 IAM_LOGE("Add scheduleInfo failed, fail code : %{public}d", result);
148 CallError(callbackObj, GENERAL_ERROR);
149 return HDF_SUCCESS;
150 }
151 result = callbackObj->OnGetData(scheduleId, salt, 0);
152 if (result != SUCCESS) {
153 IAM_LOGE("Enroll Pin failed, fail code : %{public}d", result);
154 // If the enroll fails, delete scheduleId of scheduleMap
155 if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
156 IAM_LOGI("delete scheduleId failed");
157 }
158 return result;
159 }
160
161 return HDF_SUCCESS;
162 }
163
EnrollV1_1(uint64_t scheduleId,const std::vector<uint8_t> & extraInfo,const sptr<IExecutorCallbackV1_1> & callbackObj)164 int32_t ExecutorImpl::EnrollV1_1(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo,
165 const sptr<IExecutorCallbackV1_1> &callbackObj)
166 {
167 IAM_LOGI("interface mock start");
168 static_cast<void>(scheduleId);
169 static_cast<void>(extraInfo);
170 static_cast<void>(callbackObj);
171
172 return HDF_SUCCESS;
173 }
174
Authenticate(uint64_t scheduleId,uint64_t templateId,const std::vector<uint8_t> & extraInfo,const sptr<IExecutorCallback> & callbackObj)175 int32_t ExecutorImpl::Authenticate(uint64_t scheduleId, uint64_t templateId, const std::vector<uint8_t> &extraInfo,
176 const sptr<IExecutorCallback> &callbackObj)
177 {
178 IAM_LOGI("start");
179 if (callbackObj == nullptr) {
180 IAM_LOGE("callbackObj is nullptr");
181 return HDF_ERR_INVALID_PARAM;
182 }
183 if (pinHdi_ == nullptr) {
184 IAM_LOGE("pinHdi_ is nullptr");
185 CallError(callbackObj, INVALID_PARAMETERS);
186 return HDF_SUCCESS;
187 }
188 static_cast<void>(extraInfo);
189 std::vector<uint8_t> salt;
190 int32_t result = pinHdi_->GetSalt(templateId, salt);
191 if (result != SUCCESS) {
192 IAM_LOGE("get salt failed, fail code : %{public}d", result);
193 CallError(callbackObj, GENERAL_ERROR);
194 return HDF_SUCCESS;
195 }
196 result = scheduleMap_.AddScheduleInfo(scheduleId, AUTH_PIN, callbackObj, templateId, salt);
197 if (result != HDF_SUCCESS) {
198 IAM_LOGE("Add scheduleInfo failed, fail code : %{public}d", result);
199 CallError(callbackObj, GENERAL_ERROR);
200 return HDF_SUCCESS;
201 }
202 OHOS::UserIam::PinAuth::PinCredentialInfo infoRet = {};
203 result = pinHdi_->QueryPinInfo(templateId, infoRet);
204 if (result != SUCCESS) {
205 IAM_LOGE("Get TemplateInfo failed, fail code : %{public}d", result);
206 CallError(callbackObj, result);
207 return HDF_SUCCESS;
208 }
209 if (infoRet.remainTimes == 0 || infoRet.freezingTime > 0) {
210 IAM_LOGE("Pin authentication is now frozen state");
211 CallError(callbackObj, LOCKED);
212 return HDF_SUCCESS;
213 }
214 result = callbackObj->OnGetData(scheduleId, salt, 0);
215 if (result != SUCCESS) {
216 IAM_LOGE("Authenticate Pin failed, fail code : %{public}d", result);
217 // If the authentication fails, delete scheduleId of scheduleMap
218 if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
219 IAM_LOGI("delete scheduleId failed");
220 }
221 return result;
222 }
223
224 return HDF_SUCCESS;
225 }
226
AuthenticateV1_1(uint64_t scheduleId,uint64_t templateId,const std::vector<uint8_t> & extraInfo,const sptr<IExecutorCallbackV1_1> & callbackObj)227 int32_t ExecutorImpl::AuthenticateV1_1(uint64_t scheduleId, uint64_t templateId, const std::vector<uint8_t> &extraInfo,
228 const sptr<IExecutorCallbackV1_1> &callbackObj)
229 {
230 IAM_LOGI("interface mock start");
231 static_cast<void>(scheduleId);
232 static_cast<void>(templateId);
233 static_cast<void>(extraInfo);
234 static_cast<void>(callbackObj);
235
236 return HDF_SUCCESS;
237 }
238
AuthPin(uint64_t scheduleId,uint64_t templateId,const std::vector<uint8_t> & data,std::vector<uint8_t> & resultTlv)239 int32_t ExecutorImpl::AuthPin(uint64_t scheduleId, uint64_t templateId,
240 const std::vector<uint8_t> &data, std::vector<uint8_t> &resultTlv)
241 {
242 int32_t result = pinHdi_->AuthPin(scheduleId, templateId, data, resultTlv);
243 if (result != SUCCESS) {
244 IAM_LOGE("Auth Pin failed, fail code : %{public}d", result);
245 return result;
246 }
247 threadPool_.AddTask([hdi = pinHdi_, id = templateId]() {
248 if (hdi == nullptr) {
249 return;
250 }
251 hdi->WriteAntiBrute(id);
252 });
253 IAM_LOGI("Auth Pin success");
254 return result;
255 }
256
OnSetData(uint64_t scheduleId,uint64_t authSubType,const std::vector<uint8_t> & data)257 int32_t ExecutorImpl::OnSetData(uint64_t scheduleId, uint64_t authSubType, const std::vector<uint8_t> &data)
258 {
259 IAM_LOGI("start");
260 if (pinHdi_ == nullptr) {
261 IAM_LOGE("pinHdi_ is nullptr");
262 return HDF_FAILURE;
263 }
264 std::vector<uint8_t> resultTlv;
265 int32_t result = GENERAL_ERROR;
266 constexpr uint32_t INVALID_ID = 2;
267 uint32_t commandId = INVALID_ID;
268 sptr<IExecutorCallback> callback = nullptr;
269 uint64_t templateId = 0;
270 std::vector<uint8_t> salt(0, 0);
271 if (scheduleMap_.GetScheduleInfo(scheduleId, commandId, callback, templateId, salt) != HDF_SUCCESS) {
272 IAM_LOGE("Get ScheduleInfo failed, fail code : %{public}d", result);
273 return HDF_FAILURE;
274 }
275 switch (commandId) {
276 case ENROLL_PIN:
277 result = pinHdi_->EnrollPin(scheduleId, authSubType, salt, data, resultTlv);
278 if (result != SUCCESS) {
279 IAM_LOGE("Enroll Pin failed, fail code : %{public}d", result);
280 }
281 break;
282 case AUTH_PIN:
283 result = AuthPin(scheduleId, templateId, data, resultTlv);
284 if (result != SUCCESS) {
285 IAM_LOGE("Auth Pin failed, fail code : %{public}d", result);
286 }
287 break;
288 default:
289 IAM_LOGE("Error commandId");
290 }
291
292 if (callback == nullptr || callback->OnResult(result, resultTlv) != SUCCESS) {
293 IAM_LOGE("callbackObj Pin failed");
294 }
295 // Delete scheduleId from the scheduleMap_ when the enroll and authentication are successful
296 if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
297 IAM_LOGI("delete scheduleId failed");
298 }
299
300 return HDF_SUCCESS;
301 }
302
Delete(uint64_t templateId)303 int32_t ExecutorImpl::Delete(uint64_t templateId)
304 {
305 IAM_LOGI("start");
306 if (pinHdi_ == nullptr) {
307 IAM_LOGE("pinHdi_ is nullptr");
308 return HDF_FAILURE;
309 }
310 int32_t result = pinHdi_->DeleteTemplate(templateId);
311 if (result != SUCCESS) {
312 IAM_LOGE("Verify templateData failed, fail code : %{public}d", result);
313 return result;
314 }
315
316 return HDF_SUCCESS;
317 }
318
Cancel(uint64_t scheduleId)319 int32_t ExecutorImpl::Cancel(uint64_t scheduleId)
320 {
321 IAM_LOGI("start");
322 if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
323 IAM_LOGE("scheduleId is not found");
324 return HDF_FAILURE;
325 }
326 return HDF_SUCCESS;
327 }
328
SendCommand(int32_t commandId,const std::vector<uint8_t> & extraInfo,const sptr<IExecutorCallback> & callbackObj)329 int32_t ExecutorImpl::SendCommand(int32_t commandId, const std::vector<uint8_t> &extraInfo,
330 const sptr<IExecutorCallback> &callbackObj)
331 {
332 IAM_LOGI("Extension interface, temporarily useless");
333 static_cast<void>(commandId);
334 static_cast<void>(extraInfo);
335 static_cast<void>(callbackObj);
336 return HDF_SUCCESS;
337 }
338
NewSalt(std::vector<uint8_t> & salt)339 uint32_t ExecutorImpl::NewSalt(std::vector<uint8_t> &salt)
340 {
341 IAM_LOGI("start");
342 constexpr uint32_t DEVICE_UUID_LENGTH = 65;
343 char localDeviceId[DEVICE_UUID_LENGTH] = {0};
344 if (GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH) != EC_SUCCESS) {
345 IAM_LOGE("GetDevUdid failed");
346 return HDF_FAILURE;
347 }
348 constexpr int RANDOM_LENGTH = 32;
349 unsigned char random[RANDOM_LENGTH] = {0};
350 if (RAND_bytes(random, (int)RANDOM_LENGTH) != OPENSSL_SUCCESS) {
351 IAM_LOGE("Generate random number failed");
352 return HDF_FAILURE;
353 }
354 std::vector<uint8_t> sum;
355 for (uint32_t i = 0; i < DEVICE_UUID_LENGTH; i++) {
356 sum.push_back(localDeviceId[i]);
357 }
358 for (uint32_t i = 0; i < RANDOM_LENGTH; i++) {
359 sum.push_back(random[i]);
360 }
361 const EVP_MD *alg = EVP_sha256();
362 if (alg == nullptr) {
363 IAM_LOGE("EVP_sha256 failed");
364 return HDF_FAILURE;
365 }
366 IAM_LOGI("EVP_sha256 success");
367 constexpr uint32_t SHA256_LENGTH = 32;
368 uint8_t result[SHA256_LENGTH] = {0};
369 uint32_t size = 0;
370 if (EVP_Digest(sum.data(), sum.size(), result, &size, alg, NULL) != OPENSSL_SUCCESS) {
371 IAM_LOGE("EVP_Digest failed");
372 return HDF_FAILURE;
373 }
374 for (uint32_t i = 0; i < size; i++) {
375 salt.push_back(result[i]);
376 }
377 IAM_LOGI("result size is : [%{public}u]", size);
378 return HDF_SUCCESS;
379 }
380
AddScheduleInfo(const uint64_t scheduleId,const uint32_t commandId,const sptr<IExecutorCallback> callback,const uint64_t templateId,const std::vector<uint8_t> salt)381 uint32_t ExecutorImpl::ScheduleMap::AddScheduleInfo(const uint64_t scheduleId, const uint32_t commandId,
382 const sptr<IExecutorCallback> callback, const uint64_t templateId, const std::vector<uint8_t> salt)
383 {
384 IAM_LOGI("start");
385 std::lock_guard<std::mutex> guard(mutex_);
386 if (callback == nullptr) {
387 IAM_LOGE("callback is nullptr");
388 return HDF_ERR_INVALID_PARAM;
389 }
390 struct ExecutorImpl::ScheduleMap::ScheduleInfo info {
391 .commandId = commandId,
392 .callback = callback,
393 .templateId = templateId,
394 .salt = salt
395 };
396 scheduleInfo_[scheduleId] = info;
397
398 return HDF_SUCCESS;
399 }
400
GetScheduleInfo(const uint64_t scheduleId,uint32_t & commandId,sptr<IExecutorCallback> & callback,uint64_t & templateId,std::vector<uint8_t> & salt)401 uint32_t ExecutorImpl::ScheduleMap::GetScheduleInfo(const uint64_t scheduleId, uint32_t &commandId,
402 sptr<IExecutorCallback> &callback, uint64_t &templateId, std::vector<uint8_t> &salt)
403 {
404 IAM_LOGI("start");
405 std::lock_guard<std::mutex> guard(mutex_);
406 if (scheduleInfo_.find(scheduleId) == scheduleInfo_.end()) {
407 IAM_LOGE("scheduleId is invalid");
408 return HDF_FAILURE;
409 }
410 commandId = scheduleInfo_[scheduleId].commandId;
411 callback = scheduleInfo_[scheduleId].callback;
412 templateId = scheduleInfo_[scheduleId].templateId;
413 salt = scheduleInfo_[scheduleId].salt;
414
415 return HDF_SUCCESS;
416 }
417
DeleteScheduleId(const uint64_t scheduleId)418 uint32_t ExecutorImpl::ScheduleMap::DeleteScheduleId(const uint64_t scheduleId)
419 {
420 IAM_LOGI("start");
421 std::lock_guard<std::mutex> guard(mutex_);
422 if (scheduleInfo_.erase(scheduleId) == 1) {
423 IAM_LOGI("Delete scheduleId succ");
424 return HDF_SUCCESS;
425 }
426 IAM_LOGE("Delete scheduleId fail");
427 return HDF_FAILURE;
428 }
429
GetProperty(const std::vector<uint64_t> & templateIdList,const std::vector<GetPropertyType> & propertyTypes,Property & property)430 int32_t ExecutorImpl::GetProperty(
431 const std::vector<uint64_t> &templateIdList, const std::vector<GetPropertyType> &propertyTypes, Property &property)
432 {
433 IAM_LOGI("start");
434 if (pinHdi_ == nullptr) {
435 IAM_LOGE("pinHdi_ is nullptr");
436 return HDF_FAILURE;
437 }
438
439 if (templateIdList.size() != 1) {
440 IAM_LOGE("templateIdList size is not 1");
441 return HDF_ERR_INVALID_PARAM;
442 }
443
444 uint64_t templateId = templateIdList[0];
445 OHOS::UserIam::PinAuth::PinCredentialInfo infoRet = {};
446 int32_t result = pinHdi_->QueryPinInfo(templateId, infoRet);
447 if (result != SUCCESS) {
448 IAM_LOGE("Get TemplateInfo failed, fail code : %{public}d", result);
449 return HDF_FAILURE;
450 }
451
452 property.authSubType = infoRet.subType;
453 property.remainAttempts = infoRet.remainTimes;
454 property.lockoutDuration = infoRet.freezingTime;
455 return HDF_SUCCESS;
456 }
457 } // PinAuth
458 } // HDI
459 } // OHOS