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 "tee_client_app_load.h"
14 #include <fcntl.h>
15 #include <limits.h>
16 #include <securec.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <sys/mman.h> /* for mmap */
21 #include <sys/ioctl.h> /* for ioctl */
22 #include <sys/stat.h>
23 #include <sys/types.h> /* for open close */
24 #include "load_sec_file.h"
25 #include "tc_ns_client.h"
26 #include "tee_client_inner.h"
27 #include "tee_log.h"
28
29 #ifdef LOG_TAG
30 #undef LOG_TAG
31 #endif
32 #define LOG_TAG "teec_app_load"
33
34 #define MAX_PATH_LEN 256
35 const char *g_imagePath = TEE_DEFAULT_PATH;
36
37 static int32_t TEEC_ReadApp(const TaFileInfo *taFile, const char *loadFile, bool defaultPath,
38 TC_NS_ClientContext *cliContext);
39
TEEC_GetApp(const TaFileInfo * taFile,const TEEC_UUID * srvUuid,TC_NS_ClientContext * cliContext)40 int32_t TEEC_GetApp(const TaFileInfo *taFile, const TEEC_UUID *srvUuid, TC_NS_ClientContext *cliContext)
41 {
42 int32_t ret;
43
44 if ((taFile == NULL) || (srvUuid == NULL) || (cliContext == NULL)) {
45 tloge("param is null\n");
46 return -1;
47 }
48
49 /* get file name and file patch */
50 bool condition = (taFile->taPath != NULL) && (strlen((const char *)taFile->taPath) < MAX_PATH_LEN) &&
51 strstr((const char *)taFile->taPath, ".sec");
52 if (condition) {
53 ret = TEEC_ReadApp(taFile, (const char *)taFile->taPath, false, cliContext);
54 if (ret < 0) {
55 tloge("teec load app erro, ta path is not NULL\n");
56 }
57 } else {
58 char fileName[MAX_FILE_NAME_LEN] = { 0 };
59 char tempName[MAX_FILE_PATH_LEN + MAX_FILE_NAME_LEN + MAX_FILE_EXT_LEN] = { 0 };
60 const char *filePath = g_imagePath;
61 ret = snprintf_s(fileName, sizeof(fileName), sizeof(fileName) - 1,
62 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", srvUuid->timeLow, srvUuid->timeMid,
63 srvUuid->timeHiAndVersion, srvUuid->clockSeqAndNode[0], srvUuid->clockSeqAndNode[1],
64 srvUuid->clockSeqAndNode[2], srvUuid->clockSeqAndNode[3], srvUuid->clockSeqAndNode[4],
65 srvUuid->clockSeqAndNode[5], srvUuid->clockSeqAndNode[6], srvUuid->clockSeqAndNode[7]);
66 if (ret < 0) {
67 tloge("get file name err\n");
68 return -1;
69 }
70
71 size_t filePathLen = strnlen(filePath, MAX_FILE_PATH_LEN);
72 filePathLen = filePathLen + strnlen(fileName, MAX_FILE_NAME_LEN);
73 filePathLen = filePathLen + MAX_FILE_EXT_LEN;
74 int32_t len = snprintf_s(tempName, sizeof(tempName), filePathLen, "%s/%s.sec", filePath, fileName);
75 if (len < 0) {
76 tloge("file path too long\n");
77 return -1;
78 }
79
80 ret = TEEC_ReadApp(taFile, (const char *)tempName, true, cliContext);
81 if (ret < 0) {
82 tloge("teec load app erro\n");
83 }
84 }
85
86 return ret;
87 }
88
GetTaVersion(FILE * fp,uint32_t * taHeadLen,uint32_t * version,uint32_t * contextLen,uint32_t * totalImgLen)89 static int32_t GetTaVersion(FILE *fp, uint32_t *taHeadLen, uint32_t *version,
90 uint32_t *contextLen, uint32_t *totalImgLen)
91 {
92 int32_t ret;
93 TaImageHdrV3 imgHdr = { { 0 }, 0, 0 };
94
95 if (fp == NULL) {
96 tloge("invalid fp\n");
97 return -1;
98 }
99
100 /* get magic-num & version-num */
101 ret = (int32_t)fread(&imgHdr, sizeof(imgHdr), 1, fp);
102 if (ret != 1) {
103 tloge("read file failed, ret=%d, error=%d\n", ret, ferror(fp));
104 return -1;
105 }
106
107 bool condition = (imgHdr.imgIdentity.magicNum1 == TA_HEAD_MAGIC1) &&
108 (imgHdr.imgIdentity.magicNum2 == TA_HEAD_MAGIC2) &&
109 (imgHdr.imgIdentity.versionNum > 1);
110 if (condition) {
111 tlogd("new verison ta\n");
112 *taHeadLen = sizeof(TeecTaHead);
113 *version = imgHdr.imgIdentity.versionNum;
114 if (*version >= CIPHER_LAYER_VERSION) {
115 *contextLen = imgHdr.contextLen;
116 *totalImgLen = *contextLen + sizeof(imgHdr);
117 } else {
118 ret = fseek(fp, sizeof(imgHdr.imgIdentity), SEEK_SET);
119 if (ret != 0) {
120 tloge("fseek error\n");
121 return -1;
122 }
123 }
124 } else {
125 /* read the oldverison head again */
126 tlogd("old verison ta\n");
127 *taHeadLen = sizeof(TeecImageHead);
128 ret = fseek(fp, 0, SEEK_SET);
129 if (ret != 0) {
130 tloge("fseek error\n");
131 return -1;
132 }
133 }
134 return 0;
135 }
136
TEEC_GetImageLenth(FILE * fp,uint32_t * imgLen)137 static int32_t TEEC_GetImageLenth(FILE *fp, uint32_t *imgLen)
138 {
139 int32_t ret;
140 TeecImageHead imageHead = { 0 };
141 uint32_t totalImgLen;
142 uint32_t taHeadLen = 0;
143 uint32_t readSize;
144 uint32_t version = 0;
145 uint32_t contextLen = 0;
146
147 /* decide the TA verison */
148 ret = GetTaVersion(fp, &taHeadLen, &version, &contextLen, &totalImgLen);
149 if (ret != 0) {
150 tloge("get Ta version failed\n");
151 return ret;
152 }
153
154 if (version >= CIPHER_LAYER_VERSION) {
155 goto CHECK_LENTH;
156 }
157
158 /* get image head */
159 readSize = (uint32_t)fread(&imageHead, sizeof(TeecImageHead), 1, fp);
160 if (readSize != 1) {
161 tloge("read file failed, err=%u\n", readSize);
162 return -1;
163 }
164 contextLen = imageHead.contextLen;
165 totalImgLen = contextLen + taHeadLen;
166
167 CHECK_LENTH:
168 /* for no overflow */
169 if ((contextLen > MAX_IMAGE_LEN) || (totalImgLen > MAX_IMAGE_LEN)) {
170 tloge("check img size failed\n");
171 return -1;
172 }
173
174 ret = fseek(fp, 0, SEEK_SET);
175 if (ret != 0) {
176 tloge("fseek error\n");
177 return -1;
178 }
179
180 *imgLen = totalImgLen;
181 return 0;
182 }
183
TEEC_DoReadApp(FILE * fp,TC_NS_ClientContext * cliContext)184 static int32_t TEEC_DoReadApp(FILE *fp, TC_NS_ClientContext *cliContext)
185 {
186 uint32_t totalImgLen = 0;
187
188 /* get magic-num & version-num */
189 int32_t ret = TEEC_GetImageLenth(fp, &totalImgLen);
190 if (ret) {
191 tloge("get image lenth fail\n");
192 return -1;
193 }
194
195 if (totalImgLen == 0 || totalImgLen > MAX_IMAGE_LEN) {
196 tloge("image lenth invalid\n");
197 return -1;
198 }
199
200 /* alloc a less than 8M heap memory, it needn't slice. */
201 char *fileBuffer = malloc(totalImgLen);
202 if (fileBuffer == NULL) {
203 tloge("alloc TA file buffer(size=%u) failed\n", totalImgLen);
204 return -1;
205 }
206
207 /* read total ta file to file buffer */
208 uint32_t readSize = (uint32_t)fread(fileBuffer, 1, totalImgLen, fp);
209 if (readSize != totalImgLen) {
210 tloge("read ta file failed, read size/total size=%u/%u\n", readSize, totalImgLen);
211 free(fileBuffer);
212 return -1;
213 }
214 cliContext->file_size = totalImgLen;
215 cliContext->file_buffer = fileBuffer;
216 return 0;
217 }
218
TEEC_ReadApp(const TaFileInfo * taFile,const char * loadFile,bool defaultPath,TC_NS_ClientContext * cliContext)219 static int32_t TEEC_ReadApp(const TaFileInfo *taFile, const char *loadFile, bool defaultPath,
220 TC_NS_ClientContext *cliContext)
221 {
222 int32_t ret = 0;
223 FILE *fp = NULL;
224 FILE *fpTmp = NULL;
225 char realLoadFile[PATH_MAX + 1] = { 0 };
226
227 if (taFile->taFp != NULL) {
228 fp = taFile->taFp;
229 tlogd("libteec_vendor-read_app: get fp from ta fp\n");
230 goto READ_APP;
231 }
232
233 if (realpath(loadFile, realLoadFile) == NULL) {
234 if (!defaultPath) {
235 tloge("get file realpath error%d\n", errno);
236 return -1;
237 }
238
239 /* maybe it's a built-in TA */
240 tlogd("maybe it's a built-in TA or file is not in default path\n");
241 return ret;
242 }
243
244 /* open image file */
245 fpTmp = fopen(realLoadFile, "r");
246 if (fpTmp == NULL) {
247 tloge("open file error%d\n", errno);
248 return -1;
249 }
250 fp = fpTmp;
251
252 READ_APP:
253 ret = TEEC_DoReadApp(fp, cliContext);
254 if (ret != 0) {
255 tloge("do read app fail\n");
256 }
257
258 if (fpTmp != NULL) {
259 fclose(fpTmp);
260 }
261
262 return ret;
263 }
264
TEEC_LoadSecfile(const char * filePath,int tzFd,FILE * fp)265 int32_t TEEC_LoadSecfile(const char *filePath, int tzFd, FILE *fp)
266 {
267 int ret;
268 FILE *fpUsable = NULL;
269 bool checkValue = (tzFd < 0 || filePath == NULL);
270 FILE *fpCur = NULL;
271
272 if (checkValue) {
273 tloge("Param err!\n");
274 return -1;
275 }
276 if (fp == NULL) {
277 char realPath[PATH_MAX + 1] = { 0 };
278 if (realpath(filePath, realPath) != NULL) {
279 fpCur = fopen(realPath, "r");
280 }
281 if (fpCur == NULL) {
282 tloge("realpath open file erro%d, path=%s\n", errno, filePath);
283 return -1;
284 }
285 fpUsable = fpCur;
286 } else {
287 fpUsable = fp;
288 }
289 ret = LoadSecFile(tzFd, fpUsable, LOAD_LIB, NULL);
290 if (fpCur != NULL) {
291 fclose(fpCur);
292 }
293 return ret;
294 }
295