diff options
Diffstat (limited to 'mobicore/MobiCoreDriverLib/Registry/PrivateRegistry.cpp')
-rw-r--r-- | mobicore/MobiCoreDriverLib/Registry/PrivateRegistry.cpp | 1492 |
1 files changed, 1492 insertions, 0 deletions
diff --git a/mobicore/MobiCoreDriverLib/Registry/PrivateRegistry.cpp b/mobicore/MobiCoreDriverLib/Registry/PrivateRegistry.cpp new file mode 100644 index 0000000..f51571b --- /dev/null +++ b/mobicore/MobiCoreDriverLib/Registry/PrivateRegistry.cpp @@ -0,0 +1,1492 @@ +/* + * Copyright (c) 2013-2014 TRUSTONIC LIMITED + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the TRUSTONIC LIMITED nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** Mobicore Driver Registry. + * + * Implements the MobiCore driver registry which maintains trustlets. + * + * @file + * @ingroup MCD_MCDIMPL_DAEMON_REG + */ +#include <stdlib.h> +#include <dirent.h> +#include <stdio.h> +#include <sys/stat.h> +#include <assert.h> +#include <string.h> +#include <string> +#include <cstring> +#include <cstddef> +#include <sys/mman.h> +#include <errno.h> +#include <fcntl.h> +#include <libgen.h> + +#include "mcLoadFormat.h" +#include "mcSpid.h" +#include "mcVersionHelper.h" + +#include "PrivateRegistry.h" +#include "MobiCoreRegistry.h" + +#include "uuid_attestation.h" + +#include "log.h" + +/** Maximum size of a trustlet in bytes. */ +#define MAX_TL_SIZE (1 * 1024 * 1024) +/** Maximum size of a shared object container in bytes. */ +#define MAX_SO_CONT_SIZE (512) + +#define MC_REGISTRY_ALL 0 +#define MC_REGISTRY_WRITABLE 1 + +#define MC_REGISTRY_SYSTEM_PATH "/system/app/mcRegistry" +#define MC_REGISTRY_DATA_PATH "/data/app/mcRegistry" +#define AUTH_TOKEN_FILE_NAME "00000000.authtokcont" +#define AUTH_TOKEN_FILE_NAME_BACKUP_SUFFIX ".backup" +#define ENV_MC_AUTH_TOKEN_PATH "MC_AUTH_TOKEN_PATH" +#define ROOT_FILE_NAME "00000000.rootcont" +#define SP_CONT_FILE_EXT ".spcont" +#define TL_CONT_FILE_EXT ".tlcont" +#define DATA_CONT_FILE_EXT ".datacont" +#define TL_BIN_FILE_EXT ".tlbin" +#define GP_TA_BIN_FILE_EXT ".tabin" +#define GP_TA_SPID_FILE_EXT ".spid" + +using namespace std; + +//------------------------------------------------------------------------------ +static string byteArrayToString(const void *bytes, size_t elems) +{ + char hx[elems * 2 + 1]; + + for (size_t i = 0; i < elems; i++) { + sprintf(&hx[i * 2], "%02x", ((uint8_t *)bytes)[i]); + } + return string(hx); +} + +//------------------------------------------------------------------------------ +static string uint32ToString(uint32_t value) +{ + char hx[8 + 1]; + snprintf(hx, sizeof(hx), "%08X", value); + string str(hx); + return string(str.rbegin(), str.rend()); +} + +//------------------------------------------------------------------------------ +static bool doesDirExist(const char *path) +{ + struct stat ss; + if (path != NULL && stat(path, &ss) == 0 && S_ISDIR(ss.st_mode)) { + return true; + } + return false; +} + +//------------------------------------------------------------------------------ +string getTbStoragePath() +{ + return MC_REGISTRY_DATA_PATH "/TbStorage"; +} + +//------------------------------------------------------------------------------ +static string getAuthTokenFilePath() +{ + const char *path; + string authTokenPath; + + // First, attempt to use regular auth token path environment variable. + path = getenv(ENV_MC_AUTH_TOKEN_PATH); + if (doesDirExist(path)) { + LOG_I("getAuthTokenFilePath(): Using MC_AUTH_TOKEN_PATH %s", path); + authTokenPath = path; + } else { + authTokenPath = MC_REGISTRY_DATA_PATH; + LOG_I("getAuthTokenFilePath(): Using path %s", authTokenPath.c_str()); + } + + return authTokenPath + "/" + AUTH_TOKEN_FILE_NAME; +} + +//------------------------------------------------------------------------------ +static string getAuthTokenFilePathBackup() +{ + return getAuthTokenFilePath() + AUTH_TOKEN_FILE_NAME_BACKUP_SUFFIX; +} + +//------------------------------------------------------------------------------ +static string getRootContFilePath() +{ + return MC_REGISTRY_DATA_PATH "/" ROOT_FILE_NAME; +} + +//------------------------------------------------------------------------------ +static string getSpDataPath(mcSpid_t spid) +{ + return MC_REGISTRY_DATA_PATH "/" + uint32ToString(spid); +} + +//------------------------------------------------------------------------------ +static string getSpContFilePath(mcSpid_t spid) +{ + return MC_REGISTRY_DATA_PATH "/" + uint32ToString(spid) + SP_CONT_FILE_EXT; +} + +//------------------------------------------------------------------------------ +static string getTlContFilePath(const mcUuid_t *uuid, const mcSpid_t spid) +{ + return MC_REGISTRY_DATA_PATH "/" + byteArrayToString(uuid, sizeof(*uuid)) + + "." + uint32ToString(spid) + TL_CONT_FILE_EXT; +} + +//------------------------------------------------------------------------------ +static string getTlDataPath(const mcUuid_t *uuid) +{ + return MC_REGISTRY_DATA_PATH "/" + byteArrayToString(uuid, sizeof(*uuid)); +} + +//------------------------------------------------------------------------------ +static string getTlDataFilePath(const mcUuid_t *uuid, mcPid_t pid) +{ + return getTlDataPath(uuid) + "/" + uint32ToString(pid.data) + DATA_CONT_FILE_EXT; +} + +//------------------------------------------------------------------------------ +static string getTlBinFilePath(const mcUuid_t *uuid, int registry) +{ + string path_ro_registry = MC_REGISTRY_SYSTEM_PATH"/" + byteArrayToString(uuid, sizeof(*uuid)) + TL_BIN_FILE_EXT; + string path_rw_registry = MC_REGISTRY_DATA_PATH"/" + byteArrayToString(uuid, sizeof(*uuid)) + TL_BIN_FILE_EXT; + + if (registry == MC_REGISTRY_ALL) { + struct stat tmp; + if (stat(path_ro_registry.c_str(), &tmp) == 0) { + return path_ro_registry; + } + } + return path_rw_registry; +} + +//------------------------------------------------------------------------------ +static string getTABinFilePath(const mcUuid_t *uuid, int registry) +{ + string path_ro_registry = MC_REGISTRY_SYSTEM_PATH"/" + byteArrayToString(uuid, sizeof(*uuid)) + GP_TA_BIN_FILE_EXT; + string path_rw_registry = MC_REGISTRY_DATA_PATH"/" + byteArrayToString(uuid, sizeof(*uuid)) + GP_TA_BIN_FILE_EXT; + + if (registry == MC_REGISTRY_ALL) { + struct stat tmp; + if (stat(path_ro_registry.c_str(), &tmp) == 0) { + return path_ro_registry; + } + } + return path_rw_registry; +} + +//------------------------------------------------------------------------------ +static string getTASpidFilePath(const mcUuid_t *uuid, int registry) +{ + string path_ro_registry = MC_REGISTRY_SYSTEM_PATH"/" + byteArrayToString(uuid, sizeof(*uuid)) + GP_TA_SPID_FILE_EXT; + string path_rw_registry = MC_REGISTRY_DATA_PATH"/" + byteArrayToString(uuid, sizeof(*uuid)) + GP_TA_SPID_FILE_EXT; + + if (registry == MC_REGISTRY_ALL) { + struct stat tmp; + if (stat(path_ro_registry.c_str(), &tmp) == 0) { + return path_ro_registry; + } + } + return path_rw_registry; +} + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryStoreAuthToken(void *so, uint32_t size) +{ + int res = 0; + if (so == NULL || size > 3 * MAX_SO_CONT_SIZE) { + LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + const string &authTokenFilePath = getAuthTokenFilePath(); + LOG_I("store AuthToken: %s", authTokenFilePath.c_str()); + + FILE *fs = fopen(authTokenFilePath.c_str(), "wb"); + if (fs==NULL) { + LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + res = fseek(fs, 0, SEEK_SET); + if (res!=0) { + LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + fwrite((char *)so, 1, size, fs); + if (ferror(fs)) { + LOG_E("mcRegistry store So.Soc failed %d", MC_DRV_ERR_OUT_OF_RESOURCES); + fclose(fs); + return MC_DRV_ERR_OUT_OF_RESOURCES; + } + fflush(fs); + fclose(fs); + + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryReadAuthToken(mcSoAuthTokenCont_t *so) +{ + int res = 0; + if (NULL == so) { + LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + const string &authTokenFilePath = getAuthTokenFilePath(); + LOG_I("read AuthToken: %s", authTokenFilePath.c_str()); + + FILE *fs = fopen(authTokenFilePath.c_str(), "rb"); + if (fs==NULL) { + LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + res = fseek(fs, 0, SEEK_END); + if (res!=0) { + LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + int32_t filesize = ftell(fs); + // We ensure that mcSoAuthTokenCont_t matches with filesize, as ferror (during fread operation) can't + // handle the case where mcSoAuthTokenCont_t < filesize + if (sizeof(mcSoAuthTokenCont_t) != filesize) { + fclose(fs); + LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES); + return MC_DRV_ERR_OUT_OF_RESOURCES; + } + res = fseek(fs, 0, SEEK_SET); + if (res!=0) { + LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + res = fread((char *)so, 1, sizeof(mcSoAuthTokenCont_t), fs); + if (ferror(fs)) { + fclose(fs); + LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + if ((unsigned)res<sizeof(mcSoAuthTokenCont_t)) { + //File is shorter than expected + if (feof(fs)) { + LOG_E("%s(): EOF reached: res is %u, size of mcSoAuthTokenCont_t is %u", __func__, (unsigned)res, + sizeof(mcSoAuthTokenCont_t)); + } + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + fclose(fs); + + return MC_DRV_OK; +} + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryReadAuthTokenBackup(mcSoAuthTokenCont_t *so) +{ + int res = 0; + if (NULL == so) { + LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + const string &authTokenFilePath = getAuthTokenFilePathBackup(); + LOG_I("read AuthToken: %s", authTokenFilePath.c_str()); + + FILE *fs = fopen(authTokenFilePath.c_str(), "rb"); + if (fs==NULL) { + LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + res = fseek(fs, 0, SEEK_END); + if (res!=0) { + LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + int32_t filesize = ftell(fs); + // We ensure that mcSoAuthTokenCont_t matches with filesize, as ferror (during fread operation) can't + // handle the case where mcSoAuthTokenCont_t < filesize + if (sizeof(mcSoAuthTokenCont_t) != filesize) { + fclose(fs); + LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES); + return MC_DRV_ERR_OUT_OF_RESOURCES; + } + res = fseek(fs, 0, SEEK_SET); + if (res!=0) { + LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + res = fread((char *)so, 1, sizeof(mcSoAuthTokenCont_t), fs); + if (ferror(fs)) { + fclose(fs); + LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + if ((unsigned)res<sizeof(mcSoAuthTokenCont_t)) { + //File is shorter than expected + if (feof(fs)) { + LOG_E("%s(): EOF reached: res is %u, size of mcSoAuthTokenCont_t is %u", __func__, + (unsigned)res, sizeof(mcSoAuthTokenCont_t)); + } + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + fclose(fs); + + return MC_DRV_OK; +} + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryDeleteAuthToken(void) +{ + if (rename(getAuthTokenFilePath().c_str(), getAuthTokenFilePathBackup().c_str())) { + LOG_ERRNO("Rename Auth token file!"); + return MC_DRV_ERR_UNKNOWN; + } else + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryStoreRoot(void *so, uint32_t size) +{ + int res = 0; + if (so == NULL || size > 3 * MAX_SO_CONT_SIZE) { + LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + + const string &rootContFilePath = getRootContFilePath(); + LOG_I("store Root: %s", rootContFilePath.c_str()); + + FILE *fs = fopen(rootContFilePath.c_str(), "wb"); + if (fs==NULL) { + LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + res = fseek(fs, 0, SEEK_SET); + if (res!=0) { + LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + fwrite((char *)so, 1, size, fs); + if (ferror(fs)) { + LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES); + fclose(fs); + return MC_DRV_ERR_OUT_OF_RESOURCES; + } + fflush(fs); + fclose(fs); + + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryReadRoot(void *so, uint32_t *size) +{ + const string &rootContFilePath = getRootContFilePath(); + size_t readBytes; + + if (so == NULL) { + LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + LOG_I(" Opening %s", rootContFilePath.c_str()); + + FILE *fs = fopen(rootContFilePath.c_str(), "rb"); + if (fs==NULL) { + LOG_W("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + readBytes = fread((char *)so, 1, *size, fs); + if (ferror(fs)) { + fclose(fs); + LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + fclose(fs); + + if (readBytes > 0) { + *size = readBytes; + return MC_DRV_OK; + } else { + LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryStoreSp(mcSpid_t spid, void *so, uint32_t size) +{ + int res = 0; + if ((spid == 0) || (so == NULL) || size > 3 * MAX_SO_CONT_SIZE) { + LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + + const string &spContFilePath = getSpContFilePath(spid); + LOG_I("store SP: %s", spContFilePath.c_str()); + + FILE *fs = fopen(spContFilePath.c_str(), "wb"); + if (fs==NULL) { + LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + res = fseek(fs, 0, SEEK_SET); + if (res!=0) { + LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + fwrite((char *)so, 1, size, fs); + if (ferror(fs)) { + LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES); + fclose(fs); + return MC_DRV_ERR_OUT_OF_RESOURCES; + } + fflush(fs); + fclose(fs); + + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryReadSp(mcSpid_t spid, void *so, uint32_t *size) +{ + const string &spContFilePath = getSpContFilePath(spid); + size_t readBytes; + if ((spid == 0) || (so == NULL)) { + LOG_E("mcRegistry read So.Sp(SpId=0x%x) failed", spid); + return MC_DRV_ERR_INVALID_PARAMETER; + } + LOG_I(" Reading %s", spContFilePath.c_str()); + + FILE *fs = fopen(spContFilePath.c_str(), "rb"); + if (fs==NULL) { + LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + readBytes = fread((char *)so, 1, *size, fs); + if (ferror(fs)) { + fclose(fs); + LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + fclose(fs); + + if (readBytes > 0) { + *size = readBytes; + return MC_DRV_OK; + } else { + LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryStoreTrustletCon(const mcUuid_t *uuid, const mcSpid_t spid, void *so, uint32_t size) +{ + int res = 0; + if ((uuid == NULL) || (so == NULL) || size > 3 * MAX_SO_CONT_SIZE) { + LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + + const string &tlContFilePath = getTlContFilePath(uuid, spid); + LOG_I("store TLc: %s", tlContFilePath.c_str()); + + FILE *fs = fopen(tlContFilePath.c_str(), "wb"); + if (fs==NULL) { + LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + res = fseek(fs, 0, SEEK_SET); + if (res!=0) { + LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + fwrite((char *)so, 1, size, fs); + if (ferror(fs)) { + LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES); + fclose(fs); + return MC_DRV_ERR_OUT_OF_RESOURCES; + } + fflush(fs); + fclose(fs); + + return MC_DRV_OK; +} + +static uint32_t getAsUint32BE( + void *pValueUnaligned +) +{ + uint8_t *p = (uint8_t *)pValueUnaligned; + uint32_t val = p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24); + return val; +} + +mcResult_t mcRegistryStoreTABlob(mcSpid_t spid, void *blob, uint32_t size) +{ + int res = 0; + LOG_I("mcRegistryStoreTABlob started"); + + // Check blob size + if (size < sizeof(mclfHeaderV24_t)) { + LOG_E("RegistryStoreTABlob failed - TA blob length is less then header size"); + return MC_DRV_ERR_INVALID_PARAMETER; + } + + mclfHeaderV24_t *header24 = (mclfHeaderV24_t *)blob; + mclfHeaderV2_t *header20 = (mclfHeaderV2_t *)blob; + + // Check header version + if (header20->intro.version < MC_MAKE_VERSION(2, 4)) { + LOG_E("RegistryStoreTABlob failed - TA blob header version is less than 2.4"); + return MC_DRV_ERR_TA_HEADER_ERROR; + } + + //Check GP version + if (header24->gp_level != 1) { + LOG_E("RegistryStoreTABlob failed - TA blob header gp_level is not equal to 1"); + return MC_DRV_ERR_TA_HEADER_ERROR; + } + + TEEC_UUID uuid; + switch (header20->serviceType) { + case SERVICE_TYPE_SYSTEM_TRUSTLET: { + // Check spid + if (spid != MC_SPID_SYSTEM) { + LOG_E("RegistryStoreTABlob failed - SPID is not equal to %d for System TA", spid); + return MC_DRV_ERR_INVALID_PARAMETER; + } + memcpy(&uuid, &header20->uuid, sizeof(mcUuid_t)); + break; + } + case SERVICE_TYPE_SP_TRUSTLET: { + // Check spid + if (spid >= MC_SPID_SYSTEM) { + LOG_E("RegistryStoreTABlob failed - SPID is equal to %u ", spid); + return MC_DRV_ERR_INVALID_PARAMETER; + } + + uuid_attestation *pUa = (uuid_attestation *) & ((uint8_t *)blob)[header24->attestationOffset]; + // Check attestation size + if ((header24->attestationOffset > size) && (header24->attestationOffset + getAsUint32BE(&pUa->size) > size)) { + LOG_E("RegistryStoreTABlob failed - Attestation size is not correct"); + return MC_DRV_ERR_TA_HEADER_ERROR; + } + + // Check attestation size + if (getAsUint32BE(&pUa->size) < sizeof(uuid_attestation)) { + LOG_E("RegistryStoreTABlob failed - Attestation size is equal to %d and is less then %d", getAsUint32BE(&pUa->size), sizeof(uuid_attestation)); + return MC_DRV_ERR_TA_ATTESTATION_ERROR; + } + + // Check magic word + if (memcmp(pUa->magic, MAGIC, AT_MAGIC_SIZE)) { + LOG_E("RegistryStoreTABlob failed - Attestation magic word is not correct"); + return MC_DRV_ERR_TA_ATTESTATION_ERROR; + } + + // Check version + if (getAsUint32BE(&pUa->version) != AT_VERSION) { + LOG_E("RegistryStoreTABlob failed - Attestation version is equal to %08X. It has to be equal to %08X", getAsUint32BE(&pUa->version), AT_VERSION); + return MC_DRV_ERR_TA_ATTESTATION_ERROR; + } + + memcpy(&uuid, &pUa->uuid, sizeof(mcUuid_t)); + break; + } + default: { + return MC_DRV_ERR_INVALID_PARAMETER; + } + } + const string taBinFilePath = getTABinFilePath((mcUuid_t *)&uuid, MC_REGISTRY_WRITABLE); + + LOG_I("Store TA blob at: %s", taBinFilePath.c_str()); + + FILE *fs = fopen(taBinFilePath.c_str(), "wb"); + if (fs==NULL) { + LOG_E("RegistryStoreTABlob failed - TA blob file open error: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + res = fseek(fs, 0, SEEK_SET); + if (res!=0) { + LOG_E("RegistryStoreTABlob failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + fwrite(blob, 1, size, fs); + if (ferror(fs)) { + LOG_E("RegistryStoreTABlob failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES); + fclose(fs); + return MC_DRV_ERR_OUT_OF_RESOURCES; + } + fflush(fs); + fclose(fs); + + if (header20->serviceType == SERVICE_TYPE_SP_TRUSTLET) { + const string taspidFilePath = getTASpidFilePath((mcUuid_t *)&uuid, MC_REGISTRY_WRITABLE); + + LOG_I("Store spid file at: %s", taspidFilePath.c_str()); + + FILE *fs = fopen(taspidFilePath.c_str(), "wb"); + if (fs==NULL) { + //TODO: shouldn't we delete TA blob file ? + LOG_E("RegistryStoreTABlob failed - TA blob file open error: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + res = fseek(fs, 0, SEEK_SET); + if (res!=0) { + LOG_E("RegistryStoreTABlob failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + fwrite(&spid, 1, sizeof(mcSpid_t), fs); + if (ferror(fs)) { + LOG_E("RegistryStoreTABlob failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES); + fclose(fs); + return MC_DRV_ERR_OUT_OF_RESOURCES; + } + fflush(fs); + fclose(fs); + } + return MC_DRV_OK; +} + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryReadTrustletCon(const mcUuid_t *uuid, const mcSpid_t spid, void *so, uint32_t *size) +{ + int res = 0; + if ((uuid == NULL) || (so == NULL)) { + LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + size_t readBytes; + const string &tlContFilePath = getTlContFilePath(uuid, spid); + LOG_I("read TLc: %s", tlContFilePath.c_str()); + + FILE *fs = fopen(tlContFilePath.c_str(), "rb"); + if (fs==NULL) { + LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + res = fseek(fs, 0, SEEK_SET); + if (res!=0) { + LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + readBytes = fread((char *)so, 1, *size, fs); + if (ferror(fs)) { + fclose(fs); + LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + fclose(fs); + + if (readBytes > 0) { + *size = readBytes; + return MC_DRV_OK; + } else { + LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryStoreData(void *so, uint32_t size) +{ + mcSoDataCont_t *dataCont = (mcSoDataCont_t *)so; + int res = 0; + + if (dataCont == NULL || size != sizeof(mcSoDataCont_t)) { + LOG_E("mcRegistry store So.Data failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + string pathname, filename; + + switch (dataCont->cont.type) { + case CONT_TYPE_SPDATA: + LOG_E("SPDATA not supported"); + return MC_DRV_ERR_INVALID_PARAMETER; + break; + case CONT_TYPE_TLDATA: + pathname = getTlDataPath(&dataCont->cont.uuid); + filename = getTlDataFilePath(&dataCont->cont.uuid, dataCont->cont.pid); + break; + default: + LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + if (mkdir(pathname.c_str(), 0777) < 0) + { + LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + + LOG_I("store DT: %s", filename.c_str()); + + FILE *fs = fopen(filename.c_str(), "wb"); + if (fs==NULL) { + LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + res = fseek(fs, 0, SEEK_SET); + if (res!=0) { + LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + fwrite((char *)dataCont, 1, MC_SO_SIZE(dataCont->soHeader.plainLen, dataCont->soHeader.encryptedLen), fs); + if (ferror(fs)) { + LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES); + fclose(fs); + return MC_DRV_ERR_OUT_OF_RESOURCES; + } + fflush(fs); + fclose(fs); + + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryReadData(uint32_t context, const mcCid_t *cid, mcPid_t pid, + mcSoDataCont_t *so, uint32_t maxLen) +{ + int res = 0; + + if ((NULL == cid) || (NULL == so)) { + LOG_E("mcRegistry read So.Data failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + string filename; + switch (context) { + case 0: + LOG_E("SPDATA not supported"); + return MC_DRV_ERR_INVALID_PARAMETER; + break; + case 1: + filename = getTlDataFilePath(&so->cont.uuid, so->cont.pid); + break; + default: + LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + LOG_I("read DT: %s", filename.c_str()); + + FILE *fs = fopen(filename.c_str(), "rb"); + if (fs==NULL) { + LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE); + return MC_DRV_ERR_INVALID_DEVICE_FILE; + } + res = fseek(fs, 0, SEEK_END); + if (res!=0) { + LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + uint32_t filesize = ftell(fs); + if (maxLen < filesize) { + fclose(fs); + LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES); + return MC_DRV_ERR_OUT_OF_RESOURCES; + } + res = fseek(fs, 0, SEEK_SET); + if (res!=0) { + LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + char *p = (char *) so; + res = fread(p, 1, sizeof(mcSoHeader_t), fs); + if (ferror(fs)) { + fclose(fs); + LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + if ((unsigned)res<sizeof(mcSoHeader_t)) { + //File is shorter than expected + if (feof(fs)) { + LOG_E("%s(): EOF reached: res is %u, size of mcSoHeader_t is %u", __func__, (unsigned)res, sizeof(mcSoHeader_t)); + } + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + p += sizeof(mcSoHeader_t); + res = fread(p, 1, MC_SO_SIZE(so->soHeader.plainLen, + so->soHeader.encryptedLen) + - sizeof(mcSoHeader_t), fs); + if (ferror(fs)) { + fclose(fs); + LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + if ((unsigned)res<(MC_SO_SIZE(so->soHeader.plainLen, so->soHeader.encryptedLen) - sizeof(mcSoHeader_t))) { + //File is shorter than expected + if (feof(fs)) { + LOG_E("%s(): EOF reached: res is %u, size of secure object is %u", __func__, (unsigned)res, + MC_SO_SIZE(so->soHeader.plainLen, so->soHeader.encryptedLen) - sizeof(mcSoHeader_t)); + } + fclose(fs); + return MC_DRV_ERR_INVALID_PARAMETER; + } + fclose(fs); + + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +static size_t getFileContent( + const char *pPath, + uint8_t **ppContent) +{ + FILE *pStream; + long filesize; + uint8_t *content = NULL; + int res = 0; + + /* Open the file */ + pStream = fopen(pPath, "rb"); + if (pStream == NULL) { + LOG_E("Error: Cannot open file: %s.", pPath); + return 0; + } + + if (fseek(pStream, 0L, SEEK_END) != 0) { + LOG_E("Error: Cannot read file: %s.", pPath); + goto error; + } + + filesize = ftell(pStream); + if (filesize < 0) { + LOG_E("Error: Cannot get the file size: %s.", pPath); + goto error; + } + + if (filesize == 0) { + LOG_E("Error: Empty file: %s.", pPath); + goto error; + } + + /* Set the file pointer at the beginning of the file */ + if (fseek(pStream, 0L, SEEK_SET) != 0) { + LOG_E("Error: Cannot read file: %s.", pPath); + goto error; + } + + /* Allocate a buffer for the content */ + content = (uint8_t *)malloc(filesize); + if (content == NULL) { + LOG_E("Error: Cannot read file: Out of memory."); + goto error; + } + + /* Read data from the file into the buffer */ + res = fread(content, (size_t)filesize, 1, pStream); + if (ferror(pStream)) { + LOG_E("Error: Cannot read file: %s.", pPath); + goto error; + } + if ((unsigned)res<1) { + //File is shorter than expected + if (feof(pStream)) { + LOG_E("Error: EOF reached: %s.", pPath); + } + goto error; + } + + /* Close the file */ + fclose(pStream); + *ppContent = content; + + /* Return number of bytes read */ + return (size_t)filesize; + +error: + if (content != NULL) { + free(content); + } + fclose(pStream); + return 0; +} + +//------------------------------------------------------------------------------ +static bool mcCheckUuid(const mcUuid_t *uuid, const char *filename) +{ + uint8_t *pTAData = NULL; + uint32_t nTASize; + bool res; + + nTASize = getFileContent(filename, &pTAData); + if (nTASize == 0) { + LOG_E("err: Trusted Application not found."); + return false; + } + + // Check blob size + if (nTASize < sizeof(mclfHeaderV24_t)) { + free(pTAData); + LOG_E("RegistryStoreTABlob failed - TA blob length is less then header size"); + return false; + } + + mclfHeaderV2_t *header20 = (mclfHeaderV2_t *)pTAData; + + // Check header version + if (header20->intro.version < MC_MAKE_VERSION(2, 4)) { + free(pTAData); + LOG_E("RegistryStoreTABlob failed - TA blob header version is less than 2.4"); + return false; + } + + // Check blob size + if (memcmp(uuid, &header20->uuid, sizeof(mcUuid_t)) == 0) { + res = true; + } else { + res = false; + } + + free(pTAData); + + return res; +} + +//this function deletes all the files owned by a GP TA and stored in the tbase secure storage dir. +//then it deletes GP TA folder. +static int CleanupGPTAStorage(const char *uuid) +{ + DIR *dp; + struct dirent *de; + int e; + string TAPath = getTbStoragePath() + "/" + uuid; + if (NULL != (dp = opendir(TAPath.c_str()))) { + while (NULL != (de = readdir(dp))) { + if (de->d_name[0] != '.') { + string dname = TAPath + "/" + string (de->d_name); + LOG_I("delete DT: %s", dname.c_str()); + if (0 != (e = remove(dname.c_str()))) { + LOG_E("remove UUID-files %s failed! error: %d", dname.c_str(), e); + } + } + } + if (dp) { + closedir(dp); + } + LOG_I("delete dir: %s", TAPath.c_str()); + if (0 != (e = rmdir(TAPath.c_str()))) { + LOG_E("remove UUID-dir failed! errno: %d", e); + return e; + } + } + return MC_DRV_OK; +} + +static void deleteSPTA(const mcUuid_t *uuid, const mcSpid_t spid) +{ + DIR *dp; + struct dirent *de; + int e; + + // Delete TABIN and SPID files - we loop searching required spid file + if (NULL != (dp = opendir(MC_REGISTRY_DATA_PATH))) { + while (NULL != (de = readdir(dp))) { + string spidFile; + string tabinFile; + string tabinUuid; + size_t pch_dot, pch_slash; + spidFile = MC_REGISTRY_DATA_PATH "/" + string(de->d_name); + pch_dot = spidFile.find_last_of('.'); + if (pch_dot == string::npos) continue; + pch_slash = spidFile.find_last_of('/'); + if ((pch_slash != string::npos) && (pch_slash > pch_dot)) continue; + if (spidFile.substr(pch_dot).compare(GP_TA_SPID_FILE_EXT) != 0) continue; + + mcSpid_t curSpid = 0; + + int fd = open(spidFile.c_str(), O_RDONLY); + if (fd != -1) { + if (read(fd, &curSpid, sizeof(mcSpid_t))!=sizeof(mcSpid_t)) { + curSpid = 0; + } + close(fd); + } + if (spid == curSpid) { + tabinFile = spidFile.substr(0, pch_dot) + GP_TA_BIN_FILE_EXT; + if (mcCheckUuid(uuid, tabinFile.c_str())) { + tabinUuid = spidFile.substr(0, pch_dot); + tabinUuid = tabinUuid.substr(tabinUuid.find_last_of('/')+1); + LOG_I("Remove TA storage %s", tabinUuid.c_str()); + if (0 != (e = CleanupGPTAStorage(tabinUuid.c_str()))){ + LOG_E("Remove TA storage failed! errno: %d", e); + /* Discard error */ + } + LOG_I("Remove TA file %s", tabinFile.c_str()); + if (0 != (e = remove(tabinFile.c_str()))) { + LOG_E("Remove TA file failed! errno: %d", e); + /* Discard error */ + } + LOG_I("Remove spid file %s", spidFile.c_str()); + if (0 != (e = remove(spidFile.c_str()))) { + LOG_E("Remove spid file failed! errno: %d", e); + /* Discard error */ + } + break; + } + } + } + if (dp) { + closedir(dp); + } + } +} + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryCleanupTrustlet(const mcUuid_t *uuid, const mcSpid_t spid) +{ + DIR *dp; + struct dirent *de; + int e; + + if (NULL == uuid) { + LOG_E("mcRegistry cleanupTrustlet(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + + // Delete all TA related data + string pathname = getTlDataPath(uuid); + if (NULL != (dp = opendir(pathname.c_str()))) { + while (NULL != (de = readdir(dp))) { + if (de->d_name[0] != '.') { + string dname = pathname + "/" + string (de->d_name); + LOG_I("delete DT: %s", dname.c_str()); + if (0 != (e = remove(dname.c_str()))) { + LOG_E("remove UUID-data %s failed! error: %d", dname.c_str(), e); + } + } + } + if (dp) { + closedir(dp); + } + LOG_I("delete dir: %s", pathname.c_str()); + if (0 != (e = rmdir(pathname.c_str()))) { + LOG_E("remove UUID-dir failed! errno: %d", e); + return MC_DRV_ERR_UNKNOWN; + } + } + + string tlBinFilePath = getTlBinFilePath(uuid, MC_REGISTRY_WRITABLE); + struct stat tmp; + string tlContFilePath = getTlContFilePath(uuid, spid);; + + if (stat(tlBinFilePath.c_str(), &tmp) == 0) { + /* Legacy TA */ + LOG_I("Remove TA file %s", tlBinFilePath.c_str()); + if (0 != (e = remove(tlBinFilePath.c_str()))) { + LOG_E("Remove TA file failed! errno: %d", e); + } + } else { + /* GP TA */ + deleteSPTA(uuid, spid); + } + + LOG_I("Remove TA container %s", tlContFilePath.c_str()); + if (0 != (e = remove(tlContFilePath.c_str()))) { + LOG_E("Remove TA container failed! errno: %d", e); + return MC_DRV_ERR_UNKNOWN; + } + + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryCleanupSp(mcSpid_t spid) +{ + DIR *dp; + struct dirent *de; + mcResult_t ret; + mcSoSpCont_t data; + uint32_t i, len; + int e; + + if (0 == spid) { + LOG_E("mcRegistry cleanupSP(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER); + return MC_DRV_ERR_INVALID_PARAMETER; + } + len = sizeof(mcSoSpCont_t); + ret = mcRegistryReadSp(spid, &data, &len); + if (MC_DRV_OK != ret || len != sizeof(mcSoSpCont_t)) { + LOG_E("read SP->UUID aborted! Return code: %d", ret); + return ret; + } + for (i = 0; (i < MC_CONT_CHILDREN_COUNT) && (ret == MC_DRV_OK); i++) { + if (0 != strncmp((const char *) & (data.cont.children[i]), (const char *)&MC_UUID_FREE, sizeof(mcUuid_t))) { + ret = mcRegistryCleanupTrustlet(&(data.cont.children[i]), spid); + } + } + if (MC_DRV_OK != ret) { + LOG_E("delete SP->UUID failed! Return code: %d", ret); + return ret; + } + + string pathname = getSpDataPath(spid); + + if (NULL != (dp = opendir(pathname.c_str()))) { + while (NULL != (de = readdir(dp))) { + if (de->d_name[0] != '.') { + string dname = pathname + "/" + string (de->d_name); + LOG_I("delete DT: %s", dname.c_str()); + if (0 != (e = remove(dname.c_str()))) { + LOG_E("remove SPID-data %s failed! error: %d", dname.c_str(), e); + } + } + } + if (dp) { + closedir(dp); + } + LOG_I("delete dir: %s", pathname.c_str()); + if (0 != (e = rmdir(pathname.c_str()))) { + LOG_E("remove SPID-dir failed! error: %d", e); + return MC_DRV_ERR_UNKNOWN; + } + } + string spContFilePath = getSpContFilePath(spid); + LOG_I("delete Sp: %s", spContFilePath.c_str()); + if (0 != (e = remove(spContFilePath.c_str()))) { + LOG_E("remove SP failed! error: %d", e); + return MC_DRV_ERR_UNKNOWN; + } + return MC_DRV_OK; +} + + +//------------------------------------------------------------------------------ +mcResult_t mcRegistryCleanupRoot(void) +{ + mcResult_t ret; + mcSoRootCont_t data; + uint32_t i, len; + int e; + len = sizeof(mcSoRootCont_t); + ret = mcRegistryReadRoot(&data, &len); + if (MC_DRV_OK != ret || len != sizeof(mcSoRootCont_t)) { + LOG_E("read Root aborted! Return code: %d", ret); + return ret; + } + for (i = 0; (i < MC_CONT_CHILDREN_COUNT) && (ret == MC_DRV_OK); i++) { + mcSpid_t spid = data.cont.children[i]; + if (spid != MC_SPID_FREE) { + ret = mcRegistryCleanupSp(spid); + if (MC_DRV_OK != ret) { + LOG_E("Cleanup SP failed! Return code: %d", ret); + return ret; + } + } + } + + string rootContFilePath = getRootContFilePath(); + LOG_I("Delete root: %s", rootContFilePath.c_str()); + if (0 != (e = remove(rootContFilePath.c_str()))) { + LOG_E("Delete root failed! error: %d", e); + return MC_DRV_ERR_UNKNOWN; + } + return MC_DRV_OK; +} + +//------------------------------------------------------------------------------ +regObject_t *mcRegistryMemGetServiceBlob(mcSpid_t spid, void *trustlet, uint32_t tlSize) +{ + regObject_t *regobj = NULL; + + // Ensure that a UUID is provided. + if (NULL == trustlet) { + LOG_E("No trustlet buffer given"); + return NULL; + } + + // Check service blob size. + if (tlSize > MAX_TL_SIZE ) { + LOG_E("mcRegistryMemGetServiceBlob() failed: service blob too big: %d", tlSize); + return NULL; + } + + mclfIntro_t *pIntro = (mclfIntro_t *)trustlet; + // Check TL magic value. + if (pIntro->magic != MC_SERVICE_HEADER_MAGIC_BE) { + LOG_E("mcRegistryMemGetServiceBlob() failed: wrong header magic value: %d", pIntro->magic); + return NULL; + } + + // Get service type. + mclfHeaderV2_t *pHeader = (mclfHeaderV2_t *)trustlet; +#ifndef NDEBUG + { + const char *service_types[] = { + "illegal", "Driver", "Trustlet", "System Trustlet" + }; + int serviceType_safe = pHeader->serviceType > SERVICE_TYPE_SYSTEM_TRUSTLET ? SERVICE_TYPE_ILLEGAL : pHeader->serviceType; + LOG_I(" Service is a %s (service type %d)", service_types[serviceType_safe], pHeader->serviceType); + } +#endif + + LOG_I(" Trustlet text %u data %u ", pHeader->text.len, pHeader->data.len); + + // If loadable driver or system trustlet. + if (pHeader->serviceType == SERVICE_TYPE_DRIVER || pHeader->serviceType == SERVICE_TYPE_SYSTEM_TRUSTLET) { + // Take trustlet blob 'as is'. + if (NULL == (regobj = (regObject_t *) (malloc(sizeof(regObject_t) + tlSize)))) { + LOG_E("mcRegistryMemGetServiceBlob() failed: Out of memory"); + return NULL; + } + regobj->len = tlSize; + regobj->tlStartOffset = 0; + memcpy((char *)regobj->value, trustlet, tlSize); + // If user trustlet. + } else if (pHeader->serviceType == SERVICE_TYPE_SP_TRUSTLET) { + // Take trustlet blob and append root, sp, and tl container. + size_t regObjValueSize = tlSize + sizeof(mcBlobLenInfo_t) + 3 * MAX_SO_CONT_SIZE; + + // Prepare registry object. + if (NULL == (regobj = (regObject_t *) malloc(sizeof(regObject_t) + regObjValueSize))) { + LOG_E("mcRegistryMemGetServiceBlob() failed: Out of memory"); + return NULL; + } + regobj->len = regObjValueSize; + regobj->tlStartOffset = sizeof(mcBlobLenInfo_t); + uint8_t *p = regobj->value; + + // Reserve space for the blob length structure + mcBlobLenInfo_ptr lenInfo = (mcBlobLenInfo_ptr)p; + lenInfo->magic = MC_TLBLOBLEN_MAGIC; + p += sizeof(mcBlobLenInfo_t); + // Fill in trustlet blob after the len info + memcpy(p, trustlet, tlSize); + p += tlSize; + + // Final registry object value looks like this: + // + // +---------------+---------------------------+-----------+---------+---------+ + // | Blob Len Info | TL-Header TL-Code TL-Data | Root Cont | SP Cont | TL Cont | + // +---------------+---------------------------+-----------+-------------------+ + // /------ Trustlet BLOB ------/ + // + // /------------------ regobj->header.len -------------------------------------/ + + // start at the end of the trustlet blob + mcResult_t ret; + do { + uint32_t soTltContSize = MAX_SO_CONT_SIZE; + uint32_t len; + + // Fill in root container. + len = sizeof(mcSoRootCont_t); + if (MC_DRV_OK != (ret = mcRegistryReadRoot(p, &len))) { + break; + } + lenInfo->rootContBlobSize = len; + p += len; + + // Fill in SP container. + len = sizeof(mcSoSpCont_t); + if (MC_DRV_OK != (ret = mcRegistryReadSp(spid, p, &len))) { + break; + } + lenInfo->spContBlobSize = len; + p += len; + + // Fill in TLT Container + // We know exactly how much space is left in the buffer + soTltContSize = regObjValueSize - tlSize + sizeof(mcBlobLenInfo_t) + - lenInfo->spContBlobSize - lenInfo->rootContBlobSize; + if (MC_DRV_OK != (ret = mcRegistryReadTrustletCon(&pHeader->uuid, spid, p, &soTltContSize))) { + break; + } + lenInfo->tlContBlobSize = soTltContSize; + LOG_I(" Trustlet container %u bytes loaded", soTltContSize); + // Depending on the trustlet container size we decide which structure to use + // Unfortunate design but it should have to do for now + if (soTltContSize == sizeof(mcSoTltCont_2_0_t)) { + LOG_I(" Using 2.0 trustlet container"); + } else if (soTltContSize == sizeof(mcSoTltCont_2_1_t)) { + LOG_I(" Using 2.1 trustlet container"); + } else { + LOG_E("Trustlet container has unknown size"); + break; + } + } while (false); + + if (MC_DRV_OK != ret) { + LOG_E("mcRegistryMemGetServiceBlob() failed: Error code: %d", ret); + free(regobj); + return NULL; + } + // Now we know the sizes for all containers so set the correct size + regobj->len = sizeof(mcBlobLenInfo_t) + tlSize + + lenInfo->rootContBlobSize + + lenInfo->spContBlobSize + + lenInfo->tlContBlobSize; + // Any other service type. + } else { + LOG_E("mcRegistryMemGetServiceBlob() failed: Unsupported service type %u", pHeader->serviceType); + } + return regobj; +} + + +//------------------------------------------------------------------------------ +regObject_t *mcRegistryFileGetServiceBlob(const char *trustlet, mcSpid_t spid) +{ + struct stat sb; + regObject_t *regobj = NULL; + void *buffer; + + // Ensure that a file name is provided. + if (trustlet == NULL) { + LOG_E("No file given"); + return NULL; + } + + int fd = open(trustlet, O_RDONLY); + if (fd == -1) { + LOG_E("Cannot open %s", trustlet); + return NULL; + } + + if (fstat(fd, &sb) == -1) { + LOG_E("mcRegistryFileGetServiceBlob() failed: Cound't get file size"); + goto error; + } + + buffer = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (buffer == MAP_FAILED) { + LOG_E("mcRegistryFileGetServiceBlob(): Failed to map file to memory"); + goto error; + } + + regobj = mcRegistryMemGetServiceBlob(spid, buffer, sb.st_size); + + // We don't actually care if either of them fails but should still print warnings + if (munmap(buffer, sb.st_size)) { + LOG_E("mcRegistryFileGetServiceBlob(): Failed to unmap memory"); + } + +error: + if (close(fd)) { + LOG_E("mcRegistryFileGetServiceBlob(): Failed to close file %s", trustlet); + } + + return regobj; +} + + +//------------------------------------------------------------------------------ +regObject_t *mcRegistryGetServiceBlob(const mcUuid_t *uuid, bool isGpUuid) +{ + // Ensure that a UUID is provided. + if (NULL == uuid) { + LOG_E("No UUID given"); + return NULL; + } + + // Open service blob file. + string tlBinFilePath; + if (isGpUuid) { + tlBinFilePath = getTABinFilePath(uuid, MC_REGISTRY_ALL); + } else { + tlBinFilePath = getTlBinFilePath(uuid, MC_REGISTRY_ALL); + } + LOG_I("Loading %s", tlBinFilePath.c_str()); + + mcSpid_t spid = 0; + if (isGpUuid) { + string taspidFilePath = getTASpidFilePath(uuid, MC_REGISTRY_ALL); + int fd = open(taspidFilePath.c_str(), O_RDONLY); + if (fd == -1) { + // This can be ok for System TAs + //LOG_ERRNO("open"); + //LOG_E("Cannot open %s", taspidFilePath.c_str()); + //return NULL; + } else { + if (read(fd, &spid, sizeof(mcSpid_t))!=sizeof(mcSpid_t)) { + close(fd); + return NULL; + } + close(fd); + } + } + + return mcRegistryFileGetServiceBlob(tlBinFilePath.c_str(), spid); +} + +//------------------------------------------------------------------------------ +regObject_t *mcRegistryGetDriverBlob(const char *filename) +{ + regObject_t *regobj = mcRegistryFileGetServiceBlob(filename, 0); + + if (regobj == NULL) { + LOG_E("mcRegistryGetDriverBlob() failed"); + return NULL; + } + + // Get service type. + mclfHeaderV2_t *pHeader = (mclfHeaderV2_t *)regobj->value; + + // If file is not a driver we are not interested + if (pHeader->serviceType != SERVICE_TYPE_DRIVER) { + LOG_E("mcRegistryGetDriverBlob() failed: Unsupported service type %u", pHeader->serviceType); + pHeader = NULL; + free(regobj); + regobj = NULL; + } + + return regobj; +} + |