1 /** Mobicore Driver Registry.
2 *
3 * Implements the MobiCore driver registry which maintains trustlets.
4 *
5 * @file
6 * @ingroup MCD_MCDIMPL_DAEMON_REG
7 * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior
19 * written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
22 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include "MobiCoreRegistry.h"
35 #include <stdlib.h>
36 #include <dirent.h>
37 #include <stdio.h>
38 #include <sys/stat.h>
39 #include <assert.h>
40 #include <string>
41 #include <cstring>
42 #include <cstddef>
43 #include "mcLoadFormat.h"
44 #include "mcSpid.h"
45 #include "mcVersionHelper.h"
46
47 #include "log.h"
48
49 MC_CHECK_DATA_OBJECT_VERSION(MCLF, 2, 0);
50 MC_CHECK_DATA_OBJECT_VERSION(CONTAINER, 2, 0);
51
52 // Asserts expression at compile-time (to be used within a function body).
53 #define ASSERT_STATIC(e) do { enum { assert_static__ = 1 / (e) }; } while (0)
54
55 using namespace std;
56
57 static const string MC_REGISTRY_DEFAULT_PATH = "/data/app/mcRegistry";
58 static const string AUTH_TOKEN_FILE_NAME = "00000000.authtokcont";
59 static const string ROOT_FILE_NAME = "00000000.rootcont";
60 static const string SP_CONT_FILE_EXT = ".spcont";
61 static const string TL_CONT_FILE_EXT = ".tlcont";
62 static const string TL_BIN_FILE_EXT = ".tlbin";
63 static const string DATA_CONT_FILE_EXT = ".datacont";
64
65 static const string ENV_MC_REGISTRY_PATH = "MC_REGISTRY_PATH";
66 static const string ENV_MC_REGISTRY_FALLBACK_PATH = "MC_REGISTRY_FALLBACK_PATH";
67 static const string ENV_MC_AUTH_TOKEN_PATH = "MC_AUTH_TOKEN_PATH";
68
69 static const string getRegistryPath();
70 static const string getAuthTokenFilePath();
71 static const string getRootContFilePath();
72 static const string getSpDataPath(mcSpid_t spid);
73 static const string getSpContFilePath(mcSpid_t spid);
74 static const string getTlContFilePath(const mcUuid_t *uuid);
75 static const string getTlDataPath(const mcUuid_t *uuid);
76 static const string getTlDataFilePath(const mcUuid_t *uuid, mcPid_t pid);
77 static const string getTlBinFilePath(const mcUuid_t *uuid);
78
79 static const string uint32ToString(mcSpid_t spid);
80 static const string byteArrayToString(const void *bytes, size_t elems);
81 static bool doesDirExist(const char *path);
82
83 //------------------------------------------------------------------------------
mcRegistryStoreAuthToken(const mcSoAuthTokenCont_t * so)84 mcResult_t mcRegistryStoreAuthToken(
85 const mcSoAuthTokenCont_t *so
86 )
87 {
88 if (NULL == so) {
89 LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
90 return MC_DRV_ERR_INVALID_PARAMETER;
91 }
92 if (CONT_TYPE_SOC != so->coSoc.type) {
93 LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
94 return MC_DRV_ERR_INVALID_PARAMETER;
95 }
96 const string &authTokenFilePath = getAuthTokenFilePath();
97 LOG_I("store AuthToken: %s", authTokenFilePath.c_str());
98
99 FILE *fs = fopen(authTokenFilePath.c_str(), "wb");
100 if (!fs) {
101 LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
102 return MC_DRV_ERR_INVALID_DEVICE_FILE;
103 }
104 fseek(fs, 0, SEEK_SET);
105 fwrite((char *)so, 1, sizeof(mcSoAuthTokenCont_t), fs);
106 fflush(fs);
107 fclose(fs);
108
109 return MC_DRV_OK;
110 }
111
112
113 //------------------------------------------------------------------------------
mcRegistryReadAuthToken(mcSoAuthTokenCont_t * so)114 mcResult_t mcRegistryReadAuthToken(
115 mcSoAuthTokenCont_t *so
116 )
117 {
118 if (NULL == so) {
119 LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
120 return MC_DRV_ERR_INVALID_PARAMETER;
121 }
122 const string &authTokenFilePath = getAuthTokenFilePath();
123 LOG_I("read AuthToken: %s", authTokenFilePath.c_str());
124
125 FILE *fs = fopen(authTokenFilePath.c_str(), "rb");
126 if (!fs) {
127 LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
128 return MC_DRV_ERR_INVALID_DEVICE_FILE;
129 }
130 fseek(fs, 0, SEEK_END);
131 int32_t filesize = ftell(fs);
132 if (sizeof(mcSoAuthTokenCont_t) != filesize) {
133 fclose(fs);
134 LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
135 return MC_DRV_ERR_OUT_OF_RESOURCES;
136 }
137 fseek(fs, 0, SEEK_SET);
138 fread((char *)so, 1, sizeof(mcSoAuthTokenCont_t), fs);
139 fclose(fs);
140
141 return MC_DRV_OK;
142 }
143
144 //------------------------------------------------------------------------------
mcRegistryDeleteAuthToken(void)145 mcResult_t mcRegistryDeleteAuthToken(
146 void
147 )
148 {
149 remove(getAuthTokenFilePath().c_str());
150 // @TODO: is return to check ?
151 return MC_DRV_OK;
152 }
153
154
155 //------------------------------------------------------------------------------
mcRegistryStoreRoot(const mcSoRootCont_t * so)156 mcResult_t mcRegistryStoreRoot(
157 const mcSoRootCont_t *so
158 )
159 {
160 if (NULL == so) {
161 LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
162 return MC_DRV_ERR_INVALID_PARAMETER;
163 }
164 if (CONT_TYPE_ROOT != so->cont.type) {
165 LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
166 return MC_DRV_ERR_INVALID_PARAMETER;
167 }
168 const string &rootContFilePath = getRootContFilePath();
169 LOG_I("store Root: %s", rootContFilePath.c_str());
170
171 FILE *fs = fopen(rootContFilePath.c_str(), "wb");
172 if (!fs) {
173 LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
174 return MC_DRV_ERR_INVALID_DEVICE_FILE;
175 }
176 fseek(fs, 0, SEEK_SET);
177 fwrite((char *)so, 1, sizeof(mcSoRootCont_t), fs);
178 fflush(fs);
179 fclose(fs);
180
181 return MC_DRV_OK;
182 }
183
184
185 //------------------------------------------------------------------------------
mcRegistryReadRoot(mcSoRootCont_t * so)186 mcResult_t mcRegistryReadRoot(
187 mcSoRootCont_t *so
188 )
189 {
190 if (NULL == so) {
191 LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
192 return MC_DRV_ERR_INVALID_PARAMETER;
193 }
194 const string &rootContFilePath = getRootContFilePath();
195 LOG_I("read Root: %s", rootContFilePath.c_str());
196
197 FILE *fs = fopen(rootContFilePath.c_str(), "rb");
198 if (!fs) {
199 LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
200 return MC_DRV_ERR_INVALID_DEVICE_FILE;
201 }
202 fseek(fs, 0, SEEK_END);
203 int32_t filesize = ftell(fs);
204 if (sizeof(mcSoRootCont_t) != filesize) {
205 fclose(fs);
206 LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
207 return MC_DRV_ERR_OUT_OF_RESOURCES;
208 }
209 fseek(fs, 0, SEEK_SET);
210 fread((char *)so, 1, sizeof(mcSoRootCont_t), fs);
211 fclose(fs);
212
213 return MC_DRV_OK;
214 }
215
216
217 //------------------------------------------------------------------------------
mcRegistryStoreSp(mcSpid_t spid,const mcSoSpCont_t * so)218 mcResult_t mcRegistryStoreSp(
219 mcSpid_t spid,
220 const mcSoSpCont_t *so
221 )
222 {
223 if ((0 == spid) || (NULL == so)) {
224 LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
225 return MC_DRV_ERR_INVALID_PARAMETER;
226 }
227 if (CONT_TYPE_SP != so->cont.type) {
228 LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
229 return MC_DRV_ERR_INVALID_PARAMETER;
230 }
231 const string &spContFilePath = getSpContFilePath(spid);
232 LOG_I("store SP: %s", spContFilePath.c_str());
233
234 FILE *fs = fopen(spContFilePath.c_str(), "wb");
235 if (!fs) {
236 LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
237 return MC_DRV_ERR_INVALID_DEVICE_FILE;
238 }
239 fseek(fs, 0, SEEK_SET);
240 fwrite((char *)so, 1, sizeof(mcSoSpCont_t), fs);
241 fflush(fs);
242 fclose(fs);
243
244 return MC_DRV_OK;
245 }
246
247
248 //------------------------------------------------------------------------------
mcRegistryReadSp(mcSpid_t spid,mcSoSpCont_t * so)249 mcResult_t mcRegistryReadSp(
250 mcSpid_t spid,
251 mcSoSpCont_t *so
252 )
253 {
254 if ((0 == spid) || (NULL == so)) {
255 LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
256 return MC_DRV_ERR_INVALID_PARAMETER;
257 }
258 const string &spContFilePath = getSpContFilePath(spid);
259 LOG_I("read SP: %s", spContFilePath.c_str());
260
261 FILE *fs = fopen(spContFilePath.c_str(), "rb");
262 if (!fs) {
263 LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
264 return MC_DRV_ERR_INVALID_DEVICE_FILE;
265 }
266 fseek(fs, 0, SEEK_END);
267 int32_t filesize = ftell(fs);
268 if (sizeof(mcSoSpCont_t) != filesize) {
269 fclose(fs);
270 LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
271 return MC_DRV_ERR_OUT_OF_RESOURCES;
272 }
273 fseek(fs, 0, SEEK_SET);
274 fread((char *)so, 1, sizeof(mcSoSpCont_t), fs);
275 fclose(fs);
276
277 return MC_DRV_OK;
278 }
279
280
281 //------------------------------------------------------------------------------
mcRegistryStoreTrustletCon(const mcUuid_t * uuid,const mcSoTltCont_t * so)282 mcResult_t mcRegistryStoreTrustletCon(
283 const mcUuid_t *uuid,
284 const mcSoTltCont_t *so
285 )
286 {
287 if ((NULL == uuid) || (NULL == so)) {
288 LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
289 return MC_DRV_ERR_INVALID_PARAMETER;
290 }
291 if (CONT_TYPE_TLCON != so->cont.type) {
292 LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
293 return MC_DRV_ERR_INVALID_PARAMETER;
294 }
295 const string &tlContFilePath = getTlContFilePath(uuid);
296 LOG_I("store TLc: %s", tlContFilePath.c_str());
297
298 FILE *fs = fopen(tlContFilePath.c_str(), "wb");
299 if (!fs) {
300 LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
301 return MC_DRV_ERR_INVALID_DEVICE_FILE;
302 }
303 fseek(fs, 0, SEEK_SET);
304 fwrite((char *)so, 1, sizeof(mcSoTltCont_t), fs);
305 fflush(fs);
306 fclose(fs);
307
308 return MC_DRV_OK;
309 }
310
311
312 //------------------------------------------------------------------------------
mcRegistryReadTrustletCon(const mcUuid_t * uuid,mcSoTltCont_t * so)313 mcResult_t mcRegistryReadTrustletCon(
314 const mcUuid_t *uuid,
315 mcSoTltCont_t *so
316 )
317 {
318 if ((NULL == uuid) || (NULL == so)) {
319 LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
320 return MC_DRV_ERR_INVALID_PARAMETER;
321 }
322 const string &tlContFilePath = getTlContFilePath(uuid);
323 LOG_I("read TLc: %s", tlContFilePath.c_str());
324
325 FILE *fs = fopen(tlContFilePath.c_str(), "rb");
326 if (!fs) {
327 LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
328 return MC_DRV_ERR_INVALID_DEVICE_FILE;
329 }
330 fseek(fs, 0, SEEK_END);
331 int32_t filesize = ftell(fs);
332 if (sizeof(mcSoTltCont_t) != filesize) {
333 fclose(fs);
334 LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d. Size=%i, expected=%i", MC_DRV_ERR_OUT_OF_RESOURCES, filesize, sizeof(mcSoTltCont_t));
335 return MC_DRV_ERR_OUT_OF_RESOURCES;
336 }
337 fseek(fs, 0, SEEK_SET);
338 fread((char *)so, 1, sizeof(mcSoTltCont_t), fs);
339 fclose(fs);
340
341 return MC_DRV_OK;
342 }
343
344
345 //------------------------------------------------------------------------------
mcRegistryStoreData(const mcSoDataCont_t * so)346 mcResult_t mcRegistryStoreData(
347 const mcSoDataCont_t *so
348 )
349 {
350 if (NULL == so) {
351 LOG_E("mcRegistry store So.Data failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
352 return MC_DRV_ERR_INVALID_PARAMETER;
353 }
354 string pathname, filename;
355
356 switch (so->cont.type) {
357 case CONT_TYPE_SPDATA:
358 LOG_E("SPDATA not supported");
359 return MC_DRV_ERR_INVALID_PARAMETER;
360 break;
361 case CONT_TYPE_TLDATA:
362 pathname = getTlDataPath(&so->cont.uuid);
363 filename = getTlDataFilePath(&so->cont.uuid, so->cont.pid);
364 break;
365 default:
366 LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
367 return MC_DRV_ERR_INVALID_PARAMETER;
368 }
369 mkdir(pathname.c_str(), 0777);
370
371 LOG_I("store DT: %s", filename.c_str());
372
373 FILE *fs = fopen(filename.c_str(), "wb");
374 if (!fs) {
375 LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
376 return MC_DRV_ERR_INVALID_DEVICE_FILE;
377 }
378 fseek(fs, 0, SEEK_SET);
379 fwrite((char *)so, 1, MC_SO_SIZE(so->soHeader.plainLen, so->soHeader.encryptedLen), fs);
380 fflush(fs);
381 fclose(fs);
382
383 return MC_DRV_OK;
384 }
385
386
387 //------------------------------------------------------------------------------
mcRegistryReadData(uint32_t context,const mcCid_t * cid,mcPid_t pid,mcSoDataCont_t * so,uint32_t maxLen)388 mcResult_t mcRegistryReadData(
389 uint32_t context,
390 const mcCid_t *cid,
391 mcPid_t pid,
392 mcSoDataCont_t *so,
393 uint32_t maxLen
394 )
395 {
396 if ((NULL == cid) || (NULL == so)) {
397 LOG_E("mcRegistry read So.Data failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
398 return MC_DRV_ERR_INVALID_PARAMETER;
399 }
400 string filename;
401 switch (context) {
402 case 0:
403 LOG_E("SPDATA not supported");
404 return MC_DRV_ERR_INVALID_PARAMETER;
405 break;
406 case 1:
407 filename = getTlDataFilePath(&so->cont.uuid, so->cont.pid);
408 break;
409 default:
410 LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
411 return MC_DRV_ERR_INVALID_PARAMETER;
412 }
413 LOG_I("read DT: %s", filename.c_str());
414
415 FILE *fs = fopen(filename.c_str(), "rb");
416 if (!fs) {
417 LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
418 return MC_DRV_ERR_INVALID_DEVICE_FILE;
419 }
420 fseek(fs, 0, SEEK_END);
421 uint32_t filesize = ftell(fs);
422 if (maxLen < filesize) {
423 fclose(fs);
424 LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
425 return MC_DRV_ERR_OUT_OF_RESOURCES;
426 }
427 fseek(fs, 0, SEEK_SET);
428 char *p = (char *) so;
429 fread(p, 1, sizeof(mcSoHeader_t), fs);
430 p += sizeof(mcSoHeader_t);
431 fread(p, 1, MC_SO_SIZE(so->soHeader.plainLen, so->soHeader.encryptedLen) - sizeof(mcSoHeader_t), fs);
432 fclose(fs);
433
434 return MC_DRV_OK;
435 }
436
437
438 //------------------------------------------------------------------------------
mcRegistryCleanupTrustlet(const mcUuid_t * uuid)439 mcResult_t mcRegistryCleanupTrustlet(
440 const mcUuid_t *uuid
441 )
442 {
443 DIR *dp;
444 struct dirent *de;
445 int e;
446
447 if (NULL == uuid) {
448 LOG_E("mcRegistry cleanupTrustlet(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
449 return MC_DRV_ERR_INVALID_PARAMETER;
450 }
451 string pathname = getTlDataPath(uuid);
452 if (NULL != (dp = opendir(pathname.c_str()))) {
453 while (NULL != (de = readdir(dp))) {
454 if (de->d_name[0] != '.') {
455 string dname = pathname + "/" + string (de->d_name);
456 LOG_I("delete DT: %s", dname.c_str());
457 if (0 != (e = remove(dname.c_str()))) {
458 LOG_E("remove UUID-data %s failed! error: %d", dname.c_str(), e);
459 return MC_DRV_ERR_UNKNOWN;
460 }
461 }
462 }
463 LOG_I("delete dir: %s", pathname.c_str());
464 if (0 != (e = rmdir(pathname.c_str()))) {
465 LOG_E("remove UUID-dir failed! errno: %d", e);
466 return MC_DRV_ERR_UNKNOWN;
467 }
468 }
469 string tlBinFilePath = getTlBinFilePath(uuid);
470 LOG_I("delete Tlb: %s", tlBinFilePath.c_str());
471 if (0 != (e = remove(tlBinFilePath.c_str()))) {
472 LOG_E("remove Tlb failed! errno: %d", e);
473 // return MC_DRV_ERR_UNKNOWN; // a trustlet-binary must not be present ! (registered but not usable)
474 }
475 string tlContFilePath = getTlContFilePath(uuid);
476 LOG_I("delete Tlc: %s", tlContFilePath.c_str());
477 if (0 != (e = remove(tlContFilePath.c_str()))) {
478 LOG_E("remove Tlc failed! errno: %d", e);
479 return MC_DRV_ERR_UNKNOWN;
480 }
481 return MC_DRV_OK;
482 }
483
484
485 //------------------------------------------------------------------------------
mcRegistryCleanupSp(mcSpid_t spid)486 mcResult_t mcRegistryCleanupSp(
487 mcSpid_t spid
488 )
489 {
490 mcResult_t ret;
491 mcSoSpCont_t data;
492 uint32_t i;
493 DIR *dp;
494 struct dirent *de;
495 int e;
496
497 if (0 == spid) {
498 LOG_E("mcRegistry cleanupSP(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
499 return MC_DRV_ERR_INVALID_PARAMETER;
500 }
501 ret = mcRegistryReadSp(spid, &data);
502 if (MC_DRV_OK != ret) {
503 LOG_E("read SP->UUID aborted! Return code: %d", ret);
504 return ret;
505 }
506 for (i = 0; (i < MC_CONT_CHILDREN_COUNT) && (ret == MC_DRV_OK); i++) {
507 if (0 != strncmp((const char *) & (data.cont.children[i]), (const char *)&MC_UUID_FREE, sizeof(mcUuid_t))) {
508 ret = mcRegistryCleanupTrustlet(&(data.cont.children[i]));
509 }
510 }
511 if (MC_DRV_OK != ret) {
512 LOG_E("delete SP->UUID failed! Return code: %d", ret);
513 return ret;
514 }
515 string pathname = getSpDataPath(spid);
516
517 if (NULL != (dp = opendir(pathname.c_str()))) {
518 while (NULL != (de = readdir(dp))) {
519 if (de->d_name[0] != '.') {
520 string dname = pathname + "/" + string (de->d_name);
521 LOG_I("delete DT: %s", dname.c_str());
522 if (0 != (e = remove(dname.c_str()))) {
523 LOG_E("remove SPID-data %s failed! error: %d", dname.c_str(), e);
524 return MC_DRV_ERR_UNKNOWN;
525 }
526 }
527 }
528 LOG_I("delete dir: %s", pathname.c_str());
529 if (0 != (e = rmdir(pathname.c_str()))) {
530 LOG_E("remove SPID-dir failed! error: %d", e);
531 return MC_DRV_ERR_UNKNOWN;
532 }
533 }
534 string spContFilePath = getSpContFilePath(spid);
535 LOG_I("delete Sp: %s", spContFilePath.c_str());
536 if (0 != (e = remove(spContFilePath.c_str()))) {
537 LOG_E("remove SP failed! error: %d", e);
538 return MC_DRV_ERR_UNKNOWN;
539 }
540 return MC_DRV_OK;
541 }
542
543
544 //------------------------------------------------------------------------------
mcRegistryCleanupRoot(void)545 mcResult_t mcRegistryCleanupRoot(void)
546 {
547 mcResult_t ret;
548 mcSoRootCont_t data;
549 uint32_t i;
550 int e;
551
552 ret = mcRegistryReadRoot(&data);
553 if (MC_DRV_OK != ret) {
554 LOG_E("read Root aborted! Return code: %d", ret);
555 return ret;
556 }
557 for (i = 0; (i < MC_CONT_CHILDREN_COUNT) && (ret == MC_DRV_OK); i++) {
558 mcSpid_t spid = data.cont.children[i];
559 if (spid != MC_SPID_FREE) {
560 ret = mcRegistryCleanupSp(spid);
561 if (MC_DRV_OK != ret) {
562 LOG_E("Cleanup SP failed! Return code: %d", ret);
563 return ret;
564 }
565 }
566 }
567
568 string rootContFilePath = getRootContFilePath();
569 LOG_I("Delete root: %s", rootContFilePath.c_str());
570 if (0 != (e = remove(rootContFilePath.c_str()))) {
571 LOG_E("Delete root failed! error: %d", e);
572 return MC_DRV_ERR_UNKNOWN;
573 }
574 return MC_DRV_OK;
575 }
576
577
578 //------------------------------------------------------------------------------
mcRegistryGetServiceBlob(const mcUuid_t * uuid)579 regObject_t *mcRegistryGetServiceBlob(
580 const mcUuid_t *uuid
581 )
582 {
583 regObject_t *regobj = NULL;
584
585 // Ensure that a UUID is provided.
586 if (NULL == uuid) {
587 LOG_E("No UUID given");
588 return NULL;
589 }
590
591 // Open service blob file.
592 string tlBinFilePath = getTlBinFilePath(uuid);
593 LOG_I(" Loading %s", tlBinFilePath.c_str());
594
595 FILE *fs = fopen(tlBinFilePath.c_str(), "rb");
596 if (!fs) {
597 LOG_E("Cannot open %s", tlBinFilePath.c_str());
598 return NULL;
599 }
600
601 // Determine and check service blob size.
602 fseek(fs, 0, SEEK_END);
603 int32_t tlSize = ftell(fs);
604 fseek(fs, 0, SEEK_SET);
605 if (MAX_TL_SIZE < tlSize) {
606 LOG_E("mcRegistryGetServiceBlob() failed: service blob too big: %d", tlSize);
607 return NULL;
608 }
609
610 // Check TL magic value.
611 fseek(fs, offsetof(mclfIntro_t, magic), SEEK_SET);
612 uint32_t magic;
613 fread((char *)&magic, 1, sizeof(magic), fs);
614 if (magic != MC_SERVICE_HEADER_MAGIC_BE) {
615 fclose(fs);
616 LOG_E("mcRegistryGetServiceBlob() failed: wrong header magic value: %d", magic);
617 return NULL;
618 }
619
620 // Check header version.
621 fseek(fs, offsetof(mclfIntro_t, version), SEEK_SET);
622 uint32_t version;
623 fread((char *)&version, 1, sizeof(version), fs);
624
625 char *msg;
626 if (!checkVersionOkDataObjectMCLF(version, &msg)) {
627 fclose(fs);
628 LOG_E("%s", msg);
629 return NULL;
630 }
631
632 // Get service type.
633 fseek(fs, offsetof(mclfHeaderV2_t, serviceType), SEEK_SET);
634 serviceType_t serviceType;
635 fread((char *)&serviceType, 1, sizeof(serviceType), fs);
636 fseek(fs, 0, SEEK_SET);
637
638 #ifndef NDEBUG
639 {
640 const char *service_types[] = {
641 "illegal", "Driver", "Trustlet", "System Trustlet"
642 };
643 int serviceType_safe = serviceType > SERVICE_TYPE_SYSTEM_TRUSTLET ? SERVICE_TYPE_ILLEGAL : serviceType;
644 LOG_I(" Service is a %s (service type %d)", service_types[serviceType_safe], serviceType);
645 }
646 #endif
647
648 // If loadable driver or system trustlet.
649 if (SERVICE_TYPE_DRIVER == serviceType || SERVICE_TYPE_SYSTEM_TRUSTLET == serviceType) {
650 // Take trustlet blob 'as is'.
651 if (NULL == (regobj = (regObject_t *) (malloc(sizeof(regObject_t) + tlSize)))) {
652 fclose(fs);
653 LOG_E("mcRegistryGetServiceBlob() failed: Out of memory");
654 return NULL;
655 }
656 regobj->len = tlSize;
657 fread((char *)regobj->value, 1, tlSize, fs);
658 fclose(fs);
659 // If user trustlet.
660 } else if (SERVICE_TYPE_SP_TRUSTLET == serviceType) {
661 // Take trustlet blob and append root, sp, and tl container.
662 size_t regObjValueSize = tlSize + sizeof(mcSoContainerPath_t);
663
664 // Prepare registry object.
665 if (NULL == (regobj = (regObject_t *) malloc(sizeof(regObject_t) + regObjValueSize))) {
666 fclose(fs);
667 LOG_E("mcRegistryGetServiceBlob() failed: Out of memory");
668 return NULL;
669 }
670 regobj->len = regObjValueSize;
671
672 // Read and fill in trustlet blob at beginning.
673 fread((char *)regobj->value, 1, tlSize, fs);
674 fclose(fs);
675
676 // Goto end of allocated space and fill in tl container, sp container,
677 // and root container from back to front. Final registry object value
678 // looks like this:
679 //
680 // +---------------------------+-----------+---------+---------+
681 // | TL-Header TL-Code TL-Data | Root Cont | SP Cont | TL Cont |
682 // +---------------------------+-----------+-------------------+
683 // /------ Trustlet BLOB ------/
684 //
685 // /------------------ regobj->header.len ---------------------/
686
687 uint8_t *p = regobj->value + regobj->len;
688 mcResult_t ret;
689 do {
690 char *msg;
691
692 // Fill in TL container.
693 p -= sizeof(mcSoTltCont_t);
694 mcSoTltCont_t *soTlt = (mcSoTltCont_t *)p;
695 if (MC_DRV_OK != (ret = mcRegistryReadTrustletCon(uuid, soTlt))) {
696 break;
697 }
698 mcTltCont_t *tltCont = &soTlt->cont;
699 if (!checkVersionOkDataObjectCONTAINER(tltCont->version, &msg)) {
700 LOG_E("Tlt container %s", msg);
701 ret = MC_DRV_ERR_CONTAINER_VERSION;
702 break;
703 }
704
705 // Fill in SP container.
706 mcSpid_t spid = tltCont->parent;
707 p -= sizeof(mcSoSpCont_t);
708 mcSoSpCont_t *soSp = (mcSoSpCont_t *)p;
709 if (MC_DRV_OK != (ret = mcRegistryReadSp(spid, soSp))) {
710 break;
711 }
712 mcSpCont_t *spCont = &soSp->cont;
713 if (!checkVersionOkDataObjectCONTAINER(spCont->version, &msg)) {
714 LOG_E("SP container %s", msg);
715 ret = MC_DRV_ERR_CONTAINER_VERSION;
716 break;
717 }
718
719 // Fill in root container.
720 p -= sizeof(mcSoRootCont_t);
721 mcSoRootCont_t *soRoot = (mcSoRootCont_t *)p;
722 if (MC_DRV_OK != (ret = mcRegistryReadRoot(soRoot))) {
723 break;
724 }
725 mcRootCont_t *rootCont = &soRoot->cont;
726 if (!checkVersionOkDataObjectCONTAINER(rootCont->version, &msg)) {
727 LOG_E("Root container %s", msg);
728 ret = MC_DRV_ERR_CONTAINER_VERSION;
729 break;
730 }
731
732 // Ensure order of elements in registry object value.
733 assert(p - tlSize - sizeof(regObject_t) == (uint8_t *)regobj);
734 } while (false);
735
736 if (MC_DRV_OK != ret) {
737 LOG_E("mcRegistryGetServiceBlob() failed: Error code: %d", ret);
738 free(regobj);
739 return NULL;
740 }
741 // Any other service type.
742 } else {
743 fclose(fs);
744 LOG_E("mcRegistryGetServiceBlob() failed: Unsupported service type %u", serviceType);
745 }
746
747 return regobj;
748 }
749
750 //------------------------------------------------------------------------------
mcRegistryGetDriverBlob(const char * driverFilename)751 regObject_t *mcRegistryGetDriverBlob(
752 const char *driverFilename
753 )
754 {
755 regObject_t *regobj = NULL;
756
757 // Open service blob file.
758 FILE *fs = fopen(driverFilename, "rb");
759 if (!fs) {
760 LOG_E("mcRegistryGetDriverBlob() failed: cannot open %s", driverFilename);
761 return NULL;
762 }
763
764 // Determine and check service blob size.
765 fseek(fs, 0, SEEK_END);
766 int32_t tlSize = ftell(fs);
767 fseek(fs, 0, SEEK_SET);
768 if (MAX_TL_SIZE < tlSize) {
769 LOG_E("mcRegistryGetDriverBlob() failed: service blob too big: %d", tlSize);
770 fclose(fs);
771 return NULL;
772 }
773
774 // Check TL magic value.
775 fseek(fs, offsetof(mclfIntro_t, magic), SEEK_SET);
776 uint32_t magic;
777 fread((char *)&magic, 1, sizeof(magic), fs);
778 if (magic != MC_SERVICE_HEADER_MAGIC_BE) {
779 LOG_E("mcRegistryGetDriverBlob() failed: wrong header magic value: %d", magic);
780 fclose(fs);
781 return NULL;
782 }
783
784 // Check header version.
785 fseek(fs, offsetof(mclfIntro_t, version), SEEK_SET);
786 uint32_t version;
787 fread((char *)&version, 1, sizeof(version), fs);
788
789 char *msg;
790 if (!checkVersionOkDataObjectMCLF(version, &msg)) {
791 LOG_E("%s", msg);
792 fclose(fs);
793 return NULL;
794 }
795
796 // Get service type.
797 fseek(fs, offsetof(mclfHeaderV2_t, serviceType), SEEK_SET);
798 serviceType_t serviceType;
799 fread((char *)&serviceType, 1, sizeof(serviceType), fs);
800 fseek(fs, 0, SEEK_SET);
801
802 LOG_I("mcRegistryGetDriverBlob() Service is of type: %d", serviceType);
803
804 // If loadable driver or system trustlet.
805 if (SERVICE_TYPE_DRIVER == serviceType) {
806 // Take trustlet blob 'as is'.
807 if (NULL == (regobj = (regObject_t *) (malloc(sizeof(regObject_t) + tlSize)))) {
808 LOG_E("mcRegistryGetDriverBlob() failed: Out of memory");
809 fclose(fs);
810 return NULL;
811 }
812 regobj->len = tlSize;
813 fread((char *)regobj->value, 1, tlSize, fs);
814 // Otherwise we are not interested
815 } else {
816 LOG_E("mcRegistryGetServiceBlob() failed: Unsupported service type %u", serviceType);
817 }
818
819 fclose(fs);
820
821 return regobj;
822 }
823
824 //------------------------------------------------------------------------------
getRegistryPath()825 static const string getRegistryPath()
826 {
827 const char *path;
828 string registryPath;
829
830 // First, attempt to use regular registry environment variable.
831 path = getenv(ENV_MC_REGISTRY_PATH.c_str());
832 if (doesDirExist(path)) {
833 LOG_I("getRegistryPath(): Using MC_REGISTRY_PATH %s", path);
834 registryPath = path;
835 } else {
836 // Second, attempt to use fallback registry environment variable.
837 path = getenv(ENV_MC_REGISTRY_FALLBACK_PATH.c_str());
838 if (doesDirExist(path)) {
839 LOG_I("getRegistryPath(): Using MC_REGISTRY_FALLBACK_PATH %s", path);
840 registryPath = path;
841 }
842 }
843
844 // As a last resort, use the default registry path.
845 if (registryPath.length() == 0) {
846 registryPath = MC_REGISTRY_DEFAULT_PATH;
847 LOG_I(" Using default registry path %s", registryPath.c_str());
848 }
849
850 assert(registryPath.length() != 0);
851
852 return registryPath;
853 }
854
855 //------------------------------------------------------------------------------
getAuthTokenFilePath()856 static const string getAuthTokenFilePath()
857 {
858 const char *path;
859 string authTokenPath;
860
861 // First, attempt to use regular auth token path environment variable.
862 path = getenv(ENV_MC_AUTH_TOKEN_PATH.c_str());
863 if (doesDirExist(path)) {
864 LOG_I("getAuthTokenFilePath(): Using MC_AUTH_TOKEN_PATH %s", path);
865 authTokenPath = path;
866 } else {
867 authTokenPath = getRegistryPath();
868 LOG_I("getAuthTokenFilePath(): Using path %s", authTokenPath.c_str());
869 }
870
871 return authTokenPath + "/" + AUTH_TOKEN_FILE_NAME;
872 }
873
874 //------------------------------------------------------------------------------
getRootContFilePath()875 static const string getRootContFilePath()
876 {
877 return getRegistryPath() + "/" + ROOT_FILE_NAME;
878 }
879
880 //------------------------------------------------------------------------------
getSpDataPath(mcSpid_t spid)881 static const string getSpDataPath(mcSpid_t spid)
882 {
883 return getRegistryPath() + "/" + uint32ToString(spid);
884 }
885
886 //------------------------------------------------------------------------------
getSpContFilePath(mcSpid_t spid)887 static const string getSpContFilePath(mcSpid_t spid)
888 {
889 return getRegistryPath() + "/" + uint32ToString(spid) + SP_CONT_FILE_EXT;
890 }
891
892 //------------------------------------------------------------------------------
getTlContFilePath(const mcUuid_t * uuid)893 static const string getTlContFilePath(const mcUuid_t *uuid)
894 {
895 return getRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid)) + TL_CONT_FILE_EXT;
896 }
897
898 //------------------------------------------------------------------------------
getTlDataPath(const mcUuid_t * uuid)899 static const string getTlDataPath(const mcUuid_t *uuid)
900 {
901 return getRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid));
902 }
903
904 //------------------------------------------------------------------------------
getTlDataFilePath(const mcUuid_t * uuid,mcPid_t pid)905 static const string getTlDataFilePath(const mcUuid_t *uuid, mcPid_t pid)
906 {
907 return getTlDataPath(uuid) + "/" + uint32ToString(pid.data) + DATA_CONT_FILE_EXT;
908 }
909
910 //------------------------------------------------------------------------------
getTlBinFilePath(const mcUuid_t * uuid)911 static const string getTlBinFilePath(const mcUuid_t *uuid)
912 {
913 return getRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid)) + TL_BIN_FILE_EXT;
914 }
915
916 //------------------------------------------------------------------------------
byteArrayToString(const void * bytes,size_t elems)917 static const string byteArrayToString(const void *bytes, size_t elems)
918 {
919 char hx[elems * 2 + 1];
920
921 for (size_t i = 0; i < elems; i++) {
922 sprintf(&hx[i * 2], "%02x", ((uint8_t *)bytes)[i]);
923 }
924 return string(hx);
925 }
926
927 //------------------------------------------------------------------------------
uint32ToString(uint32_t value)928 static const string uint32ToString(
929 uint32_t value
930 )
931 {
932 char hx[sizeof(uint32_t) * 2 + 1];
933 uint32_t i;
934
935 for (i = 0; i < (2 * sizeof(value)); i++) {
936 hx[i] = (value >> (28 - (i * 4))) & 0x0F;
937 if (hx[i] > 9) {
938 hx[i] = (hx[i] - 9) | 0x40;
939 } else {
940 hx[i] |= 0x30;
941 }
942 }
943 hx[i] = '\0';
944 return string(hx);
945 }
946
947 //------------------------------------------------------------------------------
doesDirExist(const char * path)948 static bool doesDirExist(const char *path)
949 {
950 struct stat ss;
951 if (path != NULL && stat(path, &ss) == 0 && S_ISDIR(ss.st_mode)) {
952 return true;
953 }
954 return false;
955 }
956
957
958 /** @} */
959