• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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