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