/** * 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. */ #include #include #include #define MTC_EXPORTS #include "mtc.h" /* Included for the TEE management */ #include "pkcs11_internal.h" /*------------------------------------------------------------------------------ Defines ------------------------------------------------------------------------------*/ /** * The magic word. */ #define MTC_SESSION_MAGIC ( (uint32_t)0x4D544300 ) /* "MTC\0" */ /** * The MTC session context */ typedef struct { /* Magic word, must be set to {MTC_SESSION_MAGIC}. */ uint32_t nMagicWord; /* MTC Identifier */ uint32_t nCounterIdentifier; /* TEEC session and cryptoki session */ TEEC_Session sSession; uint32_t hCryptoSession; } MTC_SESSION_CONTEXT; static bool g_bMTCInitialized = false; /*------------------------------------------------------------------------------ Static functions ------------------------------------------------------------------------------*/ static S_RESULT static_getMonotonicCounter(S_HANDLE hCounter, S_MONOTONIC_COUNTER_VALUE* psValue, bool bIncrement) { TEEC_Result nError; TEEC_Operation sOperation; MTC_SESSION_CONTEXT* pSession = NULL; uint32_t nCommandID; if (!g_bMTCInitialized) { return S_ERROR_BAD_STATE; } pSession = (MTC_SESSION_CONTEXT *)hCounter; if ((pSession == NULL) || (pSession->nMagicWord != MTC_SESSION_MAGIC)) { return S_ERROR_BAD_PARAMETERS; } if (bIncrement) { nCommandID = SERVICE_SYSTEM_PKCS11_INCREMENT_MTC_COMMAND_ID; } else { nCommandID = SERVICE_SYSTEM_PKCS11_GET_MTC_COMMAND_ID; } sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); sOperation.params[0].value.a = pSession->nCounterIdentifier; sOperation.params[0].value.b = 0; nError = TEEC_InvokeCommand(&pSession->sSession, (pSession->hCryptoSession << 16 ) | (nCommandID & 0x00007FFF), &sOperation, NULL); psValue->nLow = sOperation.params[0].value.a; psValue->nHigh = sOperation.params[0].value.b; return nError; } /*------------------------------------------------------------------------------ API ------------------------------------------------------------------------------*/ MTC_EXPORT S_RESULT SMonotonicCounterInit(void) { TEEC_Result nTeeError; stubMutexLock(); if (g_bMTCInitialized) { nTeeError = TEEC_SUCCESS; } else { nTeeError = stubInitializeContext(); if (nTeeError == TEEC_SUCCESS) { g_bMTCInitialized = true; } } stubMutexUnlock(); return nTeeError; } MTC_EXPORT void SMonotonicCounterTerminate(void) { stubMutexLock(); if (g_bMTCInitialized) { stubFinalizeContext(); g_bMTCInitialized = false; } stubMutexUnlock(); } MTC_EXPORT S_RESULT SMonotonicCounterOpen( uint32_t nCounterIdentifier, OUT S_HANDLE* phCounter) { TEEC_Result nError; TEEC_Operation sOperation; MTC_SESSION_CONTEXT* pSession = NULL; S_MONOTONIC_COUNTER_VALUE nCounterValue; if (phCounter == NULL) { return S_ERROR_BAD_PARAMETERS; } *phCounter = S_HANDLE_NULL; if (!g_bMTCInitialized) { return S_ERROR_BAD_STATE; } if (nCounterIdentifier != S_MONOTONIC_COUNTER_GLOBAL) { return S_ERROR_ITEM_NOT_FOUND; } pSession = (MTC_SESSION_CONTEXT*)malloc(sizeof(MTC_SESSION_CONTEXT)); if (pSession == NULL) { return S_ERROR_OUT_OF_MEMORY; } memset(pSession, 0, sizeof(MTC_SESSION_CONTEXT)); pSession->nMagicWord = MTC_SESSION_MAGIC; /* Open a TEE session with the system service */ nError = TEEC_OpenSession(&g_sContext, &pSession->sSession, &SERVICE_UUID, TEEC_LOGIN_PUBLIC, NULL, NULL, /* No operation parameters */ NULL); if (nError != TEEC_SUCCESS) { goto error; } /* Open a cryptoki session */ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); sOperation.params[0].value.a = CKV_TOKEN_SYSTEM_SHARED; sOperation.params[0].value.b = CKF_RW_SESSION | CKF_SERIAL_SESSION; nError = TEEC_InvokeCommand(&pSession->sSession, SERVICE_SYSTEM_PKCS11_C_OPEN_SESSION_COMMAND_ID & 0x00007FFF, &sOperation, NULL); if (nError != TEEC_SUCCESS) { TEEC_CloseSession(&pSession->sSession); goto error; } pSession->hCryptoSession = sOperation.params[0].value.a; pSession->nCounterIdentifier = nCounterIdentifier; nError = SMonotonicCounterGet((S_HANDLE)pSession, &nCounterValue); if (nError != TEEC_SUCCESS) { SMonotonicCounterClose((S_HANDLE)pSession); return nError; } *phCounter = (S_HANDLE)pSession; return TEEC_SUCCESS; error: free(pSession); return nError; } MTC_EXPORT void SMonotonicCounterClose(S_HANDLE hCounter) { MTC_SESSION_CONTEXT* pSession; if (!g_bMTCInitialized) { return; } pSession = (MTC_SESSION_CONTEXT *)hCounter; if ((pSession == NULL) || (pSession->nMagicWord != MTC_SESSION_MAGIC)) { return; } (void)TEEC_InvokeCommand(&pSession->sSession, (pSession->hCryptoSession << 16 ) | (SERVICE_SYSTEM_PKCS11_C_CLOSE_SESSION_COMMAND_ID & 0x00007FFF), NULL, /* No operation parameters */ NULL); TEEC_CloseSession(&pSession->sSession); free(pSession); } MTC_EXPORT S_RESULT SMonotonicCounterGet( S_HANDLE hCounter, S_MONOTONIC_COUNTER_VALUE* psCurrentValue) { return static_getMonotonicCounter(hCounter, psCurrentValue, false); } MTC_EXPORT S_RESULT SMonotonicCounterIncrement( S_HANDLE hCounter, S_MONOTONIC_COUNTER_VALUE* psNewValue) { return static_getMonotonicCounter(hCounter, psNewValue, true); }