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
20 #define HAP_APPID_SPLIT_CHA '_'
21 #define BASE_NUM_TWO 2
22 #define BASE_NUM_THREE 3
23 #define BASE_NUM_FOUR 4
24 #define MAX_BASE64_PADDING_LEN 2
25 #define MAX_PUBKEY_LEN 512
26 #define UNCOMPRESSED_PUBKEY_PREFIX 0x04
27
28 using namespace std;
29 using namespace OHOS::Security::AccessToken;
30
Base64Decode(string & encodedStr,unsigned char * decodedStr,uint32_t * decodedLen)31 static int32_t Base64Decode(string& encodedStr, unsigned char *decodedStr, uint32_t *decodedLen)
32 {
33 size_t encodedLen = encodedStr.length();
34 if (encodedLen == 0 || encodedLen % BASE_NUM_FOUR != 0) {
35 tloge("invaild based64 string, size %zu\n", encodedLen);
36 return -1;
37 }
38 if (*decodedLen < ((encodedLen / BASE_NUM_FOUR) * BASE_NUM_THREE)) {
39 tloge("decode string len too short, %zu, %u\n", encodedLen, (unsigned int)*decodedLen);
40 return -1;
41 }
42
43 int32_t ret = EVP_DecodeBlock(decodedStr, (const unsigned char*)encodedStr.c_str(), (int)encodedLen);
44 if (ret < 0) {
45 tloge("EVP DecodeBlock failed, ret %d\n", ret);
46 return -1;
47 }
48
49 uint32_t padLen = 0;
50 for (uint32_t i = 1; i <= BASE_NUM_FOUR; i++) {
51 if (encodedStr.at(encodedLen - i) == '=') {
52 padLen++;
53 } else {
54 break;
55 }
56 }
57
58 if (padLen > MAX_BASE64_PADDING_LEN) {
59 tloge("invaild base64 padding len, %u\n", padLen);
60 return -1;
61 }
62
63 if (ret == 0 || ret <= padLen) {
64 tloge("base64 decoded failed, decoded len %u, pad len %u\n", ret, padLen);
65 return -1;
66 }
67
68 *decodedLen = ret - padLen;
69 return 0;
70 }
71
FillEccHapCaInfo(string & packageName,const char * pubKey,uint32_t pubKeyLen,CaAuthInfo * caInfo)72 static int32_t FillEccHapCaInfo(string& packageName, const char *pubKey, uint32_t pubKeyLen, CaAuthInfo *caInfo)
73 {
74 /* certs format: packageNameLen || packageName || pubKeyLen || pubKey (xLen || x || yLen || y) */
75 uint64_t hapInfoSize = sizeof(uint32_t) + packageName.length() +
76 sizeof(uint32_t) + sizeof(uint32_t) * BASE_NUM_TWO + pubKeyLen;
77 if (hapInfoSize > sizeof(caInfo->certs)) {
78 tloge("buf too short, %u, %zu, %u\n", (unsigned int)sizeof(caInfo->certs), packageName.length(), pubKeyLen);
79 return -1;
80 }
81
82 /* packageNameLen || packageName */
83 uint32_t offset = 0;
84 *((uint32_t *)(caInfo->certs + offset)) = packageName.length();
85 offset += sizeof(uint32_t);
86 packageName.copy((char *)caInfo->certs + offset, packageName.length(), 0);
87 offset += packageName.length();
88
89 /* pubKey: pubKeyLen */
90 *((uint32_t *)(caInfo->certs + offset)) = pubKeyLen + sizeof(uint32_t) * BASE_NUM_TWO;
91 offset += sizeof(uint32_t);
92
93 /* pubKey: ecc.xLen */
94 *((uint32_t *)(caInfo->certs + offset)) = pubKeyLen / BASE_NUM_TWO;
95 offset += sizeof(uint32_t);
96 /* pubKey: ecc.x */
97 if (memcpy_s(caInfo->certs + offset, sizeof(caInfo->certs) - offset,
98 pubKey, pubKeyLen / BASE_NUM_TWO) != EOK) {
99 tloge("copy ecc pubkey x point failed\n");
100 return -1;
101 }
102 offset += pubKeyLen / BASE_NUM_TWO;
103
104 /* pubKey: ecc.yLen */
105 *((uint32_t *)(caInfo->certs + offset)) = pubKeyLen / BASE_NUM_TWO;
106 offset += sizeof(uint32_t);
107 /* pubKey: ecc.y */
108 if (memcpy_s(caInfo->certs + offset, sizeof(caInfo->certs) - offset,
109 pubKey + pubKeyLen / BASE_NUM_TWO, pubKeyLen / BASE_NUM_TWO) != EOK) {
110 tloge("copy ecc pubkey y point failed\n");
111 return -1;
112 }
113 offset += pubKeyLen / BASE_NUM_TWO;
114
115 return 0;
116 }
117
ConstructHapCaInfoFromToken(uint32_t tokenID,CaAuthInfo * caInfo)118 static int32_t ConstructHapCaInfoFromToken(uint32_t tokenID, CaAuthInfo *caInfo)
119 {
120 HapTokenInfo hapTokenInfo;
121 int32_t ret = AccessTokenKit::GetHapTokenInfo(tokenID, hapTokenInfo);
122 if (ret != 0) {
123 tloge("get hap token info failed, ret %d\n", ret);
124 return ret;
125 }
126
127 size_t appIDLen = hapTokenInfo.appID.length();
128 if (appIDLen == 0 || appIDLen > sizeof(caInfo->certs)) {
129 tloge("hap appid invaild, len %zu\n", appIDLen);
130 return -1;
131 }
132
133 size_t posSplit = hapTokenInfo.appID.find(HAP_APPID_SPLIT_CHA);
134 if (posSplit == string::npos) {
135 tloge("hap appid format is invaild\n");
136 return -1;
137 }
138 string packageName = hapTokenInfo.appID.substr(0, posSplit);
139 string pubkeyBase64 = hapTokenInfo.appID.substr(posSplit + 1, appIDLen - posSplit - 1);
140
141 char decodedPubkey[MAX_PUBKEY_LEN] = { 0 };
142 uint32_t decodedPubkeyLen = sizeof(decodedPubkey);
143 ret = Base64Decode(pubkeyBase64, (unsigned char *)decodedPubkey, &decodedPubkeyLen);
144 if (ret != 0) {
145 tloge("based64 pubkey decoded failed, ret %d\n", ret);
146 return ret;
147 }
148 uint8_t unCompressedPubkeyPrefix = UNCOMPRESSED_PUBKEY_PREFIX;
149 if (decodedPubkeyLen < sizeof(unCompressedPubkeyPrefix) || decodedPubkey[0] != unCompressedPubkeyPrefix) {
150 tloge("invaild decoded pubkey, %u\n", decodedPubkeyLen);
151 return -1;
152 }
153 decodedPubkeyLen = decodedPubkeyLen - sizeof(unCompressedPubkeyPrefix);
154
155 if (decodedPubkeyLen == 0 || decodedPubkeyLen % BASE_NUM_TWO != 0) {
156 tloge("invaild pub key, %u\n", decodedPubkeyLen);
157 return -1;
158 }
159
160 ret = FillEccHapCaInfo(packageName, decodedPubkey + sizeof(unCompressedPubkeyPrefix), decodedPubkeyLen, caInfo);
161 if (ret != 0) {
162 tloge("fill ecc hap cainfo failed, ret %d\n", ret);
163 return ret;
164 }
165 caInfo->type = APP_CA;
166 return 0;
167 }
168
ConstructNativeCaInfoFromToken(uint32_t tokenID,CaAuthInfo * caInfo)169 static int32_t ConstructNativeCaInfoFromToken(uint32_t tokenID, CaAuthInfo *caInfo)
170 {
171 NativeTokenInfo nativeTokenInfo;
172 int32_t ret = AccessTokenKit::GetNativeTokenInfo(tokenID, nativeTokenInfo);
173 if (ret == 0) {
174 uint32_t processNameLen = nativeTokenInfo.processName.length();
175 if (processNameLen == 0 || processNameLen > sizeof(caInfo->certs)) {
176 tloge("native ca process name too long, len %u\n", processNameLen);
177 return -1;
178 }
179
180 nativeTokenInfo.processName.copy((char *)caInfo->certs, processNameLen, 0);
181 } else {
182 tlogd("get native token info from atm failed, ret %d\n", ret);
183 int32_t rc = TeeGetPkgName(caInfo->pid, (char *)caInfo->certs, MAX_PATH_LENGTH);
184 if (rc != 0) {
185 tloge("get native ca info failed, rc %d\n", rc);
186 return -1;
187 }
188 }
189
190 caInfo->type = SA_CA;
191
192 return 0;
193 }
194
ConstructCaAuthInfo(uint32_t tokenID,CaAuthInfo * caInfo)195 int32_t ConstructCaAuthInfo(uint32_t tokenID, CaAuthInfo *caInfo)
196 {
197 if (caInfo == nullptr) {
198 tloge("bad params, ca info is null\n");
199 return -1;
200 }
201
202 ATokenTypeEnum tokenType = AccessTokenKit::GetTokenTypeFlag(tokenID);
203 switch (tokenType) {
204 case TOKEN_HAP: /* for hap ca */
205 tlogd("hap ca type, tokenID %u\n", tokenID);
206 return ConstructHapCaInfoFromToken(tokenID, caInfo);
207 case TOKEN_NATIVE: /* for native ca */
208 tlogd("native ca type, tokenID %u\n", tokenID);
209 return ConstructNativeCaInfoFromToken(tokenID, caInfo);
210 case TOKEN_SHELL: /* for native ca created by hdc */
211 tlogd("shell ca type, tokenID %u\n", tokenID);
212 caInfo->type = SYSTEM_CA;
213 return 0; /* cainfo: cmdline + uid */
214 default:
215 tloge("invaild token type %d\n", tokenType);
216 return -1;
217 }
218 }
219
TEEGetNativeSACaInfo(const CaAuthInfo * caInfo,uint8_t * buf,uint32_t bufLen)220 int32_t TEEGetNativeSACaInfo(const CaAuthInfo *caInfo, uint8_t *buf, uint32_t bufLen)
221 {
222 if (caInfo == nullptr || buf == nullptr || bufLen == 0) {
223 tloge("bad params\n");
224 return -1;
225 }
226
227 /* buf format: processNameLen || processName || uidLen || uid */
228 uint32_t processNameLen = strnlen((char *)caInfo->certs, sizeof(caInfo->certs));
229 uint32_t uidLen = sizeof(caInfo->uid);
230
231 uint64_t caInfoSize = sizeof(processNameLen) + processNameLen + sizeof(uidLen) + uidLen;
232 if ((uint64_t)bufLen < caInfoSize) {
233 tloge("buf too short, %u, %u\n", bufLen, processNameLen);
234 return -1;
235 }
236
237 /* processNameLen */
238 uint32_t offset = 0;
239 if (memcpy_s(buf + offset, bufLen - offset, &processNameLen, sizeof(processNameLen)) != EOK) {
240 tloge("copy process name len failed\n");
241 return -1;
242 }
243 offset += sizeof(processNameLen);
244 /* processName */
245 if (memcpy_s(buf + offset, bufLen - offset, caInfo->certs, processNameLen) != EOK) {
246 tloge("copy process name failed\n");
247 return -1;
248 }
249 offset += processNameLen;
250 /* uidLen */
251 if (memcpy_s(buf + offset, bufLen - offset, &uidLen, sizeof(uidLen)) != EOK) {
252 tloge("copy uid len failed\n");
253 return -1;
254 }
255 offset += sizeof(uidLen);
256 /* uid */
257 if (memcpy_s(buf + offset, bufLen - offset, &(caInfo->uid), uidLen) != EOK) {
258 tloge("copy uid failed\n");
259 return -1;
260 }
261
262 return 0;
263 }
264