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 #include "tee_file.h"
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
35 static const char *g_vendorCaHashFileList[] = {
36 "/vendor/etc/native_packages.xml",
37 "/vendor/root/res/native_packages.xml",
38 };
39
40 static const char *g_systemCaHashFileList[] = {
41 "/system/etc/native_packages.xml",
42 };
43
GetCaHashFileList(uint8_t * num,uint8_t hash_type)44 static 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
IsNotValidFname(const char * path)60 static 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
GetFileSize(const char * path,int * realSize)76 static 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
GetFileInfo(int bufLen,uint8_t * buffer,const char * path)124 static 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:%" PUBLIC "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
InitTempBuf(int bufLen)156 static 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
ReadXmlFile(const char * xmlFile)184 static 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
TeeSetNativeCaHash(const char * xmlFlie)209 static 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 = tee_open(TC_PRIVATE_DEV_NAME, O_RDWR, 0);
222 if (fd < 0) {
223 tloge("Failed to open dev node: %" PUBLIC "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 %" PUBLIC "d\n", ret);
231 }
232
233 free(buffer);
234 buffer = NULL;
235 tee_close(&fd);
236 return ret;
237 }
238
IsFileExist(const char * name)239 static bool IsFileExist(const char *name)
240 {
241 struct stat statbuf;
242
243 if (name == NULL) {
244 return false;
245 }
246 if (stat(name, &statbuf) != 0) {
247 if (errno == ENOENT) { /* file not exist */
248 tlogi("file not exist: %" PUBLIC "s\n", name);
249 return false;
250 }
251 return true;
252 }
253
254 return true;
255 }
256
TcuAuthentication(uint8_t hash_type)257 int TcuAuthentication(uint8_t hash_type)
258 {
259 uint8_t listLen;
260 const char **hashFileList = GetCaHashFileList(&listLen, hash_type);
261 if (hashFileList == NULL) {
262 tloge("get hashFileList failed\n");
263 return -1;
264 }
265 if (listLen == 0) {
266 tloge("list num is 0, please set hashfile\n");
267 return -1;
268 }
269 static int gHashXmlSetted;
270 uint8_t count = 0;
271 if (gHashXmlSetted == 0) {
272 for (uint8_t index = 0; index < listLen; index++) {
273 if (hashFileList[index] == NULL) {
274 tloge("get hashFile failed, index is %" PUBLIC "d\n", index);
275 continue;
276 }
277 if (!IsFileExist(hashFileList[index])) {
278 continue;
279 }
280
281 int setRet = TeeSetNativeCaHash(hashFileList[index]);
282 if (setRet != 0) {
283 tloge("hashfile read failed, index is %" PUBLIC "d\n", index);
284 continue;
285 }
286 count++;
287 }
288 }
289
290 if (count == listLen) {
291 gHashXmlSetted = 1;
292 return 0;
293 }
294
295 return -1;
296 }
297