1 /*
2 * Copyright (C) 2022 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 "secfile_load_agent.h"
14 #include <limits.h>
15 #include <securec.h>
16 #include <sys/prctl.h>
17 #include "tc_ns_client.h"
18 #include "tee_log.h"
19
20 #define MAX_PATH_LEN 256
21 #ifdef LOG_TAG
22 #undef LOG_TAG
23 #endif
24 #define LOG_TAG "teecd_agent"
25 #define MAX_BUFFER_LEN (8 * 1024 * 1024)
26 #define H_OFFSET 32
27 int g_secLoadAgentFd = -1;
28
GetSecLoadAgentFd(void)29 int GetSecLoadAgentFd(void)
30 {
31 return g_secLoadAgentFd;
32 }
33
SetSecLoadAgentFd(int secLoadAgentFd)34 void SetSecLoadAgentFd(int secLoadAgentFd)
35 {
36 g_secLoadAgentFd = secLoadAgentFd;
37 }
38
GetImgLen(FILE * fp,long * totalLlen)39 static int GetImgLen(FILE *fp, long *totalLlen)
40 {
41 int ret;
42
43 ret = fseek(fp, 0, SEEK_END);
44 if (ret != 0) {
45 tloge("fseek error\n");
46 return -1;
47 }
48 *totalLlen = ftell(fp);
49 if (*totalLlen <= 0 || *totalLlen > MAX_BUFFER_LEN) {
50 tloge("file is not exist or size is too large, filesize = %ld\n", *totalLlen);
51 return -1;
52 }
53 ret = fseek(fp, 0, SEEK_SET);
54 if (ret != 0) {
55 tloge("fseek error\n");
56 return -1;
57 }
58 return ret;
59 }
60
SecFileLoadWork(int tzFd,const char * filePath,enum SecFileType fileType,const TEEC_UUID * uuid)61 static int32_t SecFileLoadWork(int tzFd, const char *filePath, enum SecFileType fileType, const TEEC_UUID *uuid)
62 {
63 char realPath[PATH_MAX + 1] = { 0 };
64 FILE *fp = NULL;
65 int ret;
66
67 if (tzFd < 0) {
68 tloge("fd of tzdriver is valid!\n");
69 return -1;
70 }
71 if (realpath(filePath, realPath) == NULL) {
72 tloge("realpath open file err=%d, filePath=%s\n", errno, filePath);
73 return -1;
74 }
75 if (strncmp(realPath, TEE_DEFAULT_PATH, strlen(TEE_DEFAULT_PATH)) != 0) {
76 tloge("realpath -%s- is invalid\n", realPath);
77 return -1;
78 }
79 fp = fopen(realPath, "r");
80 if (fp == NULL) {
81 tloge("open file err=%d, path=%s\n", errno, filePath);
82 return -1;
83 }
84 ret = LoadSecFile(tzFd, fp, fileType, uuid);
85 if (fp != NULL) {
86 fclose(fp);
87 }
88 return ret;
89 }
90
91 // input param uuid may be NULL, so don need to check if uuid is NULL
LoadSecFile(int tzFd,FILE * fp,enum SecFileType fileType,const TEEC_UUID * uuid)92 int32_t LoadSecFile(int tzFd, FILE *fp, enum SecFileType fileType, const TEEC_UUID *uuid)
93 {
94 int32_t ret;
95 char *fileBuffer = NULL;
96 struct SecLoadIoctlStruct ioctlArg = {{ 0 }, { 0 }, { NULL } };
97
98 if (tzFd < 0 || fp == NULL) {
99 tloge("param erro!\n");
100 return -1;
101 }
102
103 do {
104 long totalLen = 0;
105 ret = GetImgLen(fp, &totalLen);
106 if (ret != 0) {
107 break;
108 }
109
110 if (totalLen <= 0 || totalLen > MAX_BUFFER_LEN) {
111 ret = -1;
112 tloge("totalLen is invalid\n");
113 break;
114 }
115
116 /* alloc a less than 8M heap memory, it needn't slice. */
117 fileBuffer = malloc((size_t)totalLen);
118 if (fileBuffer == NULL) {
119 tloge("alloc TA file buffer(size=%ld) failed\n", totalLen);
120 ret = -1;
121 break;
122 }
123
124 /* read total ta file to file buffer */
125 long fileSize = (long)fread(fileBuffer, 1, totalLen, fp);
126 if (fileSize != totalLen) {
127 tloge("read ta file failed, read size/total size=%ld/%ld\n", fileSize, totalLen);
128 ret = -1;
129 break;
130 }
131
132 ioctlArg.secFileInfo.fileType = fileType;
133 ioctlArg.secFileInfo.fileSize = (uint32_t)totalLen;
134 ioctlArg.memref.file_addr = (uint32_t)(uintptr_t)fileBuffer;
135 ioctlArg.memref.file_h_addr = (uint32_t)(((uint64_t)(uintptr_t)fileBuffer) >> H_OFFSET);
136 if (uuid != NULL && memcpy_s((void *)(&ioctlArg.uuid), sizeof(ioctlArg.uuid), uuid, sizeof(*uuid)) != EOK) {
137 tloge("memcpy uuid fail\n");
138 break;
139 }
140
141 ret = ioctl(tzFd, (int)TC_NS_CLIENT_IOCTL_LOAD_APP_REQ, &ioctlArg);
142 if (ret != 0) {
143 tloge("ioctl to load sec file failed, ret = 0x%x\n", ret);
144 }
145 } while (false);
146
147 if (fileBuffer != NULL) {
148 free(fileBuffer);
149 }
150 return ret;
151 }
152
IsTaLib(const TEEC_UUID * uuid)153 static bool IsTaLib(const TEEC_UUID *uuid)
154 {
155 char *chr = (char *)uuid;
156 uint32_t i;
157
158 for (i = 0; i < sizeof(*uuid); i++) {
159 if (chr[i] != 0) {
160 return true;
161 }
162 }
163 return false;
164 }
165
LoadLib(struct SecAgentControlType * secAgentControl)166 static void LoadLib(struct SecAgentControlType *secAgentControl)
167 {
168 int32_t ret;
169 char fname[MAX_PATH_LEN] = { 0 };
170
171 if (secAgentControl == NULL) {
172 tloge("secAgentControl is null\n");
173 return;
174 }
175 if (strnlen(secAgentControl->LibSec.libName, MAX_SEC_FILE_NAME_LEN) >= MAX_SEC_FILE_NAME_LEN) {
176 tloge("libName is too long!\n");
177 secAgentControl->ret = -1;
178 return;
179 }
180
181 if (IsTaLib(&(secAgentControl->LibSec.uuid))) {
182 ret =
183 snprintf_s(fname, sizeof(fname), MAX_PATH_LEN - 1,
184 "%s/%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x%s.sec",
185 TEE_DEFAULT_PATH, secAgentControl->LibSec.uuid.timeLow, secAgentControl->LibSec.uuid.timeMid,
186 secAgentControl->LibSec.uuid.timeHiAndVersion, secAgentControl->LibSec.uuid.clockSeqAndNode[0],
187 secAgentControl->LibSec.uuid.clockSeqAndNode[1], secAgentControl->LibSec.uuid.clockSeqAndNode[2],
188 secAgentControl->LibSec.uuid.clockSeqAndNode[3], secAgentControl->LibSec.uuid.clockSeqAndNode[4],
189 secAgentControl->LibSec.uuid.clockSeqAndNode[5], secAgentControl->LibSec.uuid.clockSeqAndNode[6],
190 secAgentControl->LibSec.uuid.clockSeqAndNode[7], secAgentControl->LibSec.libName);
191 } else {
192 ret = snprintf_s(fname, sizeof(fname), MAX_PATH_LEN - 1,
193 "%s/%s.sec", TEE_DEFAULT_PATH, secAgentControl->LibSec.libName);
194 }
195 if (ret < 0) {
196 tloge("pack fname err\n");
197 secAgentControl->ret = -1;
198 return;
199 }
200 ret = SecFileLoadWork(g_secLoadAgentFd, (const char *)fname, LOAD_LIB, NULL);
201 if (ret != 0) {
202 tloge("teec load app failed\n");
203 secAgentControl->ret = -1;
204 secAgentControl->error = errno;
205 return;
206 }
207 secAgentControl->ret = 0;
208 return;
209 }
210
LoadTa(struct SecAgentControlType * secAgentControl)211 static void LoadTa(struct SecAgentControlType *secAgentControl)
212 {
213 int32_t ret;
214 char fname[MAX_PATH_LEN] = { 0 };
215
216 if (secAgentControl == NULL) {
217 tloge("secAgentControl is null\n");
218 return;
219 }
220
221 ret = snprintf_s(fname, sizeof(fname), MAX_PATH_LEN - 1, "%s/%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x.sec",
222 TEE_DEFAULT_PATH, secAgentControl->TaSec.uuid.timeLow, secAgentControl->TaSec.uuid.timeMid,
223 secAgentControl->TaSec.uuid.timeHiAndVersion, secAgentControl->TaSec.uuid.clockSeqAndNode[0],
224 secAgentControl->TaSec.uuid.clockSeqAndNode[1], secAgentControl->TaSec.uuid.clockSeqAndNode[2],
225 secAgentControl->TaSec.uuid.clockSeqAndNode[3], secAgentControl->TaSec.uuid.clockSeqAndNode[4],
226 secAgentControl->TaSec.uuid.clockSeqAndNode[5], secAgentControl->TaSec.uuid.clockSeqAndNode[6],
227 secAgentControl->TaSec.uuid.clockSeqAndNode[7]);
228 if (ret < 0) {
229 tloge("pack fname err\n");
230 secAgentControl->ret = -1;
231 return;
232 }
233 secAgentControl->ret = 0;
234 ret = SecFileLoadWork(g_secLoadAgentFd, (const char *)fname, LOAD_TA, &(secAgentControl->TaSec.uuid));
235 if (ret != 0) {
236 tloge("teec load TA app failed\n");
237 secAgentControl->ret = ret;
238 secAgentControl->error = errno;
239 return;
240 }
241 return;
242 }
243
SecLoadAgentWork(struct SecAgentControlType * secAgentControl)244 static void SecLoadAgentWork(struct SecAgentControlType *secAgentControl)
245 {
246 if (secAgentControl == NULL) {
247 tloge("secAgentControl is null\n");
248 return;
249 }
250 switch (secAgentControl->cmd) {
251 case LOAD_LIB_SEC:
252 LoadLib(secAgentControl);
253 break;
254 case LOAD_TA_SEC:
255 LoadTa(secAgentControl);
256 break;
257 case LOAD_SERVICE_SEC:
258 default:
259 tloge("gtask agent error cmd:%d\n", secAgentControl->cmd);
260 secAgentControl->ret = -1;
261 break;
262 }
263 }
264
SecfileLoadAgentThread(void * control)265 void *SecfileLoadAgentThread(void *control)
266 {
267 (void)prctl(PR_SET_NAME, "teecd_sec_load_agent", 0, 0, 0);
268 struct SecAgentControlType *secAgentControl = NULL;
269 if (control == NULL) {
270 tloge("control is NULL\n");
271 return NULL;
272 }
273 secAgentControl = (struct SecAgentControlType *)control;
274 if (g_secLoadAgentFd < 0) {
275 tloge("m_gtask_agent_fd is -1\n");
276 return NULL;
277 }
278 secAgentControl->magic = SECFILE_LOAD_AGENT_ID;
279 while (true) {
280 int ret = ioctl(g_secLoadAgentFd, (int)TC_NS_CLIENT_IOCTL_WAIT_EVENT, SECFILE_LOAD_AGENT_ID);
281 if (ret) {
282 tloge("gtask agent wait event failed, errno = %d\n", errno);
283 break;
284 }
285 SecLoadAgentWork(secAgentControl);
286
287 __asm__ volatile("isb");
288 __asm__ volatile("dsb sy");
289
290 secAgentControl->magic = SECFILE_LOAD_AGENT_ID;
291
292 __asm__ volatile("isb");
293 __asm__ volatile("dsb sy");
294 ret = ioctl(g_secLoadAgentFd, (int)TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE, SECFILE_LOAD_AGENT_ID);
295 if (ret) {
296 tloge("gtask agent send reponse failed\n");
297 break;
298 }
299 }
300 return NULL;
301 }
302