1 /*
2 * Copyright (c) 2014, STMicroelectronics International N.V.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27 #include <dirent.h>
28 #include <fcntl.h>
29 #include <stdbool.h>
30 #include <stdio.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <pthread.h>
35
36 #include <teec_trace.h>
37 #include <teec_ta_load.h>
38
39 /*
40 * Attempt to first load TAs from a writable directory. This is
41 * intended for testing (xtest 1008, load_corrupt_ta specifically),
42 * and should not be enabled in a production system, as it would
43 * greatly facilitate loading rogue TA code.
44 */
45 #ifdef CFG_TA_TEST_PATH
46 # ifndef TEEC_TEST_LOAD_PATH
47 # ifdef __ANDROID__
48 # define TEEC_TEST_LOAD_PATH "/data/vendor/tee"
49 # else
50 # define TEEC_TEST_LOAD_PATH "/tmp"
51 # endif
52 # endif
53 #endif
54
55 #ifndef PATH_MAX
56 #define PATH_MAX 255
57 #endif
58
59 struct tee_rpc_cmd {
60 void *buffer;
61 uint32_t size;
62 uint32_t type;
63 int fd;
64 };
65
66 /*
67 * Based on the uuid this function will try to find a TA-binary on the
68 * filesystem and return it back to the caller in the parameter ta.
69 *
70 * @param: prefix Prefix for TA load path
71 * @param: dev_path Where to load the TA from. The full path to the TA
72 * binary is @prefix/@dev_path/@destination.ta.
73 * @param: destination The uuid of the TA we are searching for.
74 * @param: ta A pointer which this function will allocate and copy
75 * the TA from the filesystem to the pointer itself. It is
76 * the callers responsibility to free the pointer.
77 * @param: ta_size The size of the TA found on file system. It will be 0
78 * if no TA was not found.
79 *
80 * @return 0 if TA was found, otherwise -1.
81 */
try_load_secure_module(const char * prefix,const char * dev_path,const TEEC_UUID * destination,void * ta,size_t * ta_size)82 static int try_load_secure_module(const char* prefix,
83 const char* dev_path,
84 const TEEC_UUID *destination, void *ta,
85 size_t *ta_size)
86 {
87 char fname[PATH_MAX] = { 0 };
88 FILE *file = NULL;
89 bool first_try = true;
90 size_t s = 0;
91 long l = 0;
92 int n = 0;
93
94 if (!ta_size || !destination) {
95 DMSG("wrong inparameter to TEECI_LoadSecureModule");
96 return TA_BINARY_NOT_FOUND;
97 }
98
99 /*
100 * We expect the TA binary to be named after the UUID as per RFC4122,
101 * that is: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.ta
102 * If the file cannot be open, try the deprecated format:
103 * xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx.ta
104 */
105 again:
106 n = snprintf(fname, PATH_MAX,
107 "%s/%s/%08x-%04x-%04x-%02x%02x%s%02x%02x%02x%02x%02x%02x.ta",
108 prefix, dev_path,
109 destination->timeLow,
110 destination->timeMid,
111 destination->timeHiAndVersion,
112 destination->clockSeqAndNode[0],
113 destination->clockSeqAndNode[1],
114 first_try ? "-" : "",
115 destination->clockSeqAndNode[2],
116 destination->clockSeqAndNode[3],
117 destination->clockSeqAndNode[4],
118 destination->clockSeqAndNode[5],
119 destination->clockSeqAndNode[6],
120 destination->clockSeqAndNode[7]);
121
122 DMSG("Attempt to load %s", fname);
123
124 if ((n < 0) || (n >= PATH_MAX)) {
125 EMSG("wrong TA path [%s]", fname);
126 return TA_BINARY_NOT_FOUND;
127 }
128
129 file = fopen(fname, "r");
130 if (file == NULL) {
131 DMSG("failed to open the ta %s TA-file", fname);
132 if (first_try) {
133 first_try = false;
134 goto again;
135 }
136 return TA_BINARY_NOT_FOUND;
137 }
138
139 if (fseek(file, 0, SEEK_END) != 0) {
140 fclose(file);
141 return TA_BINARY_NOT_FOUND;
142 }
143
144 l = ftell(file);
145 if (l < 0) {
146 DMSG("failed to ftell the ta %s TA-file", fname);
147 fclose(file);
148 return TA_BINARY_NOT_FOUND;
149 }
150
151 s = l;
152 if (s > *ta_size || !ta) {
153 /*
154 * Buffer isn't large enough, return the required size to
155 * let the caller increase the size of the buffer and try
156 * again.
157 */
158 goto out;
159 }
160
161 if (fseek(file, 0, SEEK_SET) != 0) {
162 fclose(file);
163 return TA_BINARY_NOT_FOUND;
164 }
165
166 if (s != fread(ta, 1, s, file)) {
167 DMSG("failed to fread the ta %s TA-file", fname);
168 fclose(file);
169 return TA_BINARY_NOT_FOUND;
170 }
171
172 out:
173 *ta_size = s;
174 fclose(file);
175 return TA_BINARY_FOUND;
176 }
177
TEECI_LoadSecureModule(const char * dev_path,const TEEC_UUID * destination,void * ta,size_t * ta_size)178 int TEECI_LoadSecureModule(const char* dev_path,
179 const TEEC_UUID *destination, void *ta,
180 size_t *ta_size)
181 {
182 int res = TA_BINARY_NOT_FOUND;
183 char **path = NULL;
184
185 for (path = ta_path; *path; path++) {
186 res = try_load_secure_module(*path, dev_path, destination, ta,
187 ta_size);
188 if (res == TA_BINARY_FOUND)
189 break;
190 }
191 return res;
192 }
193