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