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 #ifndef PATH_MAX
40 #define PATH_MAX 255
41 #endif
42
43 struct tee_rpc_cmd {
44 void *buffer;
45 uint32_t size;
46 uint32_t type;
47 int fd;
48 };
49
50 /*
51 * Based on the uuid this function will try to find a TA-binary on the
52 * filesystem and return it back to the caller in the parameter ta.
53 *
54 * @param: ta_load_path Where to load the TA from. The full path to the TA
55 * binary is @ta_load_path/@destination.ta.
56 * @param: destination The uuid of the TA we are searching for.
57 * @param: ta A pointer which this function will allocate and copy
58 * the TA from the filesystem to the pointer itself. It is
59 * the callers responsibility to free the pointer.
60 * @param: ta_size The size of the TA found on file system. It will be 0
61 * if no TA was not found.
62 *
63 * @return 0 if TA was found, otherwise -1.
64 */
try_load_secure_module(const char * ta_load_path,const TEEC_UUID * destination,void * ta,size_t * ta_size)65 static int try_load_secure_module(const char *ta_load_path,
66 const TEEC_UUID *destination, void *ta,
67 size_t *ta_size)
68 {
69 char fname[PATH_MAX] = { 0 };
70 FILE *file = NULL;
71 bool first_try = true;
72 size_t s = 0;
73 long l = 0;
74 int n = 0;
75
76 if (!ta_size || !destination) {
77 DMSG("wrong inparameter to TEECI_LoadSecureModule");
78 return TA_BINARY_NOT_FOUND;
79 }
80
81 /*
82 * We expect the TA binary to be named after the UUID as per RFC4122,
83 * that is: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.ta
84 * If the file cannot be open, try the deprecated format:
85 * xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx.ta
86 */
87 again:
88 n = snprintf(fname, PATH_MAX,
89 "%s/%08x-%04x-%04x-%02x%02x%s%02x%02x%02x%02x%02x%02x.ta",
90 ta_load_path,
91 destination->timeLow,
92 destination->timeMid,
93 destination->timeHiAndVersion,
94 destination->clockSeqAndNode[0],
95 destination->clockSeqAndNode[1],
96 first_try ? "-" : "",
97 destination->clockSeqAndNode[2],
98 destination->clockSeqAndNode[3],
99 destination->clockSeqAndNode[4],
100 destination->clockSeqAndNode[5],
101 destination->clockSeqAndNode[6],
102 destination->clockSeqAndNode[7]);
103
104 DMSG("Attempt to load %s", fname);
105
106 if ((n < 0) || (n >= PATH_MAX)) {
107 EMSG("wrong TA path [%s]", fname);
108 return TA_BINARY_NOT_FOUND;
109 }
110
111 file = fopen(fname, "r");
112 if (file == NULL) {
113 DMSG("failed to open the ta %s TA-file", fname);
114 if (first_try) {
115 first_try = false;
116 goto again;
117 }
118 return TA_BINARY_NOT_FOUND;
119 }
120
121 if (fseek(file, 0, SEEK_END) != 0) {
122 fclose(file);
123 return TA_BINARY_NOT_FOUND;
124 }
125
126 l = ftell(file);
127 if (l < 0) {
128 DMSG("failed to ftell the ta %s TA-file", fname);
129 fclose(file);
130 return TA_BINARY_NOT_FOUND;
131 }
132
133 s = l;
134 if (s > *ta_size || !ta) {
135 /*
136 * Buffer isn't large enough, return the required size to
137 * let the caller increase the size of the buffer and try
138 * again.
139 */
140 goto out;
141 }
142
143 if (fseek(file, 0, SEEK_SET) != 0) {
144 fclose(file);
145 return TA_BINARY_NOT_FOUND;
146 }
147
148 if (s != fread(ta, 1, s, file)) {
149 DMSG("failed to fread the ta %s TA-file", fname);
150 fclose(file);
151 return TA_BINARY_NOT_FOUND;
152 }
153
154 out:
155 *ta_size = s;
156 fclose(file);
157 return TA_BINARY_FOUND;
158 }
159
TEECI_LoadSecureModule(const TEEC_UUID * destination,void * ta,size_t * ta_size)160 int TEECI_LoadSecureModule(const TEEC_UUID *destination, void *ta,
161 size_t *ta_size)
162 {
163 int res = TA_BINARY_NOT_FOUND;
164 char **path = NULL;
165
166 for (path = ta_path; *path; path++) {
167 res = try_load_secure_module(*path, destination, ta, ta_size);
168 if (res == TA_BINARY_FOUND)
169 break;
170 }
171 return res;
172 }
173