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 "tcu_authentication.h" 14#include <unistd.h> 15#include <errno.h> /* for errno */ 16#include <fcntl.h> 17#include <sys/types.h> /* for open close */ 18#include <sys/ioctl.h> /* for ioctl */ 19#include <sys/stat.h> /* for stat */ 20#include <linux/limits.h> 21#include "securec.h" 22#include "tee_log.h" 23#include "tc_ns_client.h" 24#include "tee_client_type.h" 25 26#ifdef LOG_TAG 27#undef LOG_TAG 28#endif 29#define LOG_TAG "tcu_authentication" 30#define HASH_FILE_MAX_SIZE (16 * 1024) 31#define ERR_SIZE (-1) 32#define XML_HEADER 4 33#define MAX_HASHFILE_PATHLEN 256 34 35static const char *g_vendorCaHashFileList[] = { 36 "/vendor/etc/native_packages.xml", 37 "/vendor/root/res/native_packages.xml", 38}; 39 40static const char *g_systemCaHashFileList[] = { 41 "/system/etc/native_packages.xml", 42}; 43 44static const char **GetCaHashFileList(uint8_t *num, uint8_t hash_type) 45{ 46 if (num == NULL) { 47 tloge("input parameter error\n"); 48 return NULL; 49 } 50 51 if (hash_type == HASH_TYPE_SYSTEM) { 52 *num = sizeof(g_systemCaHashFileList) / sizeof(intptr_t); 53 return g_systemCaHashFileList; 54 } else { 55 *num = sizeof(g_vendorCaHashFileList) / sizeof(intptr_t); 56 return g_vendorCaHashFileList; 57 } 58} 59 60static int IsNotValidFname(const char *path) 61{ 62 if (path == NULL) { 63 tloge("filename is invalid ...\n"); 64 return 1; 65 } 66 67 /* filter the .. dir in the pname: */ 68 if (strstr(path, "..") != NULL) { 69 tloge("filename should not include .. dir\n"); 70 return 1; 71 } 72 73 return 0; 74} 75 76static int GetFileSize(const char *path, int *realSize) 77{ 78 FILE *fp = NULL; 79 int ret; 80 int fileSize = -1; 81 int xmlHeader = 0; 82 char realPath[PATH_MAX + 1] = { 0 }; 83 84 bool paramInvlid = ((path == NULL) || (IsNotValidFname(path) != 0) || (strlen(path) > PATH_MAX) || 85 (realpath(path, realPath) == NULL)); 86 if (paramInvlid) { 87 return fileSize; 88 } 89 90 fp = fopen(realPath, "r"); 91 if (fp == NULL) { 92 return fileSize; 93 } 94 95 ret = fseek(fp, 0L, SEEK_END); 96 if (ret < 0) { 97 fclose(fp); 98 fp = NULL; 99 return fileSize; 100 } 101 102 fileSize = (int)ftell(fp); 103 104 ret = fseek(fp, 0L, SEEK_SET); 105 if (ret < 0 || fileSize < XML_HEADER) { 106 fclose(fp); 107 fp = NULL; 108 return ERR_SIZE; 109 } 110 int len = (int)fread(&xmlHeader, 1, sizeof(int), fp); 111 if (len != sizeof(int) || xmlHeader < fileSize) { 112 tloge("size read is invalid\n"); 113 fclose(fp); 114 fp = NULL; 115 return ERR_SIZE; 116 } 117 118 (void)fclose(fp); 119 fp = NULL; 120 *realSize = fileSize; 121 return xmlHeader; 122} 123 124static int GetFileInfo(int bufLen, uint8_t *buffer, const char *path) 125{ 126 FILE *fp = NULL; 127 int fileSize; 128 char realPath[PATH_MAX + 1] = { 0 }; 129 130 bool paramInvlid = ((buffer == NULL) || (path == NULL) || (IsNotValidFname(path) != 0) || 131 (strlen(path) > PATH_MAX) || (realpath(path, realPath) == NULL) || 132 (bufLen == 0)); 133 if (paramInvlid) { 134 return -1; 135 } 136 137 fp = fopen(realPath, "rb"); 138 if (fp == NULL) { 139 tloge("open file failed\n"); 140 return -1; 141 } 142 143 fileSize = (int)fread(buffer, sizeof(char), (unsigned int)bufLen, fp); 144 if (fileSize != bufLen) { 145 tloge("read file read number:%d\n", fileSize); 146 fclose(fp); 147 fp = NULL; 148 return -1; 149 } 150 151 (void)fclose(fp); 152 fp = NULL; 153 return 0; 154} 155 156static uint8_t *InitTempBuf(int bufLen) 157{ 158 errno_t ret; 159 uint8_t *buffer = NULL; 160 161 bool variablesCheck = ((bufLen <= 0) || (bufLen > HASH_FILE_MAX_SIZE)); 162 if (variablesCheck) { 163 tloge("wrong buflen\n"); 164 return buffer; 165 } 166 167 buffer = (uint8_t *)malloc((unsigned int)bufLen); 168 if (buffer == NULL) { 169 tloge("malloc failed!\n"); 170 return buffer; 171 } 172 173 ret = memset_s(buffer, (unsigned int)bufLen, 0, (unsigned int)bufLen); 174 if (ret != EOK) { 175 tloge("memset failed!\n"); 176 free(buffer); 177 buffer = NULL; 178 return buffer; 179 } 180 181 return buffer; 182} 183 184static uint8_t *ReadXmlFile(const char *xmlFile) 185{ 186 int ret; 187 int bufLen; 188 uint8_t *buffer = NULL; 189 int realSize = 0; 190 191 bufLen = GetFileSize(xmlFile, &realSize); 192 buffer = InitTempBuf(bufLen); 193 if (buffer == NULL) { 194 tloge("init temp buffer failed\n"); 195 return buffer; 196 } 197 198 ret = GetFileInfo(realSize, buffer, xmlFile); 199 if (ret != 0) { 200 tloge("get xml file info failed\n"); 201 free(buffer); 202 buffer = NULL; 203 return buffer; 204 } 205 206 return buffer; 207} 208 209static int TeeSetNativeCaHash(const char *xmlFlie) 210{ 211 int ret; 212 int fd = -1; 213 uint8_t *buffer = NULL; 214 215 buffer = ReadXmlFile(xmlFlie); 216 if (buffer == NULL) { 217 tloge("read xml file failed\n"); 218 return fd; 219 } 220 221 fd = open(TC_PRIVATE_DEV_NAME, O_RDWR); 222 if (fd < 0) { 223 tloge("Failed to open dev node: %d\n", errno); 224 free(buffer); 225 buffer = NULL; 226 return -1; 227 } 228 ret = ioctl(fd, (int)(TC_NS_CLIENT_IOCTL_SET_NATIVE_IDENTITY), buffer); 229 if (ret != 0) { 230 tloge("ioctl fail %d\n", ret); 231 } 232 233 free(buffer); 234 buffer = NULL; 235 close(fd); 236 fd = -1; 237 return ret; 238} 239 240static bool IsFileExist(const char *name) 241{ 242 struct stat statbuf; 243 244 if (name == NULL) { 245 return false; 246 } 247 if (stat(name, &statbuf) != 0) { 248 if (errno == ENOENT) { /* file not exist */ 249 tlogi("file not exist: %s\n", name); 250 return false; 251 } 252 return true; 253 } 254 255 return true; 256} 257 258int TcuAuthentication(uint8_t hash_type) 259{ 260 uint8_t listLen; 261 const char **hashFileList = GetCaHashFileList(&listLen, hash_type); 262 if (hashFileList == NULL) { 263 tloge("get hashFileList failed\n"); 264 return -1; 265 } 266 if (listLen == 0) { 267 tloge("list num is 0, please set hashfile\n"); 268 return -1; 269 } 270 static int gHashXmlSetted; 271 uint8_t count = 0; 272 if (gHashXmlSetted == 0) { 273 for (uint8_t index = 0; index < listLen; index++) { 274 if (hashFileList[index] == NULL) { 275 tloge("get hashFile failed, index is %d\n", index); 276 continue; 277 } 278 if (!IsFileExist(hashFileList[index])) { 279 continue; 280 } 281 282 int setRet = TeeSetNativeCaHash(hashFileList[index]); 283 if (setRet != 0) { 284 tloge("hashfile read failed, index is %d\n", index); 285 continue; 286 } 287 count++; 288 } 289 } 290 291 if (count == listLen) { 292 gHashXmlSetted = 1; 293 return 0; 294 } 295 296 return -1; 297}