1 /*
2  * Copyright (c) 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 <unistd.h>
17 
18 #include "iam_client.h"
19 #include "storage_service_log.h"
20 #include "utils/storage_radar.h"
21 
22 using namespace OHOS::StorageService;
23 namespace OHOS {
24 namespace StorageDaemon {
25 const uint8_t IAM_MAX_RETRY_TIME = 3;
26 const uint16_t IAM_RETRY_INTERVAL_MS = 50 * 1000;
IamClient()27 IamClient::IamClient()
28 {
29     LOGD("enter");
30 }
31 
~IamClient()32 IamClient::~IamClient()
33 {
34     LOGD("enter");
35 }
36 
37 #ifdef USER_AUTH_FRAMEWORK
OnSecUserInfo(const UserIam::UserAuth::SecUserInfo & info)38 void UserSecCallback::OnSecUserInfo(const UserIam::UserAuth::SecUserInfo &info)
39 {
40     LOGI("enter");
41     secureUid_ = info.secureUid;
42     IamClient::GetInstance().NotifyGetSecureUid();
43 }
44 
GetSecureUid()45 uint64_t UserSecCallback::GetSecureUid()
46 {
47     LOGI("enter");
48     return secureUid_;
49 }
50 
OnSecUserInfo(const UserIam::UserAuth::SecUserInfo & info)51 void UserEnrollCallback::OnSecUserInfo(const UserIam::UserAuth::SecUserInfo &info)
52 {
53     LOGI("enter");
54     info_ = info;
55     IamClient::GetInstance().NotifyGetSecUserInfo();
56 }
57 
GetSecUserInfo()58 UserIam::UserAuth::SecUserInfo UserEnrollCallback::GetSecUserInfo()
59 {
60     LOGI("enter");
61     return info_;
62 }
63 #endif
64 
GetSecureUid(uint32_t userId,uint64_t & secureUid)65 bool IamClient::GetSecureUid(uint32_t userId, uint64_t &secureUid)
66 {
67     LOGI("enter");
68 #ifdef USER_AUTH_FRAMEWORK
69     LOGI("get secure uid real !");
70     secureUidStatus_ = FAILED;
71     std::shared_ptr<UserSecCallback> secCallback = std::make_shared<UserSecCallback>();
72     int32_t retCode = UserIam::UserAuth::UserIdmClient::GetInstance().GetSecUserInfo(userId, secCallback);
73     if (retCode != UserIam::UserAuth::ResultCode::SUCCESS) {
74         for (int i = 0; i < IAM_MAX_RETRY_TIME; ++i) {
75             usleep(IAM_RETRY_INTERVAL_MS);
76             retCode = UserIam::UserAuth::UserIdmClient::GetInstance().GetSecUserInfo(userId, secCallback);
77             LOGE("GetSecureUid has retry %{public}d times, retryRet %{public}d", i, retCode);
78             if (retCode == UserIam::UserAuth::ResultCode::SUCCESS) {
79                 break;
80             }
81         }
82     }
83     if (retCode != UserIam::UserAuth::ResultCode::SUCCESS) {
84         LOGE("Get secure uid failed !");
85         StorageRadar::ReportIamResult("GetSecureUid", userId, retCode);
86         return false;
87     }
88     std::unique_lock<std::mutex> lock(iamMutex_);
89     iamCon_.wait_for(lock, std::chrono::seconds(GET_SEC_TIMEOUT), [this] {
90         return (this->secureUidStatus_ == SUCCESS);
91     });
92     if (secureUidStatus_ == FAILED) {
93         LOGE("Get secure uid failed, use default !");
94     }
95     secureUid = secCallback->GetSecureUid();
96 #else
97     LOGI("iam not support, use default !");
98     secureUid = { 0 };
99 #endif
100     LOGI("finish");
101     return true;
102 }
103 
GetSecUserInfo(uint32_t userId,UserIam::UserAuth::SecUserInfo & info)104 bool IamClient::GetSecUserInfo(uint32_t userId, UserIam::UserAuth::SecUserInfo &info)
105 {
106     LOGI("enter");
107 #ifdef USER_AUTH_FRAMEWORK
108     LOGI("Get SecUserInfo real !");
109     secUserInfoState_ = SEC_USER_INFO_FAILED;
110     std::shared_ptr<UserEnrollCallback> userEnrollCallback = std::make_shared<UserEnrollCallback>();
111     int32_t retCode = UserIam::UserAuth::UserIdmClient::GetInstance().GetSecUserInfo(userId, userEnrollCallback);
112     if (retCode != UserIam::UserAuth::ResultCode::SUCCESS && retCode != UserIam::UserAuth::ResultCode::NOT_ENROLLED &&
113         retCode != UserIam::UserAuth::ResultCode::GENERAL_ERROR) {
114         for (int i = 0; i < IAM_MAX_RETRY_TIME; ++i) {
115             usleep(IAM_RETRY_INTERVAL_MS);
116             retCode = UserIam::UserAuth::UserIdmClient::GetInstance().GetSecUserInfo(userId, userEnrollCallback);
117             LOGE("GetSecureUid has retry %{public}d times, retryRet %{public}d", i, retCode);
118             if (retCode == UserIam::UserAuth::ResultCode::SUCCESS ||
119                 retCode == UserIam::UserAuth::ResultCode::NOT_ENROLLED ||
120                 retCode == UserIam::UserAuth::ResultCode::GENERAL_ERROR) {
121                 break;
122             }
123         }
124     }
125     if (retCode != UserIam::UserAuth::ResultCode::SUCCESS && retCode != UserIam::UserAuth::ResultCode::NOT_ENROLLED &&
126         retCode != UserIam::UserAuth::ResultCode::GENERAL_ERROR) {
127         LOGE("Get SecUserInfo failed !");
128         return false;
129     }
130     std::unique_lock<std::mutex> lock(iamMutex_);
131     iamCon_.wait_for(lock, std::chrono::seconds(GET_SEC_TIMEOUT),
132                      [this] { return (this->secUserInfoState_ == SEC_USER_INFO_SUCCESS); });
133     if (secUserInfoState_ == SEC_USER_INFO_FAILED) {
134         LOGE("Get SecUserInfo failed, use default !");
135     }
136     info = userEnrollCallback->GetSecUserInfo();
137 #else
138     LOGI("iam not support, use default !");
139     info = {};
140 #endif
141     LOGI("finish");
142     return true;
143 }
144 
HasFaceFinger(uint32_t userId,bool & isExist)145 int IamClient::HasFaceFinger(uint32_t userId, bool &isExist)
146 {
147     isExist = false;
148     UserIam::UserAuth::SecUserInfo info;
149     if (!GetSecUserInfo(userId, info)) {
150         LOGE("Get SecUserInfo failed!");
151         return -ENOENT;
152     }
153     std::vector<UserIam::UserAuth::EnrolledInfo> enrollInfo = info.enrolledInfo;
154     for (auto &item : enrollInfo) {
155         LOGI("EnrollInfo authType is : %{public}d", item.authType);
156         if (item.authType == UserIam::UserAuth::FACE || item.authType == UserIam::UserAuth::FINGERPRINT) {
157             LOGI("The user: %{public}d have authType: %{public}d", userId, item.authType);
158             isExist = true;
159             return 0;
160         }
161     }
162     LOGI("The Face And FingerPrint are not exist !");
163     return 0;
164 }
165 
HasPinProtect(uint32_t userId)166 bool IamClient::HasPinProtect(uint32_t userId)
167 {
168     UserIam::UserAuth::SecUserInfo info;
169     if (!GetSecUserInfo(userId, info)) {
170         LOGE("Get SecUserInfo failed!");
171         return false;
172     }
173     std::vector<UserIam::UserAuth::EnrolledInfo> enrollInfo = info.enrolledInfo;
174     for (auto &item : enrollInfo) {
175         if (item.authType == UserIam::UserAuth::PIN) {
176             LOGI("The device have pin protect for userId = %{public}d.", userId);
177             return true;
178         }
179     }
180     LOGI("The device has no pin protect for userId = %{public}d.", userId);
181     return false;
182 }
183 
NotifyGetSecUserInfo()184 int32_t IamClient::NotifyGetSecUserInfo()
185 {
186     std::lock_guard<std::mutex> lock(iamMutex_);
187     secUserInfoState_ = SEC_USER_INFO_SUCCESS;
188     iamCon_.notify_one();
189     return 0;
190 }
191 
NotifyGetSecureUid()192 int32_t IamClient::NotifyGetSecureUid()
193 {
194     std::lock_guard<std::mutex> lock(iamMutex_);
195     secureUidStatus_ = SUCCESS;
196     iamCon_.notify_one();
197     return 0;
198 }
199 } // namespace StorageDaemon
200 } // namespace HOHS