Home | History | Annotate | Download | only in tf_crypto_sst
      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 /*
     32  * Implementation Notes:
     33  *
     34  * This API is NOT thread-safe. Indeed this Cryptoki implementation
     35  * only supports option 1 defined in PKCS#11, section 6.5.2:
     36  * "The application can specify that it will not be accessing the library concurrently
     37  * from multiple threads, and so the library need not worry about performing any type
     38  * of locking for the sake of thread-safety."
     39  */
     40 
     41 #include "pkcs11_internal.h"
     42 
     43 /* ------------------------------------------------------------------------
     44     System Service UUID
     45 ------------------------------------------------------------------------- */
     46 const TEEC_UUID SERVICE_UUID = SERVICE_SYSTEM_UUID;
     47 
     48 /* ------------------------------------------------------------------------
     49     Definition of the global TEE Context
     50 ------------------------------------------------------------------------- */
     51 TEEC_Context g_sContext;
     52 /* A mutex that protects the access to the global context and to the
     53    g_bContextRefCounter flag */
     54 LIB_MUTEX g_sContextMutex = LIB_MUTEX_INITIALIZER;
     55 /* Whether the context has already been initialized or not */
     56 uint32_t  g_nContextRefCounter = 0;
     57 
     58 bool g_bCryptokiInitialized = false;
     59 
     60 /* ------------------------------------------------------------------------
     61    Internal global TEE context management
     62 ------------------------------------------------------------------------- */
     63 
     64 void stubMutexLock(void)
     65 {
     66    libMutexLock(&g_sContextMutex);
     67 }
     68 
     69 void stubMutexUnlock(void)
     70 {
     71    libMutexUnlock(&g_sContextMutex);
     72 }
     73 
     74 /* This API must be protected by stubMutexLock/Unlock */
     75 TEEC_Result stubInitializeContext(void)
     76 {
     77    TEEC_Result nTeeError;
     78 
     79    if (g_nContextRefCounter)
     80    {
     81       g_nContextRefCounter ++;
     82       return TEEC_SUCCESS;
     83    }
     84 
     85    nTeeError = TEEC_InitializeContext(NULL, &g_sContext);
     86    if (nTeeError == TEEC_SUCCESS)
     87    {
     88       g_nContextRefCounter = 1;
     89    }
     90 
     91    return nTeeError;
     92 }
     93 
     94 /* This API must be protected by stubMutexLock/Unlock */
     95 void stubFinalizeContext(void)
     96 {
     97    if (g_nContextRefCounter > 0)
     98    {
     99       g_nContextRefCounter --;
    100    }
    101 
    102    if (g_nContextRefCounter == 0)
    103    {
    104       TEEC_FinalizeContext(&g_sContext);
    105       memset(&g_sContext, 0, sizeof(TEEC_Context));
    106    }
    107 }
    108 
    109 
    110 /* ------------------------------------------------------------------------
    111                           Internal monitor management
    112 ------------------------------------------------------------------------- */
    113 /**
    114 * Check that hSession is a valid primary session,
    115 * or a valid secondary session attached to a valid primary session.
    116 *
    117 * input:
    118 *   S_HANDLE hSession: the session handle to check
    119 * output:
    120 *   bool* pBoolIsPrimarySession: a boolean set to true if the session is primary,
    121 *             set to false if the session if the session is secondary
    122 *   returned boolean: set to true iff :
    123 *              - either hSession is a valid primary session
    124 *              - or hSession is a valid secondary session attached to a valid primary session
    125 **/
    126 bool ckInternalSessionIsOpenedEx(S_HANDLE hSession, bool* pBoolIsPrimarySession)
    127 {
    128    PPKCS11_SESSION_CONTEXT_HEADER   pHeader = (PPKCS11_SESSION_CONTEXT_HEADER)hSession;
    129    PPKCS11_PRIMARY_SESSION_CONTEXT  pSession = NULL;
    130 
    131    if ((pHeader == NULL) || (pHeader->nMagicWord != PKCS11_SESSION_MAGIC))
    132    {
    133       return FALSE;
    134    }
    135    if (pHeader->nSessionTag == PKCS11_PRIMARY_SESSION_TAG) /* primary session */
    136    {
    137       pSession = (PPKCS11_PRIMARY_SESSION_CONTEXT)pHeader;
    138 
    139       *pBoolIsPrimarySession = true;
    140 
    141       /* check that primary session is valid */
    142       return (pSession->hCryptoSession != CK_INVALID_HANDLE);
    143    }
    144    else if (pHeader->nSessionTag == PKCS11_SECONDARY_SESSION_TAG) /*secondary session */
    145    {
    146       PPKCS11_SECONDARY_SESSION_CONTEXT pSecSession = (PPKCS11_SECONDARY_SESSION_CONTEXT)pHeader;
    147 
    148       *pBoolIsPrimarySession = false;
    149 
    150       /* check that primary session is still valid */
    151       pSession = pSecSession->pPrimarySession;
    152       if (  (pSession == NULL) ||
    153             (pSession->sHeader.nMagicWord != PKCS11_SESSION_MAGIC) ||
    154             (pSession->sHeader.nSessionTag != PKCS11_PRIMARY_SESSION_TAG))
    155       {
    156          return FALSE;
    157       }
    158 
    159       if (pSession->hCryptoSession == CK_INVALID_HANDLE)
    160       {
    161          return FALSE;
    162       }
    163 
    164       /* check that secondary session is valid */
    165       return (pSecSession->hSecondaryCryptoSession != CK_INVALID_HANDLE);
    166    }
    167    else
    168    {
    169      return FALSE;
    170    }
    171 }
    172 
    173 /* ------------------------------------------------------------------------
    174                           Internal error management
    175 ------------------------------------------------------------------------- */
    176 
    177 CK_RV ckInternalTeeErrorToCKError(TEEC_Result nError)
    178 {
    179    switch (nError)
    180    {
    181       case TEEC_SUCCESS:
    182          return CKR_OK;
    183 
    184       case TEEC_ERROR_BAD_PARAMETERS:
    185       case TEEC_ERROR_BAD_FORMAT:
    186          return CKR_ARGUMENTS_BAD;
    187       case TEEC_ERROR_OUT_OF_MEMORY:
    188          return CKR_HOST_MEMORY;
    189       case TEEC_ERROR_ACCESS_DENIED:
    190          return CKR_TOKEN_NOT_PRESENT;
    191       default:
    192          return CKR_DEVICE_ERROR;
    193    }
    194 }
    195 
    196 /* ------------------------------------------------------------------------
    197                           Public Functions
    198 ------------------------------------------------------------------------- */
    199 CK_RV PKCS11_EXPORT C_Initialize(CK_VOID_PTR pInitArgs)
    200 {
    201    CK_RV       nErrorCode;
    202    TEEC_Result nTeeError;
    203 
    204    if (pInitArgs != NULL_PTR)
    205    {
    206       return CKR_ARGUMENTS_BAD;
    207    }
    208 
    209    stubMutexLock();
    210    if (g_bCryptokiInitialized)
    211    {
    212       nErrorCode = CKR_CRYPTOKI_ALREADY_INITIALIZED;
    213    }
    214    else
    215    {
    216       nTeeError = stubInitializeContext();
    217       if (nTeeError == TEEC_SUCCESS)
    218       {
    219          g_bCryptokiInitialized = true;
    220       }
    221       nErrorCode = ckInternalTeeErrorToCKError(nTeeError);
    222    }
    223    stubMutexUnlock();
    224 
    225    return nErrorCode;
    226 }
    227 
    228 CK_RV PKCS11_EXPORT C_Finalize(CK_VOID_PTR pReserved)
    229 {
    230    CK_RV nErrorCode;
    231 
    232    if (pReserved != NULL_PTR)
    233    {
    234       return CKR_ARGUMENTS_BAD;
    235    }
    236 
    237    stubMutexLock();
    238    if (g_bCryptokiInitialized)
    239    {
    240       stubFinalizeContext();
    241       g_bCryptokiInitialized = false;
    242       nErrorCode = CKR_OK;
    243    }
    244    else
    245    {
    246       nErrorCode = CKR_CRYPTOKI_NOT_INITIALIZED;
    247    }
    248    stubMutexUnlock();
    249 
    250    return nErrorCode;
    251 }
    252 
    253 static const CK_INFO sImplementationInfo =
    254 {
    255    {2, 20},         /* cryptokiVersion, spec 2.20 */
    256    "Trusted Logic", /* manufacturerID */
    257    0,               /* flags */
    258    "PKCS#11",       /* libraryDescription */
    259    {3, 0}           /* libraryVersion */
    260 };
    261 
    262 CK_RV PKCS11_EXPORT C_GetInfo(CK_INFO_PTR pInfo)
    263 {
    264    if (!g_bCryptokiInitialized)
    265    {
    266       return CKR_CRYPTOKI_NOT_INITIALIZED;
    267    }
    268    if (pInfo == NULL_PTR)
    269    {
    270       return CKR_ARGUMENTS_BAD;
    271    }
    272 
    273    memcpy(pInfo, &sImplementationInfo, sizeof(CK_INFO));
    274    return CKR_OK;
    275 }
    276