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