Commit | Line | Data |
---|---|---|
15e8442f JA |
1 | /** Mobicore Driver Registry. |
2 | * | |
3 | * Implements the MobiCore driver registry which maintains trustlets. | |
4 | * | |
5 | * @file | |
6 | * @ingroup MCD_MCDIMPL_DAEMON_REG | |
7 | */ | |
8 | ||
cd9434cc | 9 | /* |
15e8442f | 10 | * Copyright (c) 2013 TRUSTONIC LIMITED |
cd9434cc T |
11 | * All rights reserved. |
12 | * | |
13 | * Redistribution and use in source and binary forms, with or without | |
14 | * modification, are permitted provided that the following conditions are met: | |
15 | * | |
16 | * 1. Redistributions of source code must retain the above copyright notice, | |
17 | * this list of conditions and the following disclaimer. | |
18 | * | |
19 | * 2. Redistributions in binary form must reproduce the above copyright | |
20 | * notice, this list of conditions and the following disclaimer in the | |
21 | * documentation and/or other materials provided with the distribution. | |
22 | * | |
23 | * 3. Neither the name of the TRUSTONIC LIMITED nor the names of its | |
24 | * contributors may be used to endorse or promote products derived from | |
25 | * this software without specific prior written permission. | |
26 | * | |
27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
29 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR | |
31 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
32 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
33 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
34 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
35 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
36 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
37 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
38 | */ | |
15e8442f | 39 | |
cd9434cc | 40 | #include <stdlib.h> |
cd9434cc T |
41 | #include <dirent.h> |
42 | #include <stdio.h> | |
43 | #include <sys/stat.h> | |
44 | #include <assert.h> | |
45 | #include <string.h> | |
46 | #include <string> | |
47 | #include <cstring> | |
48 | #include <cstddef> | |
49 | #include <sys/mman.h> | |
50 | #include <errno.h> | |
51 | #include <fcntl.h> | |
52 | #include <libgen.h> | |
53 | ||
54 | #include "mcLoadFormat.h" | |
55 | #include "mcSpid.h" | |
56 | #include "mcVersionHelper.h" | |
57 | ||
58 | #include "PrivateRegistry.h" | |
15e8442f | 59 | #include "MobiCoreRegistry.h" |
cd9434cc | 60 | |
cd9434cc T |
61 | #include "uuid_attestation.h" |
62 | ||
15e8442f | 63 | #include "log.h" |
cd9434cc | 64 | |
15e8442f JA |
65 | /** Maximum size of a trustlet in bytes. */ |
66 | #define MAX_TL_SIZE (1 * 1024 * 1024) | |
cd9434cc T |
67 | /** Maximum size of a shared object container in bytes. */ |
68 | #define MAX_SO_CONT_SIZE (512) | |
69 | ||
15e8442f JA |
70 | // Asserts expression at compile-time (to be used within a function body). |
71 | #define ASSERT_STATIC(e) do { enum { assert_static__ = 1 / (e) }; } while (0) | |
cd9434cc | 72 | |
15e8442f JA |
73 | #define MC_REGISTRY_CONTAINER_PATH "/data/app/mcRegistry" |
74 | #define MC_REGISTRY_DEFAULT_PATH "/system/app/mcRegistry" | |
e586d28c | 75 | #define MC_REGISTRY_VENDOR_PATH "/vendor/app/mcRegistry" |
15e8442f | 76 | #define MC_REGISTRY_FALLBACK_PATH "/data/app/mcRegistry" |
cd9434cc | 77 | #define AUTH_TOKEN_FILE_NAME "00000000.authtokcont" |
cd9434cc T |
78 | #define ENV_MC_AUTH_TOKEN_PATH "MC_AUTH_TOKEN_PATH" |
79 | #define ROOT_FILE_NAME "00000000.rootcont" | |
80 | #define SP_CONT_FILE_EXT ".spcont" | |
81 | #define TL_CONT_FILE_EXT ".tlcont" | |
82 | #define DATA_CONT_FILE_EXT ".datacont" | |
83 | #define TL_BIN_FILE_EXT ".tlbin" | |
84 | #define GP_TA_BIN_FILE_EXT ".tabin" | |
85 | #define GP_TA_SPID_FILE_EXT ".spid" | |
86 | ||
15e8442f | 87 | using namespace std; |
cd9434cc T |
88 | |
89 | //------------------------------------------------------------------------------ | |
15e8442f | 90 | static string byteArrayToString(const void *bytes, size_t elems) |
cd9434cc | 91 | { |
cd9434cc T |
92 | char hx[elems * 2 + 1]; |
93 | ||
94 | for (size_t i = 0; i < elems; i++) { | |
15e8442f | 95 | sprintf(&hx[i * 2], "%02x", ((uint8_t *)bytes)[i]); |
cd9434cc | 96 | } |
15e8442f | 97 | return string(hx); |
cd9434cc T |
98 | } |
99 | ||
100 | //------------------------------------------------------------------------------ | |
15e8442f | 101 | static string uint32ToString(uint32_t value) |
cd9434cc T |
102 | { |
103 | char hx[8 + 1]; | |
104 | snprintf(hx, sizeof(hx), "%08X", value); | |
15e8442f JA |
105 | string str(hx); |
106 | return string(str.rbegin(), str.rend()); | |
cd9434cc T |
107 | } |
108 | ||
109 | //------------------------------------------------------------------------------ | |
15e8442f | 110 | static bool doesDirExist(const char *path) |
cd9434cc T |
111 | { |
112 | struct stat ss; | |
15e8442f JA |
113 | if (path != NULL && stat(path, &ss) == 0 && S_ISDIR(ss.st_mode)) { |
114 | return true; | |
115 | } | |
116 | return false; | |
117 | } | |
118 | ||
119 | //------------------------------------------------------------------------------ | |
120 | static string getRegistryPath() | |
121 | { | |
122 | string registryPath; | |
123 | ||
124 | // use the default registry path. | |
125 | registryPath = MC_REGISTRY_CONTAINER_PATH; | |
126 | LOG_I(" Using default registry path %s", registryPath.c_str()); | |
cd9434cc | 127 | |
15e8442f JA |
128 | assert(registryPath.length() != 0); |
129 | ||
130 | return registryPath; | |
cd9434cc T |
131 | } |
132 | ||
133 | //------------------------------------------------------------------------------ | |
15e8442f | 134 | string getTlRegistryPath() |
cd9434cc | 135 | { |
15e8442f JA |
136 | string registryPath; |
137 | ||
138 | // First, attempt to use regular registry environment variable. | |
139 | if (doesDirExist(MC_REGISTRY_DEFAULT_PATH)) { | |
140 | registryPath = MC_REGISTRY_DEFAULT_PATH; | |
141 | LOG_I(" Using MC_REGISTRY_PATH %s", registryPath.c_str()); | |
e586d28c DW |
142 | } else if (doesDirExist(MC_REGISTRY_VENDOR_PATH)) { |
143 | // Second, attempt to use regular registry environment variable. | |
144 | registryPath = MC_REGISTRY_VENDOR_PATH; | |
145 | LOG_I(" Using MC_REGISTRY_VENDOR_PATH %s", registryPath.c_str()); | |
15e8442f | 146 | } else if (doesDirExist(MC_REGISTRY_FALLBACK_PATH)) { |
e586d28c | 147 | // Third, attempt to use fallback registry environment variable. |
15e8442f JA |
148 | registryPath = MC_REGISTRY_FALLBACK_PATH; |
149 | LOG_I(" Using MC_REGISTRY_FALLBACK_PATH %s", registryPath.c_str()); | |
150 | } | |
151 | ||
152 | // As a last resort, use the default registry path. | |
153 | if (registryPath.length() == 0) { | |
154 | registryPath = MC_REGISTRY_CONTAINER_PATH; | |
155 | LOG_I(" Using default registry path %s", registryPath.c_str()); | |
156 | } | |
157 | ||
158 | assert(registryPath.length() != 0); | |
159 | ||
160 | return registryPath; | |
cd9434cc T |
161 | } |
162 | ||
163 | //------------------------------------------------------------------------------ | |
15e8442f | 164 | static string getAuthTokenFilePath() |
cd9434cc T |
165 | { |
166 | const char *path; | |
15e8442f | 167 | string authTokenPath; |
cd9434cc T |
168 | |
169 | // First, attempt to use regular auth token path environment variable. | |
170 | path = getenv(ENV_MC_AUTH_TOKEN_PATH); | |
15e8442f JA |
171 | if (doesDirExist(path)) { |
172 | LOG_I("getAuthTokenFilePath(): Using MC_AUTH_TOKEN_PATH %s", path); | |
cd9434cc T |
173 | authTokenPath = path; |
174 | } else { | |
15e8442f JA |
175 | authTokenPath = getRegistryPath(); |
176 | LOG_I("getAuthTokenFilePath(): Using path %s", authTokenPath.c_str()); | |
cd9434cc T |
177 | } |
178 | ||
179 | return authTokenPath + "/" + AUTH_TOKEN_FILE_NAME; | |
180 | } | |
181 | ||
182 | //------------------------------------------------------------------------------ | |
15e8442f | 183 | static string getRootContFilePath() |
cd9434cc | 184 | { |
15e8442f | 185 | return getRegistryPath() + "/" + ROOT_FILE_NAME; |
cd9434cc T |
186 | } |
187 | ||
188 | //------------------------------------------------------------------------------ | |
15e8442f | 189 | static string getSpDataPath(mcSpid_t spid) |
cd9434cc | 190 | { |
15e8442f | 191 | return getRegistryPath() + "/" + uint32ToString(spid); |
cd9434cc T |
192 | } |
193 | ||
194 | //------------------------------------------------------------------------------ | |
15e8442f | 195 | static string getSpContFilePath(mcSpid_t spid) |
cd9434cc | 196 | { |
15e8442f | 197 | return getRegistryPath() + "/" + uint32ToString(spid) + SP_CONT_FILE_EXT; |
cd9434cc T |
198 | } |
199 | ||
200 | //------------------------------------------------------------------------------ | |
15e8442f | 201 | static string getTlContFilePath(const mcUuid_t *uuid, const mcSpid_t spid) |
cd9434cc | 202 | { |
15e8442f | 203 | return getRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid)) |
cd9434cc T |
204 | + "." + uint32ToString(spid) + TL_CONT_FILE_EXT; |
205 | } | |
206 | ||
207 | //------------------------------------------------------------------------------ | |
15e8442f | 208 | static string getTlDataPath(const mcUuid_t *uuid) |
cd9434cc | 209 | { |
15e8442f | 210 | return getRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid)); |
cd9434cc T |
211 | } |
212 | ||
213 | //------------------------------------------------------------------------------ | |
15e8442f | 214 | static string getTlDataFilePath(const mcUuid_t *uuid, mcPid_t pid) |
cd9434cc T |
215 | { |
216 | return getTlDataPath(uuid) + "/" + uint32ToString(pid.data) + DATA_CONT_FILE_EXT; | |
217 | } | |
218 | ||
219 | //------------------------------------------------------------------------------ | |
15e8442f | 220 | static string getTlBinFilePath(const mcUuid_t *uuid) |
cd9434cc | 221 | { |
15e8442f | 222 | return getTlRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid)) + TL_BIN_FILE_EXT; |
cd9434cc T |
223 | } |
224 | ||
225 | //------------------------------------------------------------------------------ | |
15e8442f | 226 | static string getTABinFilePath(const mcUuid_t *uuid) |
cd9434cc | 227 | { |
15e8442f | 228 | return getTlRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid)) + GP_TA_BIN_FILE_EXT; |
cd9434cc T |
229 | } |
230 | ||
231 | //------------------------------------------------------------------------------ | |
15e8442f | 232 | static string getTASpidFilePath(const mcUuid_t *uuid) |
cd9434cc | 233 | { |
15e8442f | 234 | return getTlRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid)) + GP_TA_SPID_FILE_EXT; |
cd9434cc T |
235 | } |
236 | ||
237 | //------------------------------------------------------------------------------ | |
15e8442f | 238 | mcResult_t mcRegistryStoreAuthToken(void *so, uint32_t size) |
cd9434cc | 239 | { |
cd9434cc T |
240 | if (so == NULL || size > 3 * MAX_SO_CONT_SIZE) { |
241 | LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER); | |
242 | return MC_DRV_ERR_INVALID_PARAMETER; | |
243 | } | |
15e8442f JA |
244 | const string &authTokenFilePath = getAuthTokenFilePath(); |
245 | LOG_I("store AuthToken: %s", authTokenFilePath.c_str()); | |
cd9434cc | 246 | |
cd9434cc | 247 | FILE *fs = fopen(authTokenFilePath.c_str(), "wb"); |
15e8442f JA |
248 | if (!fs) { |
249 | LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); | |
cd9434cc T |
250 | return MC_DRV_ERR_INVALID_DEVICE_FILE; |
251 | } | |
15e8442f JA |
252 | fseek(fs, 0, SEEK_SET); |
253 | fwrite((char *)so, 1, size, fs); | |
254 | fflush(fs); | |
cd9434cc T |
255 | fclose(fs); |
256 | ||
257 | return MC_DRV_OK; | |
258 | } | |
259 | ||
15e8442f | 260 | |
cd9434cc | 261 | //------------------------------------------------------------------------------ |
15e8442f | 262 | mcResult_t mcRegistryReadAuthToken(mcSoAuthTokenCont_t *so) |
cd9434cc | 263 | { |
cd9434cc T |
264 | if (NULL == so) { |
265 | LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER); | |
266 | return MC_DRV_ERR_INVALID_PARAMETER; | |
267 | } | |
15e8442f JA |
268 | const string &authTokenFilePath = getAuthTokenFilePath(); |
269 | LOG_I("read AuthToken: %s", authTokenFilePath.c_str()); | |
cd9434cc T |
270 | |
271 | FILE *fs = fopen(authTokenFilePath.c_str(), "rb"); | |
15e8442f | 272 | if (!fs) { |
cd9434cc T |
273 | LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); |
274 | return MC_DRV_ERR_INVALID_DEVICE_FILE; | |
275 | } | |
15e8442f JA |
276 | fseek(fs, 0, SEEK_END); |
277 | int32_t filesize = ftell(fs); | |
cd9434cc T |
278 | if (sizeof(mcSoAuthTokenCont_t) != filesize) { |
279 | fclose(fs); | |
280 | LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES); | |
281 | return MC_DRV_ERR_OUT_OF_RESOURCES; | |
282 | } | |
15e8442f JA |
283 | fseek(fs, 0, SEEK_SET); |
284 | if (fread((char *)so, 1, sizeof(mcSoAuthTokenCont_t), fs) != | |
285 | sizeof(mcSoAuthTokenCont_t)) | |
286 | { | |
cd9434cc | 287 | fclose(fs); |
15e8442f | 288 | LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER); |
cd9434cc T |
289 | return MC_DRV_ERR_INVALID_PARAMETER; |
290 | } | |
291 | fclose(fs); | |
292 | ||
293 | return MC_DRV_OK; | |
294 | } | |
295 | ||
296 | //------------------------------------------------------------------------------ | |
297 | mcResult_t mcRegistryDeleteAuthToken(void) | |
298 | { | |
15e8442f JA |
299 | if (remove(getAuthTokenFilePath().c_str())) { |
300 | LOG_ERRNO("Delete Auth token file!"); | |
cd9434cc T |
301 | return MC_DRV_ERR_UNKNOWN; |
302 | } else | |
303 | return MC_DRV_OK; | |
304 | } | |
305 | ||
306 | ||
307 | //------------------------------------------------------------------------------ | |
15e8442f | 308 | mcResult_t mcRegistryStoreRoot(void *so, uint32_t size) |
cd9434cc | 309 | { |
cd9434cc T |
310 | if (so == NULL || size > 3 * MAX_SO_CONT_SIZE) { |
311 | LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER); | |
312 | return MC_DRV_ERR_INVALID_PARAMETER; | |
313 | } | |
314 | ||
15e8442f JA |
315 | const string &rootContFilePath = getRootContFilePath(); |
316 | LOG_I("store Root: %s", rootContFilePath.c_str()); | |
cd9434cc T |
317 | |
318 | FILE *fs = fopen(rootContFilePath.c_str(), "wb"); | |
15e8442f | 319 | if (!fs) { |
cd9434cc T |
320 | LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); |
321 | return MC_DRV_ERR_INVALID_DEVICE_FILE; | |
322 | } | |
15e8442f JA |
323 | fseek(fs, 0, SEEK_SET); |
324 | fwrite((char *)so, 1, size, fs); | |
cd9434cc T |
325 | fflush(fs); |
326 | fclose(fs); | |
327 | ||
328 | return MC_DRV_OK; | |
329 | } | |
330 | ||
331 | ||
332 | //------------------------------------------------------------------------------ | |
333 | mcResult_t mcRegistryReadRoot(void *so, uint32_t *size) | |
334 | { | |
15e8442f | 335 | const string &rootContFilePath = getRootContFilePath(); |
cd9434cc T |
336 | size_t readBytes; |
337 | ||
338 | if (so == NULL) { | |
339 | LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER); | |
340 | return MC_DRV_ERR_INVALID_PARAMETER; | |
341 | } | |
15e8442f | 342 | LOG_I(" Opening %s", rootContFilePath.c_str()); |
cd9434cc T |
343 | |
344 | FILE *fs = fopen(rootContFilePath.c_str(), "rb"); | |
15e8442f | 345 | if (!fs) { |
cd9434cc T |
346 | LOG_W("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); |
347 | return MC_DRV_ERR_INVALID_DEVICE_FILE; | |
348 | } | |
15e8442f | 349 | readBytes = fread((char *)so, 1, *size, fs); |
cd9434cc T |
350 | fclose(fs); |
351 | ||
352 | if (readBytes > 0) { | |
15e8442f | 353 | *size = readBytes; |
cd9434cc T |
354 | return MC_DRV_OK; |
355 | } else { | |
356 | LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); | |
357 | return MC_DRV_ERR_INVALID_DEVICE_FILE; | |
358 | } | |
359 | } | |
360 | ||
361 | ||
362 | //------------------------------------------------------------------------------ | |
15e8442f | 363 | mcResult_t mcRegistryStoreSp(mcSpid_t spid, void *so, uint32_t size) |
cd9434cc | 364 | { |
cd9434cc T |
365 | if ((spid == 0) || (so == NULL) || size > 3 * MAX_SO_CONT_SIZE) { |
366 | LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); | |
367 | return MC_DRV_ERR_INVALID_PARAMETER; | |
368 | } | |
369 | ||
15e8442f JA |
370 | const string &spContFilePath = getSpContFilePath(spid); |
371 | LOG_I("store SP: %s", spContFilePath.c_str()); | |
cd9434cc T |
372 | |
373 | FILE *fs = fopen(spContFilePath.c_str(), "wb"); | |
15e8442f | 374 | if (!fs) { |
cd9434cc T |
375 | LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); |
376 | return MC_DRV_ERR_INVALID_DEVICE_FILE; | |
377 | } | |
15e8442f JA |
378 | fseek(fs, 0, SEEK_SET); |
379 | fwrite((char *)so, 1, size, fs); | |
cd9434cc T |
380 | fflush(fs); |
381 | fclose(fs); | |
382 | ||
383 | return MC_DRV_OK; | |
384 | } | |
385 | ||
386 | ||
387 | //------------------------------------------------------------------------------ | |
388 | mcResult_t mcRegistryReadSp(mcSpid_t spid, void *so, uint32_t *size) | |
389 | { | |
15e8442f | 390 | const string &spContFilePath = getSpContFilePath(spid); |
cd9434cc T |
391 | size_t readBytes; |
392 | if ((spid == 0) || (so == NULL)) { | |
393 | LOG_E("mcRegistry read So.Sp(SpId=0x%x) failed", spid); | |
394 | return MC_DRV_ERR_INVALID_PARAMETER; | |
395 | } | |
15e8442f | 396 | LOG_I(" Reading %s", spContFilePath.c_str()); |
cd9434cc T |
397 | |
398 | FILE *fs = fopen(spContFilePath.c_str(), "rb"); | |
15e8442f | 399 | if (!fs) { |
cd9434cc T |
400 | LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); |
401 | return MC_DRV_ERR_INVALID_DEVICE_FILE; | |
402 | } | |
15e8442f | 403 | readBytes = fread((char *)so, 1, *size, fs); |
cd9434cc T |
404 | fclose(fs); |
405 | ||
406 | if (readBytes > 0) { | |
15e8442f | 407 | *size = readBytes; |
cd9434cc T |
408 | return MC_DRV_OK; |
409 | } else { | |
410 | LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); | |
411 | return MC_DRV_ERR_INVALID_DEVICE_FILE; | |
412 | } | |
413 | } | |
414 | ||
415 | ||
416 | //------------------------------------------------------------------------------ | |
15e8442f | 417 | mcResult_t mcRegistryStoreTrustletCon(const mcUuid_t *uuid, const mcSpid_t spid, void *so, uint32_t size) |
cd9434cc | 418 | { |
cd9434cc T |
419 | if ((uuid == NULL) || (so == NULL) || size > 3 * MAX_SO_CONT_SIZE) { |
420 | LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); | |
421 | return MC_DRV_ERR_INVALID_PARAMETER; | |
422 | } | |
423 | ||
15e8442f JA |
424 | const string &tlContFilePath = getTlContFilePath(uuid, spid); |
425 | LOG_I("store TLc: %s", tlContFilePath.c_str()); | |
cd9434cc T |
426 | |
427 | FILE *fs = fopen(tlContFilePath.c_str(), "wb"); | |
15e8442f | 428 | if (!fs) { |
cd9434cc T |
429 | LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); |
430 | return MC_DRV_ERR_INVALID_DEVICE_FILE; | |
431 | } | |
15e8442f JA |
432 | fseek(fs, 0, SEEK_SET); |
433 | fwrite((char *)so, 1, size, fs); | |
cd9434cc T |
434 | fflush(fs); |
435 | fclose(fs); | |
436 | ||
437 | return MC_DRV_OK; | |
438 | } | |
439 | ||
440 | static uint32_t getAsUint32BE( | |
15e8442f | 441 | void *pValueUnaligned |
cd9434cc T |
442 | ) |
443 | { | |
15e8442f | 444 | uint8_t *p = (uint8_t *)pValueUnaligned; |
cd9434cc T |
445 | uint32_t val = p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24); |
446 | return val; | |
447 | } | |
448 | ||
15e8442f | 449 | mcResult_t mcRegistryStoreTABlob(mcSpid_t spid, void *blob, uint32_t size) |
cd9434cc | 450 | { |
15e8442f JA |
451 | |
452 | LOG_I("mcRegistryStoreTABlob started"); | |
cd9434cc T |
453 | |
454 | // Check blob size | |
455 | if (size < sizeof(mclfHeaderV24_t)) { | |
456 | LOG_E("RegistryStoreTABlob failed - TA blob length is less then header size"); | |
457 | return MC_DRV_ERR_INVALID_PARAMETER; | |
458 | } | |
459 | ||
15e8442f JA |
460 | mclfHeaderV24_t *header24 = (mclfHeaderV24_t *)blob; |
461 | mclfHeaderV2_t *header20 = (mclfHeaderV2_t *)blob; | |
cd9434cc T |
462 | |
463 | // Check header version | |
464 | if (header20->intro.version < MC_MAKE_VERSION(2, 4)) { | |
465 | LOG_E("RegistryStoreTABlob failed - TA blob header version is less than 2.4"); | |
466 | return MC_DRV_ERR_TA_HEADER_ERROR; | |
467 | } | |
468 | ||
469 | //Check GP version | |
470 | if (header24->gp_level != 1) { | |
471 | LOG_E("RegistryStoreTABlob failed - TA blob header gp_level is not equal to 1"); | |
472 | return MC_DRV_ERR_TA_HEADER_ERROR; | |
473 | } | |
474 | ||
15e8442f | 475 | TEEC_UUID uuid; |
cd9434cc T |
476 | switch (header20->serviceType) { |
477 | case SERVICE_TYPE_SYSTEM_TRUSTLET: { | |
478 | // Check spid | |
479 | if (spid != MC_SPID_SYSTEM) { | |
480 | LOG_E("RegistryStoreTABlob failed - SPID is not equal to %d for System TA", spid); | |
481 | return MC_DRV_ERR_INVALID_PARAMETER; | |
482 | } | |
483 | memcpy(&uuid, &header20->uuid, sizeof(mcUuid_t)); | |
484 | break; | |
485 | } | |
486 | case SERVICE_TYPE_SP_TRUSTLET: { | |
487 | // Check spid | |
488 | if (spid >= MC_SPID_SYSTEM) { | |
489 | LOG_E("RegistryStoreTABlob failed - SPID is equal to %u ", spid); | |
490 | return MC_DRV_ERR_INVALID_PARAMETER; | |
491 | } | |
492 | ||
15e8442f | 493 | uuid_attestation *pUa = (uuid_attestation *) & ((uint8_t *)blob)[header24->attestationOffset]; |
cd9434cc T |
494 | // Check attestation size |
495 | if ((header24->attestationOffset > size) && (header24->attestationOffset + getAsUint32BE(&pUa->size) > size)) { | |
496 | LOG_E("RegistryStoreTABlob failed - Attestation size is not correct"); | |
497 | return MC_DRV_ERR_TA_HEADER_ERROR; | |
498 | } | |
499 | ||
500 | // Check attestation size | |
501 | if (getAsUint32BE(&pUa->size) < sizeof(uuid_attestation)) { | |
15e8442f | 502 | LOG_E("RegistryStoreTABlob failed - Attestation size is equal to %d and is less then %d", getAsUint32BE(&pUa->size), sizeof(uuid_attestation)); |
cd9434cc T |
503 | return MC_DRV_ERR_TA_ATTESTATION_ERROR; |
504 | } | |
505 | ||
506 | // Check magic word | |
507 | if (memcmp(pUa->magic, MAGIC, AT_MAGIC_SIZE)) { | |
508 | LOG_E("RegistryStoreTABlob failed - Attestation magic word is not correct"); | |
509 | return MC_DRV_ERR_TA_ATTESTATION_ERROR; | |
510 | } | |
511 | ||
512 | // Check version | |
513 | if (getAsUint32BE(&pUa->version) != AT_VERSION) { | |
514 | LOG_E("RegistryStoreTABlob failed - Attestation version is equal to %08X. It has to be equal to %08X", getAsUint32BE(&pUa->version), AT_VERSION); | |
515 | return MC_DRV_ERR_TA_ATTESTATION_ERROR; | |
516 | } | |
517 | ||
518 | memcpy(&uuid, &pUa->uuid, sizeof(mcUuid_t)); | |
519 | break; | |
520 | } | |
521 | default: { | |
522 | return MC_DRV_ERR_INVALID_PARAMETER; | |
523 | } | |
524 | } | |
15e8442f | 525 | const string tlBinFilePath = getTABinFilePath((mcUuid_t *)&uuid); |
cd9434cc | 526 | |
15e8442f | 527 | LOG_I("Store TA blob at: %s", tlBinFilePath.c_str()); |
cd9434cc | 528 | |
15e8442f JA |
529 | FILE *fs = fopen(tlBinFilePath.c_str(), "wb"); |
530 | if (!fs) { | |
cd9434cc T |
531 | LOG_E("RegistryStoreTABlob failed - TA blob file open error: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); |
532 | return MC_DRV_ERR_INVALID_DEVICE_FILE; | |
533 | } | |
15e8442f | 534 | fseek(fs, 0, SEEK_SET); |
cd9434cc | 535 | fwrite(blob, 1, size, fs); |
cd9434cc T |
536 | fflush(fs); |
537 | fclose(fs); | |
538 | ||
539 | if (header20->serviceType == SERVICE_TYPE_SP_TRUSTLET) { | |
15e8442f | 540 | const string taspidFilePath = getTASpidFilePath((mcUuid_t *)&uuid); |
cd9434cc | 541 | |
15e8442f | 542 | LOG_I("Store spid file at: %s", taspidFilePath.c_str()); |
cd9434cc T |
543 | |
544 | FILE *fs = fopen(taspidFilePath.c_str(), "wb"); | |
15e8442f JA |
545 | if (!fs) { |
546 | //TODO: shouldn't we delete TA blob file ? | |
cd9434cc T |
547 | LOG_E("RegistryStoreTABlob failed - TA blob file open error: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); |
548 | return MC_DRV_ERR_INVALID_DEVICE_FILE; | |
549 | } | |
15e8442f | 550 | fseek(fs, 0, SEEK_SET); |
cd9434cc | 551 | fwrite(&spid, 1, sizeof(mcSpid_t), fs); |
cd9434cc T |
552 | fflush(fs); |
553 | fclose(fs); | |
554 | } | |
555 | return MC_DRV_OK; | |
556 | } | |
557 | ||
558 | //------------------------------------------------------------------------------ | |
559 | mcResult_t mcRegistryReadTrustletCon(const mcUuid_t *uuid, const mcSpid_t spid, void *so, uint32_t *size) | |
560 | { | |
cd9434cc T |
561 | if ((uuid == NULL) || (so == NULL)) { |
562 | LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); | |
563 | return MC_DRV_ERR_INVALID_PARAMETER; | |
564 | } | |
565 | size_t readBytes; | |
15e8442f JA |
566 | const string &tlContFilePath = getTlContFilePath(uuid, spid); |
567 | LOG_I("read TLc: %s", tlContFilePath.c_str()); | |
cd9434cc T |
568 | |
569 | FILE *fs = fopen(tlContFilePath.c_str(), "rb"); | |
15e8442f | 570 | if (!fs) { |
cd9434cc T |
571 | LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); |
572 | return MC_DRV_ERR_INVALID_DEVICE_FILE; | |
573 | } | |
15e8442f JA |
574 | fseek(fs, 0, SEEK_SET); |
575 | readBytes = fread((char *)so, 1, *size, fs); | |
cd9434cc T |
576 | fclose(fs); |
577 | ||
578 | if (readBytes > 0) { | |
15e8442f | 579 | *size = readBytes; |
cd9434cc T |
580 | return MC_DRV_OK; |
581 | } else { | |
582 | LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); | |
583 | return MC_DRV_ERR_INVALID_DEVICE_FILE; | |
584 | } | |
585 | } | |
586 | ||
587 | ||
588 | //------------------------------------------------------------------------------ | |
15e8442f | 589 | mcResult_t mcRegistryStoreData(void *so, uint32_t size) |
cd9434cc | 590 | { |
15e8442f | 591 | mcSoDataCont_t *dataCont = (mcSoDataCont_t *)so; |
cd9434cc T |
592 | |
593 | if (dataCont == NULL || size != sizeof(mcSoDataCont_t)) { | |
594 | LOG_E("mcRegistry store So.Data failed: %d", MC_DRV_ERR_INVALID_PARAMETER); | |
595 | return MC_DRV_ERR_INVALID_PARAMETER; | |
596 | } | |
15e8442f | 597 | string pathname, filename; |
cd9434cc T |
598 | |
599 | switch (dataCont->cont.type) { | |
600 | case CONT_TYPE_SPDATA: | |
601 | LOG_E("SPDATA not supported"); | |
602 | return MC_DRV_ERR_INVALID_PARAMETER; | |
603 | break; | |
604 | case CONT_TYPE_TLDATA: | |
605 | pathname = getTlDataPath(&dataCont->cont.uuid); | |
606 | filename = getTlDataFilePath(&dataCont->cont.uuid, dataCont->cont.pid); | |
607 | break; | |
608 | default: | |
609 | LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); | |
610 | return MC_DRV_ERR_INVALID_PARAMETER; | |
611 | } | |
612 | if (mkdir(pathname.c_str(), 0777) < 0) | |
613 | { | |
614 | LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); | |
615 | return MC_DRV_ERR_INVALID_PARAMETER; | |
616 | } | |
617 | ||
15e8442f | 618 | LOG_I("store DT: %s", filename.c_str()); |
cd9434cc T |
619 | |
620 | FILE *fs = fopen(filename.c_str(), "wb"); | |
15e8442f | 621 | if (!fs) { |
cd9434cc T |
622 | LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); |
623 | return MC_DRV_ERR_INVALID_DEVICE_FILE; | |
624 | } | |
15e8442f JA |
625 | fseek(fs, 0, SEEK_SET); |
626 | fwrite((char *)dataCont, 1, MC_SO_SIZE(dataCont->soHeader.plainLen, dataCont->soHeader.encryptedLen), fs); | |
cd9434cc T |
627 | fflush(fs); |
628 | fclose(fs); | |
629 | ||
630 | return MC_DRV_OK; | |
631 | } | |
632 | ||
633 | ||
634 | //------------------------------------------------------------------------------ | |
15e8442f | 635 | mcResult_t mcRegistryReadData(uint32_t context, const mcCid_t *cid, mcPid_t pid __unused, |
cd9434cc T |
636 | mcSoDataCont_t *so, uint32_t maxLen) |
637 | { | |
cd9434cc T |
638 | |
639 | if ((NULL == cid) || (NULL == so)) { | |
640 | LOG_E("mcRegistry read So.Data failed: %d", MC_DRV_ERR_INVALID_PARAMETER); | |
641 | return MC_DRV_ERR_INVALID_PARAMETER; | |
642 | } | |
15e8442f | 643 | string filename; |
cd9434cc T |
644 | switch (context) { |
645 | case 0: | |
646 | LOG_E("SPDATA not supported"); | |
647 | return MC_DRV_ERR_INVALID_PARAMETER; | |
648 | break; | |
649 | case 1: | |
650 | filename = getTlDataFilePath(&so->cont.uuid, so->cont.pid); | |
651 | break; | |
652 | default: | |
653 | LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); | |
654 | return MC_DRV_ERR_INVALID_PARAMETER; | |
655 | } | |
15e8442f | 656 | LOG_I("read DT: %s", filename.c_str()); |
cd9434cc T |
657 | |
658 | FILE *fs = fopen(filename.c_str(), "rb"); | |
15e8442f | 659 | if (!fs) { |
cd9434cc T |
660 | LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); |
661 | return MC_DRV_ERR_INVALID_DEVICE_FILE; | |
662 | } | |
15e8442f JA |
663 | fseek(fs, 0, SEEK_END); |
664 | uint32_t filesize = ftell(fs); | |
665 | if (maxLen < filesize) { | |
cd9434cc T |
666 | fclose(fs); |
667 | LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES); | |
668 | return MC_DRV_ERR_OUT_OF_RESOURCES; | |
669 | } | |
15e8442f JA |
670 | fseek(fs, 0, SEEK_SET); |
671 | char *p = (char *) so; | |
672 | if (fread(p, 1, sizeof(mcSoHeader_t), fs) != sizeof(mcSoHeader_t)) | |
673 | { | |
cd9434cc T |
674 | fclose(fs); |
675 | LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); | |
676 | return MC_DRV_ERR_INVALID_PARAMETER; | |
677 | } | |
cd9434cc | 678 | p += sizeof(mcSoHeader_t); |
15e8442f | 679 | if (fread(p, 1, MC_SO_SIZE(so->soHeader.plainLen, |
cd9434cc | 680 | so->soHeader.encryptedLen) |
15e8442f JA |
681 | - sizeof(mcSoHeader_t), fs) != |
682 | MC_SO_SIZE(so->soHeader.plainLen, so->soHeader.encryptedLen) | |
683 | - sizeof(mcSoHeader_t)) | |
684 | { | |
cd9434cc T |
685 | fclose(fs); |
686 | LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); | |
687 | return MC_DRV_ERR_INVALID_PARAMETER; | |
688 | } | |
cd9434cc T |
689 | fclose(fs); |
690 | ||
691 | return MC_DRV_OK; | |
692 | } | |
693 | ||
694 | ||
695 | //------------------------------------------------------------------------------ | |
15e8442f | 696 | static size_t getFileContent( |
cd9434cc T |
697 | const char *pPath, |
698 | uint8_t **ppContent) | |
699 | { | |
700 | FILE *pStream; | |
701 | long filesize; | |
702 | uint8_t *content = NULL; | |
cd9434cc T |
703 | |
704 | /* Open the file */ | |
705 | pStream = fopen(pPath, "rb"); | |
706 | if (pStream == NULL) { | |
707 | LOG_E("Error: Cannot open file: %s.", pPath); | |
708 | return 0; | |
709 | } | |
710 | ||
711 | if (fseek(pStream, 0L, SEEK_END) != 0) { | |
712 | LOG_E("Error: Cannot read file: %s.", pPath); | |
713 | goto error; | |
714 | } | |
715 | ||
716 | filesize = ftell(pStream); | |
717 | if (filesize < 0) { | |
718 | LOG_E("Error: Cannot get the file size: %s.", pPath); | |
719 | goto error; | |
720 | } | |
721 | ||
722 | if (filesize == 0) { | |
723 | LOG_E("Error: Empty file: %s.", pPath); | |
724 | goto error; | |
725 | } | |
726 | ||
727 | /* Set the file pointer at the beginning of the file */ | |
728 | if (fseek(pStream, 0L, SEEK_SET) != 0) { | |
729 | LOG_E("Error: Cannot read file: %s.", pPath); | |
730 | goto error; | |
731 | } | |
732 | ||
733 | /* Allocate a buffer for the content */ | |
15e8442f | 734 | content = (uint8_t *)malloc(filesize); |
cd9434cc T |
735 | if (content == NULL) { |
736 | LOG_E("Error: Cannot read file: Out of memory."); | |
737 | goto error; | |
738 | } | |
739 | ||
740 | /* Read data from the file into the buffer */ | |
15e8442f | 741 | if (fread(content, (size_t)filesize, 1, pStream) != 1) { |
cd9434cc T |
742 | LOG_E("Error: Cannot read file: %s.", pPath); |
743 | goto error; | |
744 | } | |
cd9434cc T |
745 | |
746 | /* Close the file */ | |
747 | fclose(pStream); | |
748 | *ppContent = content; | |
749 | ||
750 | /* Return number of bytes read */ | |
15e8442f | 751 | return (size_t)filesize; |
cd9434cc T |
752 | |
753 | error: | |
15e8442f JA |
754 | if (content != NULL) { |
755 | free(content); | |
cd9434cc T |
756 | } |
757 | fclose(pStream); | |
758 | return 0; | |
759 | } | |
760 | ||
761 | //------------------------------------------------------------------------------ | |
762 | static bool mcCheckUuid(const mcUuid_t *uuid, const char *filename) | |
763 | { | |
764 | uint8_t *pTAData = NULL; | |
765 | uint32_t nTASize; | |
766 | bool res; | |
767 | ||
768 | nTASize = getFileContent(filename, &pTAData); | |
769 | if (nTASize == 0) { | |
770 | LOG_E("err: Trusted Application not found."); | |
771 | return false; | |
772 | } | |
773 | ||
774 | // Check blob size | |
775 | if (nTASize < sizeof(mclfHeaderV24_t)) { | |
15e8442f JA |
776 | free(pTAData); |
777 | LOG_E("RegistryStoreTABlob failed - TA blob length is less then header size"); | |
cd9434cc T |
778 | return false; |
779 | } | |
780 | ||
15e8442f | 781 | mclfHeaderV2_t *header20 = (mclfHeaderV2_t *)pTAData; |
cd9434cc T |
782 | |
783 | // Check header version | |
784 | if (header20->intro.version < MC_MAKE_VERSION(2, 4)) { | |
15e8442f JA |
785 | free(pTAData); |
786 | LOG_E("RegistryStoreTABlob failed - TA blob header version is less than 2.4"); | |
cd9434cc T |
787 | return false; |
788 | } | |
789 | ||
15e8442f | 790 | // Check blob size |
cd9434cc T |
791 | if (memcmp(uuid, &header20->uuid, sizeof(mcUuid_t)) == 0) { |
792 | res = true; | |
793 | } else { | |
794 | res = false; | |
795 | } | |
796 | ||
15e8442f | 797 | free(pTAData); |
cd9434cc T |
798 | |
799 | return res; | |
800 | } | |
801 | ||
802 | //this function deletes all the files owned by a GP TA and stored in the tbase secure storage dir. | |
803 | //then it deletes GP TA folder. | |
15e8442f | 804 | static int CleanupGPTAStorage(const char *basename) |
cd9434cc T |
805 | { |
806 | DIR *dp; | |
807 | struct dirent *de; | |
808 | int e; | |
15e8442f JA |
809 | string TAPath = getTlRegistryPath()+"/TbStorage/"+ basename; |
810 | ||
cd9434cc T |
811 | if (NULL != (dp = opendir(TAPath.c_str()))) { |
812 | while (NULL != (de = readdir(dp))) { | |
813 | if (de->d_name[0] != '.') { | |
15e8442f JA |
814 | string dname = TAPath + "/" + string (de->d_name); |
815 | LOG_I("delete DT: %s", dname.c_str()); | |
cd9434cc T |
816 | if (0 != (e = remove(dname.c_str()))) { |
817 | LOG_E("remove UUID-files %s failed! error: %d", dname.c_str(), e); | |
818 | } | |
819 | } | |
820 | } | |
821 | if (dp) { | |
822 | closedir(dp); | |
823 | } | |
15e8442f | 824 | LOG_I("delete dir: %s", TAPath.c_str()); |
cd9434cc T |
825 | if (0 != (e = rmdir(TAPath.c_str()))) { |
826 | LOG_E("remove UUID-dir failed! errno: %d", e); | |
827 | return e; | |
828 | } | |
829 | } | |
830 | return MC_DRV_OK; | |
831 | } | |
832 | ||
15e8442f | 833 | static void deleteSPTA(const mcUuid_t *uuid, const mcSpid_t spid, bool checkUuid) |
cd9434cc T |
834 | { |
835 | DIR *dp; | |
836 | struct dirent *de; | |
837 | int e; | |
838 | ||
839 | // Delete TABIN and SPID files - we loop searching required spid file | |
15e8442f JA |
840 | string pathname = getRegistryPath(); |
841 | if (NULL != (dp = opendir(pathname.c_str()))) { | |
cd9434cc | 842 | while (NULL != (de = readdir(dp))) { |
15e8442f JA |
843 | string spidFile; |
844 | string tabinFile; | |
845 | string tabinUuid; | |
cd9434cc | 846 | size_t pch_dot, pch_slash; |
15e8442f | 847 | spidFile = pathname + '/' + string(de->d_name); |
cd9434cc | 848 | pch_dot = spidFile.find_last_of('.'); |
15e8442f | 849 | if (pch_dot == string::npos) continue; |
cd9434cc | 850 | pch_slash = spidFile.find_last_of('/'); |
15e8442f | 851 | if ((pch_slash != string::npos) && (pch_slash > pch_dot)) continue; |
cd9434cc T |
852 | if (spidFile.substr(pch_dot).compare(GP_TA_SPID_FILE_EXT) != 0) continue; |
853 | ||
854 | mcSpid_t curSpid = 0; | |
855 | ||
856 | int fd = open(spidFile.c_str(), O_RDONLY); | |
857 | if (fd != -1) { | |
858 | if (read(fd, &curSpid, sizeof(mcSpid_t))!=sizeof(mcSpid_t)) { | |
859 | curSpid = 0; | |
860 | } | |
861 | close(fd); | |
862 | } | |
863 | if (spid == curSpid) { | |
864 | tabinFile = spidFile.substr(0, pch_dot) + GP_TA_BIN_FILE_EXT; | |
15e8442f JA |
865 | if ((!checkUuid)||(mcCheckUuid(uuid, tabinFile.c_str()))) { |
866 | tabinUuid = spidFile.substr(0, pch_dot); | |
867 | if (0 != (e = CleanupGPTAStorage(tabinUuid.c_str()))){ | |
868 | LOG_E("cleanup TA Storage dir failed! errno: %d", e); | |
869 | //return MC_DRV_ERR_UNKNOWN; | |
870 | } | |
cd9434cc | 871 | if (0 != (e = remove(tabinFile.c_str()))) { |
15e8442f JA |
872 | LOG_E("remove TA file failed! errno: %d", e); |
873 | //return MC_DRV_ERR_UNKNOWN; | |
cd9434cc | 874 | } |
cd9434cc | 875 | if (0 != (e = remove(spidFile.c_str()))) { |
15e8442f JA |
876 | LOG_E("remove SPID file failed! errno: %d", e); |
877 | //return MC_DRV_ERR_UNKNOWN; | |
cd9434cc | 878 | } |
15e8442f | 879 | if (checkUuid) break; |
cd9434cc T |
880 | } |
881 | } | |
882 | } | |
883 | if (dp) { | |
884 | closedir(dp); | |
885 | } | |
15e8442f | 886 | |
cd9434cc T |
887 | } |
888 | } | |
889 | ||
890 | //------------------------------------------------------------------------------ | |
891 | mcResult_t mcRegistryCleanupTrustlet(const mcUuid_t *uuid, const mcSpid_t spid) | |
892 | { | |
893 | DIR *dp; | |
894 | struct dirent *de; | |
895 | int e; | |
896 | ||
897 | if (NULL == uuid) { | |
898 | LOG_E("mcRegistry cleanupTrustlet(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); | |
899 | return MC_DRV_ERR_INVALID_PARAMETER; | |
900 | } | |
901 | ||
902 | // Delete all TA related data | |
15e8442f | 903 | string pathname = getTlDataPath(uuid); |
cd9434cc T |
904 | if (NULL != (dp = opendir(pathname.c_str()))) { |
905 | while (NULL != (de = readdir(dp))) { | |
906 | if (de->d_name[0] != '.') { | |
15e8442f JA |
907 | string dname = pathname + "/" + string (de->d_name); |
908 | LOG_I("delete DT: %s", dname.c_str()); | |
cd9434cc T |
909 | if (0 != (e = remove(dname.c_str()))) { |
910 | LOG_E("remove UUID-data %s failed! error: %d", dname.c_str(), e); | |
911 | } | |
912 | } | |
913 | } | |
914 | if (dp) { | |
915 | closedir(dp); | |
916 | } | |
15e8442f | 917 | LOG_I("delete dir: %s", pathname.c_str()); |
cd9434cc T |
918 | if (0 != (e = rmdir(pathname.c_str()))) { |
919 | LOG_E("remove UUID-dir failed! errno: %d", e); | |
920 | return MC_DRV_ERR_UNKNOWN; | |
921 | } | |
922 | } | |
923 | ||
15e8442f JA |
924 | // Delete TA binary with the name uuid.tlbin |
925 | string tlBinFilePath = getTlBinFilePath(uuid); | |
926 | LOG_I("delete Tlb: %s", tlBinFilePath.c_str()); | |
927 | if (0 != (e = remove(tlBinFilePath.c_str()))) { | |
928 | LOG_E("remove Tlb failed! errno: %d", e); | |
929 | // return MC_DRV_ERR_UNKNOWN; // a trustlet-binary must not be present ! (registered but not usable) | |
cd9434cc T |
930 | } |
931 | ||
15e8442f JA |
932 | // Delete TABIN and SPID files - we loop searching required spid file |
933 | deleteSPTA(uuid,spid,true); | |
934 | ||
935 | string tlContFilePath = getTlContFilePath(uuid, spid); | |
936 | LOG_I("delete Tlc: %s", tlContFilePath.c_str()); | |
cd9434cc | 937 | if (0 != (e = remove(tlContFilePath.c_str()))) { |
15e8442f | 938 | LOG_E("remove Tlc failed! errno: %d", e); |
cd9434cc T |
939 | return MC_DRV_ERR_UNKNOWN; |
940 | } | |
cd9434cc T |
941 | return MC_DRV_OK; |
942 | } | |
943 | ||
944 | ||
945 | //------------------------------------------------------------------------------ | |
946 | mcResult_t mcRegistryCleanupSp(mcSpid_t spid) | |
947 | { | |
948 | DIR *dp; | |
949 | struct dirent *de; | |
950 | mcResult_t ret; | |
951 | mcSoSpCont_t data; | |
952 | uint32_t i, len; | |
953 | int e; | |
954 | ||
955 | if (0 == spid) { | |
956 | LOG_E("mcRegistry cleanupSP(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); | |
957 | return MC_DRV_ERR_INVALID_PARAMETER; | |
958 | } | |
959 | len = sizeof(mcSoSpCont_t); | |
960 | ret = mcRegistryReadSp(spid, &data, &len); | |
961 | if (MC_DRV_OK != ret || len != sizeof(mcSoSpCont_t)) { | |
962 | LOG_E("read SP->UUID aborted! Return code: %d", ret); | |
963 | return ret; | |
964 | } | |
965 | for (i = 0; (i < MC_CONT_CHILDREN_COUNT) && (ret == MC_DRV_OK); i++) { | |
15e8442f | 966 | if (0 != strncmp((const char *) & (data.cont.children[i]), (const char *)&MC_UUID_FREE, sizeof(mcUuid_t))) { |
cd9434cc T |
967 | ret = mcRegistryCleanupTrustlet(&(data.cont.children[i]), spid); |
968 | } | |
969 | } | |
970 | if (MC_DRV_OK != ret) { | |
971 | LOG_E("delete SP->UUID failed! Return code: %d", ret); | |
972 | return ret; | |
973 | } | |
974 | ||
15e8442f JA |
975 | // Delete remaining TABIN and SPID files |
976 | deleteSPTA(NULL,spid,false); | |
977 | ||
978 | string pathname = getSpDataPath(spid); | |
cd9434cc T |
979 | |
980 | if (NULL != (dp = opendir(pathname.c_str()))) { | |
981 | while (NULL != (de = readdir(dp))) { | |
982 | if (de->d_name[0] != '.') { | |
15e8442f JA |
983 | string dname = pathname + "/" + string (de->d_name); |
984 | LOG_I("delete DT: %s", dname.c_str()); | |
cd9434cc T |
985 | if (0 != (e = remove(dname.c_str()))) { |
986 | LOG_E("remove SPID-data %s failed! error: %d", dname.c_str(), e); | |
987 | } | |
988 | } | |
989 | } | |
990 | if (dp) { | |
991 | closedir(dp); | |
992 | } | |
15e8442f | 993 | LOG_I("delete dir: %s", pathname.c_str()); |
cd9434cc T |
994 | if (0 != (e = rmdir(pathname.c_str()))) { |
995 | LOG_E("remove SPID-dir failed! error: %d", e); | |
996 | return MC_DRV_ERR_UNKNOWN; | |
997 | } | |
998 | } | |
15e8442f JA |
999 | string spContFilePath = getSpContFilePath(spid); |
1000 | LOG_I("delete Sp: %s", spContFilePath.c_str()); | |
cd9434cc T |
1001 | if (0 != (e = remove(spContFilePath.c_str()))) { |
1002 | LOG_E("remove SP failed! error: %d", e); | |
1003 | return MC_DRV_ERR_UNKNOWN; | |
1004 | } | |
1005 | return MC_DRV_OK; | |
1006 | } | |
1007 | ||
1008 | ||
1009 | //------------------------------------------------------------------------------ | |
1010 | mcResult_t mcRegistryCleanupRoot(void) | |
1011 | { | |
1012 | mcResult_t ret; | |
1013 | mcSoRootCont_t data; | |
1014 | uint32_t i, len; | |
1015 | int e; | |
1016 | len = sizeof(mcSoRootCont_t); | |
1017 | ret = mcRegistryReadRoot(&data, &len); | |
1018 | if (MC_DRV_OK != ret || len != sizeof(mcSoRootCont_t)) { | |
1019 | LOG_E("read Root aborted! Return code: %d", ret); | |
1020 | return ret; | |
1021 | } | |
1022 | for (i = 0; (i < MC_CONT_CHILDREN_COUNT) && (ret == MC_DRV_OK); i++) { | |
1023 | mcSpid_t spid = data.cont.children[i]; | |
1024 | if (spid != MC_SPID_FREE) { | |
1025 | ret = mcRegistryCleanupSp(spid); | |
1026 | if (MC_DRV_OK != ret) { | |
1027 | LOG_E("Cleanup SP failed! Return code: %d", ret); | |
1028 | return ret; | |
1029 | } | |
1030 | } | |
1031 | } | |
1032 | ||
15e8442f JA |
1033 | string rootContFilePath = getRootContFilePath(); |
1034 | LOG_I("Delete root: %s", rootContFilePath.c_str()); | |
cd9434cc T |
1035 | if (0 != (e = remove(rootContFilePath.c_str()))) { |
1036 | LOG_E("Delete root failed! error: %d", e); | |
1037 | return MC_DRV_ERR_UNKNOWN; | |
1038 | } | |
1039 | return MC_DRV_OK; | |
1040 | } | |
1041 | ||
1042 | //------------------------------------------------------------------------------ | |
15e8442f JA |
1043 | regObject_t *mcRegistryMemGetServiceBlob(mcSpid_t spid, void *trustlet, uint32_t tlSize) |
1044 | { | |
1045 | regObject_t *regobj = NULL; | |
1046 | ||
1047 | // Ensure that a UUID is provided. | |
1048 | if (NULL == trustlet) { | |
1049 | LOG_E("No trustlet buffer given"); | |
1050 | return NULL; | |
1051 | } | |
1052 | ||
1053 | // Check service blob size. | |
1054 | if (tlSize > MAX_TL_SIZE ) { | |
1055 | LOG_E("mcRegistryMemGetServiceBlob() failed: service blob too big: %d", tlSize); | |
1056 | return NULL; | |
1057 | } | |
1058 | ||
1059 | mclfIntro_t *pIntro = (mclfIntro_t *)trustlet; | |
1060 | // Check TL magic value. | |
1061 | if (pIntro->magic != MC_SERVICE_HEADER_MAGIC_BE) { | |
1062 | LOG_E("mcRegistryMemGetServiceBlob() failed: wrong header magic value: %d", pIntro->magic); | |
1063 | return NULL; | |
1064 | } | |
1065 | ||
1066 | // Get service type. | |
1067 | mclfHeaderV2_t *pHeader = (mclfHeaderV2_t *)trustlet; | |
1068 | #ifndef NDEBUG | |
1069 | { | |
1070 | const char *service_types[] = { | |
1071 | "illegal", "Driver", "Trustlet", "System Trustlet" | |
1072 | }; | |
1073 | int serviceType_safe = pHeader->serviceType > SERVICE_TYPE_SYSTEM_TRUSTLET ? SERVICE_TYPE_ILLEGAL : pHeader->serviceType; | |
1074 | LOG_I(" Service is a %s (service type %d)", service_types[serviceType_safe], pHeader->serviceType); | |
1075 | } | |
1076 | #endif | |
1077 | ||
1078 | LOG_I(" Trustlet text %u data %u ", pHeader->text.len, pHeader->data.len); | |
1079 | ||
1080 | // If loadable driver or system trustlet. | |
1081 | if (pHeader->serviceType == SERVICE_TYPE_DRIVER || pHeader->serviceType == SERVICE_TYPE_SYSTEM_TRUSTLET) { | |
1082 | // Take trustlet blob 'as is'. | |
1083 | if (NULL == (regobj = (regObject_t *) (malloc(sizeof(regObject_t) + tlSize)))) { | |
1084 | LOG_E("mcRegistryMemGetServiceBlob() failed: Out of memory"); | |
1085 | return NULL; | |
1086 | } | |
1087 | regobj->len = tlSize; | |
1088 | regobj->tlStartOffset = 0; | |
1089 | memcpy((char *)regobj->value, trustlet, tlSize); | |
1090 | // If user trustlet. | |
1091 | } else if (pHeader->serviceType == SERVICE_TYPE_SP_TRUSTLET) { | |
1092 | // Take trustlet blob and append root, sp, and tl container. | |
1093 | size_t regObjValueSize = tlSize + sizeof(mcBlobLenInfo_t) + 3 * MAX_SO_CONT_SIZE; | |
1094 | ||
1095 | // Prepare registry object. | |
1096 | if (NULL == (regobj = (regObject_t *) malloc(sizeof(regObject_t) + regObjValueSize))) { | |
1097 | LOG_E("mcRegistryMemGetServiceBlob() failed: Out of memory"); | |
1098 | return NULL; | |
1099 | } | |
1100 | regobj->len = regObjValueSize; | |
1101 | regobj->tlStartOffset = sizeof(mcBlobLenInfo_t); | |
1102 | uint8_t *p = regobj->value; | |
1103 | ||
1104 | // Reserve space for the blob length structure | |
1105 | mcBlobLenInfo_ptr lenInfo = (mcBlobLenInfo_ptr)p; | |
1106 | lenInfo->magic = MC_TLBLOBLEN_MAGIC; | |
1107 | p += sizeof(mcBlobLenInfo_t); | |
1108 | // Fill in trustlet blob after the len info | |
1109 | memcpy(p, trustlet, tlSize); | |
1110 | p += tlSize; | |
1111 | ||
1112 | // Final registry object value looks like this: | |
1113 | // | |
1114 | // +---------------+---------------------------+-----------+---------+---------+ | |
1115 | // | Blob Len Info | TL-Header TL-Code TL-Data | Root Cont | SP Cont | TL Cont | | |
1116 | // +---------------+---------------------------+-----------+-------------------+ | |
1117 | // /------ Trustlet BLOB ------/ | |
1118 | // | |
1119 | // /------------------ regobj->header.len -------------------------------------/ | |
1120 | ||
1121 | // start at the end of the trustlet blob | |
1122 | mcResult_t ret; | |
1123 | do { | |
1124 | uint32_t soTltContSize = MAX_SO_CONT_SIZE; | |
1125 | uint32_t len; | |
1126 | ||
1127 | // Fill in root container. | |
1128 | len = sizeof(mcSoRootCont_t); | |
1129 | if (MC_DRV_OK != (ret = mcRegistryReadRoot(p, &len))) { | |
1130 | break; | |
1131 | } | |
1132 | lenInfo->rootContBlobSize = len; | |
1133 | p += len; | |
1134 | ||
1135 | // Fill in SP container. | |
1136 | len = sizeof(mcSoSpCont_t); | |
1137 | if (MC_DRV_OK != (ret = mcRegistryReadSp(spid, p, &len))) { | |
1138 | break; | |
1139 | } | |
1140 | lenInfo->spContBlobSize = len; | |
1141 | p += len; | |
1142 | ||
1143 | // Fill in TLT Container | |
1144 | // We know exactly how much space is left in the buffer | |
1145 | soTltContSize = regObjValueSize - tlSize + sizeof(mcBlobLenInfo_t) | |
1146 | - lenInfo->spContBlobSize - lenInfo->rootContBlobSize; | |
1147 | if (MC_DRV_OK != (ret = mcRegistryReadTrustletCon(&pHeader->uuid, spid, p, &soTltContSize))) { | |
1148 | break; | |
1149 | } | |
1150 | lenInfo->tlContBlobSize = soTltContSize; | |
1151 | LOG_I(" Trustlet container %u bytes loaded", soTltContSize); | |
1152 | // Depending on the trustlet container size we decide which structure to use | |
1153 | // Unfortunate design but it should have to do for now | |
1154 | if (soTltContSize == sizeof(mcSoTltCont_2_0_t)) { | |
1155 | LOG_I(" Using 2.0 trustlet container"); | |
1156 | } else if (soTltContSize == sizeof(mcSoTltCont_2_1_t)) { | |
1157 | LOG_I(" Using 2.1 trustlet container"); | |
1158 | } else { | |
1159 | LOG_E("Trustlet container has unknown size"); | |
1160 | break; | |
1161 | } | |
1162 | } while (false); | |
1163 | ||
1164 | if (MC_DRV_OK != ret) { | |
1165 | LOG_E("mcRegistryMemGetServiceBlob() failed: Error code: %d", ret); | |
1166 | free(regobj); | |
1167 | return NULL; | |
1168 | } | |
1169 | // Now we know the sizes for all containers so set the correct size | |
1170 | regobj->len = sizeof(mcBlobLenInfo_t) + tlSize + | |
1171 | lenInfo->rootContBlobSize + | |
1172 | lenInfo->spContBlobSize + | |
1173 | lenInfo->tlContBlobSize; | |
1174 | // Any other service type. | |
1175 | } else { | |
1176 | LOG_E("mcRegistryMemGetServiceBlob() failed: Unsupported service type %u", pHeader->serviceType); | |
1177 | } | |
1178 | return regobj; | |
1179 | } | |
1180 | ||
1181 | ||
1182 | //------------------------------------------------------------------------------ | |
1183 | regObject_t *mcRegistryFileGetServiceBlob(const char *trustlet, mcSpid_t spid) | |
1184 | { | |
1185 | struct stat sb; | |
1186 | regObject_t *regobj = NULL; | |
1187 | void *buffer; | |
1188 | ||
1189 | // Ensure that a file name is provided. | |
1190 | if (trustlet == NULL) { | |
1191 | LOG_E("No file given"); | |
1192 | return NULL; | |
1193 | } | |
1194 | ||
1195 | int fd = open(trustlet, O_RDONLY); | |
1196 | if (fd == -1) { | |
1197 | LOG_E("Cannot open %s", trustlet); | |
1198 | return NULL; | |
1199 | } | |
1200 | ||
1201 | if (fstat(fd, &sb) == -1) { | |
1202 | LOG_E("mcRegistryFileGetServiceBlob() failed: Cound't get file size"); | |
1203 | goto error; | |
1204 | } | |
1205 | ||
1206 | buffer = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); | |
1207 | if (buffer == MAP_FAILED) { | |
1208 | LOG_E("mcRegistryFileGetServiceBlob(): Failed to map file to memory"); | |
1209 | goto error; | |
1210 | } | |
1211 | ||
1212 | regobj = mcRegistryMemGetServiceBlob(spid, buffer, sb.st_size); | |
1213 | ||
1214 | // We don't actually care if either of them fails but should still print warnings | |
1215 | if (munmap(buffer, sb.st_size)) { | |
1216 | LOG_E("mcRegistryFileGetServiceBlob(): Failed to unmap memory"); | |
1217 | } | |
1218 | ||
1219 | error: | |
1220 | if (close(fd)) { | |
1221 | LOG_E("mcRegistryFileGetServiceBlob(): Failed to close file %s", trustlet); | |
1222 | } | |
1223 | ||
1224 | return regobj; | |
1225 | } | |
1226 | ||
1227 | ||
1228 | //------------------------------------------------------------------------------ | |
1229 | regObject_t *mcRegistryGetServiceBlob(const mcUuid_t *uuid, bool isGpUuid) | |
cd9434cc T |
1230 | { |
1231 | // Ensure that a UUID is provided. | |
1232 | if (NULL == uuid) { | |
1233 | LOG_E("No UUID given"); | |
15e8442f | 1234 | return NULL; |
cd9434cc T |
1235 | } |
1236 | ||
15e8442f JA |
1237 | // Open service blob file. |
1238 | string tlBinFilePath; | |
cd9434cc | 1239 | if (isGpUuid) { |
15e8442f | 1240 | tlBinFilePath = getTABinFilePath(uuid); |
cd9434cc | 1241 | } else { |
15e8442f | 1242 | tlBinFilePath = getTlBinFilePath(uuid); |
cd9434cc | 1243 | } |
15e8442f | 1244 | LOG_I("Loading %s", tlBinFilePath.c_str()); |
cd9434cc | 1245 | |
15e8442f | 1246 | mcSpid_t spid = 0; |
cd9434cc | 1247 | if (isGpUuid) { |
15e8442f | 1248 | string taspidFilePath = getTASpidFilePath(uuid); |
cd9434cc | 1249 | int fd = open(taspidFilePath.c_str(), O_RDONLY); |
15e8442f JA |
1250 | if (fd == -1) { |
1251 | // This can be ok for System TAs | |
1252 | //LOG_ERRNO("open"); | |
1253 | //LOG_E("Cannot open %s", taspidFilePath.c_str()); | |
1254 | //return NULL; | |
1255 | } else { | |
1256 | if (read(fd, &spid, sizeof(mcSpid_t))!=sizeof(mcSpid_t)) { | |
1257 | close(fd); | |
1258 | return NULL; | |
cd9434cc | 1259 | } |
15e8442f | 1260 | close(fd); |
cd9434cc T |
1261 | } |
1262 | } | |
1263 | ||
15e8442f JA |
1264 | return mcRegistryFileGetServiceBlob(tlBinFilePath.c_str(), spid); |
1265 | } | |
1266 | ||
1267 | //------------------------------------------------------------------------------ | |
1268 | regObject_t *mcRegistryGetDriverBlob(const char *filename) | |
1269 | { | |
1270 | regObject_t *regobj = mcRegistryFileGetServiceBlob(filename, 0); | |
1271 | ||
1272 | if (regobj == NULL) { | |
1273 | LOG_E("mcRegistryGetDriverBlob() failed"); | |
1274 | return NULL; | |
1275 | } | |
1276 | ||
1277 | // Get service type. | |
1278 | mclfHeaderV2_t *pHeader = (mclfHeaderV2_t *)regobj->value; | |
1279 | ||
1280 | // If file is not a driver we are not interested | |
1281 | if (pHeader->serviceType != SERVICE_TYPE_DRIVER) { | |
1282 | LOG_E("mcRegistryGetDriverBlob() failed: Unsupported service type %u", pHeader->serviceType); | |
1283 | pHeader = NULL; | |
1284 | free(regobj); | |
1285 | regobj = NULL; | |
1286 | } | |
1287 | ||
1288 | return regobj; | |
cd9434cc | 1289 | } |
15e8442f JA |
1290 | |
1291 | /** @} */ |