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 "user_auth_impl.h"
17
18 #include <map>
19
20 #include "securec.h"
21
22 #include "iam_logger.h"
23 #include "iam_para2str.h"
24 #include "iam_ptr.h"
25
26 #include "user_auth_napi_helper.h"
27 #include "user_auth_callback_v6.h"
28 #include "user_auth_callback_v8.h"
29 #include "user_auth_client_impl.h"
30
31 #define LOG_TAG "USER_AUTH_NAPI"
32
33 namespace OHOS {
34 namespace UserIam {
35 namespace UserAuth {
GetVersion(napi_env env,napi_callback_info info)36 napi_value UserAuthImpl::GetVersion(napi_env env, napi_callback_info info)
37 {
38 int32_t version;
39 int32_t result = UserAuthClientImpl::Instance().GetVersion(version);
40 if (result != SUCCESS) {
41 IAM_LOGE("result = %{public}d", result);
42 version = 0;
43 }
44 IAM_LOGI("version = %{public}d", version);
45 napi_value jsVersion;
46 NAPI_CALL(env, napi_create_int32(env, version, &jsVersion));
47 return jsVersion;
48 }
49
GetAvailableStatus(napi_env env,napi_callback_info info)50 napi_value UserAuthImpl::GetAvailableStatus(napi_env env, napi_callback_info info)
51 {
52 napi_value argv[ARGS_TWO] = {nullptr};
53 size_t argc = ARGS_TWO;
54 napi_value result;
55 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
56 if (argc != ARGS_TWO) {
57 IAM_LOGE("parms error");
58 NAPI_CALL(env, napi_create_int32(env, INVALID_PARAMETERS, &result));
59 return result;
60 }
61 int32_t type;
62 NAPI_CALL(env, napi_get_value_int32(env, argv[PARAM0], &type));
63 int32_t level;
64 NAPI_CALL(env, napi_get_value_int32(env, argv[PARAM1], &level));
65 AuthType authType = AuthType(type);
66 AuthTrustLevel authTrustLevel = AuthTrustLevel(level);
67 ResultCode checkRet = CheckAuthTypeAndAuthTrustLevel(authType, authTrustLevel);
68 if (checkRet != SUCCESS) {
69 IAM_LOGE("CheckAuthTypeAndAuthTrsutLevel failed");
70 NAPI_CALL(env, napi_create_int32(env, checkRet, &result));
71 return result;
72 }
73 int32_t status = UserAuthClientImpl::Instance().GetNorthAvailableStatus(API_VERSION_8, authType, authTrustLevel);
74 IAM_LOGI("result = %{public}d", status);
75 NAPI_CALL(env, napi_create_int32(env, UserAuthNapiHelper::GetResultCodeV8(status), &result));
76 return result;
77 }
78
Execute(napi_env env,napi_callback_info info)79 napi_value UserAuthImpl::Execute(napi_env env, napi_callback_info info)
80 {
81 IAM_LOGI("start");
82 size_t argc = ARGS_THREE;
83 napi_value argv[ARGS_THREE] = {nullptr};
84 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
85 napi_value retPromise = nullptr;
86 std::shared_ptr<JsRefHolder> callbackRef = nullptr;
87 napi_deferred promiseDeferred = nullptr;
88 if (argc == ARGS_THREE) {
89 callbackRef = Common::MakeShared<JsRefHolder>(env, argv[PARAM2]);
90 if (callbackRef == nullptr || !callbackRef->IsValid()) {
91 IAM_LOGE("make callback ref fail");
92 return nullptr;
93 }
94 NAPI_CALL(env, napi_get_null(env, &retPromise));
95 } else if (argc == ARGS_TWO) {
96 NAPI_CALL(env, napi_create_promise(env, &promiseDeferred, &retPromise));
97 } else {
98 IAM_LOGE("bad params");
99 return retPromise;
100 }
101 std::shared_ptr<UserAuthCallbackV6> callback =
102 Common::MakeShared<UserAuthCallbackV6>(env, callbackRef, promiseDeferred);
103 if (callback == nullptr) {
104 IAM_LOGE("callback is nullptr");
105 return nullptr;
106 }
107
108 AuthType authType;
109 ResultCode resultCode;
110 NAPI_CALL(env, ParseExecuteAuthType(env, argv[PARAM0], authType, resultCode));
111 if (resultCode != ResultCode::SUCCESS) {
112 IAM_LOGE("ParseAuthType fail");
113 UserIam::UserAuth::Attributes extra;
114 callback->OnResult(resultCode, extra);
115 return retPromise;
116 }
117 AuthTrustLevel authTrustLevel;
118 NAPI_CALL(env, ParseExecuteSecureLevel(env, argv[PARAM1], authTrustLevel, resultCode));
119 if (resultCode != ResultCode::SUCCESS) {
120 IAM_LOGE("ParseExecuteSecureLevel fail");
121 UserIam::UserAuth::Attributes extra;
122 callback->OnResult(resultCode, extra);
123 return retPromise;
124 }
125
126 std::vector<uint8_t> challenge;
127 UserAuthClientImpl::Instance().BeginNorthAuthentication(API_VERSION_6, challenge, FACE, authTrustLevel, callback);
128 return retPromise;
129 }
130
ParseExecuteAuthType(napi_env env,napi_value value,AuthType & authType,ResultCode & resultCode)131 napi_status UserAuthImpl::ParseExecuteAuthType(napi_env env, napi_value value,
132 AuthType &authType, ResultCode &resultCode)
133 {
134 resultCode = ResultCode::GENERAL_ERROR;
135 static const size_t maxLen = 20;
136 char str[maxLen] = {0};
137 size_t len = maxLen;
138 napi_status result = UserAuthNapiHelper::GetStrValue(env, value, str, len);
139 if (result != napi_ok) {
140 IAM_LOGE("getStrValue fail");
141 return result;
142 }
143 static const char *authTypeAll = "ALL";
144 static const char *authTypeFaceOnly = "FACE_ONLY";
145 if (strcmp(str, authTypeAll) == 0) {
146 IAM_LOGE("type ALL not supported");
147 resultCode = ResultCode::TYPE_NOT_SUPPORT;
148 return napi_ok;
149 }
150 if (strcmp(str, authTypeFaceOnly) != 0) {
151 IAM_LOGE("type is invalid");
152 resultCode = ResultCode::INVALID_PARAMETERS;
153 return napi_ok;
154 }
155 resultCode = ResultCode::SUCCESS;
156 return napi_ok;
157 }
158
ParseExecuteSecureLevel(napi_env env,napi_value value,AuthTrustLevel & authTrustLevel,ResultCode & resultCode)159 napi_status UserAuthImpl::ParseExecuteSecureLevel(napi_env env, napi_value value,
160 AuthTrustLevel &authTrustLevel, ResultCode &resultCode)
161 {
162 resultCode = ResultCode::GENERAL_ERROR;
163 static const size_t maxLen = 20;
164 char str[maxLen] = {0};
165 size_t len = maxLen;
166 napi_status result = UserAuthNapiHelper::GetStrValue(env, value, str, len);
167 if (result != napi_ok) {
168 IAM_LOGE("getStrValue fail");
169 return result;
170 }
171 static std::map<std::string, AuthTrustLevel> convertAuthTrustLevel = {
172 {"S1", ATL1},
173 {"S2", ATL2},
174 {"S3", ATL3},
175 {"S4", ATL4},
176 };
177 if (convertAuthTrustLevel.count(str) == 0) {
178 IAM_LOGE("trust level invalid");
179 resultCode = ResultCode::INVALID_PARAMETERS;
180 return napi_ok;
181 }
182 authTrustLevel = convertAuthTrustLevel[str];
183 resultCode = ResultCode::SUCCESS;
184 return napi_ok;
185 }
186
Auth(napi_env env,napi_callback_info info)187 napi_value UserAuthImpl::Auth(napi_env env, napi_callback_info info)
188 {
189 IAM_LOGI("start");
190 size_t argc = ARGS_FOUR;
191 napi_value argv[ARGS_FOUR] = {nullptr};
192 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
193 if (argc != ARGS_FOUR) {
194 IAM_LOGE("parms error");
195 return nullptr;
196 }
197 std::vector<uint8_t> challenge;
198 if (UserAuthNapiHelper::GetUint8ArrayValue(env, argv[PARAM0], MAX_CHALLENG_LEN, challenge) != napi_ok) {
199 IAM_LOGE("challenge invalid, use null challenge");
200 challenge.clear();
201 }
202 int32_t authType;
203 NAPI_CALL(env, UserAuthNapiHelper::GetInt32Value(env, argv[PARAM1], authType));
204 int32_t authTrustLevel;
205 NAPI_CALL(env, UserAuthNapiHelper::GetInt32Value(env, argv[PARAM2], authTrustLevel));
206 NAPI_CALL(env, UserAuthNapiHelper::CheckNapiType(env, argv[PARAM3], napi_object));
207 napi_value onResultValue;
208 NAPI_CALL(env, napi_get_named_property(env, argv[PARAM3], "onResult", &onResultValue));
209 auto resultCallback = Common::MakeShared<JsRefHolder>(env, onResultValue);
210 napi_value onAcquireInfoValue;
211 NAPI_CALL(env, napi_get_named_property(env, argv[PARAM3], "onAcquireInfo", &onAcquireInfoValue));
212 auto acquireCallback = Common::MakeShared<JsRefHolder>(env, onAcquireInfoValue);
213 auto callback = Common::MakeShared<UserAuthCallbackV8>(env, resultCallback, acquireCallback);
214 if (callback == nullptr) {
215 IAM_LOGE("callback is nullptr");
216 return nullptr;
217 }
218 ResultCode checkRet = CheckAuthTypeAndAuthTrustLevel(AuthType(authType), AuthTrustLevel(authTrustLevel));
219 if (checkRet != SUCCESS) {
220 IAM_LOGE("CheckAuthTypeAndAuthTrsutLevel failed");
221 Attributes extraInfo;
222 callback->OnResult(checkRet, extraInfo);
223 napi_value key = UserAuthNapiHelper::Uint64ToNapiUint8Array(env, INVALID_CONTEXT_ID);
224 return key;
225 }
226 uint64_t result = UserAuthClientImpl::Instance().BeginNorthAuthentication(API_VERSION_8, challenge,
227 AuthType(authType), AuthTrustLevel(authTrustLevel), callback);
228 IAM_LOGI("result is %{public}s", GET_MASKED_STRING(result).c_str());
229 napi_value key = UserAuthNapiHelper::Uint64ToNapiUint8Array(env, result);
230 IAM_LOGI("end");
231 return key;
232 }
233
CancelAuth(napi_env env,napi_callback_info info)234 napi_value UserAuthImpl::CancelAuth(napi_env env, napi_callback_info info)
235 {
236 size_t argc = ARGS_ONE;
237 napi_value argv[ARGS_ONE] = {nullptr};
238 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
239 if (argc != ARGS_ONE) {
240 IAM_LOGE("parms error");
241 return nullptr;
242 }
243 const size_t maxContextIdLen = 8;
244 std::vector<uint8_t> contextIdArray;
245 NAPI_CALL(env, UserAuthNapiHelper::GetUint8ArrayValue(env, argv[PARAM0], maxContextIdLen, contextIdArray));
246 uint64_t contextId;
247 if (memcpy_s(reinterpret_cast<void *>(&contextId), sizeof(contextId),
248 contextIdArray.data(), contextIdArray.size()) != EOK) {
249 IAM_LOGE("memcpy error");
250 return nullptr;
251 }
252 IAM_LOGI("contextId's low 16 bits is %{public}s", GET_MASKED_STRING(contextId).c_str());
253 if (contextId == 0) {
254 IAM_LOGE("invalid error");
255 return nullptr;
256 }
257 int32_t result = UserAuthClient::GetInstance().CancelAuthentication(contextId);
258 IAM_LOGI("result = %{public}d", result);
259 napi_value key;
260 NAPI_CALL(env, napi_create_int32(env, UserAuthNapiHelper::GetResultCodeV8(result), &key));
261 return key;
262 }
263
CheckAuthTypeAndAuthTrustLevel(AuthType authType,AuthTrustLevel authTrustLevel)264 ResultCode UserAuthImpl::CheckAuthTypeAndAuthTrustLevel(AuthType authType, AuthTrustLevel authTrustLevel)
265 {
266 if (authType != FINGERPRINT && authType != FACE) {
267 IAM_LOGE("authType check fail:%{public}d", authType);
268 return TYPE_NOT_SUPPORT;
269 }
270 if (authTrustLevel != ATL1 && authTrustLevel != ATL2 && authTrustLevel != ATL3 && authTrustLevel != ATL4) {
271 IAM_LOGE("authTrustLevel check fail:%{public}d", authTrustLevel);
272 return TRUST_LEVEL_NOT_SUPPORT;
273 }
274 return SUCCESS;
275 }
276 } // namespace UserAuth
277 } // namespace UserIam
278 } // namespace OHOS
279