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 "fbex.h"
17
18 #include <fcntl.h>
19 #include <sys/ioctl.h>
20 #include <unistd.h>
21
22 #include "file_ex.h"
23 #include "storage_service_log.h"
24 #include "openssl_crypto.h"
25 #include "utils/storage_radar.h"
26
27 using namespace OHOS::StorageService;
28 namespace {
29 constexpr const char *FBEX_UFS_INLINE_SUPPORT_PREFIX = "/sys/devices/platform/";
30 constexpr const char *FBEX_UFS_INLINE_SUPPORT_END = "/ufs_inline_stat";
31 constexpr const char *FBEX_NVME_INLINE_SUPPORT_PATH = "/sys/block/nvme_crypto";
32 constexpr const char *FBEX_EMMC_INLINE_SUPPORT_PATH = "/sys/block/emmc_crypto";
33 constexpr const char *FBEX_UFS_INLINE_BASE_ADDR = "/proc/bootdevice/name";
34 constexpr const char *FBEX_INLINE_CRYPTO_V3 = "3\n";
35
36 constexpr const char *FBEX_CMD_PATH = "/dev/fbex_cmd";
37 constexpr const char *FBEX_UECE_PATH = "/dev/fbex_uece";
38
39 constexpr uint32_t FBEX_E_BUFFER_SIZE = 64;
40 constexpr uint32_t UNLOCK_STATUS = 0x2;
41
42 constexpr uint8_t FBEX_IOC_MAGIC = 'f';
43 constexpr uint8_t FBEX_ADD_IV = 0x1;
44 constexpr uint8_t FBEX_DEL_IV = 0x2;
45 constexpr uint8_t FBEX_LOCK_SCREEN = 0x3;
46 constexpr uint8_t FBEX_UNLOCK_SCREEN = 0x4;
47 constexpr uint8_t FBEX_USER_LOGOUT = 0x8;
48 constexpr uint8_t FBEX_STATUS_REPORT = 0xC;
49 constexpr uint8_t FBEX_ADD_DOUBLE_DE_IV = 20;
50 constexpr uint8_t FBEX_ADD_EL5 = 21;
51 constexpr uint8_t FBEX_READ_EL5 = 22;
52 constexpr uint8_t FBEX_WRITE_EL5 = 23;
53 constexpr uint8_t FBEX_DEL_EL5_PINCODE = 24;
54 constexpr uint8_t FBEX_GENERATE_APP_KEY = 25;
55 constexpr uint8_t FBEX_CHANGE_PINCODE = 26;
56 constexpr uint8_t FBEX_LOCK_EL5 = 27;
57 constexpr uint32_t FILE_ENCRY_ERROR_UECE_ALREADY_CREATED = 0xFBE30031;
58 constexpr uint32_t FILE_ENCRY_ERROR_NOT_FOUND_UECE = 0xFBE30033;
59
60 struct FbeOptStr {
61 uint32_t user = 0;
62 uint32_t type = 0;
63 uint32_t len = 0;
64 uint8_t iv[OHOS::StorageDaemon::FBEX_IV_SIZE] = {0};
65 uint8_t flag = 0;
66 };
67 using FbeOpts = FbeOptStr;
68
69 struct FbeOptStrE {
70 uint32_t userIdDouble = 0;
71 uint32_t userIdSingle = 0;
72 uint32_t status = 0;
73 uint32_t length = 0;
74 uint8_t eBuffer[FBEX_E_BUFFER_SIZE] = {0};
75 };
76 using FbeOptsE = FbeOptStrE;
77
78 #define FBEX_IOC_ADD_IV _IOWR(FBEX_IOC_MAGIC, FBEX_ADD_IV, FbeOpts)
79 #define FBEX_IOC_ADD_DOUBLE_DE_IV _IOWR(FBEX_IOC_MAGIC, FBEX_ADD_DOUBLE_DE_IV, FbeOpts)
80 #define FBEX_IOC_DEL_IV _IOW(FBEX_IOC_MAGIC, FBEX_DEL_IV, FbeOpts)
81 #define FBEX_IOC_LOCK_SCREEN _IOW(FBEX_IOC_MAGIC, FBEX_LOCK_SCREEN, FbeOpts)
82 #define FBEX_IOC_UNLOCK_SCREEN _IOWR(FBEX_IOC_MAGIC, FBEX_UNLOCK_SCREEN, FbeOpts)
83 #define FBEX_IOC_USER_LOGOUT _IOW(FBEX_IOC_MAGIC, FBEX_USER_LOGOUT, FbeOpts)
84 #define FBEX_IOC_STATUS_REPORT _IOW(FBEX_IOC_MAGIC, FBEX_STATUS_REPORT, FbeOpts)
85 #define FBEX_READ_CLASS_E _IOWR(FBEX_IOC_MAGIC, FBEX_READ_EL5, FbeOptsE)
86 #define FBEX_WRITE_CLASS_E _IOWR(FBEX_IOC_MAGIC, FBEX_WRITE_EL5, FbeOptsE)
87 #define FBEX_ADD_CLASS_E _IOWR(FBEX_IOC_MAGIC, FBEX_ADD_EL5, FbeOptsE)
88 #define FBEX_DEL_USER_PINCODE _IOWR(FBEX_IOC_MAGIC, FBEX_DEL_EL5_PINCODE, FbeOptsE)
89 #define FBEX_ADD_APPKEY2 _IOWR(FBEX_IOC_MAGIC, FBEX_GENERATE_APP_KEY, FbeOptsE)
90 #define FBEX_CHANGE_PINCODE _IOWR(FBEX_IOC_MAGIC, FBEX_CHANGE_PINCODE, FbeOptsE)
91 #define FBEX_LOCK_UECE _IOWR(FBEX_IOC_MAGIC, FBEX_LOCK_EL5, FbeOptsE)
92
93 } // namespace
94
95 namespace OHOS {
96 namespace StorageDaemon {
IsFBEXSupported()97 bool FBEX::IsFBEXSupported()
98 {
99 std::string baseAddr;
100 if (!OHOS::LoadStringFromFile(FBEX_UFS_INLINE_BASE_ADDR, baseAddr)) {
101 LOGE("Read baseAddr failed, errno: %{public}d", errno);
102 return false;
103 }
104
105 std::string path = FBEX_UFS_INLINE_SUPPORT_PREFIX + baseAddr + FBEX_UFS_INLINE_SUPPORT_END;
106 std::string nvmePath = FBEX_NVME_INLINE_SUPPORT_PATH;
107 std::string emmcPath = FBEX_EMMC_INLINE_SUPPORT_PATH;
108 std::string rpath(PATH_MAX + 1, '\0');
109
110 if ((path.length() > PATH_MAX) || (realpath(path.c_str(), rpath.data()) == nullptr)) {
111 LOGE("realpath of %{public}s failed, errno: %{public}d", path.c_str(), errno);
112 return ((access(nvmePath.c_str(), F_OK) == 0) || (access(emmcPath.c_str(), F_OK) == 0));
113 }
114 if (rpath.rfind(FBEX_UFS_INLINE_SUPPORT_PREFIX) != 0) {
115 LOGE("rpath %{public}s is invalid", rpath.c_str());
116 return false;
117 }
118
119 std::string versionNum;
120 if (!OHOS::LoadStringFromFile(rpath, versionNum)) {
121 LOGE("read ufs_inline_stat failed, errno: %{public}d", errno);
122 return false;
123 }
124 return versionNum.compare(FBEX_INLINE_CRYPTO_V3) == 0;
125 }
126
CheckIvValid(const uint8_t * iv,uint32_t size)127 static inline bool CheckIvValid(const uint8_t *iv, uint32_t size)
128 {
129 return (iv != nullptr) && (size == FBEX_IV_SIZE);
130 }
131
CheckReadBuffValid(const uint8_t * eBuffer,uint32_t size,uint32_t status)132 static inline bool CheckReadBuffValid(const uint8_t *eBuffer, uint32_t size, uint32_t status)
133 {
134 if (status == UNLOCK_STATUS) {
135 return (eBuffer != nullptr) && (size == (GCM_NONCE_BYTES + AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES));
136 }
137 return (eBuffer != nullptr) && (size == AES_256_HASH_RANDOM_SIZE);
138 }
139
CheckWriteBuffValid(const uint8_t * eBuffer,uint32_t size,uint32_t status)140 static inline bool CheckWriteBuffValid(const uint8_t *eBuffer, uint32_t size, uint32_t status)
141 {
142 if (status == UNLOCK_STATUS) {
143 return (eBuffer != nullptr) && (size == AES_256_HASH_RANDOM_SIZE);
144 }
145 return (eBuffer != nullptr) && (size == (GCM_NONCE_BYTES + AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES));
146 }
147
InstallEL5KeyToKernel(uint32_t userIdSingle,uint32_t userIdDouble,uint8_t flag,bool & isSupport,bool & isNeedEncryptClassE)148 int FBEX::InstallEL5KeyToKernel(uint32_t userIdSingle, uint32_t userIdDouble, uint8_t flag,
149 bool &isSupport, bool &isNeedEncryptClassE)
150 {
151 LOGI("InstallEL5KeyToKernel enter, userId: %{public}d, flag: %{public}u", userIdDouble, flag);
152 FILE *f = fopen(FBEX_UECE_PATH, "r+");
153 if (f == nullptr) {
154 if (errno == ENOENT) {
155 LOGE("fbex_uece does not exist, fbe not support this command!");
156 isSupport = false;
157 return 0;
158 }
159 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
160 return -errno;
161 }
162 int fd = fileno(f);
163 if (fd < 0) {
164 if (errno == ENOENT) {
165 LOGE("fbex_uece does not exist, fbe not support this command!");
166 isSupport = false;
167 (void)fclose(f);
168 return 0;
169 }
170 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
171 (void)fclose(f);
172 return -errno;
173 }
174
175 FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
176 auto fbeRet = ioctl(fd, FBEX_ADD_CLASS_E, &ops);
177 if (static_cast<uint32_t>(fbeRet) == FILE_ENCRY_ERROR_UECE_ALREADY_CREATED) {
178 LOGE("class uece has already create, ret: 0x%{public}x, errno: %{public}d", fbeRet, errno);
179 isNeedEncryptClassE = false;
180 (void)fclose(f);
181 return 0;
182 }
183 int ret = 0;
184 if (fbeRet != 0) {
185 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", fbeRet, errno);
186 std::string extraData = "ioctl cmd=FBEX_ADD_CLASS_E, userIdSingle=" + std::to_string(userIdSingle)
187 + ", userIdDouble=" + std::to_string(userIdDouble) + ", errno=" + std::to_string(errno);
188 StorageRadar::ReportFbexResult("InstallEL5KeyToKernel", userIdSingle, fbeRet, "EL5", extraData);
189 ret = -errno;
190 }
191 (void)fclose(f);
192 LOGI("InstallEL5KeyToKernel success");
193 return ret;
194 }
195
InstallKeyToKernel(uint32_t userId,uint32_t type,uint8_t * iv,uint32_t size,uint8_t flag)196 int FBEX::InstallKeyToKernel(uint32_t userId, uint32_t type, uint8_t *iv, uint32_t size, uint8_t flag)
197 {
198 LOGI("enter, userId: %{public}d, type: %{public}u, flag: %{public}u", userId, type, flag);
199 if (!CheckIvValid(iv, size)) {
200 LOGE("install key param invalid");
201 return -EINVAL;
202 }
203
204 FILE *f = fopen(FBEX_CMD_PATH, "r+");
205 if (f == nullptr) {
206 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
207 return -errno;
208 }
209 int fd = fileno(f);
210 if (fd < 0) {
211 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
212 (void)fclose(f);
213 return -errno;
214 }
215
216 FbeOpts ops{.user = userId, .type = type, .len = size, .flag = flag};
217 auto err = memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
218 if (err != EOK) {
219 LOGE("memcpy failed %{public}d", err);
220 (void)fclose(f);
221 return 0;
222 }
223 int ret = ioctl(fd, FBEX_IOC_ADD_IV, &ops);
224 if (ret != 0) {
225 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
226 std::string extraData = "ioctl cmd=FBEX_IOC_ADD_IV, errno=" + std::to_string(errno);
227 StorageRadar::ReportFbexResult("InstallKeyToKernel", userId, ret, std::to_string(type), extraData);
228 (void)fclose(f);
229 return ret;
230 }
231 (void)fclose(f);
232
233 auto errops = memcpy_s(iv, size, ops.iv, sizeof(ops.iv));
234 if (errops != EOK) {
235 LOGE("memcpy failed %{public}d", errops);
236 return 0;
237 }
238 (void)memset_s(&ops.iv, sizeof(ops.iv), 0, sizeof(ops.iv));
239 LOGI("InstallKeyToKernel success");
240 return ret;
241 }
242
InstallDoubleDeKeyToKernel(UserIdToFbeStr & userIdToFbe,uint8_t * iv,uint32_t size,uint8_t flag)243 int FBEX::InstallDoubleDeKeyToKernel(UserIdToFbeStr &userIdToFbe, uint8_t *iv, uint32_t size, uint8_t flag)
244 {
245 LOGI("id-single: %{public}d, id-double: %{public}d, flag: %{public}u",
246 userIdToFbe.userIds[SINGLE_ID_INDEX], userIdToFbe.userIds[DOUBLE_ID_INDEX], flag);
247 if (!CheckIvValid(iv, size)) {
248 LOGE("install key param invalid");
249 return -EINVAL;
250 }
251
252 int fd = open(FBEX_UECE_PATH, O_RDWR);
253 if (fd < 0) {
254 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
255 return -errno;
256 }
257
258 FbeOptsE ops{ .userIdDouble = userIdToFbe.userIds[DOUBLE_ID_INDEX],
259 .userIdSingle = userIdToFbe.userIds[SINGLE_ID_INDEX],
260 .status = flag,
261 .length = size };
262 // eBuffer -> iv
263 auto err = memcpy_s(ops.eBuffer, sizeof(ops.eBuffer), iv, size);
264 if (err != EOK) {
265 LOGE("memcpy failed %{public}d", err);
266 return 0;
267 }
268 int ret = ioctl(fd, FBEX_IOC_ADD_DOUBLE_DE_IV, &ops);
269 if (ret != 0) {
270 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
271 std::string extraData = "ioctl cmd=FBEX_IOC_ADD_DOUBLE_DE_IV, userIdSingle=" + std::to_string(ops.userIdSingle)
272 + ", userIdDouble=" + std::to_string(ops.userIdDouble) + ", errno=" + std::to_string(errno);
273 StorageRadar::ReportFbexResult("InstallDoubleDeKeyToKernel", ops.userIdSingle, ret, "EL1", extraData);
274 close(fd);
275 return ret;
276 }
277 close(fd);
278 auto errops = memcpy_s(iv, size, ops.eBuffer, sizeof(ops.eBuffer));
279 if (errops != EOK) {
280 LOGE("memcpy failed %{public}d", errops);
281 return 0;
282 }
283 LOGI("InstallDoubleDeKeyToKernel success");
284 return ret;
285 }
286
287
UninstallOrLockUserKeyToKernel(uint32_t userId,uint32_t type,uint8_t * iv,uint32_t size,bool destroy)288 int FBEX::UninstallOrLockUserKeyToKernel(uint32_t userId, uint32_t type, uint8_t *iv, uint32_t size, bool destroy)
289 {
290 LOGI("enter, userId: %{public}d, type: %{public}u, flag: %{public}d", userId, type, destroy);
291 if (!CheckIvValid(iv, size)) {
292 LOGE("uninstall key param invalid");
293 return -EINVAL;
294 }
295
296 FILE *f = fopen(FBEX_CMD_PATH, "r+");
297 if (f == nullptr) {
298 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
299 return -errno;
300 }
301 int fd = fileno(f);
302 if (fd < 0) {
303 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
304 (void)fclose(f);
305 return -errno;
306 }
307
308 FbeOpts ops{.user = userId, .type = type, .len = size};
309 auto err = memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
310 if (err != EOK) {
311 LOGE("memcpy failed %{public}d", err);
312 (void)fclose(f);
313 return 0;
314 }
315 int ret = ioctl(fd, destroy ? FBEX_IOC_DEL_IV : FBEX_IOC_USER_LOGOUT, &ops);
316 if (ret != 0 && static_cast<uint32_t>(ret) != FILE_ENCRY_ERROR_NOT_FOUND_UECE) {
317 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
318 std::string febxCmd = destroy ? "FBEX_IOC_DEL_IV" : "FBEX_IOC_USER_LOGOUT";
319 std::string extraData = "ioctl cmd=" + febxCmd + ", errno=" + std::to_string(errno);
320 StorageRadar::ReportFbexResult("UninstallOrLockUserKeyToKernel", userId, ret, std::to_string(type), extraData);
321 (void)fclose(f);
322 return ret;
323 }
324 (void)fclose(f);
325 LOGI("success");
326 return 0;
327 }
328
DeleteClassEPinCode(uint32_t userIdSingle,uint32_t userIdDouble)329 int FBEX::DeleteClassEPinCode(uint32_t userIdSingle, uint32_t userIdDouble)
330 {
331 LOGI("enter, userId: %{public}d", userIdDouble);
332 FILE *f = fopen(FBEX_UECE_PATH, "r+");
333 if (f == nullptr) {
334 if (errno == ENOENT) {
335 LOGE("fbex_uece does not exist, fbe not support this command!");
336 return 0;
337 }
338 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
339 return -errno;
340 }
341 int fd = fileno(f);
342 if (fd < 0) {
343 if (errno == ENOENT) {
344 LOGE("fbex_uece does not exist, fbe not support this command!");
345 (void)fclose(f);
346 return 0;
347 }
348 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
349 (void)fclose(f);
350 return -errno;
351 }
352 FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
353 auto fbeRet = ioctl(fd, FBEX_DEL_USER_PINCODE, &ops);
354 int ret = 0;
355 if (fbeRet != 0) {
356 LOGE("ioctl fbex_cmd failed, fbeRet: 0x%{public}x, errno: %{public}d", fbeRet, errno);
357 std::string extraData = "ioctl cmd=FBEX_DEL_USER_PINCODE, userIdSingle=" + std::to_string(userIdSingle)
358 + ", userIdDouble=" + std::to_string(userIdDouble) + ", errno=" + std::to_string(errno);
359 StorageRadar::ReportFbexResult("DeleteClassEPinCode", userIdSingle, ret, "EL5", extraData);
360 ret = -errno;
361 }
362 (void)fclose(f);
363 LOGI("success");
364 return ret;
365 }
366
ChangePinCodeClassE(uint32_t userIdSingle,uint32_t userIdDouble,bool & isFbeSupport)367 int FBEX::ChangePinCodeClassE(uint32_t userIdSingle, uint32_t userIdDouble, bool &isFbeSupport)
368 {
369 LOGI("enter, userId: %{public}d", userIdDouble);
370 FILE *f = fopen(FBEX_UECE_PATH, "r+");
371 if (f == nullptr) {
372 if (errno == ENOENT) {
373 LOGE("fbex_uece does not exist, fbe not support this command!");
374 isFbeSupport = false;
375 return 0;
376 }
377 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
378 return -errno;
379 }
380 int fd = fileno(f);
381 if (fd < 0) {
382 if (errno == ENOENT) {
383 LOGE("fbex_uece does not exist, fbe not support this command!");
384 isFbeSupport = false;
385 (void)fclose(f);
386 return 0;
387 }
388 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
389 (void)fclose(f);
390 return -errno;
391 }
392 FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
393 int ret = ioctl(fd, FBEX_CHANGE_PINCODE, &ops);
394 if (ret != 0) {
395 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
396 std::string extraData = "ioctl cmd=FBEX_CHANGE_PINCODE, userIdSingle=" + std::to_string(userIdSingle)
397 + ", userIdDouble=" + std::to_string(userIdDouble) + ", errno=" + std::to_string(errno);
398 StorageRadar::ReportFbexResult("ChangePinCodeClassE", userIdSingle, ret, "EL5", extraData);
399 ret = -errno;
400 }
401 (void)fclose(f);
402 LOGI("change pincode classE finish.");
403 return ret;
404 }
405
406 // for el3 & el4
LockScreenToKernel(uint32_t userId)407 int FBEX::LockScreenToKernel(uint32_t userId)
408 {
409 LOGI("enter, userId: %{public}d", userId);
410
411 FILE *f = fopen(FBEX_CMD_PATH, "r+");
412 if (f == nullptr) {
413 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
414 return -errno;
415 }
416 int fd = fileno(f);
417 if (fd < 0) {
418 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
419 (void)fclose(f);
420 return -errno;
421 }
422 FbeOpts ops;
423 (void)memset_s(&ops, sizeof(FbeOpts), 0, sizeof(FbeOpts));
424 ops.user = userId;
425 int ret = ioctl(fd, FBEX_IOC_LOCK_SCREEN, &ops);
426 if (ret != 0) {
427 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
428 }
429 (void)fclose(f);
430 LOGI("success");
431 return ret;
432 }
433
GenerateAppkey(UserIdToFbeStr & userIdToFbe,uint32_t hashId,std::unique_ptr<uint8_t[]> & appKey,uint32_t size)434 int FBEX::GenerateAppkey(UserIdToFbeStr &userIdToFbe, uint32_t hashId, std::unique_ptr<uint8_t[]> &appKey,
435 uint32_t size)
436 {
437 LOGI("GenerateAppkey enter");
438 FILE *f = fopen(FBEX_UECE_PATH, "r+");
439 if (f == nullptr) {
440 if (errno == ENOENT) {
441 LOGE("fbex_uece does not exist, fbe not support this command!");
442 appKey.reset(nullptr);
443 return 0;
444 }
445 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
446 return -errno;
447 }
448 int fd = fileno(f);
449 if (fd < 0) {
450 if (errno == ENOENT) {
451 LOGE("fbex_uece does not exist, fbe not support this command!");
452 appKey.reset(nullptr);
453 (void)fclose(f);
454 return 0;
455 }
456 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
457 (void)fclose(f);
458 return -errno;
459 }
460 FbeOptsE ops{ .userIdDouble = userIdToFbe.userIds[DOUBLE_ID_INDEX],
461 .userIdSingle = userIdToFbe.userIds[SINGLE_ID_INDEX],
462 .status = hashId, .length = size };
463 auto fbeRet = ioctl(fd, FBEX_ADD_APPKEY2, &ops);
464 if (fbeRet != 0) {
465 LOGE("ioctl fbex_cmd failed, fbeRet: 0x%{public}x, errno: %{public}d", fbeRet, errno);
466 (void)fclose(f);
467 return -errno;
468 }
469
470 auto err = memcpy_s(appKey.get(), size, ops.eBuffer, sizeof(ops.eBuffer));
471 if (err != EOK) {
472 LOGE("memcpy failed %{public}d", err);
473 (void)fclose(f);
474 return 0;
475 }
476 (void)fclose(f);
477 LOGI("success");
478 return 0;
479 }
480
481 // for el5
LockUece(uint32_t userIdSingle,uint32_t userIdDouble,bool & isFbeSupport)482 int FBEX::LockUece(uint32_t userIdSingle, uint32_t userIdDouble, bool &isFbeSupport)
483 {
484 LOGI("enter, userId: %{public}d", userIdDouble);
485
486 FILE *f = fopen(FBEX_UECE_PATH, "r+");
487 if (f == nullptr) {
488 if (errno == ENOENT) {
489 LOGE("fbex_uece does not exist, fbe not support this command!");
490 isFbeSupport = false;
491 return 0;
492 }
493 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
494 return -errno;
495 }
496 int fd = fileno(f);
497 if (fd < 0) {
498 if (errno == ENOENT) {
499 LOGE("fbex_uece does not exist, fbe not support this command!");
500 isFbeSupport = false;
501 (void)fclose(f);
502 return 0;
503 }
504 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
505 (void)fclose(f);
506 return -errno;
507 }
508 FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
509 int ret = ioctl(fd, FBEX_LOCK_UECE, &ops);
510 if (ret != 0) {
511 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
512 }
513 (void)fclose(f);
514 LOGI("success");
515 return ret;
516 }
517
UnlockScreenToKernel(uint32_t userId,uint32_t type,uint8_t * iv,uint32_t size)518 int FBEX::UnlockScreenToKernel(uint32_t userId, uint32_t type, uint8_t *iv, uint32_t size)
519 {
520 LOGI("enter, userId: %{public}d, type: %{public}u", userId, type);
521 if (!CheckIvValid(iv, size)) {
522 LOGE("install key param invalid");
523 return -EINVAL;
524 }
525
526 FILE *f = fopen(FBEX_CMD_PATH, "r+");
527 if (f == nullptr) {
528 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
529 return -errno;
530 }
531 int fd = fileno(f);
532 if (fd < 0) {
533 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
534 (void)fclose(f);
535 return -errno;
536 }
537
538 FbeOpts ops{.user = userId, .type = type, .len = size};
539
540 auto err = memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
541 if (err != EOK) {
542 LOGE("memcpy failed %{public}d", err);
543 (void)fclose(f);
544 return 0;
545 }
546 int ret = ioctl(fd, FBEX_IOC_UNLOCK_SCREEN, &ops);
547 if (ret != 0) {
548 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
549 std::string extraData = "ioctl cmd=FBEX_IOC_UNLOCK_SCREEN, errno=" + std::to_string(errno);
550 StorageRadar::ReportFbexResult("UnlockScreenToKernel", userId, ret, std::to_string(type), extraData);
551 (void)fclose(f);
552 return ret;
553 }
554 (void)fclose(f);
555
556 auto errops = memcpy_s(iv, size, ops.iv, sizeof(ops.iv));
557 if (errops != EOK) {
558 LOGE("memcpy failed %{public}d", errops);
559 return 0;
560 }
561 LOGI("UnlockScreenToKernel success");
562 return ret;
563 }
564
CheckPreconditions(UserIdToFbeStr & userIdToFbe,uint32_t status,std::unique_ptr<uint8_t[]> & eBuffer,uint32_t length,bool & isFbeSupport)565 bool FBEX::CheckPreconditions(UserIdToFbeStr &userIdToFbe, uint32_t status, std::unique_ptr<uint8_t[]> &eBuffer,
566 uint32_t length, bool &isFbeSupport)
567 {
568 LOGI("enter, userId: %{public}d, status: %{public}u", userIdToFbe.userIds[DOUBLE_ID_INDEX], status);
569 if (!CheckReadBuffValid(eBuffer.get(), length, status)) {
570 LOGE("read e secret invalid");
571 return false;
572 }
573 return true;
574 }
575
HandleIoctlError(int ret,int errnoVal,const std::string & cmd,uint32_t userIdSingle,uint32_t userIdDouble)576 void FBEX::HandleIoctlError(int ret, int errnoVal, const std::string &cmd, uint32_t userIdSingle,
577 uint32_t userIdDouble)
578 {
579 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errnoVal);
580 std::string extraData = "ioctl cmd=" + cmd + ", userIdSingle=" + std::to_string(userIdSingle)
581 + ", userIdDouble=" + std::to_string(userIdDouble) + ", errno=" + std::to_string(errnoVal);
582 StorageRadar::ReportFbexResult("InstallDoubleDeKeyToKernel", userIdSingle, ret, "EL5", extraData);
583 }
584
ReadESecretToKernel(UserIdToFbeStr & userIdToFbe,uint32_t status,std::unique_ptr<uint8_t[]> & eBuffer,uint32_t length,bool & isFbeSupport)585 int FBEX::ReadESecretToKernel(UserIdToFbeStr &userIdToFbe, uint32_t status, std::unique_ptr<uint8_t[]> &eBuffer,
586 uint32_t length, bool &isFbeSupport)
587 {
588 if (!CheckPreconditions(userIdToFbe, status, eBuffer, length, isFbeSupport)) {
589 return -EINVAL;
590 }
591 FILE *f = fopen(FBEX_UECE_PATH, "r+");
592 if (f == nullptr) {
593 if (errno == ENOENT) {
594 isFbeSupport = false;
595 return 0;
596 }
597 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
598 return -errno;
599 }
600 int fd = fileno(f);
601 if (fd < 0) {
602 if (errno == ENOENT) {
603 isFbeSupport = false;
604 (void)fclose(f);
605 return 0;
606 }
607 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
608 (void)fclose(f);
609 return -errno;
610 }
611 uint32_t bufferSize = AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES + GCM_NONCE_BYTES;
612 FbeOptsE ops{ .userIdDouble = userIdToFbe.userIds[DOUBLE_ID_INDEX],
613 .userIdSingle = userIdToFbe.userIds[SINGLE_ID_INDEX], .status = status, .length = bufferSize };
614 auto err = memcpy_s(ops.eBuffer, sizeof(ops.eBuffer), eBuffer.get(), length);
615 if (err != EOK) {
616 LOGE("memcpy failed %{public}d", err);
617 (void)fclose(f);
618 return 0;
619 }
620 auto ret = ioctl(fd, FBEX_READ_CLASS_E, &ops);
621 if (ret != 0) {
622 HandleIoctlError(ret, errno, "FBEX_READ_CLASS_E", ops.userIdSingle, ops.userIdDouble);
623 (void)fclose(f);
624 return -errno;
625 }
626 (void)fclose(f);
627 if (ops.length == 0) {
628 (void)memset_s(eBuffer.get(), sizeof(eBuffer.get()), 0, sizeof(eBuffer.get()));
629 eBuffer.reset(nullptr);
630 LOGE("ops length is 0, skip");
631 return 0;
632 }
633 UnlockSendSecret(status, bufferSize, length, eBuffer.get(), ops.eBuffer);
634 LOGI("ReadESecretToKernel success");
635 return 0;
636 }
637
UnlockSendSecret(uint32_t status,uint32_t bufferSize,uint32_t length,uint8_t * eBuffer,uint8_t * opseBuffer)638 int FBEX::UnlockSendSecret(uint32_t status, uint32_t bufferSize, uint32_t length, uint8_t *eBuffer, uint8_t *opseBuffer)
639 {
640 if (status == UNLOCK_STATUS) {
641 bufferSize = AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES + GCM_NONCE_BYTES;
642 } else {
643 bufferSize = AES_256_HASH_RANDOM_SIZE;
644 }
645 auto errBuffer = memcpy_s(eBuffer, length, opseBuffer, bufferSize);
646 if (errBuffer != EOK) {
647 LOGE("memcpy failed %{public}d", errBuffer);
648 return 0;
649 }
650 return 0;
651 }
652
WriteESecretToKernel(UserIdToFbeStr & userIdToFbe,uint32_t status,uint8_t * eBuffer,uint32_t length)653 int FBEX::WriteESecretToKernel(UserIdToFbeStr &userIdToFbe, uint32_t status, uint8_t *eBuffer, uint32_t length)
654 {
655 LOGI("enter, userId: %{public}d, status: %{public}u", userIdToFbe.userIds[DOUBLE_ID_INDEX], status);
656 if (!CheckWriteBuffValid(eBuffer, length, status)) {
657 LOGE("write e secret param invalid");
658 return -EINVAL;
659 }
660
661 FILE *f = fopen(FBEX_UECE_PATH, "r+");
662 if (f == nullptr) {
663 if (errno == ENOENT) {
664 LOGE("fbex_uece does not exist, fbe not support this command!");
665 return 0;
666 }
667 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
668 return -errno;
669 }
670 int fd = fileno(f);
671 if (fd < 0) {
672 if (errno == ENOENT) {
673 LOGE("fbex_uece does not exist, fbe not support this command!");
674 (void)fclose(f);
675 return 0;
676 }
677 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
678 (void)fclose(f);
679 return -errno;
680 }
681 uint32_t bufferSize = AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES + GCM_NONCE_BYTES;
682 FbeOptsE ops{ .userIdDouble = userIdToFbe.userIds[DOUBLE_ID_INDEX],
683 .userIdSingle = userIdToFbe.userIds[SINGLE_ID_INDEX],
684 .status = status, .length = bufferSize };
685 auto err = memcpy_s(ops.eBuffer, sizeof(ops.eBuffer), eBuffer, length);
686 if (err != EOK) {
687 LOGE("memcpy failed %{public}d", err);
688 (void)fclose(f);
689 return 0;
690 }
691 auto ret = ioctl(fd, FBEX_WRITE_CLASS_E, &ops);
692 if (ret != 0) {
693 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
694 std::string extraData = "ioctl cmd=FBEX_WRITE_CLASS_E, userIdSingle=" + std::to_string(ops.userIdSingle)
695 + ", userIdDouble=" + std::to_string(ops.userIdDouble) + ", errno=" + std::to_string(errno);
696 StorageRadar::ReportFbexResult("InstallDoubleDeKeyToKernel", ops.userIdSingle, ret, "EL5", extraData);
697 (void)fclose(f);
698 return -errno;
699 }
700 (void)fclose(f);
701 LOGI("success");
702 return 0;
703 }
704
IsMspReady()705 bool FBEX::IsMspReady()
706 {
707 std::string status;
708 (void)OHOS::LoadStringFromFile(FBEX_CMD_PATH, status);
709 return status == "true";
710 }
711
GetStatus()712 int FBEX::GetStatus()
713 {
714 FILE *f = fopen(FBEX_CMD_PATH, "r+");
715 if (f == nullptr) {
716 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
717 return -errno;
718 }
719 int fd = fileno(f);
720 if (fd < 0) {
721 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
722 (void)fclose(f);
723 return -errno;
724 }
725
726 FbeOpts ops;
727 int ret = ioctl(fd, FBEX_IOC_STATUS_REPORT, &ops);
728 (void)fclose(f);
729 return ret;
730 }
731 } // namespace StorageDaemon
732 } // namespace OHOS
733