import exynos 7570 bsp
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos7580.git] / mobicore / Daemon / src / SecureWorld.cpp
1 /*
2 * Copyright (c) 2013-2015 TRUSTONIC LIMITED
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
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the TRUSTONIC LIMITED nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 // Standard
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <stdint.h>
36 #include <string.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <fstream>
40 #include <sys/ioctl.h>
41 #include <sys/mman.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 // <t-base
45 #include "Mci/mcimcp.h"
46 #include "mcVersionHelper.h"
47 // Logging
48 #include <log.h>
49 // Driver
50 #include "mc_user.h"
51 #include "mc_admin.h"
52 // Registry
53 #include "PrivateRegistry.h"
54 // Self
55 #include "SecureWorld.h"
56
57 MC_CHECK_VERSION(MCDRVMODULEAPI, 2, 1);
58 #define MAX_SO_CONT_SIZE 512
59 #define CRASHDUMP_PATH "/sys/kernel/debug/trustonic_tee/crashdump"
60
61 #define MY_LOG_ERRNO(fmt, ...) \
62 LOG_E("%s: %s " fmt, __func__, strerror(errno), ##__VA_ARGS__)
63
64 struct SecureWorld::Impl {
65 int device_fd;
66 uint32_t command_id;
67 bool keep_running;
68 Impl(): device_fd(-1), command_id(0), keep_running(true) {}
69 };
70
71 SecureWorld::SecureWorld(): pimpl_(new Impl) {}
72
73 SecureWorld::~SecureWorld() {
74 delete pimpl_;
75 }
76
77 static void* getRootContainer(const struct mc_admin_request*,
78 struct mc_admin_response* response,
79 bool*) {
80 void* data = ::malloc(MAX_SO_CONT_SIZE);
81 uint32_t length = MAX_SO_CONT_SIZE;
82
83 switch (mcRegistryReadRoot(data, &length)) {
84 case MC_DRV_OK:
85 response->length = length;
86 response->error_no = 0;
87 break;
88 case MC_DRV_ERR_INVALID_PARAMETER:
89 response->error_no = EINVAL;
90 break;
91 case MC_DRV_ERR_INVALID_DEVICE_FILE:
92 response->error_no = ENOENT;
93 break;
94 default:
95 // Some kind of default
96 response->error_no = EPERM;
97 }
98
99 if (response->error_no) {
100 ::free(data);
101 return NULL;
102 }
103
104 LOG_D("Read root container, size: %u", response->length);
105 return data;
106 }
107
108 static void* getSpContainer(const struct mc_admin_request* request,
109 struct mc_admin_response* response,
110 bool*) {
111 void* data = ::malloc(MAX_SO_CONT_SIZE);
112 uint32_t length = MAX_SO_CONT_SIZE;
113
114 switch (mcRegistryReadSp(request->spid, data, &length)) {
115 case MC_DRV_OK:
116 response->length = length;
117 response->error_no = 0;
118 break;
119 case MC_DRV_ERR_INVALID_PARAMETER:
120 response->error_no = EINVAL;
121 break;
122 case MC_DRV_ERR_INVALID_DEVICE_FILE:
123 response->error_no = ENOENT;
124 break;
125 default:
126 // Some kind of default
127 response->error_no = EPERM;
128 }
129
130 if (response->error_no) {
131 ::free(data);
132 return NULL;
133 }
134
135 LOG_D("Read SP container for %u, size: %u", request->spid, response->length);
136 return data;
137 }
138
139 static void* getTrustletContainer(const struct mc_admin_request* request,
140 struct mc_admin_response* response,
141 bool*) {
142 void* data = ::malloc(MAX_SO_CONT_SIZE);
143 uint32_t length = MAX_SO_CONT_SIZE;
144
145 const mcUuid_t* uuid = reinterpret_cast<const mcUuid_t*>(&request->uuid);
146 switch (mcRegistryReadTrustletCon(uuid, request->spid, data, &length)) {
147 case MC_DRV_OK:
148 response->length = length;
149 response->error_no = 0;
150 break;
151 case MC_DRV_ERR_INVALID_PARAMETER:
152 response->error_no = EINVAL;
153 break;
154 case MC_DRV_ERR_INVALID_DEVICE_FILE:
155 response->error_no = ENOENT;
156 break;
157 case MC_DRV_ERR_OUT_OF_RESOURCES:
158 response->error_no = ENOMEM;
159 break;
160 default:
161 // Some kind of default
162 response->error_no = EPERM;
163 }
164
165 if (response->error_no) {
166 ::free(data);
167 return NULL;
168 }
169
170 LOG_D("Read trustlet container for %u, size: %u", response->spid, response->length);
171 return data;
172 }
173
174 static void* mapTrustlet(const char* path, uint32_t* length,
175 uint32_t* service_type) {
176 int fd = ::open(path, O_RDONLY);
177 if (fd < 0) {
178 LOG_W("Cannot open trustlet %s (%d)", path, errno);
179 return NULL;
180 }
181
182 void* data = NULL;
183 *service_type = SERVICE_TYPE_ILLEGAL;
184 do {
185 struct stat stat;
186 if (::fstat(fd, &stat) < 0) {
187 MY_LOG_ERRNO("getting size for trustlet %s", path);
188 break;
189 }
190
191 data = ::mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
192 if (data == MAP_FAILED) {
193 data = NULL;
194 MY_LOG_ERRNO("mapping file to memory");
195 break;
196 }
197
198 /* Give service type to driver so it knows how to allocate and copy */
199 mclfHeaderV2_t* header = static_cast<mclfHeaderV2_t*>(data);
200 *service_type = header->serviceType;
201 *length = static_cast<uint32_t>(stat.st_size);
202 } while (false);
203
204 ::close(fd);
205
206 return data;
207 }
208
209 static void* getTrustlet(const struct mc_admin_request* request,
210 struct mc_admin_response* response,
211 bool* is_mmapped) {
212 *is_mmapped = true;
213 const mcUuid_t* uuid = reinterpret_cast<const mcUuid_t*>(&request->uuid);
214 std::string path;
215
216 mcResult_t res = mcRegistryGetTrustletInfo(uuid, request->is_gp, &response->spid, path);
217 switch (res) {
218 case MC_DRV_OK:
219 response->error_no = 0;
220 break;
221 case MC_DRV_ERR_INVALID_PARAMETER:
222 response->error_no = EINVAL;
223 break;
224 case MC_DRV_ERR_TRUSTLET_NOT_FOUND:
225 response->error_no = ENOENT;
226 break;
227 default:
228 // Some kind of default
229 response->error_no = EPERM;
230 }
231
232 if (response->error_no) {
233 return NULL;
234 }
235
236 void* data = mapTrustlet(path.c_str(), &response->length,
237 &response->service_type);
238 if (!data) {
239 response->error_no = errno;
240 } else {
241 LOG_D("Read spid %u and mmap'd trustlet from %s, total size: %u", response->spid, path.c_str(), response->length);
242 }
243 return data;
244 }
245
246 static void* logCrashDump(const struct mc_admin_request*,
247 struct mc_admin_response* response,
248 bool*) {
249 std::ifstream crashdump(CRASHDUMP_PATH);
250 if (!crashdump.is_open()) {
251 MY_LOG_ERRNO("opening crash dump");
252 response->error_no = errno;
253 return NULL;
254 }
255
256 LOG_E("<t-base halted. Status dump:");
257 std::string line;
258 while (std::getline(crashdump, line)) {
259 LOG_I("%s", line.c_str());
260 }
261
262 return NULL;
263 }
264
265 int SecureWorld::open() {
266 pimpl_->device_fd = ::open("/dev/" MC_ADMIN_DEVNODE, O_RDWR);
267 if (pimpl_->device_fd < 0) {
268 MY_LOG_ERRNO("opening admin device");
269 return -1;
270 }
271
272 LOG_D("Check version of <t-base driver");
273 struct mc_admin_driver_info info;
274 if (ioctl(pimpl_->device_fd, MC_ADMIN_IO_GET_INFO, &info) != 0) {
275 LOG_ERRNO("ioctl MC_ADMIN_IO_GET_INFO");
276 ::close(pimpl_->device_fd);
277 return -1;
278 }
279
280 char *errmsg;
281 if (!checkVersionOkMCDRVMODULEAPI(info.drv_version, &errmsg)) {
282 LOG_E("%s", errmsg);
283 ::close(pimpl_->device_fd);
284 return -1;
285 }
286
287 LOG_D("%s", errmsg);
288 pimpl_->command_id = info.initial_cmd_id;
289
290 // We wait 10 times 100ms for the device file to appear
291 int counter = 10;
292 do {
293 struct stat st;
294
295 int ret = ::stat("/dev/" MC_USER_DEVNODE, &st);
296 if (!ret) {
297 break;
298 }
299
300 if (errno != ENOENT) {
301 MY_LOG_ERRNO("stat'ing user device");
302 return -1;
303 }
304
305 /* Device driver didn't appear yet: give some time */
306 usleep(100000);
307 } while (counter--);
308
309 if (counter == 0) {
310 LOG_E("timed out while waiting for user device to appear");
311 return -1;
312 }
313
314 LOG_D("TEE is ready");
315 return 0;
316 }
317
318 void SecureWorld::close() {
319 ::close(pimpl_->device_fd);
320 }
321
322 int SecureWorld::loadDriver(const char* path) {
323 struct mc_admin_load_info info;
324 uint32_t service_type;
325
326 void* data = mapTrustlet(path, &info.length, &service_type);
327 if (!data) {
328 return -1;
329 }
330
331 LOG_D("Load secure driver %s of size %d", path, info.length);
332 info.address = reinterpret_cast<uintptr_t>(data);
333 info.spid = 0;
334
335 int ret = ioctl(pimpl_->device_fd, MC_ADMIN_IO_LOAD_DRIVER, &info);
336 if (ret != 0) {
337 LOG_ERRNO("ioctl MC_ADMIN_IO_LOAD_DRIVER");
338 }
339
340 // Free memory occupied by Trustlet data
341 ::munmap(data, info.length);
342 return ret == 0;
343 }
344
345 int SecureWorld::loadToken(const void *data, uint32_t length) {
346 struct mc_admin_load_info token;
347
348 LOG_D("Load authentication token %p of size %u", data, length);
349 token.address = reinterpret_cast<uintptr_t>(data);
350 token.length = length;
351
352 int rc = ioctl(pimpl_->device_fd, MC_ADMIN_IO_LOAD_TOKEN, &token);
353 if (rc != 0) {
354 LOG_ERRNO("ioctl MC_ADMIN_IO_LOAD_TOKEN");
355 return -1;
356 }
357
358 return 0;
359 }
360
361 int SecureWorld::LoadCheck(mcSpid_t spid, const void *data, uint32_t length) {
362 struct mc_admin_load_info info;
363
364 LOG_D("Load secure object %p, length %u, spid %x", data, length, spid);
365 info.spid = spid;
366 info.address = reinterpret_cast<uintptr_t>(data);
367 info.length = length;
368
369 int rc = ioctl(pimpl_->device_fd, MC_ADMIN_IO_LOAD_CHECK, &info);
370 if (rc != 0) {
371 LOG_ERRNO("ioctl MC_ADMIN_IO_LOAD_CHECK");
372 return -1;
373 }
374
375 return 0;
376 }
377
378 int SecureWorld::listen()
379 {
380 int rc = 0;
381
382 while (pimpl_->keep_running) {
383 struct mc_admin_request request;
384
385 rc = ioctl(pimpl_->device_fd, MC_ADMIN_IO_GET_DRIVER_REQUEST, &request);
386 if (rc) {
387 if (errno == EINTR) {
388 LOG_D("Giving up on signal");
389 } else {
390 LOG_ERRNO("Getting request from driver");
391 }
392 break;
393 }
394
395 LOG_D("Request %d received (ID %u)", request.command, request.request_id);
396 if (pimpl_->command_id != request.request_id) {
397 LOG_E("Request ID counters are not synchronised (expected %u, got %u)", pimpl_->command_id, request.request_id);
398 break;
399 }
400
401 struct mc_admin_response response;
402 memset(&response, 0, sizeof(response));
403 response.request_id = pimpl_->command_id++;
404 void* response_data = NULL;
405 bool is_mmapped = false; // Response data needs freeing
406 switch (request.command) {
407 case MC_DRV_GET_ROOT_CONTAINER:
408 response_data = getRootContainer(&request, &response, &is_mmapped);
409 break;
410 case MC_DRV_GET_SP_CONTAINER:
411 response_data = getSpContainer(&request, &response, &is_mmapped);
412 break;
413 case MC_DRV_GET_TRUSTLET_CONTAINER:
414 response_data = getTrustletContainer(&request, &response, &is_mmapped);
415 break;
416 case MC_DRV_GET_TRUSTLET:
417 response_data = getTrustlet(&request, &response, &is_mmapped);
418 break;
419 case MC_DRV_SIGNAL_CRASH:
420 logCrashDump(&request, &response, &is_mmapped);
421 break;
422 default:
423 LOG_E("Unknown command");
424 response.error_no = EBADRQC;
425 }
426
427 ssize_t ret = ::write(pimpl_->device_fd, &response, sizeof(response));
428 if (ret != sizeof(response)) {
429 LOG_ERRNO("Sending response to driver");
430 ret = -1;
431 } else if (response.length > 0) {
432 ssize_t expected_length = response.length;
433 ret = ::write(pimpl_->device_fd, response_data, response.length);
434 if (ret != expected_length) {
435 LOG_ERRNO("Sending response data to driver");
436 ret = -1;
437 }
438 }
439
440 if (response_data && is_mmapped) {
441 ::munmap(response_data, response.length);
442 } else {
443 ::free(response_data);
444 }
445 }
446
447 return rc;
448 }
449
450 void SecureWorld::stopListening() {
451 pimpl_->keep_running = false;
452 }