• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "inputer_data_impl.h"
17 
18 #include <cstddef>
19 #include <regex>
20 #include <vector>
21 
22 #include <openssl/sha.h>
23 
24 #include "securec.h"
25 
26 #include "iam_logger.h"
27 #include "iam_ptr.h"
28 #include "scrypt.h"
29 #include "settings_data_manager.h"
30 #ifdef CUSTOMIZATION_ENTERPRISE_DEVICE_MANAGEMENT_ENABLE
31 #include "security_manager_proxy.h"
32 #endif
33 
34 #define LOG_TAG "PIN_AUTH_SDK"
35 
36 namespace OHOS {
37 namespace UserIam {
38 namespace PinAuth {
39 namespace {
40 constexpr uint32_t PIN_LEN_FOUR = 4;
41 constexpr uint32_t PIN_LEN_SIX = 6;
42 constexpr uint32_t PIN_LEN_SEVEN = 7;
43 constexpr uint32_t PIN_LEN_NINE = 9;
44 constexpr uint32_t SPECIFY_PIN_COMPLEXITY = 10002;
45 }
46 
InputerDataImpl(const InputerGetDataParam & param)47 InputerDataImpl::InputerDataImpl(const InputerGetDataParam &param)
48     : mode_(param.mode), algoVersion_(param.algoVersion), algoParameter_(param.algoParameter),
49       inputerSetData_(param.inputerSetData), complexityReg_(param.complexityReg), userId_(param.userId),
50       authIntent_(param.authIntent)
51 {
52 }
53 
GetPinData(int32_t authSubType,const std::vector<uint8_t> & dataIn,std::vector<uint8_t> & dataOut,int32_t & errorCode)54 void InputerDataImpl::GetPinData(
55     int32_t authSubType, const std::vector<uint8_t> &dataIn, std::vector<uint8_t> &dataOut, int32_t &errorCode)
56 {
57     IAM_LOGI("start authSubType: %{public}d", authSubType);
58     errorCode = CheckPinComplexity(authSubType, dataIn);
59     if (errorCode != UserAuth::SUCCESS && mode_ == GET_DATA_MODE_ALL_IN_ONE_ENROLL) {
60         IAM_LOGE("CheckPinComplexity enroll failed");
61         return;
62     }
63 
64     if (mode_ == GET_DATA_MODE_ALL_IN_ONE_ENROLL && authSubType == UserAuth::PIN_PATTERN) {
65         IAM_LOGE("GetPinData Enroll Unsupport Type Pattern");
66         return;
67     }
68 
69     auto scryptPointer = Common::MakeUnique<Scrypt>(algoParameter_);
70     if (scryptPointer == nullptr) {
71         IAM_LOGE("scryptPointer is nullptr");
72         return;
73     }
74 
75     if (authSubType == UserAuth::PIN_PATTERN) {
76         std::vector<uint8_t> patternDataIn(dataIn);
77         for (uint8_t &data : patternDataIn) {
78             data += 1;
79         }
80         scryptPointer->GetScrypt(patternDataIn, algoVersion_).swap(dataOut);
81         (void)memset_s(patternDataIn.data(), patternDataIn.size(), 0, patternDataIn.size());
82     } else {
83         scryptPointer->GetScrypt(dataIn, algoVersion_).swap(dataOut);
84     }
85 
86     if (dataOut.empty()) {
87         IAM_LOGE("get scrypt fail");
88         return;
89     }
90     if ((algoVersion_ > ALGO_VERSION_V1) &&
91         (mode_ == GET_DATA_MODE_ALL_IN_ONE_ENROLL) &&
92         (!GetSha256(dataIn, dataOut))) {
93         IAM_LOGE("get sha256 fail");
94         if (!dataOut.empty()) {
95             (void)memset_s(dataOut.data(), dataOut.size(), 0, dataOut.size());
96         }
97         dataOut.clear();
98     }
99 }
100 
OnSetData(int32_t authSubType,std::vector<uint8_t> data)101 void InputerDataImpl::OnSetData(int32_t authSubType, std::vector<uint8_t> data)
102 {
103     IAM_LOGI("start userId:%{public}d, data size:%{public}zu, algo version:%{public}u, complexityReg size:%{public}zu",
104         userId_, data.size(), algoVersion_, complexityReg_.size());
105     std::vector<uint8_t> setData;
106     int32_t errorCode = UserAuth::GENERAL_ERROR;
107     GetPinData(authSubType, data, setData, errorCode);
108     OnSetDataInner(authSubType, setData, errorCode);
109     if (!data.empty()) {
110         (void)memset_s(data.data(), data.size(), 0, data.size());
111     }
112     if (!setData.empty()) {
113         (void)memset_s(setData.data(), setData.size(), 0, setData.size());
114     }
115 }
116 
GetSha256(const std::vector<uint8_t> & data,std::vector<uint8_t> & out)117 bool InputerDataImpl::GetSha256(const std::vector<uint8_t> &data, std::vector<uint8_t> &out)
118 {
119     uint8_t sha256Result[SHA256_DIGEST_LENGTH] = {};
120     if (SHA256(data.data(), data.size(), sha256Result) != sha256Result) {
121         IAM_LOGE("get sha256 fail");
122         (void)memset_s(sha256Result, SHA256_DIGEST_LENGTH, 0, SHA256_DIGEST_LENGTH);
123         return false;
124     }
125     out.insert(out.end(), sha256Result, sha256Result + SHA256_DIGEST_LENGTH);
126     (void)memset_s(sha256Result, SHA256_DIGEST_LENGTH, 0, SHA256_DIGEST_LENGTH);
127     return true;
128 }
129 
OnSetDataInner(int32_t authSubType,std::vector<uint8_t> & setData,int32_t errorCode)130 void InputerDataImpl::OnSetDataInner(int32_t authSubType, std::vector<uint8_t> &setData, int32_t errorCode)
131 {
132     if (inputerSetData_ == nullptr) {
133         IAM_LOGE("inputerSetData is nullptr");
134         return;
135     }
136     inputerSetData_->OnSetData(authSubType, setData, errorCode);
137 }
138 
CheckPinSizeBySubType(int32_t authSubType,size_t size)139 bool InputerDataImpl::CheckPinSizeBySubType(int32_t authSubType, size_t size)
140 {
141     if (mode_ != GET_DATA_MODE_ALL_IN_ONE_ENROLL) {
142         return true;
143     }
144     if (size < PIN_LEN_FOUR) {
145         return false;
146     }
147     switch (authSubType) {
148         case UserAuth::PIN_FOUR:
149             return (size == PIN_LEN_FOUR);
150         case UserAuth::PIN_PATTERN:
151             return (size >= PIN_LEN_FOUR && size <= PIN_LEN_NINE);
152         default:
153             return (size >= PIN_LEN_SIX);
154     }
155 }
156 
CheckPinComplexity(int32_t authSubType,const std::vector<uint8_t> & data)157 int32_t InputerDataImpl::CheckPinComplexity(int32_t authSubType, const std::vector<uint8_t> &data)
158 {
159     if (data.empty()) {
160         IAM_LOGE("get empty data");
161         return UserAuth::COMPLEXITY_CHECK_FAILED;
162     }
163     if (!CheckPinSizeBySubType(authSubType, data.size())) {
164         IAM_LOGE("check data size failed");
165         return UserAuth::COMPLEXITY_CHECK_FAILED;
166     }
167     std::vector<uint8_t> input = data;
168     input.emplace_back('\0');
169     if (!CheckEdmPinComplexity(authSubType, input)) {
170         IAM_LOGE("CheckEdmPinComplexity failed");
171         (void)memset_s(input.data(), input.size(), 0, input.size());
172         return UserAuth::COMPLEXITY_CHECK_FAILED;
173     }
174     if (!CheckSpecialPinComplexity(input, authSubType)) {
175         IAM_LOGE("CheckSpecialPinComplexity failed");
176         (void)memset_s(input.data(), input.size(), 0, input.size());
177         return UserAuth::COMPLEXITY_CHECK_FAILED;
178     }
179     (void)memset_s(input.data(), input.size(), 0, input.size());
180     return UserAuth::SUCCESS;
181 }
182 
CheckSpecialPinComplexity(std::vector<uint8_t> & input,int32_t authSubType)183 bool InputerDataImpl::CheckSpecialPinComplexity(std::vector<uint8_t> &input, int32_t authSubType)
184 {
185     IAM_LOGI("start");
186     if (mode_ != GET_DATA_MODE_ALL_IN_ONE_ENROLL &&
187         !(mode_ == GET_DATA_MODE_ALL_IN_ONE_AUTH && authIntent_ == SPECIFY_PIN_COMPLEXITY)) {
188         return true;
189     }
190     if (complexityReg_.empty()) {
191         IAM_LOGI("complexityReg is empty");
192         return true;
193     }
194     const std::string key = "payment_security_level";
195     int32_t isCheckPinComplexity = 0;
196     if (!SettingsDataManager::GetIntValue(userId_, key, isCheckPinComplexity)) {
197         IAM_LOGI("no exist isCheckPinComplexity");
198         return true;
199     }
200     if (isCheckPinComplexity == 0) {
201         IAM_LOGI("no need check special pin complexity");
202         return true;
203     }
204     if (authSubType == UserAuth::PIN_FOUR || authSubType == UserAuth::PIN_PATTERN) {
205         IAM_LOGE("authSubType is PIN_FOUR or PIN_PATTERN");
206         return false;
207     }
208     if (input.size() < PIN_LEN_SEVEN) {
209         IAM_LOGE("check data size failed");
210         return false;
211     }
212     return CheckPinComplexityByReg(input, complexityReg_);
213 }
214 
CheckEdmPinComplexity(int32_t authSubType,std::vector<uint8_t> & input)215 bool InputerDataImpl::CheckEdmPinComplexity(int32_t authSubType, std::vector<uint8_t> &input)
216 {
217     IAM_LOGI("start");
218     if (mode_ != GET_DATA_MODE_ALL_IN_ONE_ENROLL) {
219         return true;
220     }
221 #ifdef CUSTOMIZATION_ENTERPRISE_DEVICE_MANAGEMENT_ENABLE
222     EDM::PasswordPolicy policy;
223     int32_t ret = EDM::SecurityManagerProxy::GetSecurityManagerProxy()->GetPasswordPolicy(policy);
224     if (ret != ERR_OK || policy.complexityReg.empty()) {
225         IAM_LOGE("GetPasswordPolicy failed, check other policy");
226         return true;
227     }
228     if (authSubType != UserAuth::PIN_MIXED) {
229         IAM_LOGE("GetPasswordPolicy success, authSubType can only be PIN_MIXED");
230         return false;
231     }
232     return CheckPinComplexityByReg(input, policy.complexityReg);
233 #else
234     IAM_LOGI("This device not support edm");
235 #endif
236     return true;
237 }
238 
CheckPinComplexityByReg(std::vector<uint8_t> & input,const std::string & complexityReg)239 bool InputerDataImpl::CheckPinComplexityByReg(std::vector<uint8_t> &input, const std::string &complexityReg)
240 {
241     try {
242         std::regex regex(complexityReg);
243         bool checkRet = std::regex_match(reinterpret_cast<char*>(input.data()), regex);
244         if (!checkRet) {
245             IAM_LOGE("PIN_MIXED does not pass complexity check");
246             return false;
247         }
248     } catch (const std::regex_error &e) {
249         IAM_LOGE("create regex failed");
250         return false;
251     }
252     return true;
253 }
254 } // namespace PinAuth
255 } // namespace UserIam
256 } // namespace OHOS
257