• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "fscrypt_key_v1_ext.h"
17 
18 #include <filesystem>
19 #include <vector>
20 
21 #include "fbex.h"
22 #include "storage_service_log.h"
23 #include "string_ex.h"
24 
25 namespace OHOS {
26 namespace StorageDaemon {
27 static const std::string NEED_RESTORE_PATH = "/data/service/el0/storage_daemon/sd/latest/need_restore";
28 static const uint32_t DEFAULT_SINGLE_FIRST_USER_ID = 100;
29 static const uint32_t USER_ID_DIFF = 91;
30 
31 /* sec_fbe_drv module saved userId, type and IV in ioctl FBEX_IOC_ADD_IV process.
32  * In Upgrade Scenario, before upgrade user id 0 and after upgrade  user id 100, ioctl
33  * FBEX_IOC_ADD_IV will return error.
34  * so, to solve this problem, when el3/el4 ioctl FBEX_IOC_ADD_IV, userId need be mapped
35  * in Upgrade Scenario.
36  * user id mapped as:
37  * src-userId  mapped-userId    diff
38  * 0               100          100
39  * 10              101           91
40  * 11              102           91
41  * 12              103           91
42  * ...             ...           91
43  * 128             219           91
44  * 129             220           91
45  * ...             ...           91
46  */
GetMappedUserId(uint32_t userId,uint32_t type)47 uint32_t FscryptKeyV1Ext::GetMappedUserId(uint32_t userId, uint32_t type)
48 {
49     if (std::filesystem::exists(NEED_RESTORE_PATH) &&
50         (type == TYPE_EL2 || type == TYPE_EL3 || type == TYPE_EL4)) {
51         if (userId == DEFAULT_SINGLE_FIRST_USER_ID) {
52             return 0;
53         }
54 
55         if (userId > DEFAULT_SINGLE_FIRST_USER_ID) {
56             return userId - USER_ID_DIFF;
57         }
58     }
59 
60     return userId;
61 }
62 
ActiveKeyExt(uint32_t flag,uint8_t * iv,uint32_t size,uint32_t & elType)63 bool FscryptKeyV1Ext::ActiveKeyExt(uint32_t flag, uint8_t *iv, uint32_t size, uint32_t &elType)
64 {
65     if (!FBEX::IsFBEXSupported()) {
66         return true;
67     }
68 
69     LOGD("enter");
70     uint32_t user = GetMappedUserId(userId_, type_);
71     LOGI("type_ is %{public}u, map userId %{public}u to %{public}u", type_, userId_, user);
72     // iv buffer returns derived keys
73     if (FBEX::InstallKeyToKernel(user, type_, iv, size, static_cast<uint8_t>(flag)) != 0) {
74         LOGE("InstallKeyToKernel failed, user %{public}d, type %{public}d, flag %{public}u", user, type_, flag);
75         return false;
76     }
77 
78     //Used to associate el3 and el4 kernels.
79     elType = type_;
80     return true;
81 }
82 
UnlockUserScreenExt(uint32_t flag,uint8_t * iv,uint32_t size)83 bool FscryptKeyV1Ext::UnlockUserScreenExt(uint32_t flag, uint8_t *iv, uint32_t size)
84 {
85     if (!FBEX::IsFBEXSupported()) {
86         return true;
87     }
88     LOGD("enter");
89     uint32_t user = GetMappedUserId(userId_, type_);
90     LOGI("type_ is %{public}u, map userId %{public}u to %{public}u", type_, userId_, user);
91     if (FBEX::UnlockScreenToKernel(user, type_, iv, size)) {
92         LOGE("UnlockScreenToKernel failed, userId %{public}d, %{public}d", userId_, flag);
93         return false;
94     }
95     return true;
96 }
97 
InactiveKeyExt(uint32_t flag)98 bool FscryptKeyV1Ext::InactiveKeyExt(uint32_t flag)
99 {
100     if (!FBEX::IsFBEXSupported()) {
101         return true;
102     }
103 
104     LOGD("enter");
105     bool destroy = !!flag;
106     if ((type_ != TYPE_EL2) && !destroy) {
107         LOGD("not el2, no need to inactive");
108         return true;
109     }
110     uint8_t buf[FBEX_IV_SIZE] = {0};
111     buf[0] = 0xfb; // fitst byte const to kernel
112     buf[1] = 0x30; // second byte const to kernel
113 
114     uint32_t user = GetMappedUserId(userId_, type_);
115     LOGI("type_ is %{public}u, map userId %{public}u to %{public}u", type_, userId_, user);
116     if (FBEX::UninstallOrLockUserKeyToKernel(user, type_, buf, FBEX_IV_SIZE, destroy) != 0) {
117         LOGE("UninstallOrLockUserKeyToKernel failed, userId %{public}d, type %{public}d, destroy %{public}u", userId_,
118              type_, destroy);
119         return false;
120     }
121     return true;
122 }
123 
LockUserScreenExt(uint32_t flag,uint32_t & elType)124 bool FscryptKeyV1Ext::LockUserScreenExt(uint32_t flag, uint32_t &elType)
125 {
126     if (!FBEX::IsFBEXSupported()) {
127         return true;
128     }
129     LOGD("enter");
130     uint32_t user = GetMappedUserId(userId_, type_);
131     LOGI("type_ is %{public}u, map userId %{public}u to %{public}u", type_, userId_, user);
132     if (FBEX::LockScreenToKernel(user)) {
133         LOGE("LockScreenToKernel failed, userId %{public}d", flag);
134         return false;
135     }
136     //Used to associate el3 and el4 kernels.
137     elType = type_;
138     return true;
139 }
140 
GetUserIdFromDir()141 uint32_t FscryptKeyV1Ext::GetUserIdFromDir()
142 {
143     int userId = USERID_GLOBAL_EL1; // default to global el1
144 
145     // fscrypt key dir is like `/data/foo/bar/el1/100`
146     auto slashIndex = dir_.rfind('/');
147     if (slashIndex != std::string::npos) {
148         std::string last = dir_.substr(slashIndex + 1);
149         (void)OHOS::StrToInt(last, userId);
150     }
151 
152     LOGI("dir_: %{public}s, get userId is %{public}d", dir_.c_str(), userId);
153     return static_cast<uint32_t>(userId);
154 }
155 
GetTypeFromDir()156 uint32_t FscryptKeyV1Ext::GetTypeFromDir()
157 {
158     static const std::vector<std::pair<std::string, uint32_t>> typeStrs = {
159         {"el1", TYPE_EL1},
160         {"el2", TYPE_EL2},
161         {"el3", TYPE_EL3},
162         {"el4", TYPE_EL4},
163     };
164     uint32_t type = TYPE_GLOBAL_EL1; // default to global el1
165 
166     // fscrypt key dir is like `/data/foo/bar/el1/100`
167     auto slashIndex = dir_.rfind('/');
168     if (slashIndex == std::string::npos) {
169         LOGE("bad dir %{public}s", dir_.c_str());
170         return type;
171     }
172     slashIndex = dir_.rfind('/', slashIndex - 1);
173     if (slashIndex == std::string::npos) {
174         LOGE("bad dir %{public}s", dir_.c_str());
175         return type;
176     }
177 
178     std::string el = dir_.substr(slashIndex + 1); // el string is like `el1/100`
179     for (const auto &it : typeStrs) {
180         if (el.find(it.first) != std::string::npos) {
181             type = it.second;
182             break;
183         }
184     }
185     LOGI("el string is %{public}s, parse type %{public}d", el.c_str(), type);
186     return type;
187 }
188 } // namespace StorageDaemon
189 } // namespace OHOS
190