• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cstring>
20 #include "ipc_skeleton.h"
21 #include "iservice_registry.h"
22 #include "if_system_ability_manager.h"
23 #include "system_ability_definition.h"
24 #include "bundle_mgr_mini_proxy.h"
25 
26 #define HAP_APPID_SPLIT_CHA    '_'
27 #define BASE_NUM_TWO   2
28 #define BASE_NUM_THREE  3
29 #define BASE_NUM_FOUR  4
30 #define MAX_BASE64_PADDING_LEN  2
31 #define MAX_PUBKEY_LEN  512
32 #define UNCOMPRESSED_PUBKEY_PREFIX 0x04
33 
34 using namespace std;
35 using namespace OHOS;
36 using namespace OHOS::Security::AccessToken;
37 
Base64Decode(string & encodedStr,unsigned char * decodedStr,uint32_t * decodedLen)38 static int32_t Base64Decode(string& encodedStr, unsigned char *decodedStr, uint32_t *decodedLen)
39 {
40     size_t encodedLen = encodedStr.length();
41     if (encodedLen == 0 || encodedLen % BASE_NUM_FOUR != 0) {
42         tloge("invaild based64 string, size %" PUBLIC "zu\n", encodedLen);
43         return -1;
44     }
45     if (*decodedLen < ((encodedLen / BASE_NUM_FOUR) * BASE_NUM_THREE)) {
46         tloge("decode string len too short, %" PUBLIC "zu, %" PUBLIC "u\n", encodedLen, (unsigned int)*decodedLen);
47         return -1;
48     }
49 
50     int32_t ret = EVP_DecodeBlock(decodedStr, (const unsigned char*)encodedStr.c_str(), (int)encodedLen);
51     if (ret < 0) {
52         tloge("EVP DecodeBlock failed, ret %" PUBLIC "d\n", ret);
53         return -1;
54     }
55 
56     uint32_t padLen = 0;
57     for (uint32_t i = 1; i <= BASE_NUM_FOUR; i++) {
58         if (encodedStr.at(encodedLen - i) == '=') {
59             padLen++;
60         } else {
61             break;
62         }
63     }
64 
65     if (padLen > MAX_BASE64_PADDING_LEN) {
66         tloge("invaild base64 padding len, %" PUBLIC "u\n", padLen);
67         return -1;
68     }
69 
70     if (ret == 0 || ret <= static_cast<int32_t>(padLen)) {
71         tloge("base64 decoded failed, decoded len %" PUBLIC "u, pad len %" PUBLIC "u\n", ret, padLen);
72         return -1;
73     }
74 
75     *decodedLen = ret - padLen;
76     return 0;
77 }
78 
FillEccHapCaInfo(string & packageName,const char * pubKey,uint32_t pubKeyLen,CaAuthInfo * caInfo)79 static int32_t FillEccHapCaInfo(string& packageName, const char *pubKey, uint32_t pubKeyLen, CaAuthInfo *caInfo)
80 {
81     /* certs format: packageNameLen || packageName || pubKeyLen || pubKey (xLen || x || yLen || y) */
82     uint64_t hapInfoSize = sizeof(uint32_t) + packageName.length() +
83         sizeof(uint32_t) + sizeof(uint32_t) * BASE_NUM_TWO + pubKeyLen;
84     if (hapInfoSize > sizeof(caInfo->certs)) {
85         tloge("buf too short, %" PUBLIC "u, %" PUBLIC "u, %" PUBLIC "u\n",
86             (unsigned int)sizeof(caInfo->certs), (unsigned int)packageName.length(), (unsigned int)pubKeyLen);
87         return -1;
88     }
89 
90     /* packageNameLen || packageName */
91     uint32_t offset = 0;
92     *((uint32_t *)(caInfo->certs + offset)) = packageName.length();
93     offset += sizeof(uint32_t);
94     packageName.copy((char *)caInfo->certs + offset, packageName.length(), 0);
95     offset += packageName.length();
96 
97     /* pubKey: pubKeyLen */
98     *((uint32_t *)(caInfo->certs + offset)) = pubKeyLen + sizeof(uint32_t) * BASE_NUM_TWO;
99     offset += sizeof(uint32_t);
100 
101     /* pubKey: ecc.xLen */
102     *((uint32_t *)(caInfo->certs + offset)) = pubKeyLen / BASE_NUM_TWO;
103     offset += sizeof(uint32_t);
104     /* pubKey: ecc.x */
105     if (memcpy_s(caInfo->certs + offset, sizeof(caInfo->certs) - offset,
106         pubKey, pubKeyLen / BASE_NUM_TWO) != EOK) {
107         tloge("copy ecc pubkey x point failed\n");
108         return -1;
109     }
110     offset += pubKeyLen / BASE_NUM_TWO;
111 
112     /* pubKey: ecc.yLen */
113     *((uint32_t *)(caInfo->certs + offset)) = pubKeyLen / BASE_NUM_TWO;
114     offset += sizeof(uint32_t);
115     /* pubKey: ecc.y */
116     if (memcpy_s(caInfo->certs + offset, sizeof(caInfo->certs) - offset,
117         pubKey + pubKeyLen / BASE_NUM_TWO, pubKeyLen / BASE_NUM_TWO) != EOK) {
118         tloge("copy ecc pubkey y point failed\n");
119         return -1;
120     }
121     offset += pubKeyLen / BASE_NUM_TWO;
122 
123     return 0;
124 }
125 
GetHapAppID(void)126 static std::string GetHapAppID(void)
127 {
128     sptr<ISystemAbilityManager> systemAbilityManager =
129         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
130     if (systemAbilityManager == nullptr) {
131         tloge("GetBundleManagerProxy Failed to get system ability mgr.");
132         return "";
133     }
134     sptr<IRemoteObject> remoteObject =
135         systemAbilityManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
136     if (remoteObject == nullptr) {
137         tloge("GetBundleManagerProxy Failed to get bundle manager service.");
138         return "";
139     }
140     sptr<AppExecFwk::IBundleMgr> bundleManager = iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
141     if (bundleManager == nullptr) {
142         tloge("GetBundleManagerProxy bundleManager is nullptr");
143         return "";
144     }
145     /* userID */
146     int32_t uid = IPCSkeleton::GetCallingUid();
147     int32_t userId = uid / OHOS::AppExecFwk::Constants::BASE_USER_RANGE;
148     tlogd("uid=%" PUBLIC "d, userId=%" PUBLIC "d\n", uid, userId);
149 
150     /* appID */
151     std::string bundleName;
152     bundleManager->GetNameForUid(uid, bundleName);
153     return bundleManager->GetAppIdByBundleName(bundleName, userId);
154 }
155 
ConstructHapCaInfoFromToken(CaAuthInfo * caInfo)156 static int32_t ConstructHapCaInfoFromToken(CaAuthInfo *caInfo)
157 {
158     std::string appID = GetHapAppID();
159     if (appID.empty()) {
160         tloge("get app id failed\n");
161         return -1;
162     }
163     tlogd("appid=%" PUBLIC "s\n", appID.c_str());
164     size_t appIDLen = appID.length();
165     if (appIDLen == 0 || appIDLen > sizeof(caInfo->certs)) {
166         tloge("hap appid invaild, len %" PUBLIC "zu\n", appIDLen);
167         return -1;
168     }
169 
170     size_t posSplit = appID.find_last_of(HAP_APPID_SPLIT_CHA);
171     if (posSplit == string::npos) {
172         tloge("hap appid format is invaild\n");
173         return -1;
174     }
175     string packageName = appID.substr(0, posSplit);
176     string pubkeyBase64 = appID.substr(posSplit + 1, appIDLen - posSplit - 1);
177 
178     char decodedPubkey[MAX_PUBKEY_LEN] = { 0 };
179     uint32_t decodedPubkeyLen = sizeof(decodedPubkey);
180     int ret = Base64Decode(pubkeyBase64, (unsigned char *)decodedPubkey, &decodedPubkeyLen);
181     if (ret != 0) {
182         tloge("based64 pubkey decoded failed, ret %" PUBLIC "d\n", ret);
183         return ret;
184     }
185     uint8_t unCompressedPubkeyPrefix = UNCOMPRESSED_PUBKEY_PREFIX;
186     if (decodedPubkeyLen < sizeof(unCompressedPubkeyPrefix) || decodedPubkey[0] != unCompressedPubkeyPrefix) {
187         tloge("invaild decoded pubkey, %" PUBLIC "u\n", decodedPubkeyLen);
188         return -1;
189     }
190     decodedPubkeyLen = decodedPubkeyLen - sizeof(unCompressedPubkeyPrefix);
191 
192     if (decodedPubkeyLen == 0 || decodedPubkeyLen % BASE_NUM_TWO != 0) {
193         tloge("invaild pub key, %" PUBLIC "u\n", decodedPubkeyLen);
194         return -1;
195     }
196 
197     ret = FillEccHapCaInfo(packageName, decodedPubkey + sizeof(unCompressedPubkeyPrefix), decodedPubkeyLen, caInfo);
198     if (ret != 0) {
199         tloge("fill ecc hap cainfo failed, ret %" PUBLIC "d\n", ret);
200         return ret;
201     }
202     caInfo->type = APP_CA;
203     return 0;
204 }
205 
206 #define RETRY_TIMES 5
ConstructNativeCaInfoFromToken(uint32_t tokenID,CaAuthInfo * caInfo,bool needRetry)207 static int32_t ConstructNativeCaInfoFromToken(uint32_t tokenID, CaAuthInfo *caInfo, bool needRetry)
208 {
209     NativeTokenInfo nativeTokenInfo;
210 
211     int32_t ret;
212     int32_t retry = 0;
213     bool atmReady = true;
214 
215     sptr<ISystemAbilityManager> saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
216     if (saMgr == nullptr) {
217         tloge("get system ability manager failed\n");
218         return -1;
219     }
220 
221     if (saMgr->CheckSystemAbility(ACCESS_TOKEN_MANAGER_SERVICE_ID) == nullptr) {
222         tlogi("atm service is unready.\n");
223         atmReady = false;
224     }
225 
226     if (!atmReady) {
227         tlogi("get native callinfo info not from atm\n");
228         int32_t rc = TeeGetPkgName(caInfo->pid, (char *)caInfo->certs, MAX_PATH_LENGTH);
229         if (rc != 0) {
230             tloge("get native ca info failed, rc %" PUBLIC "d\n", rc);
231             return -1;
232         }
233 
234         caInfo->type = SA_CA;
235         return 0;
236     }
237 
238     do {
239         retry++;
240         ret = AccessTokenKit::GetNativeTokenInfo(tokenID, nativeTokenInfo);
241         if (ret != 0) {
242             tlogi("get native token info from atm failed, retry times=%" PUBLIC "d\n", retry);
243             if (needRetry) {
244                 sleep(1);
245             }
246         }
247     } while (ret != 0 && retry < RETRY_TIMES && needRetry);
248 
249     if (ret != 0) {
250         tloge("get native token info from atm failed, retry times=%" PUBLIC "d, ret=0x%" PUBLIC "x\n", retry, ret);
251         return -1;
252     }
253     uint32_t processNameLen = nativeTokenInfo.processName.length();
254     if (processNameLen == 0 || processNameLen > sizeof(caInfo->certs)) {
255         tloge("native ca process name too long, len %" PUBLIC "u\n", processNameLen);
256         return -1;
257     }
258 
259     nativeTokenInfo.processName.copy((char *)caInfo->certs, processNameLen, 0);
260     caInfo->type = SA_CA;
261     return 0;
262 }
263 
ConstructCaAuthInfo(uint32_t tokenID,CaAuthInfo * caInfo)264 int32_t ConstructCaAuthInfo(uint32_t tokenID, CaAuthInfo *caInfo)
265 {
266     if (caInfo == nullptr) {
267         tloge("bad params, ca info is null\n");
268         return -1;
269     }
270 
271     ATokenTypeEnum tokenType = AccessTokenKit::GetTokenTypeFlag(tokenID);
272     switch (tokenType) {
273         case TOKEN_HAP:     /* for hap ca */
274             tlogd("hap ca type, tokenID %" PUBLIC "u\n", tokenID);
275             return ConstructHapCaInfoFromToken(caInfo);
276         case TOKEN_NATIVE:  /* for native ca */
277             tlogd("native ca type, tokenID %" PUBLIC "u\n", tokenID);
278             return ConstructNativeCaInfoFromToken(tokenID, caInfo, false);
279         case TOKEN_SHELL:   /* for native ca created by hdc */
280             tlogd("shell ca type, tokenID %" PUBLIC "u\n", tokenID);
281             caInfo->type = SYSTEM_CA;
282             return 0;       /* cainfo: cmdline + uid */
283         default:
284             tloge("invaild token type %" PUBLIC "d\n", tokenType);
285             return -1;
286     }
287 }
288 
ConstructSelfAuthInfo(CaAuthInfo * caInfo)289 int32_t ConstructSelfAuthInfo(CaAuthInfo *caInfo)
290 {
291     if (caInfo == nullptr) {
292         tloge("bad params, ca info is null\n");
293         return -1;
294     }
295 
296     caInfo->pid = getpid();
297     caInfo->uid = getuid();
298 
299     uint32_t selfTokenID = OHOS::IPCSkeleton::GetSelfTokenID();
300     tlogi("selfTokenID is %" PUBLIC "u\n", selfTokenID);
301 
302     return ConstructNativeCaInfoFromToken(selfTokenID, caInfo, true);
303 }
304 
TEEGetNativeSACaInfo(const CaAuthInfo * caInfo,uint8_t * buf,uint32_t bufLen)305 int32_t TEEGetNativeSACaInfo(const CaAuthInfo *caInfo, uint8_t *buf, uint32_t bufLen)
306 {
307     if (caInfo == nullptr || buf == nullptr || bufLen == 0) {
308         tloge("bad params\n");
309         return -1;
310     }
311 
312     /* buf format: processNameLen || processName || uidLen || uid */
313     uint32_t processNameLen = strnlen((char *)caInfo->certs, sizeof(caInfo->certs));
314     uint32_t uidLen = sizeof(caInfo->uid);
315 
316     uint64_t caInfoSize = sizeof(processNameLen) + processNameLen + sizeof(uidLen) + uidLen;
317     if ((uint64_t)bufLen < caInfoSize) {
318         tloge("buf too short, %" PUBLIC "u, %" PUBLIC "u\n", bufLen, processNameLen);
319         return -1;
320     }
321 
322     /* processNameLen */
323     uint32_t offset = 0;
324     if (memcpy_s(buf + offset, bufLen - offset, &processNameLen, sizeof(processNameLen)) != EOK) {
325         tloge("copy process name len failed\n");
326         return -1;
327     }
328     offset += sizeof(processNameLen);
329     /* processName */
330     if (memcpy_s(buf + offset, bufLen - offset, caInfo->certs, processNameLen) != EOK) {
331         tloge("copy process name failed\n");
332         return -1;
333     }
334     offset += processNameLen;
335     /* uidLen */
336     if (memcpy_s(buf + offset, bufLen - offset, &uidLen, sizeof(uidLen)) != EOK) {
337         tloge("copy uid len failed\n");
338         return -1;
339     }
340     offset += sizeof(uidLen);
341     /* uid */
342     if (memcpy_s(buf + offset, bufLen - offset, &(caInfo->uid), uidLen) != EOK) {
343         tloge("copy uid failed\n");
344         return -1;
345     }
346 
347     return 0;
348 }
349 
GetCaName(char * name,int32_t len)350 void GetCaName(char *name, int32_t len)
351 {
352     const char *res = nullptr;
353     int clen = 0;
354     CaAuthInfo info = { { 0 } };
355 
356     if (name == nullptr || len < MAX_PATH_LENGTH) {
357         return;
358     }
359     info.pid = IPCSkeleton::GetCallingPid();
360     info.uid = static_cast<unsigned int>(IPCSkeleton::GetCallingUid());
361     uint32_t tokenID = IPCSkeleton::GetCallingTokenID();
362     ATokenTypeEnum tokenType = AccessTokenKit::GetTokenTypeFlag(tokenID);
363     int ret = ConstructCaAuthInfo(tokenID, &info);
364     if (ret != 0) {
365         tloge("construct ca auth info failed %d\n", ret);
366     }
367     switch (tokenType) {
368         case TOKEN_SHELL:
369             ret = TeeGetPkgName(info.pid, name, len);
370             if (ret != 0) {
371                 tloge("get ca name failed\n");
372                 name[0] = '\0';
373             }
374             break;
375         case TOKEN_HAP:
376             res = strchr(reinterpret_cast<const char *>(info.certs), '_');
377             if (res != nullptr) {
378                 clen = res - reinterpret_cast<const char *>(info.certs);
379                 ret = memcpy_s(name, len, info.certs, clen);
380                 if (ret != 0) {
381                     tloge("get ca hap name failed\n");
382                     name[0] = '\0';
383                 }
384             } else {
385                 tloge("find _ failed in certs %s\n", info.certs);
386             }
387             break;
388         case TOKEN_NATIVE:
389             clen = strnlen(reinterpret_cast<const char *>(info.certs), MAX_PATH_LENGTH - 1);
390             ret = memcpy_s(name, len, info.certs, clen);
391             if (ret != 0) {
392                 tloge("get ca native name failed\n");
393                 name[0] = '\0';
394             }
395             break;
396         default:
397             tloge("invalid type %d\n", static_cast<int32_t>(tokenType));
398             break;
399     }
400 }
401