1 /*
2 * Copyright (c) 2024-2025 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 "el5_filekey_manager_napi.h"
17
18 #include <unordered_map>
19
20 #include "data_lock_type.h"
21 #include "el5_filekey_manager_error.h"
22 #include "el5_filekey_manager_kit.h"
23 #include "el5_filekey_manager_log.h"
24
25 namespace OHOS {
26 namespace Security {
27 namespace AccessToken {
28 namespace {
29 constexpr uint32_t MAX_PARAM_SIZE = 1;
30 const std::unordered_map<uint32_t, std::string> ErrMsgMap {
31 {EFM_ERR_NO_PERMISSION, "Permission denied."},
32 {EFM_ERR_NOT_SYSTEM_APP, "Not system app."},
33 {EFM_ERR_INVALID_PARAMETER, "Parameter error."},
34 {EFM_ERR_SYSTEMCAP_NOT_SUPPORT, "The specified SystemCapability name was not found."},
35 {EFM_ERR_INVALID_DATATYPE, "Invalid DataType."},
36 {EFM_ERR_REMOTE_CONNECTION, "The system ability work abnormally."},
37 {EFM_ERR_FIND_ACCESS_FAILED, "The application is not enabled the data protection under lock screen."},
38 {EFM_ERR_ACCESS_RELEASED, "File access is denied."},
39 {EFM_ERR_RELEASE_ACCESS_FAILED, "File access was not acquired."},
40 };
41 }
42
ThrowError(napi_env env,int32_t errCode)43 void ThrowError(napi_env env, int32_t errCode)
44 {
45 napi_value businessError = nullptr;
46
47 napi_value code = nullptr;
48 napi_create_int32(env, errCode, &code);
49
50 std::string errMsg = "Unknown error, errCode + " + std::to_string(errCode) + ".";
51 auto iter = ErrMsgMap.find(errCode);
52 if (iter != ErrMsgMap.end()) {
53 errMsg = iter->second;
54 }
55
56 napi_value msg = nullptr;
57 napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &msg);
58
59 napi_create_error(env, nullptr, msg, &businessError);
60 napi_set_named_property(env, businessError, "code", code);
61 napi_set_named_property(env, businessError, "message", msg);
62
63 napi_throw(env, businessError);
64 }
65
ParseDataType(const napi_env & env,napi_value args,int32_t & dataLockType)66 bool ParseDataType(const napi_env &env, napi_value args, int32_t &dataLockType)
67 {
68 // data-lock-type
69 napi_valuetype valuetype = napi_undefined;
70 napi_typeof(env, args, &valuetype);
71 if (valuetype != napi_number) {
72 LOG_ERROR("Parameter type %{public}d error. Number expected.", valuetype);
73 ThrowError(env, EFM_ERR_INVALID_PARAMETER);
74 return false;
75 }
76 napi_get_value_int32(env, args, &dataLockType);
77 return true;
78 }
79
CheckDataType(napi_env env,int32_t dataLockType)80 bool CheckDataType(napi_env env, int32_t dataLockType)
81 {
82 if ((static_cast<DataLockType>(dataLockType) != DataLockType::DEFAULT_DATA) &&
83 (static_cast<DataLockType>(dataLockType) != DataLockType::MEDIA_DATA) &&
84 (static_cast<DataLockType>(dataLockType) != DataLockType::GROUP_ID_DATA) &&
85 (static_cast<DataLockType>(dataLockType) != DataLockType::ALL_DATA)) {
86 ThrowError(env, EFM_ERR_INVALID_DATATYPE);
87 return false;
88 }
89 return true;
90 }
91
AcquireAccess(napi_env env,napi_callback_info info)92 napi_value AcquireAccess(napi_env env, napi_callback_info info)
93 {
94 size_t argc = MAX_PARAM_SIZE;
95 napi_value argv[MAX_PARAM_SIZE] = { nullptr };
96 if (napi_get_cb_info(env, info, &argc, argv, NULL, NULL) != napi_ok) {
97 LOG_ERROR("napi_get_cb_info failed.");
98 ThrowError(env, EFM_ERR_INVALID_PARAMETER);
99 return nullptr;
100 }
101
102 int32_t dataLockType = static_cast<int32_t>(DataLockType::DEFAULT_DATA);
103 if ((argc == MAX_PARAM_SIZE) && !ParseDataType(env, argv[0], dataLockType)) {
104 return nullptr;
105 }
106
107 if (!CheckDataType(env, dataLockType)) {
108 LOG_ERROR("Invalid DataType.");
109 return nullptr;
110 }
111
112 int32_t retCode = El5FilekeyManagerKit::AcquireAccess(static_cast<DataLockType>(dataLockType));
113 if (retCode != EFM_SUCCESS) {
114 ThrowError(env, retCode);
115 retCode = ACCESS_DENIED;
116 }
117
118 napi_value result = nullptr;
119 NAPI_CALL(env, napi_create_int32(env, retCode, &result));
120 return result;
121 }
122
ReleaseAccess(napi_env env,napi_callback_info info)123 napi_value ReleaseAccess(napi_env env, napi_callback_info info)
124 {
125 size_t argc = MAX_PARAM_SIZE;
126 napi_value argv[MAX_PARAM_SIZE] = { nullptr };
127 if (napi_get_cb_info(env, info, &argc, argv, NULL, NULL) != napi_ok) {
128 LOG_ERROR("napi_get_cb_info failed.");
129 ThrowError(env, EFM_ERR_INVALID_PARAMETER);
130 return nullptr;
131 }
132
133 int32_t dataLockType = static_cast<int32_t>(DataLockType::DEFAULT_DATA);
134 if ((argc == MAX_PARAM_SIZE) && !ParseDataType(env, argv[0], dataLockType)) {
135 return nullptr;
136 }
137
138 if (!CheckDataType(env, dataLockType)) {
139 LOG_ERROR("Invalid DataType.");
140 return nullptr;
141 }
142
143 int32_t retCode = El5FilekeyManagerKit::ReleaseAccess(static_cast<DataLockType>(dataLockType));
144 if (retCode != EFM_SUCCESS) {
145 ThrowError(env, retCode);
146 retCode = RELEASE_DENIED;
147 }
148
149 napi_value result = nullptr;
150 NAPI_CALL(env, napi_create_int32(env, retCode, &result));
151 return result;
152 }
153
QueryAppKeyState(napi_env env,napi_callback_info info)154 napi_value QueryAppKeyState(napi_env env, napi_callback_info info)
155 {
156 size_t argc = MAX_PARAM_SIZE;
157 napi_value argv[MAX_PARAM_SIZE] = { nullptr };
158 if (napi_get_cb_info(env, info, &argc, argv, NULL, NULL) != napi_ok) {
159 LOG_ERROR("napi_get_cb_info failed.");
160 ThrowError(env, EFM_ERR_INVALID_PARAMETER);
161 return nullptr;
162 }
163
164 int32_t dataLockType = static_cast<int32_t>(DataLockType::DEFAULT_DATA);
165 if ((argc == MAX_PARAM_SIZE) && !ParseDataType(env, argv[0], dataLockType)) {
166 return nullptr;
167 }
168
169 if (!CheckDataType(env, dataLockType)) {
170 LOG_ERROR("Invalid DataType.");
171 return nullptr;
172 }
173
174 int32_t retCode = El5FilekeyManagerKit::QueryAppKeyState(static_cast<DataLockType>(dataLockType));
175 switch (retCode) {
176 case EFM_SUCCESS:
177 retCode = KEY_EXIST;
178 break;
179 case EFM_ERR_ACCESS_RELEASED:
180 retCode = KEY_RELEASED;
181 break;
182 case EFM_ERR_FIND_ACCESS_FAILED:
183 retCode = KEY_NOT_EXIST;
184 break;
185 default:
186 ThrowError(env, retCode);
187 retCode = KEY_RELEASED;
188 break;
189 }
190
191 napi_value result = nullptr;
192 NAPI_CALL(env, napi_create_int32(env, retCode, &result));
193 return result;
194 }
195
SetNamedProperty(napi_env env,napi_value dstObj,const int32_t objValue,const char * propName)196 static void SetNamedProperty(napi_env env, napi_value dstObj, const int32_t objValue, const char* propName)
197 {
198 napi_value prop = nullptr;
199 napi_create_int32(env, objValue, &prop);
200 napi_set_named_property(env, dstObj, propName, prop);
201 }
202
203 EXTERN_C_START
204 /*
205 * function for module exports
206 */
Init(napi_env env,napi_value exports)207 static napi_value Init(napi_env env, napi_value exports)
208 {
209 napi_property_descriptor properties[] = {
210 DECLARE_NAPI_FUNCTION("acquireAccess", AcquireAccess),
211 DECLARE_NAPI_FUNCTION("releaseAccess", ReleaseAccess),
212 DECLARE_NAPI_FUNCTION("queryAppKeyState", QueryAppKeyState)
213 };
214
215 napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties);
216
217 napi_value dataType = nullptr;
218 napi_create_object(env, &dataType);
219 SetNamedProperty(env, dataType, static_cast<int32_t>(DataLockType::MEDIA_DATA), "MEDIA_DATA");
220 SetNamedProperty(env, dataType, static_cast<int32_t>(DataLockType::ALL_DATA), "ALL_DATA");
221
222 napi_value accessStatus = nullptr;
223 napi_create_object(env, &accessStatus);
224 SetNamedProperty(env, accessStatus, ACCESS_GRANTED, "ACCESS_GRANTED");
225 SetNamedProperty(env, accessStatus, ACCESS_DENIED, "ACCESS_DENIED");
226
227 napi_value releaseStatus = nullptr;
228 napi_create_object(env, &releaseStatus);
229 SetNamedProperty(env, releaseStatus, RELEASE_GRANTED, "RELEASE_GRANTED");
230 SetNamedProperty(env, releaseStatus, RELEASE_DENIED, "RELEASE_DENIED");
231
232 napi_value keyStatus = nullptr;
233 napi_create_object(env, &keyStatus);
234 SetNamedProperty(env, keyStatus, KEY_NOT_EXIST, "KEY_NOT_EXIST");
235 SetNamedProperty(env, keyStatus, KEY_EXIST, "KEY_EXIST");
236 SetNamedProperty(env, keyStatus, KEY_RELEASED, "KEY_RELEASED");
237
238 napi_property_descriptor exportFuncs[] = {
239 DECLARE_NAPI_PROPERTY("DataType", dataType),
240 DECLARE_NAPI_PROPERTY("AccessStatus", accessStatus),
241 DECLARE_NAPI_PROPERTY("ReleaseStatus", releaseStatus),
242 DECLARE_NAPI_PROPERTY("KeyStatus", keyStatus),
243 };
244 napi_define_properties(env, exports, sizeof(exportFuncs) / sizeof(exportFuncs[0]), exportFuncs);
245
246 return exports;
247 }
248 EXTERN_C_END
249
250 /*
251 * Module define
252 */
253 static napi_module g_module = {
254 .nm_version = 1,
255 .nm_flags = 0,
256 .nm_filename = nullptr,
257 .nm_register_func = Init,
258 .nm_modname = "ability.screenLockFileManager",
259 .nm_priv = static_cast<void*>(nullptr),
260 .reserved = {nullptr}
261 };
262
263 /*
264 * Module register function
265 */
RegisterEl5FilekeyManager(void)266 extern "C" __attribute__((constructor)) void RegisterEl5FilekeyManager(void)
267 {
268 napi_module_register(&g_module);
269 }
270 } // namespace AccessToken
271 } // namespace Security
272 } // namespace OHOS
273