• 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 AUTH_TOKEN_MAX_SIZE = 1024;
41 constexpr uint32_t UNLOCK_STATUS = 0x2;
42 
43 constexpr uint8_t FBEX_IOC_MAGIC = 'f';
44 constexpr uint8_t FBEX_ADD_IV = 0x1;
45 constexpr uint8_t FBEX_DEL_IV = 0x2;
46 constexpr uint8_t FBEX_LOCK_SCREEN = 0x3;
47 constexpr uint8_t FBEX_UNLOCK_SCREEN = 0x4;
48 constexpr uint8_t FBEX_USER_LOGOUT = 0x8;
49 constexpr uint8_t FBEX_STATUS_REPORT = 0xC;
50 constexpr uint8_t FBEX_ADD_DOUBLE_DE_IV = 20;
51 constexpr uint8_t FBEX_ADD_EL5 = 21;
52 constexpr uint8_t FBEX_READ_EL5 = 22;
53 constexpr uint8_t FBEX_WRITE_EL5 = 23;
54 constexpr uint8_t FBEX_DEL_EL5_PINCODE = 24;
55 constexpr uint8_t FBEX_GENERATE_APP_KEY = 25;
56 constexpr uint8_t FBEX_CHANGE_PINCODE = 26;
57 constexpr uint8_t FBEX_LOCK_EL5 = 27;
58 constexpr uint8_t FBEX_UECE_BACKUP = 30;
59 
60 constexpr uint32_t FILE_ENCRY_ERROR_UECE_ALREADY_CREATED = 0xFBE30031;
61 constexpr uint32_t FILE_ENCRY_ERROR_NOT_FOUND_UECE = 0xFBE30033;
62 constexpr uint32_t FILE_ENCRY_ERROR_UECE_AUTH_STATUS_WRONG = 0xFBE30034;
63 
64 struct FbeOptStr {
65     uint32_t user = 0;
66     uint32_t type = 0;
67     uint32_t len = 0;
68     uint8_t iv[OHOS::StorageDaemon::FBEX_IV_SIZE] = {0};
69     uint8_t flag = 0;
70 };
71 using FbeOpts = FbeOptStr;
72 
73 struct FbeOptStrV1 {
74     uint32_t user = 0;
75     uint32_t type = 0;
76     uint32_t len = 0;
77     uint8_t iv[OHOS::StorageDaemon::FBEX_IV_SIZE] = {0};
78     uint8_t flag = 0;
79     uint32_t authTokenSize = 0;
80     uint8_t authToken[AUTH_TOKEN_MAX_SIZE] = {0};
81 };
82 using FbeOptsV1 = FbeOptStrV1;
83 
84 struct FbeOptStrE {
85     uint32_t userIdDouble = 0;
86     uint32_t userIdSingle = 0;
87     uint32_t status = 0;
88     uint32_t length = 0;
89     uint8_t eBuffer[FBEX_E_BUFFER_SIZE] = {0};
90 };
91 using FbeOptsE = FbeOptStrE;
92 
93 struct FbeOptStrEV1 {
94     uint32_t userIdDouble = 0;
95     uint32_t userIdSingle = 0;
96     uint32_t status = 0;
97     uint32_t length = 0;
98     uint8_t eBuffer[FBEX_E_BUFFER_SIZE] = {0};
99     uint32_t authTokenSize = 0;
100     uint8_t authToken[AUTH_TOKEN_MAX_SIZE] = {0};
101 };
102 using FbeOptsEV1 = FbeOptStrEV1;
103 
104 #define FBEX_IOC_ADD_IV _IOWR(FBEX_IOC_MAGIC, FBEX_ADD_IV, FbeOpts)
105 #define FBEX_IOC_ADD_DOUBLE_DE_IV _IOWR(FBEX_IOC_MAGIC, FBEX_ADD_DOUBLE_DE_IV, FbeOpts)
106 #define FBEX_IOC_DEL_IV _IOW(FBEX_IOC_MAGIC, FBEX_DEL_IV, FbeOpts)
107 #define FBEX_IOC_LOCK_SCREEN _IOW(FBEX_IOC_MAGIC, FBEX_LOCK_SCREEN, FbeOpts)
108 #define FBEX_IOC_UNLOCK_SCREEN _IOWR(FBEX_IOC_MAGIC, FBEX_UNLOCK_SCREEN, FbeOpts)
109 #define FBEX_IOC_USER_LOGOUT _IOW(FBEX_IOC_MAGIC, FBEX_USER_LOGOUT, FbeOpts)
110 #define FBEX_IOC_STATUS_REPORT _IOW(FBEX_IOC_MAGIC, FBEX_STATUS_REPORT, FbeOpts)
111 #define FBEX_READ_CLASS_E _IOWR(FBEX_IOC_MAGIC, FBEX_READ_EL5, FbeOptsE)
112 #define FBEX_WRITE_CLASS_E _IOWR(FBEX_IOC_MAGIC, FBEX_WRITE_EL5, FbeOptsE)
113 #define FBEX_ADD_CLASS_E _IOWR(FBEX_IOC_MAGIC, FBEX_ADD_EL5, FbeOptsE)
114 #define FBEX_DEL_USER_PINCODE _IOWR(FBEX_IOC_MAGIC, FBEX_DEL_EL5_PINCODE, FbeOptsE)
115 #define FBEX_ADD_APPKEY2 _IOWR(FBEX_IOC_MAGIC, FBEX_GENERATE_APP_KEY, FbeOptsE)
116 #define FBEX_CHANGE_PINCODE _IOWR(FBEX_IOC_MAGIC, FBEX_CHANGE_PINCODE, FbeOptsE)
117 #define FBEX_LOCK_UECE _IOWR(FBEX_IOC_MAGIC, FBEX_LOCK_EL5, FbeOptsE)
118 #define FBEX_UPDATE_UECE_KEY_CONTEXT _IOWR(FBEX_IOC_MAGIC, FBEX_UECE_BACKUP, FbeOptsE)
119 
120 } // namespace
121 
122 namespace OHOS {
123 namespace StorageDaemon {
IsFBEXSupported()124 bool FBEX::IsFBEXSupported()
125 {
126     std::string baseAddr;
127     if (!OHOS::LoadStringFromFile(FBEX_UFS_INLINE_BASE_ADDR, baseAddr)) {
128         LOGE("Read baseAddr failed, errno: %{public}d", errno);
129         return false;
130     }
131 
132     std::string path = FBEX_UFS_INLINE_SUPPORT_PREFIX + baseAddr + FBEX_UFS_INLINE_SUPPORT_END;
133     std::string nvmePath = FBEX_NVME_INLINE_SUPPORT_PATH;
134     std::string emmcPath = FBEX_EMMC_INLINE_SUPPORT_PATH;
135     std::string rpath(PATH_MAX + 1, '\0');
136 
137     if ((path.length() > PATH_MAX) || (realpath(path.c_str(), rpath.data()) == nullptr)) {
138         LOGE("realpath of %{public}s failed, errno: %{public}d", path.c_str(), errno);
139         return ((access(nvmePath.c_str(), F_OK) == 0) || (access(emmcPath.c_str(), F_OK) == 0));
140     }
141     if (rpath.rfind(FBEX_UFS_INLINE_SUPPORT_PREFIX) != 0) {
142         LOGE("rpath %{public}s is invalid", rpath.c_str());
143         return false;
144     }
145 
146     std::string versionNum;
147     if (!OHOS::LoadStringFromFile(rpath, versionNum)) {
148         LOGE("read ufs_inline_stat failed, errno: %{public}d", errno);
149         return false;
150     }
151     return versionNum.compare(FBEX_INLINE_CRYPTO_V3) == 0;
152 }
153 
CheckIvValid(const uint8_t * iv,uint32_t size)154 static inline bool CheckIvValid(const uint8_t *iv, uint32_t size)
155 {
156     return (iv != nullptr) && (size == FBEX_IV_SIZE);
157 }
158 
CheckReadBuffValid(const uint8_t * eBuffer,uint32_t size,uint32_t status)159 static inline bool CheckReadBuffValid(const uint8_t *eBuffer, uint32_t size, uint32_t status)
160 {
161     if (status == UNLOCK_STATUS) {
162         return (eBuffer != nullptr) && (size == (GCM_NONCE_BYTES + AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES));
163     }
164     return (eBuffer != nullptr) && (size == AES_256_HASH_RANDOM_SIZE);
165 }
166 
CheckWriteBuffValid(const uint8_t * eBuffer,uint32_t size,uint32_t status)167 static inline bool CheckWriteBuffValid(const uint8_t *eBuffer, uint32_t size, uint32_t status)
168 {
169     if (status == UNLOCK_STATUS) {
170         return (eBuffer != nullptr) && (size == AES_256_HASH_RANDOM_SIZE);
171     }
172     return (eBuffer != nullptr) && (size == (GCM_NONCE_BYTES + AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES));
173 }
174 
MemcpyFbeOptsV1(FbeOptsV1 & ops,const KeyBlob & authToken,uint8_t * iv,uint32_t size)175 static inline int MemcpyFbeOptsV1(FbeOptsV1 &ops, const KeyBlob &authToken, uint8_t *iv, uint32_t size)
176 {
177     int err;
178     if (!authToken.IsEmpty()) {
179         err = memcpy_s(ops.authToken, AUTH_TOKEN_MAX_SIZE, authToken.data.get(), authToken.size);
180         LOGI("memcpy end for v1, res is %{public}d", err);
181     }
182     err = memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
183     if (err != EOK) {
184         LOGE("memcpy failed %{public}d", err);
185     }
186     return err;
187 }
188 
MemcpyFbeOptsEV1(FbeOptsEV1 & ops,const KeyBlob & authToken,uint8_t * eBuffer,uint32_t size)189 static inline int MemcpyFbeOptsEV1(FbeOptsEV1 &ops, const KeyBlob &authToken, uint8_t *eBuffer, uint32_t size)
190 {
191     int err;
192     if (!authToken.IsEmpty()) {
193         err = memcpy_s(ops.authToken, AUTH_TOKEN_MAX_SIZE, authToken.data.get(), authToken.size);
194         LOGI("memcpy end for ev1, res is %{public}d", err);
195     }
196     err = memcpy_s(ops.eBuffer, sizeof(ops.eBuffer), eBuffer, size);
197     if (err != EOK) {
198         LOGE("memcpy failed %{public}d", err);
199     }
200     return err;
201 }
202 
InstallEL5KeyToKernel(uint32_t userIdSingle,uint32_t userIdDouble,uint8_t flag,bool & isSupport,bool & isNeedEncryptClassE)203 int FBEX::InstallEL5KeyToKernel(uint32_t userIdSingle, uint32_t userIdDouble, uint8_t flag,
204                                 bool &isSupport, bool &isNeedEncryptClassE)
205 {
206     LOGI("InstallEL5KeyToKernel enter, userId: %{public}d, flag: %{public}u", userIdDouble, flag);
207     FILE *f = fopen(FBEX_UECE_PATH, "r+");
208     if (f == nullptr) {
209         if (errno == ENOENT) {
210             LOGE("fbex_uece does not exist, fbe not support this command!");
211             isSupport = false;
212             return 0;
213         }
214         std::string extraData = "userIdDouble=" + std::to_string(userIdDouble);
215         StorageRadar::ReportFbexResult("InstallEL5KeyToKernel::fopen", userIdSingle, errno, "EL5", extraData);
216         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
217         return -errno;
218     }
219     int fd = fileno(f);
220     if (fd < 0) {
221         if (errno == ENOENT) {
222             LOGE("fbex_uece does not exist, fbe not support this command!");
223             isSupport = false;
224             (void)fclose(f);
225             return 0;
226         }
227         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
228         (void)fclose(f);
229         return -errno;
230     }
231 
232     FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
233     auto fbeRet = ioctl(fd, FBEX_ADD_CLASS_E, &ops);
234     if (static_cast<uint32_t>(fbeRet) == FILE_ENCRY_ERROR_UECE_ALREADY_CREATED) {
235         LOGE("class uece has already create, ret: 0x%{public}x, errno: %{public}d", fbeRet, errno);
236         isNeedEncryptClassE = false;
237         (void)fclose(f);
238         return 0;
239     }
240     int ret = 0;
241     if (fbeRet != 0) {
242         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", fbeRet, errno);
243         std::string extraData = "ioctl cmd=FBEX_ADD_CLASS_E, userIdSingle=" + std::to_string(userIdSingle)
244             + ", userIdDouble=" + std::to_string(userIdDouble) + ", errno=" + std::to_string(errno);
245         StorageRadar::ReportFbexResult("InstallEL5KeyToKernel", userIdSingle, fbeRet, "EL5", extraData);
246         ret = -errno;
247     }
248     (void)fclose(f);
249     LOGI("InstallEL5KeyToKernel success");
250     return ret;
251 }
252 
InstallKeyToKernel(uint32_t userId,uint32_t type,KeyBlob & iv,uint8_t flag,const KeyBlob & authToken)253 int FBEX::InstallKeyToKernel(uint32_t userId, uint32_t type, KeyBlob &iv, uint8_t flag, const KeyBlob &authToken)
254 {
255     LOGI("enter, userId: %{public}d, type: %{public}u, flag: %{public}u", userId, type, flag);
256     auto startTime = StorageService::StorageRadar::RecordCurrentTime();
257     if (iv.IsEmpty() || !CheckIvValid(iv.data.get(), iv.size)) {
258         LOGE("install key param invalid");
259         return -EINVAL;
260     }
261 
262     FILE *f = fopen(FBEX_CMD_PATH, "r+");
263     if (f == nullptr) {
264         StorageRadar::ReportFbexResult("InstallKeyToKernel::fopen", userId, errno, std::to_string(type), "");
265         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
266         return -errno;
267     }
268     int fd = fileno(f);
269     if (fd < 0) {
270         (void)fclose(f);
271         return -errno;
272     }
273 
274     FbeOptsV1 ops{.user = userId, .type = type, .len = iv.size, .flag = flag, .authTokenSize = authToken.size};
275     if (MemcpyFbeOptsV1(ops, authToken, iv.data.get(), iv.size) != EOK) {
276         (void)fclose(f);
277         return 0;
278     }
279     auto delay = StorageService::StorageRadar::ReportDuration("KEY TO KERNEL: FILE OPS",
280         startTime, StorageService::DEFAULT_DELAY_TIME_THRESH, userId);
281     LOGI("SD_DURATION: FBEX: FILE OPS: keyType=%{public}d, delay time = %{public}s", type, delay.c_str());
282     startTime = StorageService::StorageRadar::RecordCurrentTime();
283     int ret = ioctl(fd, FBEX_IOC_ADD_IV, &ops);
284     if (ret != 0) {
285         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
286         std::string extraData = "ioctl cmd=FBEX_IOC_ADD_IV, errno=" + std::to_string(errno);
287         StorageRadar::ReportFbexResult("InstallKeyToKernel", userId, ret, std::to_string(type), extraData);
288         (void)fclose(f);
289         return ret;
290     }
291     (void)fclose(f);
292 
293     auto errops = memcpy_s(iv.data.get(), iv.size, ops.iv, sizeof(ops.iv));
294     if (errops != EOK) {
295         LOGE("memcpy failed %{public}d", errops);
296     }
297     (void)memset_s(&ops.iv, sizeof(ops.iv), 0, sizeof(ops.iv));
298     delay = StorageService::StorageRadar::ReportDuration("FBEX: INSTALL KEY TO KERNEL",
299         startTime, StorageService::DEFAULT_DELAY_TIME_THRESH, userId);
300     LOGI("SD_DURATION: FBEX: INSTALL KEY TO KERNEL: keyType=%{public}d, delay = %{public}s", type, delay.c_str());
301     return ret;
302 }
303 
InstallDoubleDeKeyToKernel(UserIdToFbeStr & userIdToFbe,KeyBlob & iv,uint8_t flag,const KeyBlob & authToken)304 int FBEX::InstallDoubleDeKeyToKernel(UserIdToFbeStr &userIdToFbe, KeyBlob &iv, uint8_t flag, const KeyBlob &authToken)
305 {
306     LOGI("id-single: %{public}d, id-double: %{public}d, flag: %{public}u",
307         userIdToFbe.userIds[SINGLE_ID_INDEX], userIdToFbe.userIds[DOUBLE_ID_INDEX], flag);
308     if (iv.IsEmpty() || !CheckIvValid(iv.data.get(), iv.size)) {
309         LOGE("install key param invalid");
310         return -EINVAL;
311     }
312 
313     int fd = open(FBEX_UECE_PATH, O_RDWR);
314     if (fd < 0) {
315         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
316         return -errno;
317     }
318 
319     FbeOptsEV1 ops{ .userIdDouble = userIdToFbe.userIds[DOUBLE_ID_INDEX],
320                     .userIdSingle = userIdToFbe.userIds[SINGLE_ID_INDEX],
321                     .status = flag, .length = iv.size, .authTokenSize = authToken.size };
322     // eBuffer -> iv
323     if (MemcpyFbeOptsEV1(ops, authToken, iv.data.get(), iv.size) != EOK) {
324         close(fd);
325         return 0;
326     }
327     int ret = ioctl(fd, FBEX_IOC_ADD_DOUBLE_DE_IV, &ops);
328     if (ret != 0) {
329         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
330         std::string extraData = "ioctl cmd=FBEX_IOC_ADD_DOUBLE_DE_IV, userIdSingle=" + std::to_string(ops.userIdSingle)
331             + ", userIdDouble=" + std::to_string(ops.userIdDouble) + ", errno=" + std::to_string(errno);
332         StorageRadar::ReportFbexResult("InstallDoubleDeKeyToKernel", ops.userIdSingle, ret, "EL1", extraData);
333         close(fd);
334         return ret;
335     }
336     close(fd);
337     auto errops = memcpy_s(iv.data.get(), iv.size, ops.eBuffer, sizeof(ops.eBuffer));
338     if (errops != EOK) {
339         LOGE("memcpy failed %{public}d", errops);
340         return 0;
341     }
342     LOGI("InstallDoubleDeKeyToKernel success");
343     return ret;
344 }
345 
UninstallOrLockUserKeyToKernel(uint32_t userId,uint32_t type,uint8_t * iv,uint32_t size,bool destroy)346 int FBEX::UninstallOrLockUserKeyToKernel(uint32_t userId, uint32_t type, uint8_t *iv, uint32_t size, bool destroy)
347 {
348     LOGI("enter, userId: %{public}d, type: %{public}u, flag: %{public}d", userId, type, destroy);
349     if (!CheckIvValid(iv, size)) {
350         LOGE("uninstall key param invalid");
351         return -EINVAL;
352     }
353 
354     FILE *f = fopen(FBEX_CMD_PATH, "r+");
355     if (f == nullptr) {
356         StorageRadar::ReportFbexResult("UninstallOrLockUserKeyToKernel:fopen", userId, errno, std::to_string(type), "");
357         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
358         return -errno;
359     }
360     int fd = fileno(f);
361     if (fd < 0) {
362         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
363         (void)fclose(f);
364         return -errno;
365     }
366 
367     FbeOpts ops{.user = userId, .type = type, .len = size};
368     auto err = memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
369     if (err != EOK) {
370         LOGE("memcpy failed %{public}d", err);
371         (void)fclose(f);
372         return 0;
373     }
374     int ret = ioctl(fd, destroy ? FBEX_IOC_DEL_IV : FBEX_IOC_USER_LOGOUT, &ops);
375     if (ret != 0 && static_cast<uint32_t>(ret) != FILE_ENCRY_ERROR_NOT_FOUND_UECE) {
376         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
377         std::string febxCmd = destroy ? "FBEX_IOC_DEL_IV" : "FBEX_IOC_USER_LOGOUT";
378         std::string extraData = "ioctl cmd=" + febxCmd + ", errno=" + std::to_string(errno);
379         StorageRadar::ReportFbexResult("UninstallOrLockUserKeyToKernel", userId, ret, std::to_string(type), extraData);
380         (void)fclose(f);
381         return ret;
382     }
383     (void)fclose(f);
384     LOGI("success");
385     return 0;
386 }
387 
DeleteClassEPinCode(uint32_t userIdSingle,uint32_t userIdDouble)388 int FBEX::DeleteClassEPinCode(uint32_t userIdSingle, uint32_t userIdDouble)
389 {
390     LOGI("enter, userId: %{public}d", userIdDouble);
391     FILE *f = fopen(FBEX_UECE_PATH, "r+");
392     if (f == nullptr) {
393         if (errno == ENOENT) {
394             LOGE("fbex_uece does not exist, fbe not support this command!");
395             return 0;
396         }
397         std::string extraData = "userIdDouble=" + std::to_string(userIdDouble);
398         StorageRadar::ReportFbexResult("DeleteClassEPinCode::fopen", userIdSingle, errno, "EL5", extraData);
399         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
400         return -errno;
401     }
402     int fd = fileno(f);
403     if (fd < 0) {
404         if (errno == ENOENT) {
405             LOGE("fbex_uece does not exist, fbe not support this command!");
406             (void)fclose(f);
407             return 0;
408         }
409         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
410         (void)fclose(f);
411         return -errno;
412     }
413     FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
414     auto fbeRet = ioctl(fd, FBEX_DEL_USER_PINCODE, &ops);
415     int ret = 0;
416     if (fbeRet != 0) {
417         LOGE("ioctl fbex_cmd failed, fbeRet: 0x%{public}x, errno: %{public}d", fbeRet, errno);
418         std::string extraData = "ioctl cmd=FBEX_DEL_USER_PINCODE, userIdSingle=" + std::to_string(userIdSingle)
419             + ", userIdDouble=" + std::to_string(userIdDouble) + ", errno=" + std::to_string(errno);
420         StorageRadar::ReportFbexResult("DeleteClassEPinCode", userIdSingle, ret, "EL5", extraData);
421         ret = -errno;
422     }
423     (void)fclose(f);
424     LOGI("success");
425     return ret;
426 }
427 
ChangePinCodeClassE(uint32_t userIdSingle,uint32_t userIdDouble,bool & isFbeSupport)428 int FBEX::ChangePinCodeClassE(uint32_t userIdSingle, uint32_t userIdDouble, bool &isFbeSupport)
429 {
430     LOGI("enter, userId: %{public}d", userIdDouble);
431     int fd = open(FBEX_UECE_PATH, O_RDWR);
432     if (fd < 0) {
433         if (errno == ENOENT) {
434             LOGE("fbex_uece does not exist, fbe not support this command!");
435             isFbeSupport = false;
436             return 0;
437         }
438         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
439         return -errno;
440     }
441     FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
442     int ret = ioctl(fd, FBEX_CHANGE_PINCODE, &ops);
443     if (ret != 0) {
444         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
445         std::string extraData = "ioctl cmd=FBEX_CHANGE_PINCODE, userIdSingle=" + std::to_string(userIdSingle)
446             + ", userIdDouble=" + std::to_string(userIdDouble) + ", errno=" + std::to_string(errno);
447         StorageRadar::ReportFbexResult("ChangePinCodeClassE", userIdSingle, ret, "EL5", extraData);
448         ret = -errno;
449     }
450     close(fd);
451     LOGI("change pincode classE finish.");
452     return ret;
453 }
454 
UpdateClassEBackUp(uint32_t userIdSingle,uint32_t userIdDouble)455 int FBEX::UpdateClassEBackUp(uint32_t userIdSingle, uint32_t userIdDouble)
456 {
457     LOGI("enter, userId: %{public}d", userIdDouble);
458     auto startTime = StorageService::StorageRadar::RecordCurrentTime();
459     FILE *f = fopen(FBEX_UECE_PATH, "r+");
460     if (f == nullptr) {
461         if (errno == ENOENT) {
462             LOGE("fbex_uece does not exist, fbe not support this command!");
463             return 0;
464         }
465         std::string extraData = "userIdDouble=" + std::to_string(userIdDouble);
466         StorageRadar::ReportFbexResult("UpdateClassEBackUp::fopen", userIdSingle, errno, "EL5", extraData);
467         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
468         return -errno;
469     }
470     int fd = fileno(f);
471     if (fd < 0) {
472         if (errno == ENOENT) {
473             LOGE("fbex_uece does not exist, fbe not support this command!");
474             (void)fclose(f);
475             return 0;
476         }
477         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
478         (void)fclose(f);
479         return -errno;
480     }
481     auto delay = StorageService::StorageRadar::ReportDuration("UPDATE E BACKUP: FILE OPS",
482         startTime, StorageService::DEFAULT_DELAY_TIME_THRESH, userIdSingle);
483     LOGI("SD_DURATION: FBEX: FILE OPS: user=%{public}d, delay time = %{public}s", userIdSingle, delay.c_str());
484     startTime = StorageService::StorageRadar::RecordCurrentTime();
485     FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
486     int ret = ioctl(fd, FBEX_UPDATE_UECE_KEY_CONTEXT, &ops);
487     if (ret != 0) {
488         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
489         ret = -errno;
490         std::string extraData = "ioctl cmd=FBEX_UPDATE_UECE_KEY_CONTEXT, userIdSingle=" + std::to_string(userIdSingle)
491             + ", userIdDouble=" + std::to_string(userIdDouble) + ", errno=" + std::to_string(errno);
492         StorageRadar::ReportFbexResult("FBEX_UPDATE_UECE_KEY_CONTEXT", userIdSingle, ret, "EL5", extraData);
493     }
494     delay = StorageService::StorageRadar::ReportDuration("FBEX:UPDATE_E_BACKUP",
495         startTime, StorageService::DEFAULT_DELAY_TIME_THRESH, userIdSingle);
496     LOGI("SD_DURATION: FBEX: CLASS E BACKUP: user=%{public}d, delay time = %{public}s", userIdSingle, delay.c_str());
497     (void)fclose(f);
498     LOGI("update FBE key backup for classE finish");
499     return ret;
500 }
501 
502 // for el3 & el4
LockScreenToKernel(uint32_t userId)503 int FBEX::LockScreenToKernel(uint32_t userId)
504 {
505     LOGI("enter, userId: %{public}d", userId);
506 
507     FILE *f = fopen(FBEX_CMD_PATH, "r+");
508     if (f == nullptr) {
509         StorageRadar::ReportFbexResult("LockScreenToKernel::fopen", userId, errno, "", "");
510         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
511         return -errno;
512     }
513     int fd = fileno(f);
514     if (fd < 0) {
515         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
516         (void)fclose(f);
517         return -errno;
518     }
519     FbeOpts ops;
520     (void)memset_s(&ops, sizeof(FbeOpts), 0, sizeof(FbeOpts));
521     ops.user = userId;
522     int ret = ioctl(fd, FBEX_IOC_LOCK_SCREEN, &ops);
523     if (ret != 0) {
524         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
525     }
526     (void)fclose(f);
527     LOGI("success");
528     return ret;
529 }
530 
GenerateAppkey(UserIdToFbeStr & userIdToFbe,uint32_t hashId,std::unique_ptr<uint8_t[]> & appKey,uint32_t size)531 int FBEX::GenerateAppkey(UserIdToFbeStr &userIdToFbe, uint32_t hashId, std::unique_ptr<uint8_t[]> &appKey,
532                          uint32_t size)
533 {
534     LOGI("GenerateAppkey enter");
535     FILE *f = fopen(FBEX_UECE_PATH, "r+");
536     if (f == nullptr) {
537         if (errno == ENOENT) {
538             LOGE("fbex_uece does not exist, fbe not support this command!");
539             appKey.reset(nullptr);
540             return 0;
541         }
542         std::string extraData = "userIdDouble=" + std::to_string(userIdToFbe.userIds[DOUBLE_ID_INDEX]);
543         StorageRadar::ReportFbexResult("GenerateAppkey::fopen", userIdToFbe.userIds[SINGLE_ID_INDEX],
544                                        errno, "EL5", extraData);
545         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
546         return -errno;
547     }
548     int fd = fileno(f);
549     if (fd < 0) {
550         if (errno == ENOENT) {
551             LOGE("fbex_uece does not exist, fbe not support this command!");
552             appKey.reset(nullptr);
553             (void)fclose(f);
554             return 0;
555         }
556         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
557         (void)fclose(f);
558         return -errno;
559     }
560     FbeOptsE ops{ .userIdDouble = userIdToFbe.userIds[DOUBLE_ID_INDEX],
561                   .userIdSingle = userIdToFbe.userIds[SINGLE_ID_INDEX],
562                   .status = hashId, .length = size };
563     auto fbeRet = ioctl(fd, FBEX_ADD_APPKEY2, &ops);
564     if (fbeRet != 0) {
565         LOGE("ioctl fbex_cmd failed, fbeRet: 0x%{public}x, errno: %{public}d", fbeRet, errno);
566         (void)fclose(f);
567         return -errno;
568     }
569 
570     auto err = memcpy_s(appKey.get(), size, ops.eBuffer, sizeof(ops.eBuffer));
571     if (err != EOK) {
572         LOGE("memcpy failed %{public}d", err);
573         (void)fclose(f);
574         return 0;
575     }
576     (void)fclose(f);
577     LOGI("success");
578     return 0;
579 }
580 
581 // for el5
LockUece(uint32_t userIdSingle,uint32_t userIdDouble,bool & isFbeSupport)582 int FBEX::LockUece(uint32_t userIdSingle, uint32_t userIdDouble, bool &isFbeSupport)
583 {
584     LOGI("enter, userId: %{public}d", userIdDouble);
585 
586     FILE *f = fopen(FBEX_UECE_PATH, "r+");
587     if (f == nullptr) {
588         if (errno == ENOENT) {
589             LOGE("fbex_uece does not exist, fbe not support this command!");
590             isFbeSupport = false;
591             return 0;
592         }
593         std::string extraData = "userIdDouble=" + std::to_string(userIdDouble);
594         StorageRadar::ReportFbexResult("GenerateAppkey::fopen", userIdSingle, errno, "EL5", extraData);
595         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
596         return -errno;
597     }
598     int fd = fileno(f);
599     if (fd < 0) {
600         if (errno == ENOENT) {
601             LOGE("fbex_uece does not exist, fbe not support this command!");
602             isFbeSupport = false;
603             (void)fclose(f);
604             return 0;
605         }
606         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
607         (void)fclose(f);
608         return -errno;
609     }
610     FbeOptsE ops{ .userIdDouble = userIdDouble, .userIdSingle = userIdSingle };
611     int ret = ioctl(fd, FBEX_LOCK_UECE, &ops);
612     if (ret != 0) {
613         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
614     }
615     (void)fclose(f);
616     LOGD("success");
617     return ret;
618 }
619 
UnlockScreenToKernel(uint32_t userId,uint32_t type,uint8_t * iv,uint32_t size,const KeyBlob & authToken)620 int FBEX::UnlockScreenToKernel(uint32_t userId, uint32_t type, uint8_t *iv, uint32_t size, const KeyBlob &authToken)
621 {
622     LOGI("enter, userId: %{public}d, type: %{public}u", userId, type);
623     if (!CheckIvValid(iv, size)) {
624         LOGE("install key param invalid");
625         return -EINVAL;
626     }
627 
628     FILE *f = fopen(FBEX_CMD_PATH, "r+");
629     if (f == nullptr) {
630         StorageRadar::ReportFbexResult("UnlockScreenToKernel::fopen", userId, errno, std::to_string(type), "");
631         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
632         return -errno;
633     }
634     int fd = fileno(f);
635     if (fd < 0) {
636         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
637         (void)fclose(f);
638         return -errno;
639     }
640 
641     FbeOptsV1 ops{.user = userId, .type = type, .len = size, .authTokenSize = authToken.size};
642     if (MemcpyFbeOptsV1(ops, authToken, iv, size) != EOK) {
643         (void)fclose(f);
644         return 0;
645     }
646 
647     int ret = ioctl(fd, FBEX_IOC_UNLOCK_SCREEN, &ops);
648     if (ret != 0) {
649         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
650         std::string extraData = "ioctl cmd=FBEX_IOC_UNLOCK_SCREEN, errno=" + std::to_string(errno);
651         StorageRadar::ReportFbexResult("UnlockScreenToKernel", userId, ret, std::to_string(type), extraData);
652         (void)fclose(f);
653         return ret;
654     }
655     (void)fclose(f);
656 
657     auto errops = memcpy_s(iv, size, ops.iv, sizeof(ops.iv));
658     if (errops != EOK) {
659         LOGE("memcpy failed %{public}d", errops);
660     }
661     (void)memset_s(&ops.iv, sizeof(ops.iv), 0, sizeof(ops.iv));
662     LOGI("UnlockScreenToKernel success");
663     return ret;
664 }
665 
CheckPreconditions(UserIdToFbeStr & userIdToFbe,uint32_t status,std::unique_ptr<uint8_t[]> & eBuffer,uint32_t length,bool & isFbeSupport)666 bool FBEX::CheckPreconditions(UserIdToFbeStr &userIdToFbe, uint32_t status, std::unique_ptr<uint8_t[]> &eBuffer,
667                               uint32_t length, bool &isFbeSupport)
668 {
669     LOGI("enter, userId: %{public}d, status: %{public}u", userIdToFbe.userIds[DOUBLE_ID_INDEX], status);
670     if (!CheckReadBuffValid(eBuffer.get(), length, status)) {
671         LOGE("read e secret invalid");
672         return false;
673     }
674     return true;
675 }
676 
HandleIoctlError(int ret,int errnoVal,const std::string & cmd,uint32_t userIdSingle,uint32_t userIdDouble)677 void FBEX::HandleIoctlError(int ret, int errnoVal, const std::string &cmd, uint32_t userIdSingle,
678                             uint32_t userIdDouble)
679 {
680     LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errnoVal);
681     std::string extraData = "ioctl cmd=" + cmd + ", userIdSingle=" + std::to_string(userIdSingle)
682                             + ", userIdDouble=" + std::to_string(userIdDouble) + ", errno=" + std::to_string(errnoVal);
683     StorageRadar::ReportFbexResult("InstallDoubleDeKeyToKernel", userIdSingle, ret, "EL5", extraData);
684 }
685 
ReadESecretToKernel(UserIdToFbeStr & userIdToFbe,uint32_t status,KeyBlob & eBuffer,const KeyBlob & authToken,bool & isFbeSupport)686 int FBEX::ReadESecretToKernel(UserIdToFbeStr &userIdToFbe, uint32_t status, KeyBlob &eBuffer,
687                               const KeyBlob &authToken, bool &isFbeSupport)
688 {
689     if (eBuffer.IsEmpty() || !CheckPreconditions(userIdToFbe, status, eBuffer.data, eBuffer.size, isFbeSupport)) {
690         return -EINVAL;
691     }
692     FILE *f = fopen(FBEX_UECE_PATH, "r+");
693     if (f == nullptr) {
694         if (errno == ENOENT) {
695             isFbeSupport = false;
696             return 0;
697         }
698         std::string extraData = "userIdDouble=" + std::to_string(userIdToFbe.userIds[DOUBLE_ID_INDEX]);
699         StorageRadar::ReportFbexResult("ReadESecretToKernel::fopen", userIdToFbe.userIds[SINGLE_ID_INDEX],
700             errno, "EL5", extraData);
701         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
702         return -errno;
703     }
704     int fd = fileno(f);
705     if (fd < 0) {
706         if (errno == ENOENT) {
707             isFbeSupport = false;
708             (void)fclose(f);
709             return 0;
710         }
711         (void)fclose(f);
712         return -errno;
713     }
714     uint32_t bufferSize = AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES + GCM_NONCE_BYTES;
715     FbeOptsEV1 ops{ .userIdDouble = userIdToFbe.userIds[DOUBLE_ID_INDEX],
716                     .userIdSingle = userIdToFbe.userIds[SINGLE_ID_INDEX],
717                     .status = status, .length = bufferSize, .authTokenSize = authToken.size };
718     if (MemcpyFbeOptsEV1(ops, authToken, eBuffer.data.get(), eBuffer.size) != EOK) {
719         (void)fclose(f);
720         return 0;
721     }
722     auto ret = ioctl(fd, FBEX_READ_CLASS_E, &ops);
723     if (ret != 0) {
724         HandleIoctlError(ret, errno, "FBEX_READ_CLASS_E", ops.userIdSingle, ops.userIdDouble);
725         (void)fclose(f);
726         return (static_cast<uint32_t>(ret) == FILE_ENCRY_ERROR_UECE_AUTH_STATUS_WRONG) ? ret : -errno;
727     }
728     (void)fclose(f);
729     if (ops.length == 0) {
730         eBuffer.Clear();
731         LOGE("ops length is 0, skip");
732         return 0;
733     }
734     UnlockSendSecret(status, bufferSize, eBuffer.size, eBuffer.data, ops.eBuffer);
735     LOGI("ReadESecretToKernel success");
736     return 0;
737 }
738 
UnlockSendSecret(uint32_t status,uint32_t bufferSize,uint32_t length,std::unique_ptr<uint8_t[]> & eBuffer,uint8_t * opseBuffer)739 int FBEX::UnlockSendSecret(uint32_t status, uint32_t bufferSize, uint32_t length, std::unique_ptr<uint8_t[]> &eBuffer,
740                            uint8_t *opseBuffer)
741 {
742     if (status == UNLOCK_STATUS) {
743         bufferSize = AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES + GCM_NONCE_BYTES;
744     } else {
745         bufferSize = AES_256_HASH_RANDOM_SIZE;
746     }
747     auto errBuffer = memcpy_s(eBuffer.get(), length, opseBuffer, bufferSize);
748     if (errBuffer != EOK) {
749         LOGE("memcpy failed %{public}d", errBuffer);
750         return 0;
751     }
752     return 0;
753 }
754 
WriteESecretToKernel(UserIdToFbeStr & userIdToFbe,uint32_t status,uint8_t * eBuffer,uint32_t length)755 int FBEX::WriteESecretToKernel(UserIdToFbeStr &userIdToFbe, uint32_t status, uint8_t *eBuffer, uint32_t length)
756 {
757     LOGI("enter, userId: %{public}d, status: %{public}u", userIdToFbe.userIds[DOUBLE_ID_INDEX], status);
758     if (!CheckWriteBuffValid(eBuffer, length, status)) {
759         LOGE("write e secret param invalid");
760         return -EINVAL;
761     }
762 
763     FILE *f = fopen(FBEX_UECE_PATH, "r+");
764     if (f == nullptr) {
765         if (errno == ENOENT) {
766             LOGE("fbex_uece does not exist, fbe not support this command!");
767             return 0;
768         }
769         std::string extraData = "userIdDouble=" + std::to_string(userIdToFbe.userIds[DOUBLE_ID_INDEX]);
770         StorageRadar::ReportFbexResult("WriteESecretToKernel::fopen", userIdToFbe.userIds[SINGLE_ID_INDEX],
771                                        errno, "EL5", extraData);
772         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
773         return -errno;
774     }
775     int fd = fileno(f);
776     if (fd < 0) {
777         (void)fclose(f);
778         return (errno == ENOENT ? 0 : -errno);
779     }
780     uint32_t bufferSize = AES_256_HASH_RANDOM_SIZE + GCM_MAC_BYTES + GCM_NONCE_BYTES;
781     FbeOptsE ops{ .userIdDouble = userIdToFbe.userIds[DOUBLE_ID_INDEX],
782                   .userIdSingle = userIdToFbe.userIds[SINGLE_ID_INDEX],
783                   .status = status, .length = bufferSize };
784     auto err = memcpy_s(ops.eBuffer, sizeof(ops.eBuffer), eBuffer, length);
785     if (err != EOK) {
786         LOGE("memcpy failed %{public}d", err);
787         (void)fclose(f);
788         return 0;
789     }
790     auto ret = ioctl(fd, FBEX_WRITE_CLASS_E, &ops);
791     if (ret != 0) {
792         LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
793         std::string extraData = "ioctl cmd=FBEX_WRITE_CLASS_E, userIdSingle=" + std::to_string(ops.userIdSingle)
794             + ", userIdDouble=" + std::to_string(ops.userIdDouble) + ", errno=" + std::to_string(errno);
795         StorageRadar::ReportFbexResult("InstallDoubleDeKeyToKernel", ops.userIdSingle, ret, "EL5", extraData);
796         (void)fclose(f);
797         return -errno;
798     }
799     (void)fclose(f);
800     LOGI("success");
801     return 0;
802 }
803 
IsMspReady()804 bool FBEX::IsMspReady()
805 {
806     std::string status;
807     (void)OHOS::LoadStringFromFile(FBEX_CMD_PATH, status);
808     return status == "true";
809 }
810 
GetStatus()811 int FBEX::GetStatus()
812 {
813     FILE *f = fopen(FBEX_CMD_PATH, "r+");
814     if (f == nullptr) {
815         StorageRadar::ReportFbexResult("GetStatus::fopen", 0, errno, "", "");
816         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
817         return -errno;
818     }
819     int fd = fileno(f);
820     if (fd < 0) {
821         LOGE("open fbex_cmd failed, errno: %{public}d", errno);
822         (void)fclose(f);
823         return -errno;
824     }
825 
826     FbeOpts ops;
827     int ret = ioctl(fd, FBEX_IOC_STATUS_REPORT, &ops);
828     (void)fclose(f);
829     return ret;
830 }
831 } // namespace StorageDaemon
832 } // namespace OHOS
833