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