• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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