| /** |
| * Copyright(c) 2011 Trusted Logic. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * 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. |
| * * Neither the name Trusted Logic 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 |
| * OWNER 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. |
| */ |
| |
| #ifdef __ANDROID32__ |
| #include <stddef.h> |
| #endif |
| |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #define SST_EXPORTS |
| #define EXCLUDE_SERVICE_SYSTEM_SST_BASIC_TYPES |
| #include "sst.h" |
| |
| /* Included for the TEE management */ |
| #include "pkcs11_internal.h" |
| |
| |
| static TEEC_Session g_SSTSession; |
| static bool g_bSSTInitialized = false; |
| |
| |
| /* ------------------------------------------------------------------------ |
| TEEC -> SST error code translation |
| ------------------------------------------------------------------------- */ |
| static SST_ERROR static_SSTConvertErrorCode(TEEC_Result nError) |
| { |
| switch (nError) |
| { |
| case TEEC_SUCCESS: |
| return SST_SUCCESS; |
| case SST_ERROR_BAD_PARAMETERS: |
| case SST_ERROR_ACCESS_DENIED: |
| case SST_ERROR_ACCESS_CONFLICT: |
| case SST_ERROR_CORRUPTED: |
| case SST_ERROR_NO_SPACE: |
| case SST_ERROR_ITEM_NOT_FOUND: |
| case SST_ERROR_OUT_OF_MEMORY: |
| case SST_ERROR_OVERFLOW: |
| return nError; |
| default: |
| return SST_ERROR_GENERIC; |
| } |
| } |
| |
| static TEEC_Session* static_SSTGetSession(void) |
| { |
| if (g_bSSTInitialized) |
| { |
| return &g_SSTSession; |
| } |
| |
| return NULL; |
| } |
| |
| SST_ERROR SST_EXPORT_API SSTInit(void) |
| { |
| TEEC_Result nTeeError = TEEC_SUCCESS; |
| TEEC_Operation sOperation; |
| uint8_t nParamType3 = TEEC_NONE; |
| void* pSignatureFile = NULL; |
| uint32_t nSignatureFileLen = 0; |
| uint32_t nLoginType; |
| |
| stubMutexLock(); |
| if (g_bSSTInitialized) |
| { |
| /* SST library already initialized */ |
| nTeeError = TEEC_SUCCESS; |
| goto end; |
| } |
| |
| nTeeError = stubInitializeContext(); |
| if (nTeeError != TEEC_SUCCESS) |
| { |
| goto end; |
| } |
| |
| /* Check if there is a signature file. |
| * If yes, send it in param3, otherwise use LOGIN_APPLICATION |
| */ |
| nTeeError = TEEC_ReadSignatureFile(&pSignatureFile, &nSignatureFileLen); |
| if (nTeeError == TEEC_ERROR_ITEM_NOT_FOUND) |
| { |
| nLoginType = TEEC_LOGIN_USER_APPLICATION; |
| } |
| else |
| { |
| if (nTeeError != TEEC_SUCCESS) |
| { |
| goto end; |
| } |
| sOperation.params[3].tmpref.buffer = pSignatureFile; |
| sOperation.params[3].tmpref.size = nSignatureFileLen; |
| nParamType3 = TEEC_MEMREF_TEMP_INPUT; |
| nLoginType = TEEC_LOGIN_AUTHENTICATION; |
| } |
| |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, nParamType3); |
| nTeeError = TEEC_OpenSession(&g_sContext, |
| &g_SSTSession, /* OUT session */ |
| &SERVICE_UUID, /* destination UUID */ |
| nLoginType, /* connectionMethod */ |
| NULL, /* connectionData */ |
| &sOperation, /* IN OUT operation */ |
| NULL /* OUT returnOrigin, optional */ |
| ); |
| if (nTeeError != TEEC_SUCCESS) |
| { |
| goto end_finalize_context; |
| } |
| |
| g_bSSTInitialized = true; |
| stubMutexUnlock(); |
| return SST_SUCCESS; |
| |
| end_finalize_context: |
| stubFinalizeContext(); |
| end: |
| stubMutexUnlock(); |
| return static_SSTConvertErrorCode(nTeeError); |
| } |
| |
| SST_ERROR SST_EXPORT_API SSTTerminate(void) |
| { |
| stubMutexLock(); |
| if (g_bSSTInitialized) |
| { |
| TEEC_CloseSession(&g_SSTSession); |
| stubFinalizeContext(); |
| g_bSSTInitialized = false; |
| } |
| /* else if not intialized => success too */ |
| stubMutexUnlock(); |
| return SST_SUCCESS; |
| } |
| |
| |
| /* ------------------------------------------------------------------------ |
| Other API Functions |
| ------------------------------------------------------------------------- */ |
| |
| |
| /* Check that the input filename is well-formed */ |
| static SST_ERROR static_SSTCheckFileName(const char* pName) |
| { |
| uint32_t i; |
| char c; |
| |
| if (pName == NULL) |
| { |
| return SST_ERROR_BAD_PARAMETERS; |
| } |
| |
| for (i = 0; i <= SST_MAX_FILENAME; i++) |
| { |
| c = pName[i]; |
| if (c == 0) |
| { |
| /* End of the string */ |
| return SST_SUCCESS; |
| } |
| |
| if (c == '/' || c == '\\') |
| { |
| /* Invalid character */ |
| return SST_ERROR_BAD_PARAMETERS; |
| } |
| |
| if (c < 0x20 || c >= 0x7F) |
| { |
| /* Filename contains illegal characters */ |
| return SST_ERROR_BAD_PARAMETERS; |
| } |
| } |
| /* Filename is too long. Zero terminator not found */ |
| return SST_ERROR_BAD_PARAMETERS; |
| } |
| |
| static SST_ERROR static_SSTCheckPattern( |
| const char* pFilenamePattern) |
| { |
| uint32_t i; |
| if(pFilenamePattern == NULL) |
| { |
| return S_SUCCESS; |
| } |
| |
| /** |
| * Check Forbidden characters. |
| */ |
| for (i = 0; pFilenamePattern[i] != 0; i++) |
| { |
| if(pFilenamePattern[i] < 0x20 ) |
| { |
| return S_ERROR_BAD_PARAMETERS; |
| } |
| else if(pFilenamePattern[i] == 0x2F ) /* '/' */ |
| { |
| return S_ERROR_BAD_PARAMETERS; |
| } |
| else if(pFilenamePattern[i] == 0x5C ) /* '\' */ |
| { |
| /** |
| * Must be directly followed by asterisk character or question-mark |
| * character. |
| */ |
| if (! ((pFilenamePattern[i+1] == '*' || |
| pFilenamePattern[i+1] == '?'))) |
| { |
| return S_ERROR_BAD_PARAMETERS; |
| } |
| } |
| else if(pFilenamePattern[i] >= 0x7F ) |
| { |
| return S_ERROR_BAD_PARAMETERS; |
| } |
| } |
| |
| return S_SUCCESS; |
| } |
| |
| |
| |
| SST_ERROR SST_EXPORT_API SSTOpen(const char* pFilename, |
| uint32_t nFlags, |
| uint32_t nReserved, |
| SST_HANDLE* phFile) |
| { |
| TEEC_Session* pSession; |
| TEEC_Result nError; |
| TEEC_Operation sOperation; |
| uint32_t nReturnOrigin; |
| SST_ERROR nErrorCode = SST_SUCCESS; |
| |
| if (phFile == NULL || nReserved != 0) |
| { |
| return SST_ERROR_BAD_PARAMETERS; |
| } |
| |
| *phFile = SST_HANDLE_INVALID; |
| |
| nErrorCode = static_SSTCheckFileName(pFilename); |
| if (nErrorCode != SST_SUCCESS) |
| { |
| return nErrorCode; |
| } |
| |
| pSession = static_SSTGetSession(); |
| if (pSession == NULL) |
| { |
| return SST_ERROR_GENERIC; |
| } |
| |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].value.a = 1; /* Private storage */ |
| sOperation.params[0].value.b = nFlags; /* Access flags */ |
| sOperation.params[1].tmpref.buffer = (void*)pFilename; |
| sOperation.params[1].tmpref.size = strlen(pFilename); |
| nError = TEEC_InvokeCommand(pSession, |
| SERVICE_SYSTEM_SST_OPEN_COMMAND_ID, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nReturnOrigin /* OUT returnOrigin, optional */ |
| ); |
| if (nError == TEEC_SUCCESS) |
| { |
| *phFile = (SST_HANDLE)sOperation.params[0].value.a; |
| } |
| |
| return static_SSTConvertErrorCode(nError); |
| } |
| |
| SST_ERROR SST_EXPORT_API SSTCloseHandle(SST_HANDLE hFile) |
| { |
| TEEC_Session* pSession; |
| TEEC_Result nError; |
| TEEC_Operation sOperation; |
| uint32_t nReturnOrigin; |
| |
| if (hFile == S_HANDLE_NULL) |
| { |
| return SST_SUCCESS; |
| } |
| |
| pSession = static_SSTGetSession(); |
| if (pSession == NULL) |
| { |
| return SST_ERROR_GENERIC; |
| } |
| |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].value.a = hFile; |
| nError = TEEC_InvokeCommand(pSession, |
| SERVICE_SYSTEM_SST_CLOSE_COMMAND_ID, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nReturnOrigin /* OUT returnOrigin, optional */ |
| ); |
| |
| return static_SSTConvertErrorCode(nError); |
| } |
| |
| SST_ERROR SST_EXPORT_API SSTWrite(SST_HANDLE hFile, |
| const uint8_t* pBuffer, |
| uint32_t nSize) |
| { |
| TEEC_Session* pSession; |
| TEEC_Result nError; |
| TEEC_Operation sOperation; |
| uint32_t nReturnOrigin; |
| |
| if (pBuffer == NULL) |
| { |
| return SST_ERROR_BAD_PARAMETERS; |
| } |
| |
| if (nSize == 0) |
| { |
| return SST_SUCCESS; |
| } |
| |
| pSession = static_SSTGetSession(); |
| if (pSession == NULL) |
| { |
| return SST_ERROR_GENERIC; |
| } |
| |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].value.a = hFile; |
| sOperation.params[1].tmpref.buffer = (void*)pBuffer; |
| sOperation.params[1].tmpref.size = nSize; |
| |
| nError = TEEC_InvokeCommand(pSession, |
| SERVICE_SYSTEM_SST_WRITE_COMMAND_ID, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nReturnOrigin /* OUT returnOrigin, optional */ |
| ); |
| |
| return static_SSTConvertErrorCode(nError); |
| } |
| |
| |
| SST_ERROR SST_EXPORT_API SSTRead(SST_HANDLE hFile, |
| uint8_t* pBuffer, |
| uint32_t nSize, |
| uint32_t* pnCount) |
| { |
| TEEC_Session* pSession; |
| TEEC_Result nError; |
| TEEC_Operation sOperation; |
| uint32_t nReturnOrigin; |
| |
| if ((pBuffer == NULL) || (pnCount == NULL)) |
| { |
| return SST_ERROR_BAD_PARAMETERS; |
| } |
| *pnCount = 0; |
| |
| pSession = static_SSTGetSession(); |
| if (pSession == NULL) |
| { |
| return SST_ERROR_GENERIC; |
| } |
| |
| if (nSize == 0) |
| { |
| return SST_SUCCESS; |
| } |
| |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].value.a = hFile; |
| sOperation.params[1].tmpref.buffer = pBuffer; |
| sOperation.params[1].tmpref.size = nSize; |
| |
| nError = TEEC_InvokeCommand(pSession, |
| SERVICE_SYSTEM_SST_READ_COMMAND_ID, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nReturnOrigin /* OUT returnOrigin, optional */ |
| ); |
| |
| *pnCount = sOperation.params[1].tmpref.size; /* The returned buffer size */ |
| return static_SSTConvertErrorCode(nError); |
| } |
| |
| SST_ERROR SST_EXPORT_API SSTSeek(SST_HANDLE hFile, |
| int32_t nOffset, |
| SST_WHENCE whence) |
| { |
| TEEC_Session* pSession; |
| TEEC_Result nError; |
| TEEC_Operation sOperation; |
| uint32_t nReturnOrigin; |
| |
| switch(whence) |
| { |
| case SST_SEEK_SET: |
| case SST_SEEK_CUR: |
| case SST_SEEK_END: |
| break; |
| default: |
| return SST_ERROR_BAD_PARAMETERS; |
| } |
| |
| pSession = static_SSTGetSession(); |
| if (pSession == NULL) |
| { |
| return SST_ERROR_GENERIC; |
| } |
| |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].value.a = hFile; |
| sOperation.params[1].value.a = nOffset; |
| sOperation.params[1].value.b = (uint32_t)whence; |
| |
| nError = TEEC_InvokeCommand(pSession, |
| SERVICE_SYSTEM_SST_SEEK_COMMAND_ID, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nReturnOrigin /* OUT returnOrigin, optional */ |
| ); |
| return static_SSTConvertErrorCode(nError); |
| |
| } |
| |
| static SST_ERROR SSTGetOffsetAndSize(SST_HANDLE hFile, uint32_t* pnOffset, uint32_t* pnSize) |
| { |
| TEEC_Session* pSession; |
| TEEC_Result nError; |
| TEEC_Operation sOperation; |
| uint32_t nReturnOrigin; |
| |
| pSession = static_SSTGetSession(); |
| if (pSession == NULL) |
| { |
| return SST_ERROR_GENERIC; |
| } |
| |
| if (pnOffset == NULL) |
| { |
| return SST_ERROR_BAD_PARAMETERS; |
| } |
| |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].value.a = (uint32_t)hFile; |
| |
| nError = TEEC_InvokeCommand(pSession, |
| SERVICE_SYSTEM_SST_GET_OFFSET_AND_SIZE_COMMAND_ID, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nReturnOrigin /* OUT returnOrigin, optional */ |
| ); |
| |
| if (pnOffset != NULL) |
| { |
| *pnOffset = sOperation.params[0].value.a; |
| } |
| if (pnSize != NULL) |
| { |
| *pnSize = sOperation.params[0].value.b; |
| } |
| return static_SSTConvertErrorCode(nError); |
| |
| } |
| |
| SST_ERROR SST_EXPORT_API SSTTell(SST_HANDLE hFile, |
| uint32_t* pnPos) |
| { |
| return SSTGetOffsetAndSize(hFile, pnPos, NULL); |
| } |
| |
| SST_ERROR SST_EXPORT_API SSTGetSize(const char* pFilename, |
| uint32_t* pnSize) |
| { |
| TEEC_Session* pSession; |
| TEEC_Result nError; |
| TEEC_Operation sOperation; |
| uint32_t nReturnOrigin; |
| |
| if ((pFilename == NULL) || (pnSize == NULL)) |
| { |
| return SST_ERROR_BAD_PARAMETERS; |
| } |
| |
| nError = static_SSTCheckFileName(pFilename); |
| if (nError != SST_SUCCESS) |
| { |
| return nError; |
| } |
| |
| pSession = static_SSTGetSession(); |
| if (pSession == NULL) |
| { |
| return SST_ERROR_GENERIC; |
| } |
| |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].value.a = 1; /* private storage */ |
| sOperation.params[0].value.b = 0; |
| sOperation.params[1].tmpref.buffer = (void*)pFilename; |
| sOperation.params[1].tmpref.size = strlen(pFilename); |
| |
| nError = TEEC_InvokeCommand(pSession, |
| SERVICE_SYSTEM_SST_GET_SIZE_COMMAND_ID, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nReturnOrigin /* OUT returnOrigin, optional */ |
| ); |
| |
| *pnSize = sOperation.params[0].value.a; |
| return static_SSTConvertErrorCode(nError); |
| } |
| |
| |
| SST_ERROR SST_EXPORT_API SSTEof( SST_HANDLE hFile, |
| bool* pbEof) |
| { |
| uint32_t nOffset; |
| uint32_t nSize; |
| SST_ERROR nError; |
| if (pbEof == NULL) |
| return SST_ERROR_BAD_PARAMETERS; |
| nError = SSTGetOffsetAndSize(hFile, &nOffset, &nSize); |
| if (nError == SST_SUCCESS) |
| { |
| if (nOffset >= nSize) |
| { |
| *pbEof = true; |
| } |
| else |
| { |
| *pbEof = false; |
| } |
| } |
| return nError; |
| } |
| |
| SST_ERROR SST_EXPORT_API SSTCloseAndDelete(SST_HANDLE hFile) |
| { |
| TEEC_Session* pSession; |
| TEEC_Result nError; |
| TEEC_Operation sOperation; |
| uint32_t nReturnOrigin; |
| |
| pSession = static_SSTGetSession(); |
| if (pSession == NULL) |
| { |
| return SST_ERROR_GENERIC; |
| } |
| |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].value.a = hFile; |
| |
| nError = TEEC_InvokeCommand(pSession, |
| SERVICE_SYSTEM_SST_CLOSE_DELETE_COMMAND_ID, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nReturnOrigin /* OUT returnOrigin, optional */ |
| ); |
| return static_SSTConvertErrorCode(nError); |
| } |
| |
| SST_ERROR SST_EXPORT_API SSTTruncate(SST_HANDLE hFile, uint32_t nLength) |
| { |
| TEEC_Session* pSession; |
| TEEC_Result nError; |
| TEEC_Operation sOperation; |
| uint32_t nReturnOrigin; |
| |
| pSession = static_SSTGetSession(); |
| if (pSession == NULL) |
| { |
| return SST_ERROR_GENERIC; |
| } |
| |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].value.a = hFile; |
| sOperation.params[0].value.b = nLength; |
| |
| nError = TEEC_InvokeCommand(pSession, |
| SERVICE_SYSTEM_SST_TRUNCATE_COMMAND_ID, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nReturnOrigin /* OUT returnOrigin, optional */ |
| ); |
| return static_SSTConvertErrorCode(nError); |
| } |
| |
| SST_ERROR SST_EXPORT_API SSTRename(SST_HANDLE hFile, |
| const char* pNewFilename) |
| { |
| TEEC_Session* pSession; |
| TEEC_Result nError; |
| TEEC_Operation sOperation; |
| uint32_t nReturnOrigin; |
| |
| pSession = static_SSTGetSession(); |
| if (pSession == NULL) |
| { |
| return SST_ERROR_GENERIC; |
| } |
| |
| if (pNewFilename == NULL) |
| { |
| return SST_ERROR_BAD_PARAMETERS; |
| } |
| |
| nError = static_SSTCheckFileName(pNewFilename); |
| if (nError != SST_SUCCESS) |
| { |
| return nError; |
| } |
| |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].value.a = hFile; |
| sOperation.params[1].tmpref.buffer = (void*)pNewFilename; |
| sOperation.params[1].tmpref.size = strlen(pNewFilename); |
| |
| nError = TEEC_InvokeCommand(pSession, |
| SERVICE_SYSTEM_SST_RENAME_COMMAND_ID, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nReturnOrigin /* OUT returnOrigin, optional */ |
| ); |
| return static_SSTConvertErrorCode(nError); |
| } |
| |
| SST_ERROR SST_EXPORT_API SSTEnumerationStart(const char* pFilenamePattern, |
| uint32_t nReserved1, |
| uint32_t nReserved2, |
| SST_HANDLE* phFileEnumeration) |
| { |
| TEEC_Session* pSession; |
| TEEC_Result nError; |
| TEEC_Operation sOperation; |
| uint32_t nReturnOrigin; |
| |
| if (nReserved1!=0 || nReserved2!=0) |
| { |
| return SST_ERROR_BAD_PARAMETERS; |
| } |
| if (phFileEnumeration==NULL) |
| { |
| return SST_ERROR_BAD_PARAMETERS; |
| } |
| *phFileEnumeration = SST_HANDLE_INVALID; |
| |
| nError = static_SSTCheckPattern(pFilenamePattern); |
| if (nError != SST_SUCCESS) |
| { |
| return nError; |
| } |
| |
| pSession = static_SSTGetSession(); |
| if (pSession == NULL) |
| { |
| return SST_ERROR_GENERIC; |
| } |
| |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].value.a = 1; /* Private storage */ |
| sOperation.params[1].tmpref.buffer = (void*)pFilenamePattern; |
| if (pFilenamePattern != NULL) |
| { |
| sOperation.params[1].tmpref.size = strlen(pFilenamePattern); |
| } |
| else |
| { |
| sOperation.params[1].tmpref.size = 0; |
| } |
| |
| nError = TEEC_InvokeCommand(pSession, |
| SERVICE_SYSTEM_SST_ENUM_START_COMMAND_ID, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nReturnOrigin /* OUT returnOrigin, optional */ |
| ); |
| |
| *phFileEnumeration = (SST_HANDLE)sOperation.params[0].value.a; |
| return static_SSTConvertErrorCode(nError); |
| } |
| |
| SST_ERROR SST_EXPORT_API SSTEnumerationCloseHandle(SST_HANDLE hFileEnumeration) |
| { |
| TEEC_Session* pSession; |
| TEEC_Result nError; |
| TEEC_Operation sOperation; |
| uint32_t nReturnOrigin; |
| |
| pSession = static_SSTGetSession(); |
| if (pSession == NULL) |
| { |
| return SST_ERROR_GENERIC; |
| } |
| |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].value.a = hFileEnumeration; |
| |
| nError = TEEC_InvokeCommand(pSession, |
| SERVICE_SYSTEM_SST_ENUM_CLOSE_COMMAND_ID, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nReturnOrigin /* OUT returnOrigin, optional */ |
| ); |
| |
| return static_SSTConvertErrorCode(nError); |
| } |
| |
| SST_ERROR SST_EXPORT_API SSTEnumerationGetNext(SST_HANDLE hFileEnumeration, |
| SST_FILE_INFO** ppFileInfo) |
| |
| { |
| TEEC_Session* pSession; |
| TEEC_Result nError; |
| TEEC_Operation sOperation; |
| uint32_t nReturnOrigin; |
| SST_FILE_INFO* pInfo = NULL; |
| char sFilename[SST_MAX_FILENAME]; |
| |
| if (ppFileInfo==NULL) |
| { |
| return SST_ERROR_BAD_PARAMETERS; |
| } |
| |
| pSession = static_SSTGetSession(); |
| if (pSession == NULL) |
| { |
| return SST_ERROR_GENERIC; |
| } |
| |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].value.a = hFileEnumeration; |
| sOperation.params[1].tmpref.buffer = sFilename; |
| sOperation.params[1].tmpref.size = SST_MAX_FILENAME; |
| |
| nError = TEEC_InvokeCommand(pSession, |
| SERVICE_SYSTEM_SST_ENUM_GETNEXT_COMMAND_ID, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nReturnOrigin /* OUT returnOrigin, optional */ |
| ); |
| |
| if (nError == TEEC_SUCCESS) |
| { |
| if (sOperation.params[1].tmpref.size <= SST_MAX_FILENAME) |
| { |
| pInfo = (SST_FILE_INFO*)malloc(sizeof(SST_FILE_INFO)); |
| if (pInfo == NULL) |
| { |
| return SST_ERROR_OUT_OF_MEMORY; |
| } |
| pInfo->pName = (char*)malloc(sOperation.params[1].tmpref.size+1); |
| if (pInfo->pName == NULL) |
| { |
| free(pInfo); |
| return SST_ERROR_OUT_OF_MEMORY; |
| } |
| memcpy(pInfo->pName, sFilename, sOperation.params[1].tmpref.size); |
| /* Add zero terminator */ |
| pInfo->pName[sOperation.params[1].tmpref.size] = 0; |
| pInfo->nSize = sOperation.params[0].value.b; |
| } |
| } |
| *ppFileInfo = pInfo; |
| return static_SSTConvertErrorCode(nError); |
| } |
| |
| SST_ERROR SST_EXPORT_API SSTDestroyFileInfo(SST_FILE_INFO* pFileInfo) |
| { |
| TEEC_Session* pSession; |
| |
| pSession = static_SSTGetSession(); |
| if (pSession == NULL) |
| { |
| return SST_ERROR_GENERIC; |
| } |
| |
| if (pFileInfo != NULL) |
| { |
| free(pFileInfo->pName); |
| free(pFileInfo); |
| } |
| return SST_SUCCESS; |
| } |