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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 875 static const string getRootContFilePath() 876 { 877 return getRegistryPath() + "/" + ROOT_FILE_NAME; 878 } 879 880 //------------------------------------------------------------------------------ 881 static const string getSpDataPath(mcSpid_t spid) 882 { 883 return getRegistryPath() + "/" + uint32ToString(spid); 884 } 885 886 //------------------------------------------------------------------------------ 887 static const string getSpContFilePath(mcSpid_t spid) 888 { 889 return getRegistryPath() + "/" + uint32ToString(spid) + SP_CONT_FILE_EXT; 890 } 891 892 //------------------------------------------------------------------------------ 893 static const string getTlContFilePath(const mcUuid_t *uuid) 894 { 895 return getRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid)) + TL_CONT_FILE_EXT; 896 } 897 898 //------------------------------------------------------------------------------ 899 static const string getTlDataPath(const mcUuid_t *uuid) 900 { 901 return getRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid)); 902 } 903 904 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 911 static const string getTlBinFilePath(const mcUuid_t *uuid) 912 { 913 return getRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid)) + TL_BIN_FILE_EXT; 914 } 915 916 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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