1/** 2 * Copyright(c) 2011 Trusted Logic. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name Trusted Logic nor the names of its 15 * contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include <assert.h> 32#include <stdlib.h> 33#include <string.h> 34 35#define MTC_EXPORTS 36#include "mtc.h" 37 38/* Included for the TEE management */ 39#include "pkcs11_internal.h" 40 41 42/*------------------------------------------------------------------------------ 43 Defines 44------------------------------------------------------------------------------*/ 45 46/** 47 * The magic word. 48 */ 49#define MTC_SESSION_MAGIC ( (uint32_t)0x4D544300 ) /* "MTC\0" */ 50 51/** 52 * The MTC session context 53 */ 54typedef struct 55{ 56 /* Magic word, must be set to {MTC_SESSION_MAGIC}. */ 57 uint32_t nMagicWord; 58 59 /* MTC Identifier */ 60 uint32_t nCounterIdentifier; 61 62 /* TEEC session and cryptoki session */ 63 TEEC_Session sSession; 64 uint32_t hCryptoSession; 65 66} MTC_SESSION_CONTEXT; 67 68 69static bool g_bMTCInitialized = false; 70 71 72/*------------------------------------------------------------------------------ 73 Static functions 74------------------------------------------------------------------------------*/ 75 76static S_RESULT static_getMonotonicCounter(S_HANDLE hCounter, 77 S_MONOTONIC_COUNTER_VALUE* psValue, 78 bool bIncrement) 79{ 80 TEEC_Result nError; 81 TEEC_Operation sOperation; 82 MTC_SESSION_CONTEXT* pSession = NULL; 83 uint32_t nCommandID; 84 85 if (!g_bMTCInitialized) 86 { 87 return S_ERROR_BAD_STATE; 88 } 89 90 pSession = (MTC_SESSION_CONTEXT *)hCounter; 91 if ((pSession == NULL) || (pSession->nMagicWord != MTC_SESSION_MAGIC)) 92 { 93 return S_ERROR_BAD_PARAMETERS; 94 } 95 96 if (bIncrement) 97 { 98 nCommandID = SERVICE_SYSTEM_PKCS11_INCREMENT_MTC_COMMAND_ID; 99 } 100 else 101 { 102 nCommandID = SERVICE_SYSTEM_PKCS11_GET_MTC_COMMAND_ID; 103 } 104 105 sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); 106 sOperation.params[0].value.a = pSession->nCounterIdentifier; 107 sOperation.params[0].value.b = 0; 108 nError = TEEC_InvokeCommand(&pSession->sSession, 109 (pSession->hCryptoSession << 16 ) | 110 (nCommandID & 0x00007FFF), 111 &sOperation, 112 NULL); 113 114 psValue->nLow = sOperation.params[0].value.a; 115 psValue->nHigh = sOperation.params[0].value.b; 116 117 return nError; 118} 119 120/*------------------------------------------------------------------------------ 121 API 122------------------------------------------------------------------------------*/ 123 124MTC_EXPORT S_RESULT SMonotonicCounterInit(void) 125{ 126 TEEC_Result nTeeError; 127 128 stubMutexLock(); 129 if (g_bMTCInitialized) 130 { 131 nTeeError = TEEC_SUCCESS; 132 } 133 else 134 { 135 nTeeError = stubInitializeContext(); 136 if (nTeeError == TEEC_SUCCESS) 137 { 138 g_bMTCInitialized = true; 139 } 140 } 141 stubMutexUnlock(); 142 143 return nTeeError; 144} 145 146MTC_EXPORT void SMonotonicCounterTerminate(void) 147{ 148 stubMutexLock(); 149 if (g_bMTCInitialized) 150 { 151 stubFinalizeContext(); 152 g_bMTCInitialized = false; 153 } 154 stubMutexUnlock(); 155} 156 157MTC_EXPORT S_RESULT SMonotonicCounterOpen( 158 uint32_t nCounterIdentifier, 159 OUT S_HANDLE* phCounter) 160{ 161 TEEC_Result nError; 162 TEEC_Operation sOperation; 163 MTC_SESSION_CONTEXT* pSession = NULL; 164 S_MONOTONIC_COUNTER_VALUE nCounterValue; 165 166 if (phCounter == NULL) 167 { 168 return S_ERROR_BAD_PARAMETERS; 169 } 170 171 *phCounter = S_HANDLE_NULL; 172 173 if (!g_bMTCInitialized) 174 { 175 return S_ERROR_BAD_STATE; 176 } 177 178 if (nCounterIdentifier != S_MONOTONIC_COUNTER_GLOBAL) 179 { 180 return S_ERROR_ITEM_NOT_FOUND; 181 } 182 183 pSession = (MTC_SESSION_CONTEXT*)malloc(sizeof(MTC_SESSION_CONTEXT)); 184 if (pSession == NULL) 185 { 186 return S_ERROR_OUT_OF_MEMORY; 187 } 188 memset(pSession, 0, sizeof(MTC_SESSION_CONTEXT)); 189 pSession->nMagicWord = MTC_SESSION_MAGIC; 190 191 /* Open a TEE session with the system service */ 192 nError = TEEC_OpenSession(&g_sContext, 193 &pSession->sSession, 194 &SERVICE_UUID, 195 TEEC_LOGIN_PUBLIC, 196 NULL, 197 NULL, /* No operation parameters */ 198 NULL); 199 if (nError != TEEC_SUCCESS) 200 { 201 goto error; 202 } 203 204 /* Open a cryptoki session */ 205 sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); 206 sOperation.params[0].value.a = CKV_TOKEN_SYSTEM_SHARED; 207 sOperation.params[0].value.b = CKF_RW_SESSION | CKF_SERIAL_SESSION; 208 nError = TEEC_InvokeCommand(&pSession->sSession, 209 SERVICE_SYSTEM_PKCS11_C_OPEN_SESSION_COMMAND_ID & 0x00007FFF, 210 &sOperation, 211 NULL); 212 if (nError != TEEC_SUCCESS) 213 { 214 TEEC_CloseSession(&pSession->sSession); 215 goto error; 216 } 217 218 pSession->hCryptoSession = sOperation.params[0].value.a; 219 pSession->nCounterIdentifier = nCounterIdentifier; 220 221 nError = SMonotonicCounterGet((S_HANDLE)pSession, &nCounterValue); 222 if (nError != TEEC_SUCCESS) 223 { 224 SMonotonicCounterClose((S_HANDLE)pSession); 225 return nError; 226 } 227 228 *phCounter = (S_HANDLE)pSession; 229 230 return TEEC_SUCCESS; 231 232error: 233 free(pSession); 234 return nError; 235} 236 237MTC_EXPORT void SMonotonicCounterClose(S_HANDLE hCounter) 238{ 239 MTC_SESSION_CONTEXT* pSession; 240 241 if (!g_bMTCInitialized) 242 { 243 return; 244 } 245 246 pSession = (MTC_SESSION_CONTEXT *)hCounter; 247 if ((pSession == NULL) || (pSession->nMagicWord != MTC_SESSION_MAGIC)) 248 { 249 return; 250 } 251 252 (void)TEEC_InvokeCommand(&pSession->sSession, 253 (pSession->hCryptoSession << 16 ) | 254 (SERVICE_SYSTEM_PKCS11_C_CLOSE_SESSION_COMMAND_ID & 0x00007FFF), 255 NULL, /* No operation parameters */ 256 NULL); 257 258 TEEC_CloseSession(&pSession->sSession); 259 free(pSession); 260} 261 262MTC_EXPORT S_RESULT SMonotonicCounterGet( 263 S_HANDLE hCounter, 264 S_MONOTONIC_COUNTER_VALUE* psCurrentValue) 265{ 266 return static_getMonotonicCounter(hCounter, psCurrentValue, false); 267} 268 269MTC_EXPORT S_RESULT SMonotonicCounterIncrement( 270 S_HANDLE hCounter, 271 S_MONOTONIC_COUNTER_VALUE* psNewValue) 272{ 273 return static_getMonotonicCounter(hCounter, psNewValue, true); 274} 275