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 */
54 typedef 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
69 static bool g_bMTCInitialized = false;
70
71
72 /*------------------------------------------------------------------------------
73 Static functions
74 ------------------------------------------------------------------------------*/
75
static_getMonotonicCounter(S_HANDLE hCounter,S_MONOTONIC_COUNTER_VALUE * psValue,bool bIncrement)76 static 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
SMonotonicCounterInit(void)124 MTC_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
SMonotonicCounterTerminate(void)146 MTC_EXPORT void SMonotonicCounterTerminate(void)
147 {
148 stubMutexLock();
149 if (g_bMTCInitialized)
150 {
151 stubFinalizeContext();
152 g_bMTCInitialized = false;
153 }
154 stubMutexUnlock();
155 }
156
SMonotonicCounterOpen(uint32_t nCounterIdentifier,OUT S_HANDLE * phCounter)157 MTC_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
232 error:
233 free(pSession);
234 return nError;
235 }
236
SMonotonicCounterClose(S_HANDLE hCounter)237 MTC_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
SMonotonicCounterGet(S_HANDLE hCounter,S_MONOTONIC_COUNTER_VALUE * psCurrentValue)262 MTC_EXPORT S_RESULT SMonotonicCounterGet(
263 S_HANDLE hCounter,
264 S_MONOTONIC_COUNTER_VALUE* psCurrentValue)
265 {
266 return static_getMonotonicCounter(hCounter, psCurrentValue, false);
267 }
268
SMonotonicCounterIncrement(S_HANDLE hCounter,S_MONOTONIC_COUNTER_VALUE * psNewValue)269 MTC_EXPORT S_RESULT SMonotonicCounterIncrement(
270 S_HANDLE hCounter,
271 S_MONOTONIC_COUNTER_VALUE* psNewValue)
272 {
273 return static_getMonotonicCounter(hCounter, psNewValue, true);
274 }
275