• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 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 "fscrypt_key_v1_ext.h"
17 
18 #include <filesystem>
19 
20 #include "fbex.h"
21 #include "file_ex.h"
22 #include "storage_service_errno.h"
23 #include "storage_service_log.h"
24 #include "string_ex.h"
25 #include "utils/storage_radar.h"
26 
27 namespace OHOS {
28 namespace StorageDaemon {
29 constexpr const char *NEED_RESTORE_PATH = "/data/service/el0/storage_daemon/sd/latest/need_restore";
30 constexpr int NEW_DOUBLE_2_SINGLE_BASE_VERSION = 2;
31 constexpr uint32_t DEFAULT_SINGLE_FIRST_USER_ID = 100;
32 constexpr uint32_t USER_ID_DIFF = 91;
33 
34 /* sec_fbe_drv module saved userId, type and IV in ioctl FBEX_IOC_ADD_IV process.
35  * In Upgrade Scenario, before upgrade user id 0 and after upgrade  user id 100, ioctl
36  * FBEX_IOC_ADD_IV will return error.
37  * so, to solve this problem, when el3/el4 ioctl FBEX_IOC_ADD_IV, userId need be mapped
38  * in Upgrade Scenario.
39  * user id mapped as:
40  * src-userId  mapped-userId    diff
41  * 0               100          100
42  * 10              101           91
43  * 11              102           91
44  * 12              103           91
45  * ...             ...           91
46  * 128             219           91
47  * 129             220           91
48  * ...             ...           91
49  */
GetMappedUserId(uint32_t userId,uint32_t type)50 uint32_t FscryptKeyV1Ext::GetMappedUserId(uint32_t userId, uint32_t type)
51 {
52     std::error_code errCode;
53     if (!std::filesystem::exists(NEED_RESTORE_PATH, errCode)) {
54         LOGE("restore path not exists, errCode = %{public}d", errCode.value());
55         return userId;
56     }
57     if (type == TYPE_EL2 || type == TYPE_EL3 || type == TYPE_EL4 || type == TYPE_EL5) {
58         if (userId == DEFAULT_SINGLE_FIRST_USER_ID) {
59             return 0;
60         }
61 
62         if (userId > DEFAULT_SINGLE_FIRST_USER_ID) {
63             return userId - USER_ID_DIFF;
64         }
65     }
66 
67     return userId;
68 }
69 
GetMappedDeUserId(uint32_t userId)70 uint32_t FscryptKeyV1Ext::GetMappedDeUserId(uint32_t userId)
71 {
72     if (userId == DEFAULT_SINGLE_FIRST_USER_ID) {
73         return 0;
74     }
75 
76     if (userId > DEFAULT_SINGLE_FIRST_USER_ID) {
77         return userId - USER_ID_DIFF;
78     }
79     return userId;
80 }
81 
ActiveKeyExt(uint32_t flag,KeyBlob & iv,uint32_t & elType,const KeyBlob & authToken)82 int32_t FscryptKeyV1Ext::ActiveKeyExt(uint32_t flag, KeyBlob &iv, uint32_t &elType, const KeyBlob &authToken)
83 {
84     auto startTime = StorageService::StorageRadar::RecordCurrentTime();
85     if (!FBEX::IsFBEXSupported()) {
86         return E_OK;
87     }
88     auto delay = StorageService::StorageRadar::ReportDuration("FBEX: IS_SUPPORT", startTime);
89     LOGI("enter. SD_DURATION: FBEX SUPPORT: elType=%{public}d, delay time = %{public}s", elType, delay.c_str());
90     std::error_code errCode;
91     std::string updateVersion;
92     int ret = OHOS::LoadStringFromFile(NEED_RESTORE_PATH, updateVersion);
93     LOGI("restore version: %{public}s, ret: %{public}d", updateVersion.c_str(), ret);
94     if (type_ == TYPE_EL1 && std::filesystem::exists(NEED_RESTORE_PATH, errCode) &&
95         std::atoi(updateVersion.c_str()) >= NEW_DOUBLE_2_SINGLE_BASE_VERSION) {
96         LOGI("restore path exists, deal double DE, errCode = %{public}d", errCode.value());
97         return ActiveDoubleKeyExt(flag, iv, elType, authToken);
98     }
99     uint32_t user = GetMappedUserId(userId_, type_);
100     LOGI("type_ is %{public}u, map userId %{public}u to %{public}u", type_, userId_, user);
101     // iv buffer returns derived keys
102     int errNo = FBEX::InstallKeyToKernel(user, type_, iv, static_cast<uint8_t>(flag), authToken);
103     if (errNo != 0) {
104         if (flag != 0) {
105             LOGE("New User InstallKeyToKernel failed, user %{public}d, type %{public}d, flag %{public}u", user, type_,
106                  flag);
107             return errNo;
108         }
109         LOGE("InstallKeyToKernel first failed, user %{public}d, type %{public}d, flag %{public}u", user, type_, flag);
110         errNo = FBEX::InstallKeyToKernel(user, type_, iv, static_cast<uint8_t>(flag), authToken);
111         if (errNo != 0) {
112             LOGE("InstallKeyToKernel failed, user %{public}d, type %{public}d, flag %{public}u", user, type_, flag);
113             return errNo;
114         }
115     }
116 
117     //Used to associate el3 and el4 kernels.
118     elType = type_;
119     return E_OK;
120 }
121 
ActiveDoubleKeyExt(uint32_t flag,KeyBlob & iv,uint32_t & elType,const KeyBlob & authToken)122 int32_t FscryptKeyV1Ext::ActiveDoubleKeyExt(uint32_t flag, KeyBlob &iv, uint32_t &elType, const KeyBlob &authToken)
123 {
124     LOGI("enter");
125     UserIdToFbeStr userIdToFbe = { .userIds = { userId_, GetMappedDeUserId(userId_) }, .size = USER_ID_SIZE };
126     int32_t errNo = FBEX::InstallDoubleDeKeyToKernel(userIdToFbe, iv, flag, authToken);
127     if (errNo != 0) {
128         LOGE("DoubleDeKeyToKernel failed, user %{public}d, type %{public}d, flag %{public}u", userId_, type_, flag);
129         return errNo;
130     }
131     elType = type_;
132     return E_OK;
133 }
134 
UnlockUserScreenExt(uint32_t flag,uint8_t * iv,uint32_t size,const KeyBlob & authToken)135 int32_t FscryptKeyV1Ext::UnlockUserScreenExt(uint32_t flag, uint8_t *iv, uint32_t size, const KeyBlob &authToken)
136 {
137     if (!FBEX::IsFBEXSupported()) {
138         return E_OK;
139     }
140     LOGI("enter");
141     uint32_t user = GetMappedUserId(userId_, type_);
142     LOGI("type_ is %{public}u, map userId %{public}u to %{public}u", type_, userId_, user);
143     int32_t ret = FBEX::UnlockScreenToKernel(user, type_, iv, size, authToken);
144     if (ret != E_OK) {
145         LOGE("UnlockScreenToKernel failed, userId %{public}d, %{public}d", userId_, flag);
146         return ret;
147     }
148     return E_OK;
149 }
150 
GenerateAppkey(uint32_t user,uint32_t hashId,std::unique_ptr<uint8_t[]> & appKey,uint32_t size)151 int32_t FscryptKeyV1Ext::GenerateAppkey(uint32_t user, uint32_t hashId,
152                                         std::unique_ptr<uint8_t[]> &appKey, uint32_t size)
153 {
154     if (!FBEX::IsFBEXSupported()) {
155         return E_OK;
156     }
157     LOGI("enter");
158     LOGI("map userId %{public}u to %{public}u", userId_, user);
159     // 0--single id, 1--double id
160     UserIdToFbeStr userIdToFbe = { .userIds = { userId_, GetMappedUserId(userId_, type_) }, .size = USER_ID_SIZE };
161     auto ret = FBEX::GenerateAppkey(userIdToFbe, hashId, appKey, size);
162     if (ret != E_OK) {
163         LOGE("GenerateAppkey failed, user %{public}d", user);
164         return ret;
165     }
166     return E_OK;
167 }
168 
AddClassE(bool & isNeedEncryptClassE,bool & isSupport,uint32_t status)169 int32_t FscryptKeyV1Ext::AddClassE(bool &isNeedEncryptClassE, bool &isSupport, uint32_t status)
170 {
171     if (!FBEX::IsFBEXSupported()) {
172         return E_OK;
173     }
174     LOGI("enter");
175     uint32_t userIdDouble = GetMappedUserId(userId_, type_);
176     LOGI("map userId %{public}u to %{public}u", userId_, userIdDouble);
177     auto ret = FBEX::InstallEL5KeyToKernel(userId_, userIdDouble, status, isSupport, isNeedEncryptClassE);
178     if (ret != E_OK) {
179         LOGE("AddESecret failed, userId_ %{public}d, status is %{public}d", userId_, status);
180         return ret;
181     }
182     return E_OK;
183 }
184 
DeleteClassEPinCode(uint32_t userId)185 int32_t FscryptKeyV1Ext::DeleteClassEPinCode(uint32_t userId)
186 {
187     if (!FBEX::IsFBEXSupported()) {
188         return E_OK;
189     }
190     LOGI("enter");
191     uint32_t userIdDouble = GetMappedUserId(userId_, type_);
192     LOGI("type_ is %{public}u, map userId %{public}u to %{public}u", type_, userId_, userIdDouble);
193     auto ret = FBEX::DeleteClassEPinCode(userId_, userIdDouble);
194     if (ret != E_OK) {
195         LOGE("UninstallOrLockUserKeyForEL5ToKernel failed, userId_ %{public}d", userId_);
196         return ret;
197     }
198     return E_OK;
199 }
200 
ChangePinCodeClassE(uint32_t userId,bool & isFbeSupport)201 int32_t FscryptKeyV1Ext::ChangePinCodeClassE(uint32_t userId, bool &isFbeSupport)
202 {
203     if (!FBEX::IsFBEXSupported()) {
204         return E_OK;
205     }
206     uint32_t userIdDouble = GetMappedUserId(userId_, type_);
207     LOGI("type_ is %{public}u, map userId %{public}u to %{public}u", type_, userId_, userIdDouble);
208     auto ret = FBEX::ChangePinCodeClassE(userId_, userIdDouble, isFbeSupport);
209     if (ret != E_OK) {
210         LOGE("ChangePinCodeClassE failed, userId_ %{public}d", userId_);
211         return ret;
212     }
213     return E_OK;
214 }
215 
UpdateClassEBackUp(uint32_t userId)216 int32_t FscryptKeyV1Ext::UpdateClassEBackUp(uint32_t userId)
217 {
218     if (!FBEX::IsFBEXSupported()) {
219         return E_OK;
220     }
221     uint32_t userIdDouble = GetMappedUserId(userId_, type_);
222     LOGI("type_ is %{public}u, map userId %{public}u to %{public}u", type_, userId_, userIdDouble);
223     auto ret = FBEX::UpdateClassEBackUp(userId_, userIdDouble);
224     if (ret != E_OK) {
225         LOGE("UpdateClassEBackUp failed, userId_ %{public}d", userId_);
226         return ret;
227     }
228     return E_OK;
229 }
230 
ReadClassE(uint32_t status,KeyBlob & classEBuffer,const KeyBlob & authToken,bool & isFbeSupport)231 int32_t FscryptKeyV1Ext::ReadClassE(uint32_t status, KeyBlob &classEBuffer, const KeyBlob &authToken,
232                                     bool &isFbeSupport)
233 {
234     if (!FBEX::IsFBEXSupported()) {
235         return E_OK;
236     }
237     LOGI("enter");
238     // 0--single id, 1--double id
239     UserIdToFbeStr userIdToFbe = { .userIds = { userId_, GetMappedUserId(userId_, type_) }, .size = USER_ID_SIZE };
240     LOGI("type_: %{public}u, userId %{public}u to %{public}u", type_, userId_, userIdToFbe.userIds[DOUBLE_ID_INDEX]);
241     auto ret = FBEX::ReadESecretToKernel(userIdToFbe, status, classEBuffer, authToken, isFbeSupport);
242     if (ret != E_OK) {
243         LOGE("ReadESecret failed, user %{public}d, status: %{public}d", userIdToFbe.userIds[DOUBLE_ID_INDEX], status);
244         return ret;
245     }
246     return E_OK;
247 }
248 
WriteClassE(uint32_t status,uint8_t * classEBuffer,uint32_t length)249 int32_t FscryptKeyV1Ext::WriteClassE(uint32_t status, uint8_t *classEBuffer, uint32_t length)
250 {
251     if (!FBEX::IsFBEXSupported()) {
252         return E_OK;
253     }
254     LOGI("enter");
255     // 0--single id, 1--double id
256     UserIdToFbeStr userIdToFbe = { .userIds = { userId_, GetMappedUserId(userId_, type_) }, .size = USER_ID_SIZE };
257     LOGI("type_ is %{public}u, map userId %{public}u to %{public}u",
258          type_, userId_, userIdToFbe.userIds[DOUBLE_ID_INDEX]);
259     auto ret = FBEX::WriteESecretToKernel(userIdToFbe, status, classEBuffer, length);
260     if (ret != E_OK) {
261         LOGE("WriteESecret failed,user %{public}d, status: %{public}d", userIdToFbe.userIds[DOUBLE_ID_INDEX], status);
262         return ret;
263     }
264     return E_OK;
265 }
266 
InactiveKeyExt(uint32_t flag)267 int32_t FscryptKeyV1Ext::InactiveKeyExt(uint32_t flag)
268 {
269     if (!FBEX::IsFBEXSupported()) {
270         return E_OK;
271     }
272 
273     LOGI("enter");
274     bool destroy = !!flag;
275     if ((type_ == TYPE_EL1) && !destroy) {
276         LOGI("Is el1, no need to inactive");
277         return E_OK;
278     }
279     uint8_t buf[FBEX_IV_SIZE] = {0};
280     buf[0] = 0xfb; // fitst byte const to kernel
281     buf[1] = 0x30; // second byte const to kernel
282 
283     // When double update single, el5 use single user id, like: 100  101  102 ...
284     // el1-el4 use double id, like 0 10 11 12 ...
285     uint32_t user = type_ == TYPE_EL5 ? userId_ : GetMappedUserId(userId_, type_);
286     LOGI("type_ is %{public}u, map userId %{public}u to %{public}u", type_, userId_, user);
287     int errNo = FBEX::UninstallOrLockUserKeyToKernel(user, type_, buf, FBEX_IV_SIZE, destroy);
288     if (errNo != 0) {
289         LOGE("UninstallOrLockUserKeyToKernel failed, userId %{public}d, type %{public}d, destroy %{public}u",
290              userId_, type_, destroy);
291         return errNo;
292     }
293     return E_OK;
294 }
295 
LockUserScreenExt(uint32_t flag,uint32_t & elType)296 int32_t FscryptKeyV1Ext::LockUserScreenExt(uint32_t flag, uint32_t &elType)
297 {
298     if (!FBEX::IsFBEXSupported()) {
299         return E_OK;
300     }
301     LOGI("enter");
302     uint32_t user = GetMappedUserId(userId_, type_);
303     LOGI("type_ is %{public}u, map userId %{public}u to %{public}u", type_, userId_, user);
304     int32_t ret = FBEX::LockScreenToKernel(user);
305     if (ret != E_OK) {
306         LOGE("LockScreenToKernel failed, userId %{public}d, error code: %{public}d", user, ret);
307         return ret;
308     }
309     //Used to associate el3 and el4 kernels.
310     elType = type_;
311     return E_OK;
312 }
313 
LockUeceExt(bool & isFbeSupport)314 int32_t FscryptKeyV1Ext::LockUeceExt(bool &isFbeSupport)
315 {
316     if (!FBEX::IsFBEXSupported()) {
317         return E_OK;
318     }
319     LOGD("FscryptKeyV1Ext::LockUeceExt enter");
320     uint32_t userIdDouble = GetMappedUserId(userId_, type_);
321     LOGI("type_ is %{public}u, map userId %{public}u to %{public}u", type_, userId_, userIdDouble);
322     int32_t ret = FBEX::LockUece(userId_, userIdDouble, isFbeSupport);
323     if (ret != E_OK) {
324         LOGE("LockUeceExt failed, userId");
325         return ret;
326     }
327     return E_OK;
328 }
329 
GetUserIdFromDir()330 uint32_t FscryptKeyV1Ext::GetUserIdFromDir()
331 {
332     int userId = USERID_GLOBAL_EL1; // default to global el1
333 
334     // fscrypt key dir is like `/data/foo/bar/el1/100`
335     auto slashIndex = dir_.rfind('/');
336     if (slashIndex != std::string::npos) {
337         std::string last = dir_.substr(slashIndex + 1);
338         (void)OHOS::StrToInt(last, userId);
339     }
340 
341     LOGI("dir_: %{public}s, get userId is %{public}d", dir_.c_str(), userId);
342     return static_cast<uint32_t>(userId);
343 }
344 
GetTypeFromDir()345 uint32_t FscryptKeyV1Ext::GetTypeFromDir()
346 {
347     static const std::vector<std::pair<std::string, uint32_t>> typeStrs = {
348         {"el1", TYPE_EL1},
349         {"el2", TYPE_EL2},
350         {"el3", TYPE_EL3},
351         {"el4", TYPE_EL4},
352         {"el5", TYPE_EL5},
353     };
354     uint32_t type = TYPE_GLOBAL_EL1; // default to global el1
355 
356     // fscrypt key dir is like `/data/foo/bar/el1/100`
357     auto slashIndex = dir_.rfind('/');
358     if (slashIndex == std::string::npos) {
359         LOGE("bad dir %{public}s", dir_.c_str());
360         return type;
361     }
362 
363     if (slashIndex == 0) {
364         LOGE("bad dir %{public}s", dir_.c_str());
365         return type;
366     }
367 
368     slashIndex = dir_.rfind('/', slashIndex - 1);
369     if (slashIndex == std::string::npos) {
370         LOGE("bad dir %{public}s", dir_.c_str());
371         return type;
372     }
373 
374     std::string el = dir_.substr(slashIndex + 1); // el string is like `el1/100`
375     for (const auto &it : typeStrs) {
376         if (el.find(it.first) != std::string::npos) {
377             type = it.second;
378             break;
379         }
380     }
381     LOGI("el string is %{public}s, parse type %{public}d", el.c_str(), type);
382     return type;
383 }
384 } // namespace StorageDaemon
385 } // namespace OHOS
386