1 /*
2 * Copyright (c) 2022 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
29 namespace {
30 constexpr const char *FBEX_UFS_INLINE_SUPPORT_PREFIX = "/sys/devices/platform/";
31 constexpr const char *FBEX_UFS_INLINE_SUPPORT_END = "/ufs_inline_stat";
32 constexpr const char *FBEX_UFS_INLINE_BASE_ADDR = "/proc/bootdevice/name";
33 constexpr const char *FBEX_INLINE_CRYPTO_V3 = "3\n";
34
35 constexpr const char *FBEX_CMD_PATH = "/dev/fbex_cmd";
36
37 const uint8_t FBEX_IOC_MAGIC = 'f';
38 const uint8_t FBEX_ADD_IV = 0x1;
39 const uint8_t FBEX_DEL_IV = 0x2;
40 const uint8_t FBEX_LOCK_SCREEN = 0x3;
41 const uint8_t FBEX_UNLOCK_SCREEN = 0x4;
42 const uint8_t FBEX_USER_LOGOUT = 0x8;
43 const uint8_t FBEX_STATUS_REPORT = 0xC;
44
45 struct FbeOptStr {
46 uint32_t user = 0;
47 uint32_t type = 0;
48 uint32_t len = 0;
49 uint8_t iv[OHOS::StorageDaemon::FBEX_IV_SIZE] = {0};
50 uint8_t flag = 0;
51 };
52 using FbeOpts = FbeOptStr;
53
54 #define FBEX_IOC_ADD_IV _IOWR(FBEX_IOC_MAGIC, FBEX_ADD_IV, FbeOpts)
55 #define FBEX_IOC_DEL_IV _IOW(FBEX_IOC_MAGIC, FBEX_DEL_IV, FbeOpts)
56 #define FBEX_IOC_LOCK_SCREEN _IOW(FBEX_IOC_MAGIC, FBEX_LOCK_SCREEN, FbeOpts)
57 #define FBEX_IOC_UNLOCK_SCREEN _IOWR(FBEX_IOC_MAGIC, FBEX_UNLOCK_SCREEN, FbeOpts)
58 #define FBEX_IOC_USER_LOGOUT _IOW(FBEX_IOC_MAGIC, FBEX_USER_LOGOUT, FbeOpts)
59 #define FBEX_IOC_STATUS_REPORT _IOW(FBEX_IOC_MAGIC, FBEX_STATUS_REPORT, FbeOpts)
60 } // namespace
61
62 namespace OHOS {
63 namespace StorageDaemon {
IsFBEXSupported()64 bool FBEX::IsFBEXSupported()
65 {
66 std::string baseAddr;
67 if (!OHOS::LoadStringFromFile(FBEX_UFS_INLINE_BASE_ADDR, baseAddr)) {
68 LOGE("Read baseAddr failed, errno: %{public}d", errno);
69 return false;
70 }
71
72 std::string path = FBEX_UFS_INLINE_SUPPORT_PREFIX + baseAddr + FBEX_UFS_INLINE_SUPPORT_END;
73 std::string rpath(PATH_MAX + 1, '\0');
74
75 if ((path.length() > PATH_MAX) || (realpath(path.c_str(), rpath.data()) == nullptr)) {
76 LOGE("realpath of %{public}s failed, errno: %{public}d", path.c_str(), errno);
77 return false;
78 }
79 if (rpath.rfind(FBEX_UFS_INLINE_SUPPORT_PREFIX) != 0) {
80 LOGE("rpath %{public}s is invalid", rpath.c_str());
81 return false;
82 }
83
84 std::string versionNum;
85 if (!OHOS::LoadStringFromFile(rpath, versionNum)) {
86 LOGE("read ufs_inline_stat failed, errno: %{public}d", errno);
87 return false;
88 }
89 return versionNum.compare(FBEX_INLINE_CRYPTO_V3) == 0;
90 }
91
CheckIvValid(const uint8_t * iv,uint32_t size)92 static inline bool CheckIvValid(const uint8_t *iv, uint32_t size)
93 {
94 return (iv != nullptr) && (size == FBEX_IV_SIZE);
95 }
96
InstallKeyToKernel(uint32_t userId,uint32_t type,uint8_t * iv,uint32_t size,uint8_t flag)97 int FBEX::InstallKeyToKernel(uint32_t userId, uint32_t type, uint8_t *iv, uint32_t size, uint8_t flag)
98 {
99 LOGD("enter, userId: %{public}d, type: %{public}u, flag: %{public}u", userId, type, flag);
100 if (!CheckIvValid(iv, size)) {
101 LOGE("install key param invalid");
102 return -EINVAL;
103 }
104
105 int fd = open(FBEX_CMD_PATH, O_RDWR);
106 if (fd < 0) {
107 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
108 return -errno;
109 }
110
111 FbeOpts ops{.user = userId, .type = type, .len = size, .flag = flag};
112 (void)memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
113 int ret = ioctl(fd, FBEX_IOC_ADD_IV, &ops);
114 if (ret != 0) {
115 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
116 close(fd);
117 return ret;
118 }
119 close(fd);
120
121 (void)memcpy_s(iv, size, ops.iv, sizeof(ops.iv));
122 LOGD("success");
123 return ret;
124 }
125
UninstallOrLockUserKeyToKernel(uint32_t userId,uint32_t type,uint8_t * iv,uint32_t size,bool destroy)126 int FBEX::UninstallOrLockUserKeyToKernel(uint32_t userId, uint32_t type, uint8_t *iv, uint32_t size, bool destroy)
127 {
128 LOGD("enter, userId: %{public}d, type: %{public}u, flag: %{public}d", userId, type, destroy);
129 if (!CheckIvValid(iv, size)) {
130 LOGE("uninstall key param invalid");
131 return -EINVAL;
132 }
133
134 int fd = open(FBEX_CMD_PATH, O_RDWR);
135 if (fd < 0) {
136 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
137 return -errno;
138 }
139
140 FbeOpts ops{.user = userId, .type = type, .len = size};
141 (void)memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
142 int ret = ioctl(fd, destroy ? FBEX_IOC_DEL_IV : FBEX_IOC_USER_LOGOUT, &ops);
143 if (ret != 0) {
144 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
145 }
146 close(fd);
147 return ret;
148 }
149
150 // for el3 & el4
LockScreenToKernel(uint32_t userId)151 int FBEX::LockScreenToKernel(uint32_t userId)
152 {
153 LOGD("enter, userId: %{public}d", userId);
154
155 int fd = open(FBEX_CMD_PATH, O_RDWR);
156 if (fd < 0) {
157 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
158 return -errno;
159 }
160
161 FbeOpts ops{.user = userId};
162 int ret = ioctl(fd, FBEX_IOC_LOCK_SCREEN, &ops);
163 if (ret != 0) {
164 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
165 }
166 close(fd);
167 return ret;
168 }
169
UnlockScreenToKernel(uint32_t userId,uint32_t type,uint8_t * iv,uint32_t size)170 int FBEX::UnlockScreenToKernel(uint32_t userId, uint32_t type, uint8_t *iv, uint32_t size)
171 {
172 LOGD("enter, userId: %{public}d, type: %{public}u", userId, type);
173 if (!CheckIvValid(iv, size)) {
174 LOGE("install key param invalid");
175 return -EINVAL;
176 }
177
178 int fd = open(FBEX_CMD_PATH, O_RDWR);
179 if (fd < 0) {
180 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
181 return -errno;
182 }
183
184 FbeOpts ops{.user = userId, .type = type, .len = size};
185 (void)memcpy_s(ops.iv, sizeof(ops.iv), iv, size);
186 int ret = ioctl(fd, FBEX_IOC_UNLOCK_SCREEN, &ops);
187 if (ret != 0) {
188 LOGE("ioctl fbex_cmd failed, ret: 0x%{public}x, errno: %{public}d", ret, errno);
189 close(fd);
190 return ret;
191 }
192 close(fd);
193
194 (void)memcpy_s(iv, size, ops.iv, sizeof(ops.iv));
195 LOGD("success");
196 return ret;
197 }
198
IsMspReady()199 bool FBEX::IsMspReady()
200 {
201 std::string status;
202 (void)OHOS::LoadStringFromFile(FBEX_CMD_PATH, status);
203 return status == "true";
204 }
205
GetStatus()206 int FBEX::GetStatus()
207 {
208 int fd = open(FBEX_CMD_PATH, O_RDWR);
209 if (fd < 0) {
210 LOGE("open fbex_cmd failed, errno: %{public}d", errno);
211 return -errno;
212 }
213
214 FbeOpts ops;
215 int ret = ioctl(fd, FBEX_IOC_STATUS_REPORT, &ops);
216 close(fd);
217 return ret;
218 }
219 } // namespace StorageDaemon
220 } // namespace OHOS
221