• 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 = %" PUBLIC "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=%" PUBLIC "d, filePath=%" PUBLIC "s\n", errno, filePath);
73         return -1;
74     }
75 
76 #ifndef TEE_LOAD_FROM_ROOTFS
77     if (strncmp(realPath, TEE_DEFAULT_PATH, strlen(TEE_DEFAULT_PATH)) != 0 &&
78         strncmp(realPath, TEE_FEIMA_DEFAULT_PATH, strlen(TEE_FEIMA_DEFAULT_PATH)) != 0) {
79         tloge("realpath -%" PUBLIC "s- is invalid\n", realPath);
80         return -1;
81     }
82 #else
83     if (strncmp(realPath, TEE_DEFAULT_PATH_ROOTFS, strlen(TEE_DEFAULT_PATH_ROOTFS)) != 0) {
84         tloge("realpath -%" PUBLIC "s- is invalid\n", realPath);
85         return -1;
86     }
87 #endif
88 
89     fp = fopen(realPath, "r");
90     if (fp == NULL) {
91         tloge("open file err=%" PUBLIC "d, path=%" PUBLIC "s\n", errno, filePath);
92         return -1;
93     }
94     ret = LoadSecFile(tzFd, fp, fileType, uuid);
95     if (fp != NULL) {
96         fclose(fp);
97     }
98     return ret;
99 }
100 
101 // 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)102 int32_t LoadSecFile(int tzFd, FILE *fp, enum SecFileType fileType, const TEEC_UUID *uuid)
103 {
104     int32_t ret;
105     char *fileBuffer                   = NULL;
106     struct SecLoadIoctlStruct ioctlArg = {{ 0 }, { 0 }, { NULL } };
107 
108     if (tzFd < 0 || fp == NULL) {
109         tloge("param erro!\n");
110         return -1;
111     }
112 
113     do {
114         long totalLen = 0;
115         ret           = GetImgLen(fp, &totalLen);
116         if (ret != 0) {
117             break;
118         }
119 
120         if (totalLen <= 0 || totalLen > MAX_BUFFER_LEN) {
121             ret = -1;
122             tloge("totalLen is invalid\n");
123             break;
124         }
125 
126         /* alloc a less than 8M heap memory, it needn't slice. */
127         fileBuffer = malloc((size_t)totalLen);
128         if (fileBuffer == NULL) {
129             tloge("alloc TA file buffer(size=%" PUBLIC "ld) failed\n", totalLen);
130             ret = -1;
131             break;
132         }
133 
134         /* read total ta file to file buffer */
135         long fileSize = (long)fread(fileBuffer, 1, totalLen, fp);
136         if (fileSize != totalLen) {
137             tloge("read ta file failed, read size/total size=%" PUBLIC "ld/%" PUBLIC "ld\n", fileSize, totalLen);
138             ret = -1;
139             break;
140         }
141 
142         ioctlArg.secFileInfo.fileType = fileType;
143         ioctlArg.secFileInfo.fileSize = (uint32_t)totalLen;
144         ioctlArg.memref.file_addr = (uint32_t)(uintptr_t)fileBuffer;
145         ioctlArg.memref.file_h_addr = (uint32_t)(((uint64_t)(uintptr_t)fileBuffer) >> H_OFFSET);
146         if (uuid != NULL && memcpy_s((void *)(&ioctlArg.uuid), sizeof(ioctlArg.uuid), uuid, sizeof(*uuid)) != EOK) {
147             tloge("memcpy uuid fail\n");
148             break;
149         }
150 
151         ret = ioctl(tzFd, (int)TC_NS_CLIENT_IOCTL_LOAD_APP_REQ, &ioctlArg);
152         if (ret != 0) {
153             tloge("ioctl to load sec file failed, ret = 0x%" PUBLIC "x\n", ret);
154         }
155     } while (false);
156 
157     if (fileBuffer != NULL) {
158         free(fileBuffer);
159     }
160     return ret;
161 }
162 
IsTaLib(const TEEC_UUID * uuid)163 static bool IsTaLib(const TEEC_UUID *uuid)
164 {
165     char *chr = (char *)uuid;
166     uint32_t i;
167 
168     for (i = 0; i < sizeof(*uuid); i++) {
169         if (chr[i] != 0) {
170             return true;
171         }
172     }
173     return false;
174 }
175 
GetFeimaSecFileName(const struct SecAgentControlType * secAgentControl,char * fname,int32_t fnameLen)176 static int32_t GetFeimaSecFileName(const struct SecAgentControlType *secAgentControl, char *fname, int32_t fnameLen)
177 {
178     int32_t ret = -1;
179 
180     if (IsTaLib(&(secAgentControl->LibSec.uuid))) {
181         ret = snprintf_s(fname, fnameLen, MAX_PATH_LEN - 1,
182                 "%s/%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x%s.sec",
183                 TEE_FEIMA_DEFAULT_PATH, secAgentControl->LibSec.uuid.timeLow, secAgentControl->LibSec.uuid.timeMid,
184                 secAgentControl->LibSec.uuid.timeHiAndVersion, secAgentControl->LibSec.uuid.clockSeqAndNode[0],
185                 secAgentControl->LibSec.uuid.clockSeqAndNode[1], secAgentControl->LibSec.uuid.clockSeqAndNode[2],
186                 secAgentControl->LibSec.uuid.clockSeqAndNode[3], secAgentControl->LibSec.uuid.clockSeqAndNode[4],
187                 secAgentControl->LibSec.uuid.clockSeqAndNode[5], secAgentControl->LibSec.uuid.clockSeqAndNode[6],
188                 secAgentControl->LibSec.uuid.clockSeqAndNode[7], secAgentControl->LibSec.libName);
189     } else {
190         ret = snprintf_s(fname, fnameLen, MAX_PATH_LEN - 1,
191             "%s/%s.sec", TEE_FEIMA_DEFAULT_PATH, secAgentControl->LibSec.libName);
192     }
193 
194     if (ret < 0) {
195         tloge("pack fname err\n");
196         memset_s(fname, fnameLen, 0, fnameLen);
197         return -1;
198     }
199 
200     char realPath[PATH_MAX + 1] = { 0 };
201     if (realpath(fname, realPath) == NULL) {
202         tlogi("GetNewSecFileName err=%" PUBLIC "d, filePath=%" PUBLIC "s, will get from old path\n", errno, fname);
203         memset_s(fname, fnameLen, 0, fnameLen);
204         return -1;
205     }
206 
207     return 0;
208 }
209 
LoadLib(struct SecAgentControlType * secAgentControl)210 static void LoadLib(struct SecAgentControlType *secAgentControl)
211 {
212     int32_t ret;
213     char fname[MAX_PATH_LEN] = { 0 };
214 
215     if (secAgentControl == NULL) {
216         tloge("secAgentControl is null\n");
217         return;
218     }
219     if (strnlen(secAgentControl->LibSec.libName, MAX_SEC_FILE_NAME_LEN) >= MAX_SEC_FILE_NAME_LEN) {
220         tloge("libName is too long!\n");
221         secAgentControl->ret = -1;
222         return;
223     }
224 
225     if (GetFeimaSecFileName(secAgentControl, fname, MAX_PATH_LEN) == -1) {
226         if (IsTaLib(&(secAgentControl->LibSec.uuid))) {
227             ret = snprintf_s(fname, sizeof(fname), MAX_PATH_LEN - 1,
228                     "%s/%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x%s.sec",
229                     TEE_DEFAULT_PATH, secAgentControl->LibSec.uuid.timeLow, secAgentControl->LibSec.uuid.timeMid,
230                     secAgentControl->LibSec.uuid.timeHiAndVersion, secAgentControl->LibSec.uuid.clockSeqAndNode[0],
231                     secAgentControl->LibSec.uuid.clockSeqAndNode[1], secAgentControl->LibSec.uuid.clockSeqAndNode[2],
232                     secAgentControl->LibSec.uuid.clockSeqAndNode[3], secAgentControl->LibSec.uuid.clockSeqAndNode[4],
233                     secAgentControl->LibSec.uuid.clockSeqAndNode[5], secAgentControl->LibSec.uuid.clockSeqAndNode[6],
234                     secAgentControl->LibSec.uuid.clockSeqAndNode[7], secAgentControl->LibSec.libName);
235         } else {
236             ret = snprintf_s(fname, sizeof(fname), MAX_PATH_LEN - 1,
237                 "%s/%s.sec", TEE_DEFAULT_PATH, secAgentControl->LibSec.libName);
238         }
239         if (ret < 0) {
240             tloge("pack fname err\n");
241             secAgentControl->ret = -1;
242             return;
243         }
244     }
245     ret = SecFileLoadWork(g_secLoadAgentFd, (const char *)fname, LOAD_LIB, NULL);
246     if (ret != 0) {
247         tloge("teec load app failed\n");
248         secAgentControl->ret   = -1;
249         secAgentControl->error = errno;
250         return;
251     }
252     secAgentControl->ret = 0;
253     return;
254 }
255 
GetTaPath(const TEEC_UUID * uuid,char * fname,unsigned int len)256 static int GetTaPath(const TEEC_UUID *uuid, char *fname, unsigned int len)
257 {
258     int32_t ret = -1;
259     char realPath[PATH_MAX + 1] = { 0 };
260 
261     ret = snprintf_s(fname, len, MAX_PATH_LEN - 1, "%s/%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x.sec",
262         TEE_FEIMA_DEFAULT_PATH, uuid->timeLow, uuid->timeMid,
263         uuid->timeHiAndVersion, uuid->clockSeqAndNode[0],
264         uuid->clockSeqAndNode[1], uuid->clockSeqAndNode[2],
265         uuid->clockSeqAndNode[3], uuid->clockSeqAndNode[4],
266         uuid->clockSeqAndNode[5], uuid->clockSeqAndNode[6],
267         uuid->clockSeqAndNode[7]);
268     if (ret < 0) {
269         tloge("pack new path fname err");
270         return -1;
271     }
272 
273     if (realpath(fname, realPath) == NULL) {
274         tloge("realpath open file err=" PUBLIC "d, filePath=" PUBLIC "s, will use old path\n", errno, fname);
275         ret = snprintf_s(fname, len, MAX_PATH_LEN - 1, "%s/%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x.sec",
276             TEE_DEFAULT_PATH, uuid->timeLow, uuid->timeMid,
277             uuid->timeHiAndVersion, uuid->clockSeqAndNode[0],
278             uuid->clockSeqAndNode[1], uuid->clockSeqAndNode[2],
279             uuid->clockSeqAndNode[3], uuid->clockSeqAndNode[4],
280             uuid->clockSeqAndNode[5], uuid->clockSeqAndNode[6],
281             uuid->clockSeqAndNode[7]);
282         if (ret < 0) {
283             tloge("pack old path fname err");
284             return -1;
285         }
286     }
287 
288     return 0;
289 }
290 
LoadTa(struct SecAgentControlType * secAgentControl)291 static void LoadTa(struct SecAgentControlType *secAgentControl)
292 {
293     int32_t ret;
294     char fname[MAX_PATH_LEN] = { 0 };
295 
296     if (secAgentControl == NULL) {
297         tloge("secAgentControl is null\n");
298         return;
299     }
300 
301     ret = GetTaPath(&(secAgentControl->TaSec.uuid), fname, MAX_PATH_LEN);
302     if (ret < 0) {
303         tloge("pack fname err\n");
304         secAgentControl->ret = -1;
305         return;
306     }
307     secAgentControl->ret = 0;
308     ret = SecFileLoadWork(g_secLoadAgentFd, (const char *)fname, LOAD_TA, &(secAgentControl->TaSec.uuid));
309     if (ret != 0) {
310         tloge("teec load TA app failed\n");
311         secAgentControl->ret   = ret;
312         secAgentControl->error = errno;
313         return;
314     }
315     return;
316 }
317 
SecLoadAgentWork(struct SecAgentControlType * secAgentControl)318 static void SecLoadAgentWork(struct SecAgentControlType *secAgentControl)
319 {
320     if (secAgentControl == NULL) {
321         tloge("secAgentControl is null\n");
322         return;
323     }
324     switch (secAgentControl->cmd) {
325         case LOAD_LIB_SEC:
326             LoadLib(secAgentControl);
327             break;
328         case LOAD_TA_SEC:
329             LoadTa(secAgentControl);
330             break;
331         case LOAD_SERVICE_SEC:
332         default:
333             tloge("gtask agent error cmd:%" PUBLIC "d\n", secAgentControl->cmd);
334             secAgentControl->ret = -1;
335             break;
336     }
337 }
338 
SecfileLoadAgentThread(void * control)339 void *SecfileLoadAgentThread(void *control)
340 {
341     (void)prctl(PR_SET_NAME, "teecd_sec_load_agent", 0, 0, 0);
342     struct SecAgentControlType *secAgentControl = NULL;
343     if (control == NULL) {
344         tloge("control is NULL\n");
345         return NULL;
346     }
347     secAgentControl = (struct SecAgentControlType *)control;
348     if (g_secLoadAgentFd < 0) {
349         tloge("m_gtask_agent_fd is -1\n");
350         return NULL;
351     }
352     secAgentControl->magic = SECFILE_LOAD_AGENT_ID;
353     while (true) {
354         int ret = ioctl(g_secLoadAgentFd, (int)TC_NS_CLIENT_IOCTL_WAIT_EVENT, SECFILE_LOAD_AGENT_ID);
355         if (ret) {
356             tloge("gtask agent wait event failed, errno = %" PUBLIC "d\n", errno);
357             break;
358         }
359         SecLoadAgentWork(secAgentControl);
360 
361         __asm__ volatile("isb");
362         __asm__ volatile("dsb sy");
363 
364         secAgentControl->magic = SECFILE_LOAD_AGENT_ID;
365 
366         __asm__ volatile("isb");
367         __asm__ volatile("dsb sy");
368         ret = ioctl(g_secLoadAgentFd, (int)TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE, SECFILE_LOAD_AGENT_ID);
369         if (ret) {
370             tloge("gtask agent send reponse failed\n");
371             break;
372         }
373     }
374     return NULL;
375 }
376