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