• 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 "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