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 #include "utils/storage_radar.h"
30 
31 using namespace OHOS::StorageService;
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_UFS_INLINE_BASE_ADDR = "/proc/bootdevice/name";
37 constexpr const char *FBEX_INLINE_CRYPTO_V3 = "3\n";
38 
39 constexpr const char *FBEX_CMD_PATH = "/dev/fbex_cmd";
40 constexpr const char *FBEX_UECE_PATH = "/dev/fbex_uece";
41 
42 const uint8_t FBEX_IOC_MAGIC = 'f';
43 const uint8_t FBEX_ADD_IV = 0x1;
44 const uint8_t FBEX_DEL_IV = 0x2;
45 const uint8_t FBEX_LOCK_SCREEN = 0x3;
46 const uint8_t FBEX_UNLOCK_SCREEN = 0x4;
47 const uint8_t FBEX_USER_LOGOUT = 0x8;
48 const uint8_t FBEX_STATUS_REPORT = 0xC;
49 const uint8_t FBEX_ADD_DOUBLE_DE_IV = 20;
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_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 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;
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     int fd = open(FBEX_UECE_PATH, O_RDWR);
152     if (fd < 0) {
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 
162     FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
163     auto fbeRet = ioctl(fd, FBEX_ADD_CLASS_E, &ops);
164     if (static_cast<uint32_t>(fbeRet) == FILE_ENCRY_ERROR_UECE_ALREADY_CREATED) {
165         LOGE("class uece has already create, ret: 0x%{public}x, errno: %{public}d", fbeRet, errno);
166         isNeedEncryptClassE = false;
167         close(fd);
168         return 0;
169     }
170     int ret = 0;
171     if (fbeRet != 0) {
172         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", fbeRet, errno);
173         std::string extraData = "ioctl cmd =FBEX_ADD_CLASS_E, userIdSingle=" + std::to_string(userIdSingle)
174             + ", userIdDouble=" + std::to_string(userIdDouble) + ", errno=" + std::to_string(errno);
175         StorageRadar::ReportFbexResult("InstallEL5KeyToKernel", userIdSingle, fbeRet, "EL5", extraData);
176         ret = -errno;
177     }
178     close(fd);
179     LOGI("InstallEL5KeyToKernel success");
180     return ret;
181 }
182 
InstallKeyToKernel(uint32_t userId,uint32_t type,uint8_t * iv,uint32_t size,uint8_t flag)183 int FBEX::InstallKeyToKernel(uint32_t userId, uint32_t type, uint8_t *iv, uint32_t size, uint8_t flag)
184 {
185     LOGI("enter, userId: %{public}d, type: %{public}u, flag: %{public}u", userId, type, flag);
186     if (!CheckIvValid(iv, size)) {
187         LOGE("install key param invalid");
188         return -EINVAL;
189     }
190 
191     int fd = open(FBEX_CMD_PATH, O_RDWR);
192     if (fd < 0) {
193         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
194         return -errno;
195     }
196 
197     FbeOpts ops{.user = userId, .type = type, .len = size, .flag = flag};
198     auto err = memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
199     if (err != EOK) {
200         LOGE("memcpy failed %{public}d", err);
201         close(fd);
202         return 0;
203     }
204     int ret = ioctl(fd, FBEX_IOC_ADD_IV, &ops);
205     if (ret != 0) {
206         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
207         std::string extraData = "ioctl cmd=FBEX_IOC_ADD_IV, errno=" + std::to_string(errno);
208         StorageRadar::ReportFbexResult("InstallKeyToKernel", userId, ret, std::to_string(type), extraData);
209         close(fd);
210         return ret;
211     }
212     close(fd);
213 
214     auto errops = memcpy_s(iv, size, ops.iv, sizeof(ops.iv));
215     if (errops != EOK) {
216         LOGE("memcpy failed %{public}d", errops);
217         return 0;
218     }
219     LOGI("InstallKeyToKernel success");
220     return ret;
221 }
222 
InstallDoubleDeKeyToKernel(UserIdToFbeStr & userIdToFbe,uint8_t * iv,uint32_t size,uint8_t flag)223 int FBEX::InstallDoubleDeKeyToKernel(UserIdToFbeStr &userIdToFbe, uint8_t *iv, uint32_t size, uint8_t flag)
224 {
225     LOGI("id-single: %{public}d, id-double: %{public}d, flag: %{public}u",
226         userIdToFbe.userIds[SINGLE_ID_INDEX], userIdToFbe.userIds[DOUBLE_ID_INDEX], flag);
227     if (!CheckIvValid(iv, size)) {
228         LOGE("install key param invalid");
229         return -EINVAL;
230     }
231 
232     int fd = open(FBEX_UECE_PATH, O_RDWR);
233     if (fd < 0) {
234         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
235         return -errno;
236     }
237 
238     FbeOptsE ops{ .userIdDouble = userIdToFbe.userIds[DOUBLE_ID_INDEX],
239                   .userIdSingle = userIdToFbe.userIds[SINGLE_ID_INDEX],
240                   .status = flag,
241                   .length = size };
242     // eBuffer -> iv
243     auto err = memcpy_s(ops.eBuffer, sizeof(ops.eBuffer), iv, size);
244     if (err != EOK) {
245         LOGE("memcpy failed %{public}d", err);
246         return 0;
247     }
248     int ret = ioctl(fd, FBEX_IOC_ADD_DOUBLE_DE_IV, &ops);
249     if (ret != 0) {
250         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
251         std::string extraData = "ioctl cmd = FBEX_IOC_ADD_DOUBLE_DE_IV, userIdSingle="
252             + std::to_string(ops.userIdSingle) + ", userIdDouble=" + std::to_string(ops.userIdDouble)
253             + ", errno=" + std::to_string(errno);
254         StorageRadar::ReportFbexResult("InstallDoubleDeKeyToKernel", ops.userIdSingle, ret, "EL1", extraData);
255         close(fd);
256         return ret;
257     }
258     close(fd);
259     auto errops = memcpy_s(iv, size, ops.eBuffer, sizeof(ops.eBuffer));
260     if (errops != EOK) {
261         LOGE("memcpy failed %{public}d", errops);
262         close(fd);
263         return 0;
264     }
265     LOGI("InstallDoubleDeKeyToKernel success");
266     return ret;
267 }
268 
269 
UninstallOrLockUserKeyToKernel(uint32_t userId,uint32_t type,uint8_t * iv,uint32_t size,bool destroy)270 int FBEX::UninstallOrLockUserKeyToKernel(uint32_t userId, uint32_t type, uint8_t *iv, uint32_t size, bool destroy)
271 {
272     LOGI("enter, userId: %{public}d, type: %{public}u, flag: %{public}d", userId, type, destroy);
273     if (!CheckIvValid(iv, size)) {
274         LOGE("uninstall key param invalid");
275         return -EINVAL;
276     }
277 
278     int fd = open(FBEX_CMD_PATH, O_RDWR);
279     if (fd < 0) {
280         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
281         return -errno;
282     }
283 
284     FbeOpts ops{.user = userId, .type = type, .len = size};
285     auto err = memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
286     if (err != EOK) {
287         LOGE("memcpy failed %{public}d", err);
288         close(fd);
289         return 0;
290     }
291     int ret = ioctl(fd, destroy ? FBEX_IOC_DEL_IV : FBEX_IOC_USER_LOGOUT, &ops);
292     if (ret != 0 && static_cast<uint32_t>(ret) != FILE_ENCRY_ERROR_NOT_FOUND_UECE) {
293         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
294         std::string febxCmd = destroy ? "FBEX_IOC_DEL_IV" : "FBEX_IOC_USER_LOGOUT";
295         std::string extraData = "ioctl cmd=" + febxCmd + ", errno=" + std::to_string(errno);
296         StorageRadar::ReportFbexResult("UninstallOrLockUserKeyToKernel", userId, ret, std::to_string(type), extraData);
297         close(fd);
298         return ret;
299     }
300     close(fd);
301     LOGI("success");
302     return 0;
303 }
304 
DeleteClassEPinCode(uint32_t userIdSingle,uint32_t userIdDouble)305 int FBEX::DeleteClassEPinCode(uint32_t userIdSingle, uint32_t userIdDouble)
306 {
307     LOGI("enter, userId: %{public}d", userIdDouble);
308     int fd = open(FBEX_UECE_PATH, O_RDWR);
309     if (fd < 0) {
310         if (errno == ENOENT) {
311             LOGE("fbex_uece does not exist, fbe not support this command!");
312             return 0;
313         }
314         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
315         return -errno;
316     }
317     FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
318     auto fbeRet = ioctl(fd, FBEX_DEL_USER_PINCODE, &ops);
319     int ret = 0;
320     if (fbeRet != 0) {
321         LOGE("ioctl fbex_cmd failed, fbeRet: 0x%{public}x, errno: %{public}d", fbeRet, errno);
322         std::string extraData = "ioctl cmd=FBEX_DEL_USER_PINCODE, userIdSingle=" + std::to_string(userIdSingle)
323             + ", userIdDouble=" + std::to_string(userIdDouble) + ", errno=" + std::to_string(errno);
324         StorageRadar::ReportFbexResult("DeleteClassEPinCode", userIdSingle, ret, "EL5", extraData);
325         ret = -errno;
326     }
327     close(fd);
328     LOGI("success");
329     return ret;
330 }
331 
ChangePinCodeClassE(uint32_t userIdSingle,uint32_t userIdDouble,bool & isFbeSupport)332 int FBEX::ChangePinCodeClassE(uint32_t userIdSingle, uint32_t userIdDouble, bool &isFbeSupport)
333 {
334     LOGI("enter, userId: %{public}d", userIdDouble);
335     int fd = open(FBEX_UECE_PATH, O_RDWR);
336     if (fd < 0) {
337         if (errno == ENOENT) {
338             LOGE("fbex_uece does not exist, fbe not support this command!");
339             isFbeSupport = false;
340             return 0;
341         }
342         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
343         return -errno;
344     }
345     FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
346     int ret = ioctl(fd, FBEX_CHANGE_PINCODE, &ops);
347     if (ret != 0) {
348         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
349         std::string extraData = "ioctl cmd=FBEX_CHANGE_PINCODE, userIdSingle=" + std::to_string(userIdSingle)
350             + ", userIdDouble=" + std::to_string(userIdDouble) + ", errno=" + std::to_string(errno);
351         StorageRadar::ReportFbexResult("ChangePinCodeClassE", userIdSingle, ret, "EL5", extraData);
352         ret = -errno;
353     }
354     close(fd);
355     LOGI("change pincode classE finish.");
356     return ret;
357 }
358 
359 // for el3 & el4
LockScreenToKernel(uint32_t userId)360 int FBEX::LockScreenToKernel(uint32_t userId)
361 {
362     LOGI("enter, userId: %{public}d", userId);
363 
364     int fd = open(FBEX_CMD_PATH, O_RDWR);
365     if (fd < 0) {
366         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
367         return -errno;
368     }
369     FbeOpts ops;
370     (void)memset_s(&ops, sizeof(FbeOpts), 0, sizeof(FbeOpts));
371     ops.user = userId;
372     int ret = ioctl(fd, FBEX_IOC_LOCK_SCREEN, &ops);
373     if (ret != 0) {
374         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
375     }
376     close(fd);
377     LOGI("success");
378     return ret;
379 }
380 
GenerateAppkey(UserIdToFbeStr & userIdToFbe,uint32_t hashId,std::unique_ptr<uint8_t[]> & appKey,uint32_t size)381 int FBEX::GenerateAppkey(UserIdToFbeStr &userIdToFbe, uint32_t hashId, std::unique_ptr<uint8_t[]> &appKey,
382                          uint32_t size)
383 {
384     LOGI("GenerateAppkey enter");
385     int fd = open(FBEX_UECE_PATH, O_RDWR);
386     if (fd < 0) {
387         if (errno == ENOENT) {
388             LOGE("fbex_uece does not exist, fbe not support this command!");
389             appKey.reset(nullptr);
390             return 0;
391         }
392         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
393         return -errno;
394     }
395     FbeOptsE ops{ .userIdDouble = userIdToFbe.userIds[DOUBLE_ID_INDEX],
396                   .userIdSingle = userIdToFbe.userIds[SINGLE_ID_INDEX],
397                   .status = hashId, .length = size };
398     auto fbeRet = ioctl(fd, FBEX_ADD_APPKEY2, &ops);
399     if (fbeRet != 0) {
400         LOGE("ioctl fbex_cmd failed, fbeRet: 0x%{public}x, errno: %{public}d", fbeRet, errno);
401         close(fd);
402         return -errno;
403     }
404 
405     auto err = memcpy_s(appKey.get(), size, ops.eBuffer, sizeof(ops.eBuffer));
406     if (err != EOK) {
407         LOGE("memcpy failed %{public}d", err);
408         return 0;
409     }
410     close(fd);
411     LOGI("success");
412     return 0;
413 }
414 
415 // for el5
LockUece(uint32_t userIdSingle,uint32_t userIdDouble,bool & isFbeSupport)416 int FBEX::LockUece(uint32_t userIdSingle, uint32_t userIdDouble, bool &isFbeSupport)
417 {
418     LOGD("enter, userId: %{public}d", userIdDouble);
419 
420     int fd = open(FBEX_UECE_PATH, O_RDWR);
421     if (fd < 0) {
422         if (errno == ENOENT) {
423             LOGE("fbex_uece does not exist, fbe not support this command!");
424             isFbeSupport = false;
425             return 0;
426         }
427         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
428         return -errno;
429     }
430     FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
431     int ret = ioctl(fd, FBEX_LOCK_UECE, &ops);
432     if (ret != 0) {
433         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
434     }
435     close(fd);
436     LOGD("success");
437     return ret;
438 }
439 
UnlockScreenToKernel(uint32_t userId,uint32_t type,uint8_t * iv,uint32_t size)440 int FBEX::UnlockScreenToKernel(uint32_t userId, uint32_t type, uint8_t *iv, uint32_t size)
441 {
442     LOGI("enter, userId: %{public}d, type: %{public}u", userId, type);
443     if (!CheckIvValid(iv, size)) {
444         LOGE("install key param invalid");
445         return -EINVAL;
446     }
447 
448     int fd = open(FBEX_CMD_PATH, O_RDWR);
449     if (fd < 0) {
450         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
451         return -errno;
452     }
453 
454     FbeOpts ops{.user = userId, .type = type, .len = size};
455 
456     auto err = memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
457     if (err != EOK) {
458         LOGE("memcpy failed %{public}d", err);
459         close(fd);
460         return 0;
461     }
462     int ret = ioctl(fd, FBEX_IOC_UNLOCK_SCREEN, &ops);
463     if (ret != 0) {
464         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
465         std::string extraData = "ioctl cmd=FBEX_IOC_UNLOCK_SCREEN, errno=" + std::to_string(errno);
466         StorageRadar::ReportFbexResult("UnlockScreenToKernel", userId, ret, std::to_string(type), extraData);
467         close(fd);
468         return ret;
469     }
470     close(fd);
471 
472     auto errops = memcpy_s(iv, size, ops.iv, sizeof(ops.iv));
473     if (errops != EOK) {
474         LOGE("memcpy failed %{public}d", errops);
475         return 0;
476     }
477     LOGI("UnlockScreenToKernel success");
478     return ret;
479 }
480 
ReadESecretToKernel(UserIdToFbeStr & userIdToFbe,uint32_t status,std::unique_ptr<uint8_t[]> & eBuffer,uint32_t length,bool & isFbeSupport)481 int FBEX::ReadESecretToKernel(UserIdToFbeStr &userIdToFbe, uint32_t status, std::unique_ptr<uint8_t[]> &eBuffer,
482                               uint32_t length, bool &isFbeSupport)
483 {
484     LOGI("enter, userId: %{public}d, status: %{public}u", userIdToFbe.userIds[DOUBLE_ID_INDEX], status);
485     if (!CheckReadBuffValid(eBuffer.get(), length, status)) {
486         LOGE("read e secret param invalid");
487         return -EINVAL;
488     }
489     int fd = open(FBEX_UECE_PATH, O_RDWR);
490     if (fd < 0) {
491         if (errno == ENOENT) {
492             isFbeSupport = false;
493             return 0;
494         }
495         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
496         return -errno;
497     }
498     uint32_t bufferSize = AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES + GCM_NONCE_BYTES;
499     FbeOptsE ops{ .userIdDouble = userIdToFbe.userIds[DOUBLE_ID_INDEX],
500                   .userIdSingle = userIdToFbe.userIds[SINGLE_ID_INDEX], .status = status, .length = bufferSize };
501     auto err = memcpy_s(ops.eBuffer, sizeof(ops.eBuffer), eBuffer.get(), length);
502     if (err != EOK) {
503         LOGE("memcpy failed %{public}d", err);
504         close(fd);
505         return 0;
506     }
507     auto ret = ioctl(fd, FBEX_READ_CLASS_E, &ops);
508     if (ret != 0) {
509         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
510         std::string extraData = "ioctl cmd=FBEX_READ_CLASS_E, userIdSingle=" + std::to_string(ops.userIdSingle)
511             + ", userIdDouble=" + std::to_string(ops.userIdDouble) + ", errno=" + std::to_string(errno);
512         StorageRadar::ReportFbexResult("InstallDoubleDeKeyToKernel", ops.userIdSingle, ret, "EL5", extraData);
513         close(fd);
514         return -errno;
515     }
516     close(fd);
517     if (ops.length == 0) {
518         (void)memset_s(eBuffer.get(), sizeof(eBuffer.get()), 0, sizeof(eBuffer.get()));
519         eBuffer.reset(nullptr);
520         LOGE("ops length is 0, skip");
521         return 0;
522     }
523     if (status == UNLOCK_STATUS) {
524         bufferSize = AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES + GCM_NONCE_BYTES;
525     } else {
526         bufferSize = AES_256_HASH_RANDOM_SIZE;
527     }
528     auto errBuffer = memcpy_s(eBuffer.get(), length, ops.eBuffer, bufferSize);
529     if (errBuffer != EOK) {
530         LOGE("memcpy failed %{public}d", errBuffer);
531         return 0;
532     }
533     LOGI("ReadESecretToKernel success");
534     return 0;
535 }
536 
WriteESecretToKernel(UserIdToFbeStr & userIdToFbe,uint32_t status,uint8_t * eBuffer,uint32_t length)537 int FBEX::WriteESecretToKernel(UserIdToFbeStr &userIdToFbe, uint32_t status, uint8_t *eBuffer, uint32_t length)
538 {
539     LOGI("enter, userId: %{public}d, status: %{public}u", userIdToFbe.userIds[DOUBLE_ID_INDEX], status);
540     if (!CheckWriteBuffValid(eBuffer, length, status)) {
541         LOGE("write e secret param invalid");
542         return -EINVAL;
543     }
544 
545     int fd = open(FBEX_UECE_PATH, O_RDWR);
546     if (fd < 0) {
547         if (errno == ENOENT) {
548             LOGE("fbex_uece does not exist, fbe not support this command!");
549             return 0;
550         }
551         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
552         return -errno;
553     }
554     uint32_t bufferSize = AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES + GCM_NONCE_BYTES;
555     FbeOptsE ops{ .userIdDouble = userIdToFbe.userIds[DOUBLE_ID_INDEX],
556                   .userIdSingle = userIdToFbe.userIds[SINGLE_ID_INDEX],
557                   .status = status, .length = bufferSize };
558     auto err = memcpy_s(ops.eBuffer, sizeof(ops.eBuffer), eBuffer, length);
559     if (err != EOK) {
560         LOGE("memcpy failed %{public}d", err);
561         close(fd);
562         return 0;
563     }
564     auto ret = ioctl(fd, FBEX_WRITE_CLASS_E, &ops);
565     if (ret != 0) {
566         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
567         std::string extraData = "ioctl cmd=FBEX_WRITE_CLASS_E, userIdSingle=" + std::to_string(ops.userIdSingle)
568             + ", userIdDouble=" + std::to_string(ops.userIdDouble) + ", errno=" + std::to_string(errno);
569         StorageRadar::ReportFbexResult("InstallDoubleDeKeyToKernel", ops.userIdSingle, ret, "EL5", extraData);
570         close(fd);
571         return -errno;
572     }
573     close(fd);
574     LOGI("success");
575     return 0;
576 }
577 
IsMspReady()578 bool FBEX::IsMspReady()
579 {
580     std::string status;
581     (void)OHOS::LoadStringFromFile(FBEX_CMD_PATH, status);
582     return status == "true";
583 }
584 
GetStatus()585 int FBEX::GetStatus()
586 {
587     int fd = open(FBEX_CMD_PATH, O_RDWR);
588     if (fd < 0) {
589         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
590         return -errno;
591     }
592 
593     FbeOpts ops;
594     int ret = ioctl(fd, FBEX_IOC_STATUS_REPORT, &ops);
595     close(fd);
596     return ret;
597 }
598 } // namespace StorageDaemon
599 } // namespace OHOS
600