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