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: destination The uuid of the TA we are searching for.
71 * @param: ta A pointer which this function will allocate and copy
72 * the TA from the filesystem to the pointer itself. It is
73 * the callers responsibility to free the pointer.
74 * @param: ta_size The size of the TA found on file system. It will be 0
75 * if no TA was not found.
76 *
77 * @return 0 if TA was found, otherwise -1.
78 */
try_load_secure_module(const char * prefix,const char * dev_path,const TEEC_UUID * destination,void * ta,size_t * ta_size)79 static int try_load_secure_module(const char* prefix,
80 const char* dev_path,
81 const TEEC_UUID *destination, void *ta,
82 size_t *ta_size)
83 {
84 char fname[PATH_MAX] = { 0 };
85 FILE *file = NULL;
86 bool first_try = true;
87 size_t s = 0;
88 long l = 0;
89 int n = 0;
90
91 if (!ta_size || !destination) {
92 DMSG("wrong inparameter to TEECI_LoadSecureModule");
93 return TA_BINARY_NOT_FOUND;
94 }
95
96 /*
97 * We expect the TA binary to be named after the UUID as per RFC4122,
98 * that is: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.ta
99 * If the file cannot be open, try the deprecated format:
100 * xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx.ta
101 */
102 again:
103 n = snprintf(fname, PATH_MAX,
104 "%s/%s/%08x-%04x-%04x-%02x%02x%s%02x%02x%02x%02x%02x%02x.ta",
105 prefix, dev_path,
106 destination->timeLow,
107 destination->timeMid,
108 destination->timeHiAndVersion,
109 destination->clockSeqAndNode[0],
110 destination->clockSeqAndNode[1],
111 first_try ? "-" : "",
112 destination->clockSeqAndNode[2],
113 destination->clockSeqAndNode[3],
114 destination->clockSeqAndNode[4],
115 destination->clockSeqAndNode[5],
116 destination->clockSeqAndNode[6],
117 destination->clockSeqAndNode[7]);
118
119 DMSG("Attempt to load %s", fname);
120
121 if ((n < 0) || (n >= PATH_MAX)) {
122 EMSG("wrong TA path [%s]", fname);
123 return TA_BINARY_NOT_FOUND;
124 }
125
126 file = fopen(fname, "r");
127 if (file == NULL) {
128 DMSG("failed to open the ta %s TA-file", fname);
129 if (first_try) {
130 first_try = false;
131 goto again;
132 }
133 return TA_BINARY_NOT_FOUND;
134 }
135
136 if (fseek(file, 0, SEEK_END) != 0) {
137 fclose(file);
138 return TA_BINARY_NOT_FOUND;
139 }
140
141 l = ftell(file);
142 if (l < 0) {
143 DMSG("failed to ftell the ta %s TA-file", fname);
144 fclose(file);
145 return TA_BINARY_NOT_FOUND;
146 }
147
148 s = l;
149 if (s > *ta_size || !ta) {
150 /*
151 * Buffer isn't large enough, return the required size to
152 * let the caller increase the size of the buffer and try
153 * again.
154 */
155 goto out;
156 }
157
158 if (fseek(file, 0, SEEK_SET) != 0) {
159 fclose(file);
160 return TA_BINARY_NOT_FOUND;
161 }
162
163 if (s != fread(ta, 1, s, file)) {
164 DMSG("failed to fread the ta %s TA-file", fname);
165 fclose(file);
166 return TA_BINARY_NOT_FOUND;
167 }
168
169 out:
170 *ta_size = s;
171 fclose(file);
172 return TA_BINARY_FOUND;
173 }
174
TEECI_LoadSecureModule(const char * dev_path,const TEEC_UUID * destination,void * ta,size_t * ta_size)175 int TEECI_LoadSecureModule(const char* dev_path,
176 const TEEC_UUID *destination, void *ta,
177 size_t *ta_size)
178 {
179 #ifdef TEEC_TEST_LOAD_PATH
180 int res = 0;
181
182 res = try_load_secure_module(TEEC_TEST_LOAD_PATH,
183 dev_path, destination, ta, ta_size);
184 if (res != TA_BINARY_NOT_FOUND)
185 return res;
186 #endif
187
188 return try_load_secure_module(TEEC_LOAD_PATH,
189 dev_path, destination, ta, ta_size);
190 }
191