blob: e1617ba3cfe6037889ca9ca1d5b0b90b5d2c3677 [file] [log] [blame]
/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
* @{
* @file
*
* FSD server.
*
* Handles incoming storage requests from TA through STH
*/
/* Copyright (c) 2013 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.
*/
#include "public/FSD.h"
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <cstdlib>
#include <stdio.h>
//#define LOG_VERBOSE
#include "log.h"
#define TEE_DATA_FLAG_EXCLUSIVE 0x00000400
extern string getTbStoragePath();
extern pthread_mutex_t syncMutex;
extern pthread_cond_t syncCondition;
extern bool Th_sync;
//------------------------------------------------------------------------------
FSD::FSD(
void
)
{
memset(&sessionHandle, 0, sizeof(mcSessionHandle_t));
dci = NULL;
}
FSD::~FSD(
void
)
{
FSD_Close();
}
//------------------------------------------------------------------------------
void FSD::run(
void
)
{
struct stat st = {0};
mcResult_t ret;
string storage = getTbStoragePath();
const char* tbstpath = storage.c_str();
/*Create Tbase storage directory*/
if (stat(tbstpath, &st) == -1) {
LOG_I("%s: Creating <t-base storage Folder %s\n",TAG_LOG,tbstpath);
if(mkdir(tbstpath, 0600)==-1)
{
LOG_E("%s: failed creating storage folder\n",TAG_LOG);
}
}
do{
pthread_mutex_lock(&syncMutex);
pthread_cond_wait(&syncCondition, &syncMutex);
if (Th_sync==true)
{
LOG_I("%s: starting File Storage Daemon", TAG_LOG);
}
pthread_mutex_unlock(&syncMutex);
ret = FSD_Open();
if (ret != MC_DRV_OK)
break;
LOG_I("%s: Start listening for request from STH", TAG_LOG);
FSD_listenDci();
}while(false);
LOG_E("Exiting File Storage Daemon 0x%08X", ret);
}
mcResult_t FSD::FSD_Open(void) {
mcResult_t mcRet;
const mcUuid_t uuid = DRV_STH_UUID;
memset(&sessionHandle,0, sizeof(mcSessionHandle_t));
dci = (dciMessage_t*)calloc(DCI_BUFF_SIZE,sizeof(uint8_t));
if (dci == NULL) {
LOG_E("FSD_Open(): allocation failed");
return MC_DRV_ERR_NO_FREE_MEMORY;
}
/* Open <t-base device */
mcRet = mcOpenDevice(MC_DEVICE_ID_DEFAULT);
if (MC_DRV_OK != mcRet)
{
LOG_E("FSD_Open(): mcOpenDevice returned: %d\n", mcRet);
goto error;
}
/* Open session to the sth driver */
sessionHandle.deviceId = MC_DEVICE_ID_DEFAULT;
mcRet = mcOpenSession(&sessionHandle,
&uuid,
(uint8_t *) dci,
DCI_BUFF_SIZE);
if (MC_DRV_OK != mcRet)
{
LOG_E("FSD_Open(): mcOpenSession returned: %d\n", mcRet);
goto close_device;
}
/* Wait for notification from SWd */
mcRet = mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT);
if (MC_DRV_OK != mcRet)
{
goto close_session;
}
/**
* The following notification is required for initial sync up
* with the driver
*/
dci->command.header.commandId = CMD_ST_SYNC;
mcRet = mcNotify(&sessionHandle);
if (MC_DRV_OK != mcRet)
{
LOG_E("FSD_Open(): mcNotify returned: %d\n", mcRet);
goto close_session;
}
/* Wait for notification from SWd */
mcRet = mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT);
if (MC_DRV_OK != mcRet)
{
goto close_session;
}
LOG_I("FSD_Open(): received first notification \n");
LOG_I("FSD_Open(): send notification back \n");
mcRet = mcNotify(&sessionHandle);
if (MC_DRV_OK != mcRet)
{
LOG_E("FSD_Open(): mcNotify returned: %d\n", mcRet);
goto close_session;
}
LOG_I("FSD_Open(): returning success");
return mcRet;
close_session:
mcCloseSession(&sessionHandle);
close_device:
mcCloseDevice(MC_DEVICE_ID_DEFAULT);
error:
free(dci);
dci = NULL;
return mcRet;
}
mcResult_t FSD::FSD_Close(void){
mcResult_t mcRet;
/* Clear DCI message buffer */
memset(dci, 0, sizeof(dciMessage_t));
/* Close session to the debug driver trustlet */
mcRet = mcCloseSession(&sessionHandle);
if (MC_DRV_OK != mcRet)
{
LOG_E("FSD_Close(): mcCloseSession returned: %d\n", mcRet);
}
free(dci);
dci = NULL;
memset(&sessionHandle,0,sizeof(mcSessionHandle_t));
/* Close <t-base device */
mcRet = mcCloseDevice(MC_DEVICE_ID_DEFAULT);
if (MC_DRV_OK != mcRet)
{
LOG_E("FSD_Close(): mcCloseDevice returned: %d\n", mcRet);
}
LOG_I("FSD_Close(): returning: 0x%.8x\n", mcRet);
return mcRet;
}
void FSD::FSD_listenDci(void){
mcResult_t mcRet;
LOG_I("FSD_listenDci(): DCI listener \n");
for(;;)
{
LOG_I("FSD_listenDci(): Waiting for notification\n");
/* Wait for notification from SWd */
if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
{
LOG_E("FSD_listenDci(): mcWaitNotification failed\n");
break;
}
/* Received exception. */
LOG_I("FSD_listenDci(): Received Command (0x%.8x) from STH\n", dci->sth_request.type);
mcRet = FSD_ExecuteCommand();
/* notify the STH*/
mcRet = mcNotify(&sessionHandle);
if (MC_DRV_OK != mcRet)
{
LOG_E("FSD_executeCommand(): mcNotify returned: %d\n", mcRet);
break;
}
}
}
void FSD_HexFileName(
unsigned char* fn,
char* FileName,
uint32_t elems
){
char tmp[elems * 2 + 1];
uint32_t i=0;
for (i = 0; i < elems; i++) {
sprintf(&tmp[i * 2], "%02x", fn[i]);
}
strcpy(FileName,tmp);
}
void FSD_CreateTaDirName(
TEE_UUID* ta_uuid,
char* DirName,
uint32_t elems
){
char tmp[elems * 2 + 1];
unsigned char* fn;
uint32_t i=0;
fn = (unsigned char*)ta_uuid;
for (i = 0; i < elems; i++) {
sprintf(&tmp[i * 2], "%02x", fn[i]);
}
strcat(DirName,tmp);
}
//------------------------------------------------------------------------------
mcResult_t FSD::FSD_ExecuteCommand(void){
switch(dci->sth_request.type)
{
//--------------------------------------
case STH_MESSAGE_TYPE_LOOK:
LOG_I("FSD_ExecuteCommand(): Looking for file\n");
dci->sth_request.status=FSD_LookFile();
break;
//--------------------------------------
case STH_MESSAGE_TYPE_READ:
LOG_I("FSD_ExecuteCommand(): Reading file\n");
dci->sth_request.status=FSD_ReadFile();
break;
//--------------------------------------
case STH_MESSAGE_TYPE_WRITE:
LOG_I("FSD_ExecuteCommand(): Writing file\n");
dci->sth_request.status=FSD_WriteFile();
break;
//--------------------------------------
case STH_MESSAGE_TYPE_DELETE:
LOG_I("FSD_ExecuteCommand(): Deleting file\n");
dci->sth_request.status=FSD_DeleteFile();
LOG_I("FSD_ExecuteCommand(): file deleted status is 0x%08x\n",dci->sth_request.status);
break;
//--------------------------------------
default:
LOG_E("FSD_ExecuteCommand(): Received unknown command %x. Ignoring..\n", dci->sth_request.type);
break;
}
return dci->sth_request.status;
}
/**************************** File operations *******************************/
mcResult_t FSD::FSD_LookFile(void){
FILE * pFile=NULL;
STH_FSD_message_t* sth_request=NULL;
size_t res;
string storage = getTbStoragePath();
const char* tbstpath = storage.c_str();
char tadirname[TEE_UUID_STRING_SIZE+1];
char filename[2*FILENAMESIZE+1];
char TAdirpath[strlen(tbstpath)+1+TEE_UUID_STRING_SIZE+1];
char Filepath[strlen(tbstpath)+1+TEE_UUID_STRING_SIZE+1+2*FILENAMESIZE+1];
sth_request= &dci->sth_request;
//create TA folder name from TA UUID
FSD_CreateTaDirName(&sth_request->uuid,tadirname,sizeof(TEE_UUID));
FSD_HexFileName(sth_request->filename,filename,FILENAMESIZE);
//Create path to TA folder and test if does exist
strcpy(TAdirpath,tbstpath);
strcat(TAdirpath, "/");
strcat(TAdirpath, tadirname);
strcpy(Filepath, TAdirpath);
strcat(Filepath, "/");
strcat(Filepath, filename);
LOG_I("%s: Storage %s\n", __func__, tbstpath);
LOG_I("%s: TA dirname %s\n", __func__, tadirname);
LOG_I("%s: filename %s\n", __func__, filename);
LOG_I("%s: fullpath %s\n", __func__, Filepath);
pFile = fopen(Filepath, "r");
if (pFile==NULL)
{
LOG_E("%s: Error looking for file 0x%.8x\n",__func__,TEE_ERROR_ITEM_NOT_FOUND);
return TEE_ERROR_ITEM_NOT_FOUND;
}
res = fread(sth_request->payload,sizeof(char),sth_request->payloadLen,pFile);
fclose(pFile);
if ((uint32_t)res != sth_request->payloadLen)
{
LOG_E("%s: Error reading file res is %d and errno is %s\n",__func__,res,strerror(errno));
return TEE_ERROR_ITEM_NOT_FOUND;
}
return TEE_SUCCESS;
}
mcResult_t FSD::FSD_ReadFile(void){
FILE * pFile=NULL;
STH_FSD_message_t* sth_request=NULL;
size_t res;
string storage = getTbStoragePath();
const char* tbstpath = storage.c_str();
char tadirname[TEE_UUID_STRING_SIZE+1];
char filename[2*FILENAMESIZE+1];
char TAdirpath[strlen(tbstpath)+1+TEE_UUID_STRING_SIZE+1];
char Filepath[strlen(tbstpath)+1+TEE_UUID_STRING_SIZE+1+2*FILENAMESIZE+1];
sth_request= &dci->sth_request;
//create TA folder name from TA UUID
FSD_CreateTaDirName(&sth_request->uuid,tadirname,sizeof(TEE_UUID));
FSD_HexFileName(sth_request->filename,filename,FILENAMESIZE);
//Create path to TA folder and test if does exist
strcpy(TAdirpath,tbstpath);
strcat(TAdirpath, "/");
strcat(TAdirpath, tadirname);
strcpy(Filepath, TAdirpath);
strcat(Filepath, "/");
strcat(Filepath, filename);
LOG_I("%s: Storage %s\n", __func__, tbstpath);
LOG_I("%s: TA dirname %s\n", __func__, tadirname);
LOG_I("%s: filename %s\n", __func__, filename);
LOG_I("%s: fullpath %s\n", __func__, Filepath);
pFile = fopen(Filepath, "r");
if (pFile==NULL)
{
LOG_E("%s: Error looking for file 0x%.8x\n", __func__,TEE_ERROR_ITEM_NOT_FOUND);
return TEE_ERROR_ITEM_NOT_FOUND;
}
res = fread(sth_request->payload,sizeof(char),sth_request->payloadLen,pFile);
fclose(pFile);
if ((uint32_t)res != sth_request->payloadLen)
{
LOG_E("%s: Error reading file res is %d and errno is %s\n",__func__,res,strerror(errno));
return TEE_ERROR_ITEM_NOT_FOUND;
}
return TEE_SUCCESS;
}
mcResult_t FSD::FSD_WriteFile(void){
FILE * pFile=NULL;
int fd=0;
STH_FSD_message_t* sth_request=NULL;
size_t res=0;
int stat=0;
string storage = getTbStoragePath();
const char* tbstpath = storage.c_str();
char tadirname[TEE_UUID_STRING_SIZE+1];
char filename[2*FILENAMESIZE+1];
char TAdirpath[strlen(tbstpath)+1+TEE_UUID_STRING_SIZE+1];
char Filepath[strlen(tbstpath)+1+TEE_UUID_STRING_SIZE+1+2*FILENAMESIZE+1];
char Filepath_new[strlen(tbstpath)+TEE_UUID_STRING_SIZE+2*FILENAMESIZE+strlen(NEW_EXT)+1];
sth_request= &dci->sth_request;
FSD_CreateTaDirName(&sth_request->uuid,tadirname,sizeof(TEE_UUID));
FSD_HexFileName(sth_request->filename,filename,FILENAMESIZE);
strcpy(TAdirpath,tbstpath);
strcat(TAdirpath, "/");
strcat(TAdirpath, tadirname);
stat = mkdir(TAdirpath, 0700);
if((stat==-1) && (errno!=EEXIST))
{
LOG_E("%s: error when creating TA dir: %s (%s)\n",__func__,TAdirpath,strerror(errno));
return TEE_ERROR_STORAGE_NO_SPACE;
}
/* Directory exists. */
strcpy(Filepath, TAdirpath);
strcat(Filepath, "/");
strcat(Filepath, filename);
strcpy(Filepath_new,Filepath);
strcat(Filepath_new, NEW_EXT);
LOG_I("%s: Storage %s\n", __func__, tbstpath);
LOG_I("%s: TA dirname %s\n", __func__, tadirname);
LOG_I("%s: filename %s\n", __func__, filename);
LOG_I("%s: fullpath %s\n", __func__, Filepath);
LOG_I("%s: filename.new %s\n", __func__, Filepath_new);
if(sth_request->flags == TEE_DATA_FLAG_EXCLUSIVE)
{
LOG_I("%s: opening file in exclusive mode\n",__func__);
fd = open(Filepath, O_WRONLY | O_CREAT | O_EXCL, S_IWUSR);
if (fd == -1)
{
LOG_E("%s: error creating file: %s (%s)\n",__func__,Filepath,strerror(errno));
return TEE_ERROR_CORRUPT_OBJECT;
}
else
{
close(fd);
}
}
pFile = fopen(Filepath_new, "w");
LOG_I("%s: opening file for writing\n",__func__);
if(pFile==NULL)
{
if(remove(Filepath)==-1)
{
LOG_E("%s: remove failed: %s\n",__func__, strerror(errno));
}
return TEE_ERROR_STORAGE_NO_SPACE;
}
res = fwrite(sth_request->payload,sizeof(char),sth_request->payloadLen,pFile);
if ((uint32_t)res != sth_request->payloadLen)
{
LOG_E("%s: Error writing file res is %d and errno is %s\n",__func__,res,strerror(errno));
fclose(pFile);
if(remove(Filepath)==-1)
{
LOG_E("%s: remove failed: %s\n",__func__, strerror(errno));
}
if(remove(Filepath_new)==-1)
{
LOG_E("%s: remove failed: %s\n",__func__, strerror(errno));
}
return TEE_ERROR_ITEM_NOT_FOUND;
}
else
{
res = fclose(pFile);
if (res < 0)
{
LOG_E("%s: Error closing file res is %d and errno is %s\n",__func__,res,strerror(errno));
if(remove(Filepath)==-1)
{
LOG_E("%s: remove failed: %s\n",__func__, strerror(errno));
}
if(remove(Filepath_new)==-1)
{
LOG_E("%s: remove failed: %s\n",__func__, strerror(errno));
}
return TEE_ERROR_STORAGE_NO_SPACE;
}
res = rename(Filepath_new,Filepath);
if (res < 0)
{
LOG_E("%s: Error renaming %s: %s\n",__func__,Filepath_new,strerror(errno));
if(remove(Filepath)==-1)
{
LOG_E("%s: remove failed: %s\n",__func__, strerror(errno));
}
if(remove(Filepath_new)==-1)
{
LOG_E("%s: remove failed: %s\n",__func__, strerror(errno));
}
return TEE_ERROR_STORAGE_NO_SPACE;
}
}
return TEE_SUCCESS;
}
mcResult_t FSD::FSD_DeleteFile(void){
FILE * pFile=NULL;
mcResult_t ret;
size_t res;
STH_FSD_message_t* sth_request=NULL;
string storage = getTbStoragePath();
const char* tbstpath = storage.c_str();
char tadirname[TEE_UUID_STRING_SIZE+1];
char filename[2*FILENAMESIZE+1];
char TAdirpath[strlen(tbstpath)+1+TEE_UUID_STRING_SIZE+1];
char Filepath[strlen(tbstpath)+1+TEE_UUID_STRING_SIZE+1+2*FILENAMESIZE+1];
sth_request= &dci->sth_request;
//create TA folder name from TA UUID
FSD_CreateTaDirName(&sth_request->uuid,tadirname,sizeof(TEE_UUID));
FSD_HexFileName(sth_request->filename,filename,FILENAMESIZE);
//Create path to TA folder and test if does exist
strcpy(TAdirpath,tbstpath);
strcat(TAdirpath, "/");
strcat(TAdirpath, tadirname);
/* Directory exists. */
strcpy(Filepath, TAdirpath);
strcat(Filepath, "/");
strcat(Filepath, filename);
LOG_I("%s: Storage %s\n", __func__, tbstpath);
LOG_I("%s: TA dirname %s\n", __func__, tadirname);
LOG_I("%s: filename %s\n", __func__, filename);
LOG_I("%s: fullpath %s\n", __func__, Filepath);
pFile = fopen(Filepath, "r");
if (pFile==NULL)
{
LOG_I("%s: file not found: %s (%s)\n",__func__, Filepath, strerror(errno));
ret = TEE_SUCCESS;
}
else
{
fclose(pFile);
if(remove(Filepath)==-1)
{
ret = TEE_ERROR_STORAGE_NO_SPACE;
}
}
res = rmdir(TAdirpath);
if ((res < 0) && (errno != ENOTEMPTY) && (errno != EEXIST) && (errno != ENOENT))
{
ret = TEE_ERROR_STORAGE_NO_SPACE;
LOG_E("%s: rmdir failed: %s (%s)\n",__func__, TAdirpath, strerror(errno));
}
else
{
ret = TEE_SUCCESS;
}
return ret;
}
//------------------------------------------------------------------------------
/** @} */