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