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 28using namespace std; 29using namespace OHOS::Security::AccessToken; 30 31static 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 72static 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 118static 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 169static 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 195int32_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 220int32_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