Home | History | Annotate | Download | only in Registry
      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