1 /*
2 * Copyright (C) 2023 Huawei Technologies Co., Ltd.
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12
13 #include "tee_auth_system.h"
14 #include "tee_auth_common.h"
15 #include "tee_log.h"
16 #include "accesstoken_kit.h"
17 #include "openssl/evp.h"
18 #include <securec.h>
19 #include "ipc_skeleton.h"
20 #include "iservice_registry.h"
21 #include "if_system_ability_manager.h"
22 #include "system_ability_definition.h"
23 #include "bundle_mgr_mini_proxy.h"
24
25 #define HAP_APPID_SPLIT_CHA '_'
26 #define BASE_NUM_TWO 2
27 #define BASE_NUM_THREE 3
28 #define BASE_NUM_FOUR 4
29 #define MAX_BASE64_PADDING_LEN 2
30 #define MAX_PUBKEY_LEN 512
31 #define UNCOMPRESSED_PUBKEY_PREFIX 0x04
32
33 using namespace std;
34 using namespace OHOS;
35 using namespace OHOS::Security::AccessToken;
36
Base64Decode(string & encodedStr,unsigned char * decodedStr,uint32_t * decodedLen)37 static int32_t Base64Decode(string& encodedStr, unsigned char *decodedStr, uint32_t *decodedLen)
38 {
39 size_t encodedLen = encodedStr.length();
40 if (encodedLen == 0 || encodedLen % BASE_NUM_FOUR != 0) {
41 tloge("invaild based64 string, size %" PUBLIC "zu\n", encodedLen);
42 return -1;
43 }
44 if (*decodedLen < ((encodedLen / BASE_NUM_FOUR) * BASE_NUM_THREE)) {
45 tloge("decode string len too short, %" PUBLIC "zu, %" PUBLIC "u\n", encodedLen, (unsigned int)*decodedLen);
46 return -1;
47 }
48
49 int32_t ret = EVP_DecodeBlock(decodedStr, (const unsigned char*)encodedStr.c_str(), (int)encodedLen);
50 if (ret < 0) {
51 tloge("EVP DecodeBlock failed, ret %" PUBLIC "d\n", ret);
52 return -1;
53 }
54
55 uint32_t padLen = 0;
56 for (uint32_t i = 1; i <= BASE_NUM_FOUR; i++) {
57 if (encodedStr.at(encodedLen - i) == '=') {
58 padLen++;
59 } else {
60 break;
61 }
62 }
63
64 if (padLen > MAX_BASE64_PADDING_LEN) {
65 tloge("invaild base64 padding len, %" PUBLIC "u\n", padLen);
66 return -1;
67 }
68
69 if (ret == 0 || ret <= static_cast<int32_t>(padLen)) {
70 tloge("base64 decoded failed, decoded len %" PUBLIC "u, pad len %" PUBLIC "u\n", ret, padLen);
71 return -1;
72 }
73
74 *decodedLen = ret - padLen;
75 return 0;
76 }
77
FillEccHapCaInfo(string & packageName,const char * pubKey,uint32_t pubKeyLen,CaAuthInfo * caInfo)78 static int32_t FillEccHapCaInfo(string& packageName, const char *pubKey, uint32_t pubKeyLen, CaAuthInfo *caInfo)
79 {
80 /* certs format: packageNameLen || packageName || pubKeyLen || pubKey (xLen || x || yLen || y) */
81 uint64_t hapInfoSize = sizeof(uint32_t) + packageName.length() +
82 sizeof(uint32_t) + sizeof(uint32_t) * BASE_NUM_TWO + pubKeyLen;
83 if (hapInfoSize > sizeof(caInfo->certs)) {
84 tloge("buf too short, %" PUBLIC "u, %" PUBLIC "u, %" PUBLIC "u\n",
85 (unsigned int)sizeof(caInfo->certs), (unsigned int)packageName.length(), (unsigned int)pubKeyLen);
86 return -1;
87 }
88
89 /* packageNameLen || packageName */
90 uint32_t offset = 0;
91 *((uint32_t *)(caInfo->certs + offset)) = packageName.length();
92 offset += sizeof(uint32_t);
93 packageName.copy((char *)caInfo->certs + offset, packageName.length(), 0);
94 offset += packageName.length();
95
96 /* pubKey: pubKeyLen */
97 *((uint32_t *)(caInfo->certs + offset)) = pubKeyLen + sizeof(uint32_t) * BASE_NUM_TWO;
98 offset += sizeof(uint32_t);
99
100 /* pubKey: ecc.xLen */
101 *((uint32_t *)(caInfo->certs + offset)) = pubKeyLen / BASE_NUM_TWO;
102 offset += sizeof(uint32_t);
103 /* pubKey: ecc.x */
104 if (memcpy_s(caInfo->certs + offset, sizeof(caInfo->certs) - offset,
105 pubKey, pubKeyLen / BASE_NUM_TWO) != EOK) {
106 tloge("copy ecc pubkey x point failed\n");
107 return -1;
108 }
109 offset += pubKeyLen / BASE_NUM_TWO;
110
111 /* pubKey: ecc.yLen */
112 *((uint32_t *)(caInfo->certs + offset)) = pubKeyLen / BASE_NUM_TWO;
113 offset += sizeof(uint32_t);
114 /* pubKey: ecc.y */
115 if (memcpy_s(caInfo->certs + offset, sizeof(caInfo->certs) - offset,
116 pubKey + pubKeyLen / BASE_NUM_TWO, pubKeyLen / BASE_NUM_TWO) != EOK) {
117 tloge("copy ecc pubkey y point failed\n");
118 return -1;
119 }
120 offset += pubKeyLen / BASE_NUM_TWO;
121
122 return 0;
123 }
124
GetHapAppID(void)125 static std::string GetHapAppID(void)
126 {
127 sptr<ISystemAbilityManager> systemAbilityManager =
128 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
129 if (systemAbilityManager == nullptr) {
130 tloge("GetBundleManagerProxy Failed to get system ability mgr.");
131 return "";
132 }
133 sptr<IRemoteObject> remoteObject =
134 systemAbilityManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
135 if (remoteObject == nullptr) {
136 tloge("GetBundleManagerProxy Failed to get bundle manager service.");
137 return "";
138 }
139 sptr<AppExecFwk::IBundleMgr> bundleManager = iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
140 if (bundleManager == nullptr) {
141 tloge("GetBundleManagerProxy bundleManager is nullptr");
142 return "";
143 }
144 /* userID */
145 int32_t uid = IPCSkeleton::GetCallingUid();
146 int32_t userId = uid / OHOS::AppExecFwk::Constants::BASE_USER_RANGE;
147 tlogd("uid=%" PUBLIC "d, userId=%" PUBLIC "d\n", uid, userId);
148
149 /* appID */
150 std::string bundleName;
151 bundleManager->GetNameForUid(uid, bundleName);
152 return bundleManager->GetAppIdByBundleName(bundleName, userId);
153 }
154
ConstructHapCaInfoFromToken(CaAuthInfo * caInfo)155 static int32_t ConstructHapCaInfoFromToken(CaAuthInfo *caInfo)
156 {
157 std::string appID = GetHapAppID();
158 if (appID.empty()) {
159 tloge("get app id failed\n");
160 return -1;
161 }
162 tlogd("appid=%" PUBLIC "s\n", appID.c_str());
163 size_t appIDLen = appID.length();
164 if (appIDLen == 0 || appIDLen > sizeof(caInfo->certs)) {
165 tloge("hap appid invaild, len %" PUBLIC "zu\n", appIDLen);
166 return -1;
167 }
168
169 size_t posSplit = appID.find_last_of(HAP_APPID_SPLIT_CHA);
170 if (posSplit == string::npos) {
171 tloge("hap appid format is invaild\n");
172 return -1;
173 }
174 string packageName = appID.substr(0, posSplit);
175 string pubkeyBase64 = appID.substr(posSplit + 1, appIDLen - posSplit - 1);
176
177 char decodedPubkey[MAX_PUBKEY_LEN] = { 0 };
178 uint32_t decodedPubkeyLen = sizeof(decodedPubkey);
179 int ret = Base64Decode(pubkeyBase64, (unsigned char *)decodedPubkey, &decodedPubkeyLen);
180 if (ret != 0) {
181 tloge("based64 pubkey decoded failed, ret %" PUBLIC "d\n", ret);
182 return ret;
183 }
184 uint8_t unCompressedPubkeyPrefix = UNCOMPRESSED_PUBKEY_PREFIX;
185 if (decodedPubkeyLen < sizeof(unCompressedPubkeyPrefix) || decodedPubkey[0] != unCompressedPubkeyPrefix) {
186 tloge("invaild decoded pubkey, %" PUBLIC "u\n", decodedPubkeyLen);
187 return -1;
188 }
189 decodedPubkeyLen = decodedPubkeyLen - sizeof(unCompressedPubkeyPrefix);
190
191 if (decodedPubkeyLen == 0 || decodedPubkeyLen % BASE_NUM_TWO != 0) {
192 tloge("invaild pub key, %" PUBLIC "u\n", decodedPubkeyLen);
193 return -1;
194 }
195
196 ret = FillEccHapCaInfo(packageName, decodedPubkey + sizeof(unCompressedPubkeyPrefix), decodedPubkeyLen, caInfo);
197 if (ret != 0) {
198 tloge("fill ecc hap cainfo failed, ret %" PUBLIC "d\n", ret);
199 return ret;
200 }
201 caInfo->type = APP_CA;
202 return 0;
203 }
204
205 #define RETRY_TIMES 5
ConstructNativeCaInfoFromToken(uint32_t tokenID,CaAuthInfo * caInfo,bool needRetry)206 static int32_t ConstructNativeCaInfoFromToken(uint32_t tokenID, CaAuthInfo *caInfo, bool needRetry)
207 {
208 NativeTokenInfo nativeTokenInfo;
209
210 int32_t ret;
211 int32_t retry = 0;
212 bool atmReady = true;
213
214 sptr<ISystemAbilityManager> saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
215 if (saMgr == nullptr) {
216 tloge("get system ability manager failed\n");
217 return -1;
218 }
219
220 if (saMgr->CheckSystemAbility(ACCESS_TOKEN_MANAGER_SERVICE_ID) == nullptr) {
221 tlogi("atm service is unready.\n");
222 atmReady = false;
223 }
224
225 if (!atmReady) {
226 tlogi("get native callinfo info not from atm\n");
227 int32_t rc = TeeGetPkgName(caInfo->pid, (char *)caInfo->certs, MAX_PATH_LENGTH);
228 if (rc != 0) {
229 tloge("get native ca info failed, rc %" PUBLIC "d\n", rc);
230 return -1;
231 }
232
233 caInfo->type = SA_CA;
234 return 0;
235 }
236
237 do {
238 retry++;
239 ret = AccessTokenKit::GetNativeTokenInfo(tokenID, nativeTokenInfo);
240 if (ret != 0) {
241 tlogi("get native token info from atm failed, retry times=%" PUBLIC "d\n", retry);
242 if (needRetry) {
243 sleep(1);
244 }
245 }
246 } while (ret != 0 && retry < RETRY_TIMES && needRetry);
247
248 if (ret != 0) {
249 tloge("get native token info from atm failed, retry times=%" PUBLIC "d, ret=0x%" PUBLIC "x\n", retry, ret);
250 return -1;
251 }
252 uint32_t processNameLen = nativeTokenInfo.processName.length();
253 if (processNameLen == 0 || processNameLen > sizeof(caInfo->certs)) {
254 tloge("native ca process name too long, len %" PUBLIC "u\n", processNameLen);
255 return -1;
256 }
257
258 nativeTokenInfo.processName.copy((char *)caInfo->certs, processNameLen, 0);
259 caInfo->type = SA_CA;
260 return 0;
261 }
262
ConstructCaAuthInfo(uint32_t tokenID,CaAuthInfo * caInfo)263 int32_t ConstructCaAuthInfo(uint32_t tokenID, CaAuthInfo *caInfo)
264 {
265 if (caInfo == nullptr) {
266 tloge("bad params, ca info is null\n");
267 return -1;
268 }
269
270 ATokenTypeEnum tokenType = AccessTokenKit::GetTokenTypeFlag(tokenID);
271 switch (tokenType) {
272 case TOKEN_HAP: /* for hap ca */
273 tlogd("hap ca type, tokenID %" PUBLIC "u\n", tokenID);
274 return ConstructHapCaInfoFromToken(caInfo);
275 case TOKEN_NATIVE: /* for native ca */
276 tlogd("native ca type, tokenID %" PUBLIC "u\n", tokenID);
277 return ConstructNativeCaInfoFromToken(tokenID, caInfo, false);
278 case TOKEN_SHELL: /* for native ca created by hdc */
279 tlogd("shell ca type, tokenID %" PUBLIC "u\n", tokenID);
280 caInfo->type = SYSTEM_CA;
281 return 0; /* cainfo: cmdline + uid */
282 default:
283 tloge("invaild token type %" PUBLIC "d\n", tokenType);
284 return -1;
285 }
286 }
287
ConstructSelfAuthInfo(CaAuthInfo * caInfo)288 int32_t ConstructSelfAuthInfo(CaAuthInfo *caInfo)
289 {
290 if (caInfo == nullptr) {
291 tloge("bad params, ca info is null\n");
292 return -1;
293 }
294
295 caInfo->pid = getpid();
296 caInfo->uid = getuid();
297
298 uint32_t selfTokenID = OHOS::IPCSkeleton::GetSelfTokenID();
299 tlogi("selfTokenID is %" PUBLIC "u\n", selfTokenID);
300
301 return ConstructNativeCaInfoFromToken(selfTokenID, caInfo, true);
302 }
303
TEEGetNativeSACaInfo(const CaAuthInfo * caInfo,uint8_t * buf,uint32_t bufLen)304 int32_t TEEGetNativeSACaInfo(const CaAuthInfo *caInfo, uint8_t *buf, uint32_t bufLen)
305 {
306 if (caInfo == nullptr || buf == nullptr || bufLen == 0) {
307 tloge("bad params\n");
308 return -1;
309 }
310
311 /* buf format: processNameLen || processName || uidLen || uid */
312 uint32_t processNameLen = strnlen((char *)caInfo->certs, sizeof(caInfo->certs));
313 uint32_t uidLen = sizeof(caInfo->uid);
314
315 uint64_t caInfoSize = sizeof(processNameLen) + processNameLen + sizeof(uidLen) + uidLen;
316 if ((uint64_t)bufLen < caInfoSize) {
317 tloge("buf too short, %" PUBLIC "u, %" PUBLIC "u\n", bufLen, processNameLen);
318 return -1;
319 }
320
321 /* processNameLen */
322 uint32_t offset = 0;
323 if (memcpy_s(buf + offset, bufLen - offset, &processNameLen, sizeof(processNameLen)) != EOK) {
324 tloge("copy process name len failed\n");
325 return -1;
326 }
327 offset += sizeof(processNameLen);
328 /* processName */
329 if (memcpy_s(buf + offset, bufLen - offset, caInfo->certs, processNameLen) != EOK) {
330 tloge("copy process name failed\n");
331 return -1;
332 }
333 offset += processNameLen;
334 /* uidLen */
335 if (memcpy_s(buf + offset, bufLen - offset, &uidLen, sizeof(uidLen)) != EOK) {
336 tloge("copy uid len failed\n");
337 return -1;
338 }
339 offset += sizeof(uidLen);
340 /* uid */
341 if (memcpy_s(buf + offset, bufLen - offset, &(caInfo->uid), uidLen) != EOK) {
342 tloge("copy uid failed\n");
343 return -1;
344 }
345
346 return 0;
347 }
348