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 "load_sec_file.h"
14 #include <sys/ioctl.h> /* for ioctl */
15 #include <sys/prctl.h>
16 #include "securec.h"
17 #include "tc_ns_client.h"
18 #include "tee_log.h"
19 
20 #ifdef LOG_TAG
21 #undef LOG_TAG
22 #endif
23 #define LOG_TAG "load_secfile"
24 #define MAX_BUFFER_LEN (8 * 1024 * 1024)
25 #define H_OFFSET                  32
26 
GetImgLen(FILE * fp,long * totalLlen)27 static int GetImgLen(FILE *fp, long *totalLlen)
28 {
29     int ret;
30 
31     ret = fseek(fp, 0, SEEK_END);
32     if (ret != 0) {
33         tloge("fseek end error\n");
34         return -1;
35     }
36     *totalLlen = ftell(fp);
37     if (*totalLlen <= 0 || *totalLlen > MAX_BUFFER_LEN) {
38         tloge("file is not exist or size is too large, filesize = %ld\n", *totalLlen);
39         return -1;
40     }
41     ret = fseek(fp, 0, SEEK_SET);
42     if (ret != 0) {
43         tloge("fseek head error\n");
44         return -1;
45     }
46     return ret;
47 }
48 
49 /* 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)50 int32_t LoadSecFile(int tzFd, FILE *fp, enum SecFileType fileType, const TEEC_UUID *uuid)
51 {
52     int32_t ret;
53     char *fileBuffer                   = NULL;
54     struct SecLoadIoctlStruct ioctlArg = {{ 0 }, { 0 }, { NULL } };
55 
56     if (tzFd < 0 || fp == NULL) {
57         tloge("param erro!\n");
58         return -1;
59     }
60 
61     do {
62         long totalLen = 0;
63         ret           = GetImgLen(fp, &totalLen);
64         if (ret != 0) {
65             break;
66         }
67 
68         if (totalLen <= 0 || totalLen > MAX_BUFFER_LEN) {
69             ret = -1;
70             tloge("totalLen is invalid\n");
71             break;
72         }
73 
74         /* alloc a less than 8M heap memory, it needn't slice. */
75         fileBuffer = malloc(totalLen);
76         if (fileBuffer == NULL) {
77             tloge("alloc TA file buffer(size=%ld) failed\n", totalLen);
78             ret = -1;
79             break;
80         }
81 
82         /* read total ta file to file buffer */
83         long fileSize = (long)fread(fileBuffer, 1, totalLen, fp);
84         if (fileSize != totalLen) {
85             tloge("read ta file failed, read size/total size=%ld/%ld\n", fileSize, totalLen);
86             ret = -1;
87             break;
88         }
89 
90         ioctlArg.secFileInfo.fileType = fileType;
91         ioctlArg.secFileInfo.fileSize = (uint32_t)totalLen;
92         ioctlArg.memref.file_addr = (uint32_t)(uintptr_t)fileBuffer;
93         ioctlArg.memref.file_h_addr = (uint32_t)(((uint64_t)(uintptr_t)fileBuffer) >> H_OFFSET);
94         if (uuid != NULL && memcpy_s((void *)(&ioctlArg.uuid), sizeof(ioctlArg.uuid), uuid, sizeof(*uuid)) != EOK) {
95             tloge("memcpy uuid fail\n");
96             break;
97         }
98 
99         ret = ioctl(tzFd, (int)TC_NS_CLIENT_IOCTL_LOAD_APP_REQ, &ioctlArg);
100         if (ret != 0) {
101             tloge("ioctl to load sec file failed, ret = 0x%x\n", ret);
102         }
103     } while (false);
104 
105     if (fileBuffer != NULL) {
106         free(fileBuffer);
107     }
108     return ret;
109 }
110 
111