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 <cerrno>
19 #include <cstdio>
20 #include <fcntl.h>
21 #include <securec.h>
22 #include <string>
23 #include <sys/ioctl.h>
24 #include <unistd.h>
25
26 #include "file_ex.h"
27 #include "storage_service_log.h"
28 #include "openssl_crypto.h"
29
30 namespace {
31 constexpr const char *FBEX_UFS_INLINE_SUPPORT_PREFIX = "/sys/devices/platform/";
32 constexpr const char *FBEX_UFS_INLINE_SUPPORT_END = "/ufs_inline_stat";
33 constexpr const char *FBEX_NVME_INLINE_SUPPORT_PATH = "/sys/block/nvme_crypto";
34 constexpr const char *FBEX_UFS_INLINE_BASE_ADDR = "/proc/bootdevice/name";
35 constexpr const char *FBEX_INLINE_CRYPTO_V3 = "3\n";
36
37 constexpr const char *FBEX_CMD_PATH = "/dev/fbex_cmd";
38 constexpr const char *FBEX_UECE_PATH = "/dev/fbex_uece";
39
40 const uint8_t FBEX_IOC_MAGIC = 'f';
41 const uint8_t FBEX_ADD_IV = 0x1;
42 const uint8_t FBEX_DEL_IV = 0x2;
43 const uint8_t FBEX_LOCK_SCREEN = 0x3;
44 const uint8_t FBEX_UNLOCK_SCREEN = 0x4;
45 const uint8_t FBEX_USER_LOGOUT = 0x8;
46 const uint8_t FBEX_STATUS_REPORT = 0xC;
47 const uint8_t FBEX_ADD_EL5 = 21;
48 const uint8_t FBEX_READ_EL5 = 22;
49 const uint8_t FBEX_WRITE_EL5 = 23;
50 const uint8_t FBEX_DEL_EL5_PINCODE = 24;
51 const uint8_t FBEX_GENERATE_APP_KEY = 25;
52 const uint8_t FBEX_CHANGE_PINCODE = 26;
53 const uint8_t FBEX_LOCK_EL5 = 27;
54 const uint32_t FILE_ENCRY_ERROR_UECE_ALREADY_CREATED = 0xFBE30031;
55
56 struct FbeOptStr {
57 uint32_t user = 0;
58 uint32_t type = 0;
59 uint32_t len = 0;
60 uint8_t iv[OHOS::StorageDaemon::FBEX_IV_SIZE] = {0};
61 uint8_t flag = 0;
62 };
63 using FbeOpts = FbeOptStr;
64
65 struct FbeOptStrE {
66 uint32_t userIdDouble = 0;
67 uint32_t userIdSingle = 0;
68 uint32_t status = 0;
69 uint32_t length = 0;
70 uint8_t eBuffer[OHOS::StorageDaemon::FBEX_E_BUFFER_SIZE] = {0};
71 };
72 using FbeOptsE = FbeOptStrE;
73
74 #define FBEX_IOC_ADD_IV _IOWR(FBEX_IOC_MAGIC, FBEX_ADD_IV, FbeOpts)
75 #define FBEX_IOC_DEL_IV _IOW(FBEX_IOC_MAGIC, FBEX_DEL_IV, FbeOpts)
76 #define FBEX_IOC_LOCK_SCREEN _IOW(FBEX_IOC_MAGIC, FBEX_LOCK_SCREEN, FbeOpts)
77 #define FBEX_IOC_UNLOCK_SCREEN _IOWR(FBEX_IOC_MAGIC, FBEX_UNLOCK_SCREEN, FbeOpts)
78 #define FBEX_IOC_USER_LOGOUT _IOW(FBEX_IOC_MAGIC, FBEX_USER_LOGOUT, FbeOpts)
79 #define FBEX_IOC_STATUS_REPORT _IOW(FBEX_IOC_MAGIC, FBEX_STATUS_REPORT, FbeOpts)
80 #define FBEX_READ_CLASS_E _IOWR(FBEX_IOC_MAGIC, FBEX_READ_EL5, FbeOptsE)
81 #define FBEX_WRITE_CLASS_E _IOWR(FBEX_IOC_MAGIC, FBEX_WRITE_EL5, FbeOptsE)
82 #define FBEX_ADD_CLASS_E _IOWR(FBEX_IOC_MAGIC, FBEX_ADD_EL5, FbeOptsE)
83 #define FBEX_DEL_USER_PINCODE _IOWR(FBEX_IOC_MAGIC, FBEX_DEL_EL5_PINCODE, FbeOptsE)
84 #define FBEX_ADD_APPKEY2 _IOWR(FBEX_IOC_MAGIC, FBEX_GENERATE_APP_KEY, FbeOptsE)
85 #define FBEX_CHANGE_PINCODE _IOWR(FBEX_IOC_MAGIC, FBEX_CHANGE_PINCODE, FbeOptsE)
86 #define FBEX_LOCK_UECE _IOWR(FBEX_IOC_MAGIC, FBEX_LOCK_EL5, FbeOptsE)
87
88 } // namespace
89
90 namespace OHOS {
91 namespace StorageDaemon {
IsFBEXSupported()92 bool FBEX::IsFBEXSupported()
93 {
94 std::string baseAddr;
95 if (!OHOS::LoadStringFromFile(FBEX_UFS_INLINE_BASE_ADDR, baseAddr)) {
96 LOGE("Read baseAddr failed, errno: %{public}d", errno);
97 return false;
98 }
99
100 std::string path = FBEX_UFS_INLINE_SUPPORT_PREFIX + baseAddr + FBEX_UFS_INLINE_SUPPORT_END;
101 std::string nvmePath = FBEX_NVME_INLINE_SUPPORT_PATH;
102 std::string rpath(PATH_MAX + 1, '\0');
103
104 if ((path.length() > PATH_MAX) || (realpath(path.c_str(), rpath.data()) == nullptr)) {
105 LOGE("realpath of %{public}s failed, errno: %{public}d", path.c_str(), errno);
106 return access(nvmePath.c_str(), F_OK) == 0;
107 }
108 if (rpath.rfind(FBEX_UFS_INLINE_SUPPORT_PREFIX) != 0) {
109 LOGE("rpath %{public}s is invalid", rpath.c_str());
110 return false;
111 }
112
113 std::string versionNum;
114 if (!OHOS::LoadStringFromFile(rpath, versionNum)) {
115 LOGE("read ufs_inline_stat failed, errno: %{public}d", errno);
116 return false;
117 }
118 return versionNum.compare(FBEX_INLINE_CRYPTO_V3) == 0;
119 }
120
CheckIvValid(const uint8_t * iv,uint32_t size)121 static inline bool CheckIvValid(const uint8_t *iv, uint32_t size)
122 {
123 return (iv != nullptr) && (size == FBEX_IV_SIZE);
124 }
125
CheckReadBuffValid(const uint8_t * eBuffer,uint32_t size,uint32_t status)126 static inline bool CheckReadBuffValid(const uint8_t *eBuffer, uint32_t size, uint32_t status)
127 {
128 if (status == UNLOCK_STATUS) {
129 return (eBuffer != nullptr) && (size == (GCM_NONCE_BYTES + AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES));
130 }
131 return (eBuffer != nullptr) && (size == AES_256_HASH_RANDOM_SIZE);
132 }
133
CheckWriteBuffValid(const uint8_t * eBuffer,uint32_t size,uint32_t status)134 static inline bool CheckWriteBuffValid(const uint8_t *eBuffer, uint32_t size, uint32_t status)
135 {
136 if (status == UNLOCK_STATUS) {
137 return (eBuffer != nullptr) && (size == AES_256_HASH_RANDOM_SIZE);
138 }
139 return (eBuffer != nullptr) && (size == (GCM_NONCE_BYTES + AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES));
140 }
141
InstallEL5KeyToKernel(uint32_t userIdSingle,uint32_t userIdDouble,uint8_t flag,bool & isSupport,bool & isNeedEncryptClassE)142 int FBEX::InstallEL5KeyToKernel(uint32_t userIdSingle, uint32_t userIdDouble, uint8_t flag,
143 bool &isSupport, bool &isNeedEncryptClassE)
144 {
145 LOGI("InstallEL5KeyToKernel enter, userId: %{public}d, flag: %{public}u", userIdDouble, flag);
146 int fd = open(FBEX_UECE_PATH, O_RDWR);
147 if (fd < 0) {
148 if (errno == ENOENT) {
149 LOGE("fbex_uece does not exist, fbe not support this command!");
150 isSupport = false;
151 return 0;
152 }
153 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
154 return -errno;
155 }
156
157 FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
158 auto fbeRet = ioctl(fd, FBEX_ADD_CLASS_E, &ops);
159 if (static_cast<uint32_t>(fbeRet) == FILE_ENCRY_ERROR_UECE_ALREADY_CREATED) {
160 LOGE("class uece has already create, ret: 0x%{public}x, errno: %{public}d", fbeRet, errno);
161 isNeedEncryptClassE = false;
162 close(fd);
163 return 0;
164 }
165 int ret = 0;
166 if (fbeRet != 0) {
167 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", fbeRet, errno);
168 ret = -errno;
169 }
170 close(fd);
171 LOGI("InstallEL5KeyToKernel success");
172 return ret;
173 }
174
InstallKeyToKernel(uint32_t userId,uint32_t type,uint8_t * iv,uint32_t size,uint8_t flag)175 int FBEX::InstallKeyToKernel(uint32_t userId, uint32_t type, uint8_t *iv, uint32_t size, uint8_t flag)
176 {
177 LOGI("enter, userId: %{public}d, type: %{public}u, flag: %{public}u", userId, type, flag);
178 if (!CheckIvValid(iv, size)) {
179 LOGE("install key param invalid");
180 return -EINVAL;
181 }
182
183 int fd = open(FBEX_CMD_PATH, O_RDWR);
184 if (fd < 0) {
185 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
186 return -errno;
187 }
188
189 FbeOpts ops{.user = userId, .type = type, .len = size, .flag = flag};
190 auto err = memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
191 if (err != EOK) {
192 LOGE("memcpy failed %{public}d", err);
193 close(fd);
194 return 0;
195 }
196 int ret = ioctl(fd, FBEX_IOC_ADD_IV, &ops);
197 if (ret != 0) {
198 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
199 close(fd);
200 return ret;
201 }
202 close(fd);
203
204 auto errops = memcpy_s(iv, size, ops.iv, sizeof(ops.iv));
205 if (errops != EOK) {
206 LOGE("memcpy failed %{public}d", errops);
207 return 0;
208 }
209 LOGI("InstallKeyToKernel success");
210 return ret;
211 }
212
UninstallOrLockUserKeyToKernel(uint32_t userId,uint32_t type,uint8_t * iv,uint32_t size,bool destroy)213 int FBEX::UninstallOrLockUserKeyToKernel(uint32_t userId, uint32_t type, uint8_t *iv, uint32_t size, bool destroy)
214 {
215 LOGI("enter, userId: %{public}d, type: %{public}u, flag: %{public}d", userId, type, destroy);
216 if (!CheckIvValid(iv, size)) {
217 LOGE("uninstall key param invalid");
218 return -EINVAL;
219 }
220
221 int fd = open(FBEX_CMD_PATH, O_RDWR);
222 if (fd < 0) {
223 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
224 return -errno;
225 }
226
227 FbeOpts ops{.user = userId, .type = type, .len = size};
228 auto err = memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
229 if (err != EOK) {
230 LOGE("memcpy failed %{public}d", err);
231 close(fd);
232 return 0;
233 }
234 int ret = ioctl(fd, destroy ? FBEX_IOC_DEL_IV : FBEX_IOC_USER_LOGOUT, &ops);
235 if (ret != 0) {
236 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
237 }
238 close(fd);
239 LOGI("success");
240 return ret;
241 }
242
DeleteClassEPinCode(uint32_t userIdSingle,uint32_t userIdDouble)243 int FBEX::DeleteClassEPinCode(uint32_t userIdSingle, uint32_t userIdDouble)
244 {
245 LOGI("enter, userId: %{public}d", userIdDouble);
246 int fd = open(FBEX_UECE_PATH, O_RDWR);
247 if (fd < 0) {
248 if (errno == ENOENT) {
249 LOGE("fbex_uece does not exist, fbe not support this command!");
250 return 0;
251 }
252 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
253 return -errno;
254 }
255 FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
256 auto fbeRet = ioctl(fd, FBEX_DEL_USER_PINCODE, &ops);
257 int ret = 0;
258 if (fbeRet != 0) {
259 LOGE("ioctl fbex_cmd failed, fbeRet: 0x%{public}x, errno: %{public}d", fbeRet, errno);
260 ret = -errno;
261 }
262 close(fd);
263 LOGI("success");
264 return ret;
265 }
266
ChangePinCodeClassE(uint32_t userIdSingle,uint32_t userIdDouble,bool & isFbeSupport)267 int FBEX::ChangePinCodeClassE(uint32_t userIdSingle, uint32_t userIdDouble, bool &isFbeSupport)
268 {
269 LOGI("enter, userId: %{public}d", userIdDouble);
270 int fd = open(FBEX_UECE_PATH, O_RDWR);
271 if (fd < 0) {
272 if (errno == ENOENT) {
273 LOGE("fbex_uece does not exist, fbe not support this command!");
274 isFbeSupport = false;
275 return 0;
276 }
277 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
278 return -errno;
279 }
280 FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
281 int ret = ioctl(fd, FBEX_CHANGE_PINCODE, &ops);
282 if (ret != 0) {
283 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
284 ret = -errno;
285 }
286 close(fd);
287 LOGI("change pincode classE finish.");
288 return ret;
289 }
290
291 // for el3 & el4
LockScreenToKernel(uint32_t userId)292 int FBEX::LockScreenToKernel(uint32_t userId)
293 {
294 LOGI("enter, userId: %{public}d", userId);
295
296 int fd = open(FBEX_CMD_PATH, O_RDWR);
297 if (fd < 0) {
298 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
299 return -errno;
300 }
301 FbeOpts ops;
302 (void)memset_s(&ops, sizeof(FbeOpts), 0, sizeof(FbeOpts));
303 ops.user = userId;
304 int ret = ioctl(fd, FBEX_IOC_LOCK_SCREEN, &ops);
305 if (ret != 0) {
306 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
307 }
308 close(fd);
309 LOGI("success");
310 return ret;
311 }
312
GenerateAppkey(UserIdToFbeStr & userIdToFbe,uint32_t hashId,std::unique_ptr<uint8_t[]> & appKey,uint32_t size)313 int FBEX::GenerateAppkey(UserIdToFbeStr &userIdToFbe, uint32_t hashId, std::unique_ptr<uint8_t[]> &appKey,
314 uint32_t size)
315 {
316 LOGI("GenerateAppkey enter");
317 int fd = open(FBEX_UECE_PATH, O_RDWR);
318 if (fd < 0) {
319 if (errno == ENOENT) {
320 LOGE("fbex_uece does not exist, fbe not support this command!");
321 appKey.reset(nullptr);
322 return 0;
323 }
324 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
325 return -errno;
326 }
327 FbeOptsE ops{ .userIdDouble = userIdToFbe.userIds[DOUBLE_ID_INDEX],
328 .userIdSingle = userIdToFbe.userIds[SINGLE_ID_INDEX],
329 .status = hashId, .length = size };
330 auto fbeRet = ioctl(fd, FBEX_ADD_APPKEY2, &ops);
331 if (fbeRet != 0) {
332 LOGE("ioctl fbex_cmd failed, fbeRet: 0x%{public}x, errno: %{public}d", fbeRet, errno);
333 close(fd);
334 return -errno;
335 }
336
337 auto err = memcpy_s(appKey.get(), size, ops.eBuffer, sizeof(ops.eBuffer));
338 if (err != EOK) {
339 LOGE("memcpy failed %{public}d", err);
340 return 0;
341 }
342 close(fd);
343 LOGI("success");
344 return 0;
345 }
346
347 // for el5
LockUece(uint32_t userIdSingle,uint32_t userIdDouble,bool & isFbeSupport)348 int FBEX::LockUece(uint32_t userIdSingle, uint32_t userIdDouble, bool &isFbeSupport)
349 {
350 LOGD("enter, userId: %{public}d", userIdDouble);
351
352 int fd = open(FBEX_UECE_PATH, O_RDWR);
353 if (fd < 0) {
354 if (errno == ENOENT) {
355 LOGE("fbex_uece does not exist, fbe not support this command!");
356 isFbeSupport = false;
357 return 0;
358 }
359 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
360 return -errno;
361 }
362 FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
363 int ret = ioctl(fd, FBEX_LOCK_UECE, &ops);
364 if (ret != 0) {
365 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
366 }
367 close(fd);
368 LOGD("success");
369 return ret;
370 }
371
UnlockScreenToKernel(uint32_t userId,uint32_t type,uint8_t * iv,uint32_t size)372 int FBEX::UnlockScreenToKernel(uint32_t userId, uint32_t type, uint8_t *iv, uint32_t size)
373 {
374 LOGI("enter, userId: %{public}d, type: %{public}u", userId, type);
375 if (!CheckIvValid(iv, size)) {
376 LOGE("install key param invalid");
377 return -EINVAL;
378 }
379
380 int fd = open(FBEX_CMD_PATH, O_RDWR);
381 if (fd < 0) {
382 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
383 return -errno;
384 }
385
386 FbeOpts ops{.user = userId, .type = type, .len = size};
387
388 auto err = memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
389 if (err != EOK) {
390 LOGE("memcpy failed %{public}d", err);
391 close(fd);
392 return 0;
393 }
394 int ret = ioctl(fd, FBEX_IOC_UNLOCK_SCREEN, &ops);
395 if (ret != 0) {
396 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
397 close(fd);
398 return ret;
399 }
400 close(fd);
401
402 auto errops = memcpy_s(iv, size, ops.iv, sizeof(ops.iv));
403 if (errops != EOK) {
404 LOGE("memcpy failed %{public}d", errops);
405 return 0;
406 }
407 LOGI("UnlockScreenToKernel success");
408 return ret;
409 }
410
ReadESecretToKernel(UserIdToFbeStr & userIdToFbe,uint32_t status,std::unique_ptr<uint8_t[]> & eBuffer,uint32_t length,bool & isFbeSupport)411 int FBEX::ReadESecretToKernel(UserIdToFbeStr &userIdToFbe, uint32_t status, std::unique_ptr<uint8_t[]> &eBuffer,
412 uint32_t length, bool &isFbeSupport)
413 {
414 LOGI("enter, userId: %{public}d, status: %{public}u", userIdToFbe.userIds[DOUBLE_ID_INDEX], status);
415 if (!CheckReadBuffValid(eBuffer.get(), length, status)) {
416 LOGE("read e secret param invalid");
417 return -EINVAL;
418 }
419 int fd = open(FBEX_UECE_PATH, O_RDWR);
420 if (fd < 0) {
421 if (errno == ENOENT) {
422 isFbeSupport = false;
423 return 0;
424 }
425 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
426 return -errno;
427 }
428 uint32_t bufferSize = AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES + GCM_NONCE_BYTES;
429 FbeOptsE ops{ .userIdDouble = userIdToFbe.userIds[DOUBLE_ID_INDEX],
430 .userIdSingle = userIdToFbe.userIds[SINGLE_ID_INDEX], .status = status, .length = bufferSize };
431 auto err = memcpy_s(ops.eBuffer, sizeof(ops.eBuffer), eBuffer.get(), length);
432 if (err != EOK) {
433 LOGE("memcpy failed %{public}d", err);
434 close(fd);
435 return 0;
436 }
437 auto ret = ioctl(fd, FBEX_READ_CLASS_E, &ops);
438 if (ret != 0) {
439 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
440 close(fd);
441 return -errno;
442 }
443 close(fd);
444 if (ops.length == 0) {
445 (void)memset_s(eBuffer.get(), sizeof(eBuffer.get()), 0, sizeof(eBuffer.get()));
446 eBuffer.reset(nullptr);
447 LOGE("ops length is 0, skip");
448 return 0;
449 }
450 if (status == UNLOCK_STATUS) {
451 bufferSize = AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES + GCM_NONCE_BYTES;
452 } else {
453 bufferSize = AES_256_HASH_RANDOM_SIZE;
454 }
455 auto errBuffer = memcpy_s(eBuffer.get(), length, ops.eBuffer, bufferSize);
456 if (errBuffer != EOK) {
457 LOGE("memcpy failed %{public}d", errBuffer);
458 return 0;
459 }
460 LOGI("ReadESecretToKernel success");
461 return 0;
462 }
463
WriteESecretToKernel(UserIdToFbeStr & userIdToFbe,uint32_t status,uint8_t * eBuffer,uint32_t length)464 int FBEX::WriteESecretToKernel(UserIdToFbeStr &userIdToFbe, uint32_t status, uint8_t *eBuffer, uint32_t length)
465 {
466 LOGI("enter, userId: %{public}d, status: %{public}u", userIdToFbe.userIds[DOUBLE_ID_INDEX], status);
467 if (!CheckWriteBuffValid(eBuffer, length, status)) {
468 LOGE("write e secret param invalid");
469 return -EINVAL;
470 }
471
472 int fd = open(FBEX_UECE_PATH, O_RDWR);
473 if (fd < 0) {
474 if (errno == ENOENT) {
475 LOGE("fbex_uece does not exist, fbe not support this command!");
476 return 0;
477 }
478 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
479 return -errno;
480 }
481 uint32_t bufferSize = AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES + GCM_NONCE_BYTES;
482 FbeOptsE ops{ .userIdDouble = userIdToFbe.userIds[DOUBLE_ID_INDEX],
483 .userIdSingle = userIdToFbe.userIds[SINGLE_ID_INDEX],
484 .status = status, .length = bufferSize };
485 auto err = memcpy_s(ops.eBuffer, sizeof(ops.eBuffer), eBuffer, length);
486 if (err != EOK) {
487 LOGE("memcpy failed %{public}d", err);
488 close(fd);
489 return 0;
490 }
491 auto ret = ioctl(fd, FBEX_WRITE_CLASS_E, &ops);
492 if (ret != 0) {
493 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
494 close(fd);
495 return -errno;
496 }
497 close(fd);
498 LOGI("success");
499 return 0;
500 }
501
IsMspReady()502 bool FBEX::IsMspReady()
503 {
504 std::string status;
505 (void)OHOS::LoadStringFromFile(FBEX_CMD_PATH, status);
506 return status == "true";
507 }
508
GetStatus()509 int FBEX::GetStatus()
510 {
511 int fd = open(FBEX_CMD_PATH, O_RDWR);
512 if (fd < 0) {
513 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
514 return -errno;
515 }
516
517 FbeOpts ops;
518 int ret = ioctl(fd, FBEX_IOC_STATUS_REPORT, &ops);
519 close(fd);
520 return ret;
521 }
522 } // namespace StorageDaemon
523 } // namespace OHOS
524