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  * The PKCS11 session handle is directly mapped on the
     35  * Trusted Foundations Software session handle (S_HANDLE).
     36  */
     37 
     38 #include "pkcs11_internal.h"
     39 
     40 
     41 /* ------------------------------------------------------------------------
     42                           Public Functions
     43 ------------------------------------------------------------------------- */
     44 
     45 
     46 CK_RV PKCS11_EXPORT C_OpenSession(CK_SLOT_ID              slotID,        /* the slot's ID */
     47                                     CK_FLAGS              flags,         /* defined in CK_SESSION_INFO */
     48                                     CK_VOID_PTR           pApplication,  /* pointer passed to callback */
     49                                     CK_NOTIFY             Notify,        /* notification callback function */
     50                                     CK_SESSION_HANDLE*    phSession)     /* receives new session handle */
     51 {
     52    CK_RV                   nErrorCode = CKR_OK;
     53    uint32_t                nErrorOrigin = TEEC_ORIGIN_API;
     54    TEEC_Result             nTeeError;
     55    TEEC_Operation          sOperation;
     56    PPKCS11_PRIMARY_SESSION_CONTEXT   pSession = NULL;
     57    PPKCS11_SECONDARY_SESSION_CONTEXT pSecondarySession = NULL;
     58    uint32_t                nLoginType;
     59    uint32_t                nLoginData = 0;
     60    void*                   pLoginData = NULL;
     61    bool                    bIsPrimarySession;
     62    char*                   pSignatureFile = NULL;
     63    uint32_t                nSignatureFileLen = 0;
     64    uint8_t                 nParamType3 = TEEC_NONE;
     65 
     66    /* Prevent the compiler from complaining about unused parameters */
     67    do{(void)pApplication;}while(0);
     68    do{(void)Notify;}while(0);
     69 
     70    if (phSession == NULL)
     71    {
     72       return CKR_ARGUMENTS_BAD;
     73    }
     74 
     75       /* Check Cryptoki is initialized */
     76    if (!g_bCryptokiInitialized)
     77    {
     78       return CKR_CRYPTOKI_NOT_INITIALIZED;
     79    }
     80 
     81    if ((flags & CKVF_OPEN_SUB_SESSION) == 0)
     82    {
     83       *phSession = CK_INVALID_HANDLE;
     84 
     85       /*
     86       * Allocate the session context
     87       */
     88       pSession = (PPKCS11_PRIMARY_SESSION_CONTEXT)malloc(sizeof(PKCS11_PRIMARY_SESSION_CONTEXT));
     89       if (pSession == NULL)
     90       {
     91          return CKR_DEVICE_MEMORY;
     92       }
     93 
     94       pSession->sHeader.nMagicWord  = PKCS11_SESSION_MAGIC;
     95       pSession->sHeader.nSessionTag = PKCS11_PRIMARY_SESSION_TAG;
     96       memset(&pSession->sSession, 0, sizeof(TEEC_Session));
     97       pSession->sSecondarySessionTable.pRoot = NULL_PTR;
     98 
     99       /* The structure must be initialized first (in a portable manner)
    100          to make it work on Win32 */
    101       memset(&pSession->sSecondarySessionTableMutex, 0,
    102                sizeof(pSession->sSecondarySessionTableMutex));
    103       libMutexInit(&pSession->sSecondarySessionTableMutex);
    104 
    105       switch (slotID)
    106       {
    107       case CKV_TOKEN_SYSTEM_SHARED:
    108       case CKV_TOKEN_USER_SHARED:
    109          nLoginType = TEEC_LOGIN_PUBLIC;
    110          break;
    111 
    112       case CKV_TOKEN_SYSTEM:
    113       case CKV_TOKEN_USER:
    114       default:
    115          nLoginType = TEEC_LOGIN_AUTHENTICATION;
    116          break;
    117       }
    118 
    119       /* Group tokens */
    120       if ((slotID >= 0x00010000) && (slotID <= 0x0002FFFF))
    121       {
    122          nLoginType = TEEC_LOGIN_GROUP;
    123 
    124          /* The 16 lower-order bits encode the group identifier */
    125          nLoginData = (uint32_t)slotID & 0x0000FFFF;
    126          pLoginData = (void*)&nLoginData;
    127 
    128          /* Update the slotID for the system / PKCS11 service */
    129          if ((slotID >= 0x00010000) && (slotID <= 0x0001FFFF))
    130          {
    131             /* System group token */
    132             slotID = 3;       /* CKV_TOKEN_SYSTEM_GROUP */
    133          }
    134          else  /* ((slotID >= 0x00020000) && (slotID <= 0x0002FFFF)) */
    135          {
    136             /* User group token */
    137             slotID = 0x4014;  /* CKV_TOKEN_USER_GROUP */
    138          }
    139       }
    140 
    141 retry:
    142       memset(&sOperation, 0, sizeof(TEEC_Operation));
    143 
    144       if (nLoginType == TEEC_LOGIN_AUTHENTICATION)
    145       {
    146           nTeeError = TEEC_ReadSignatureFile((void **)&pSignatureFile, &nSignatureFileLen);
    147           if (nTeeError != TEEC_ERROR_ITEM_NOT_FOUND)
    148           {
    149               if (nTeeError != TEEC_SUCCESS)
    150               {
    151                   goto error;
    152               }
    153 
    154               sOperation.params[3].tmpref.buffer = pSignatureFile;
    155               sOperation.params[3].tmpref.size   = nSignatureFileLen;
    156               nParamType3 = TEEC_MEMREF_TEMP_INPUT;
    157           }
    158           else
    159           {
    160               /* No signature file found.
    161               * Should use LOGIN_APPLICATION for now
    162               * Can not use TEEC_LOGIN_AUTHENTICATION as this means that all .exe wil need a signature file
    163               * - a bit annoying for when passing the tests
    164               */
    165               nLoginType = TEEC_LOGIN_USER_APPLICATION;
    166           }
    167       }
    168 
    169       sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, nParamType3);
    170       nTeeError = TEEC_OpenSession(&g_sContext,
    171                                 &pSession->sSession,        /* OUT session */
    172                                 &SERVICE_UUID,              /* destination UUID */
    173                                 nLoginType,                 /* connectionMethod */
    174                                 pLoginData,                 /* connectionData */
    175                                 &sOperation,                /* IN OUT operation */
    176                                 NULL                        /* OUT returnOrigin, optional */
    177                                 );
    178       if (nTeeError != TEEC_SUCCESS)
    179       {
    180          /* No need of the returnOrigin as this is not specific to P11 */
    181 
    182          if (  (nTeeError == TEEC_ERROR_NOT_SUPPORTED) &&
    183                (nLoginType == TEEC_LOGIN_AUTHENTICATION))
    184          {
    185             /* We could not open a session with the login TEEC_LOGIN_AUTHENTICATION */
    186             /* If it is not supported by the product, */
    187             /* retry with fallback to TEEC_LOGIN_USER_APPLICATION */
    188             nLoginType = TEEC_LOGIN_USER_APPLICATION;
    189             goto retry;
    190          }
    191 
    192          /* The ERROR_ACCESS_DENIED, if returned, will be converted into CKR_TOKEN_NOT_PRESENT
    193           * For the External Cryptographic API, this means that the authentication
    194           * of the calling application fails.
    195           */
    196          goto error;
    197       }
    198 
    199       memset(&sOperation, 0, sizeof(TEEC_Operation));
    200       sOperation.params[0].value.a = slotID;
    201       sOperation.params[0].value.b = flags;  /* access flags */
    202       sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
    203       nTeeError = TEEC_InvokeCommand(&pSession->sSession,
    204                                   SERVICE_SYSTEM_PKCS11_C_OPEN_SESSION_COMMAND_ID & 0x00007FFF,
    205                                   &sOperation,              /* IN OUT operation */
    206                                   &nErrorOrigin             /* OUT returnOrigin, optional */
    207                                  );
    208       if (nTeeError != TEEC_SUCCESS)
    209       {
    210          goto error;
    211       }
    212 
    213       *phSession = (CK_SESSION_HANDLE)pSession;
    214       pSession->hCryptoSession = sOperation.params[0].value.a;
    215 
    216       return CKR_OK;
    217    }
    218    else
    219    {
    220       bool bResult;
    221 
    222       /* Check that {*phSession} is a valid primary session handle */
    223       if ((!ckInternalSessionIsOpenedEx(*phSession, &bIsPrimarySession)) ||
    224          (!bIsPrimarySession))
    225       {
    226          return CKR_SESSION_HANDLE_INVALID;
    227       }
    228 
    229       pSession = (PPKCS11_PRIMARY_SESSION_CONTEXT)(*phSession);
    230 
    231       /* allocate the secondary session context */
    232       pSecondarySession = (PKCS11_SECONDARY_SESSION_CONTEXT*)malloc(sizeof(PKCS11_SECONDARY_SESSION_CONTEXT));
    233       if (pSecondarySession == NULL)
    234       {
    235          return CKR_DEVICE_MEMORY;
    236       }
    237       pSecondarySession->sHeader.nMagicWord  = PKCS11_SESSION_MAGIC;
    238       pSecondarySession->sHeader.nSessionTag = PKCS11_SECONDARY_SESSION_TAG;
    239       pSecondarySession->pPrimarySession = pSession;
    240 
    241       libMutexLock(&pSession->sSecondarySessionTableMutex);
    242       bResult = libObjectHandle16Add(&pSession->sSecondarySessionTable,
    243                                     &pSecondarySession->sSecondarySessionNode);
    244       libMutexUnlock(&pSession->sSecondarySessionTableMutex);
    245       if (bResult == false)
    246       {
    247          free(pSecondarySession);
    248          return CKR_DEVICE_MEMORY;
    249       }
    250 
    251       memset(&sOperation, 0, sizeof(TEEC_Operation));
    252       sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
    253       nTeeError = TEEC_InvokeCommand(&pSession->sSession,
    254                                   (pSession->hCryptoSession << 16) |
    255                                     (1 << 15) |
    256                                     (SERVICE_SYSTEM_PKCS11_C_OPEN_SESSION_COMMAND_ID & 0x00007FFF),
    257                                   &sOperation,                 /* IN OUT operation */
    258                                   &nErrorOrigin                /* OUT returnOrigin, optional */
    259                                  );
    260       if (nTeeError != TEEC_SUCCESS)
    261       {
    262          goto error;
    263       }
    264 
    265       *phSession = (CK_SESSION_HANDLE)pSecondarySession;
    266       pSecondarySession->hSecondaryCryptoSession = sOperation.params[0].value.a;
    267 
    268       return CKR_OK;
    269    }
    270 
    271 error:
    272    nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
    273                   nTeeError :
    274                   ckInternalTeeErrorToCKError(nTeeError));
    275 
    276    if ((flags & CKVF_OPEN_SUB_SESSION) == 0)
    277    {
    278       libMutexDestroy(&pSession->sSecondarySessionTableMutex);
    279       free(pSession);
    280    }
    281    else
    282    {
    283       libMutexLock(&pSession->sSecondarySessionTableMutex);
    284       libObjectHandle16Remove(&pSession->sSecondarySessionTable,&pSecondarySession->sSecondarySessionNode);
    285       libMutexUnlock(&pSession->sSecondarySessionTableMutex);
    286       free(pSecondarySession);
    287    }
    288 
    289    return nErrorCode;
    290 }
    291 
    292 CK_RV PKCS11_EXPORT C_CloseSession(CK_SESSION_HANDLE hSession) /* the session's handle */
    293 {
    294    CK_RV                   nErrorCode = CKR_OK;
    295    uint32_t                nErrorOrigin = TEEC_ORIGIN_API;
    296    TEEC_Result             nTeeError;
    297    TEEC_Operation          sOperation;
    298    bool                    bIsPrimarySession;
    299 
    300    /* Check Cryptoki is initialized */
    301    if (!g_bCryptokiInitialized)
    302    {
    303       return CKR_CRYPTOKI_NOT_INITIALIZED;
    304    }
    305 
    306    if (!ckInternalSessionIsOpenedEx(hSession, &bIsPrimarySession))
    307    {
    308       return CKR_SESSION_HANDLE_INVALID;
    309    }
    310 
    311    if (bIsPrimarySession)
    312    {
    313       LIB_OBJECT_NODE_HANDLE16*           pObject;
    314       PPKCS11_SECONDARY_SESSION_CONTEXT   pSecSession;
    315       PPKCS11_PRIMARY_SESSION_CONTEXT     pSession = (PPKCS11_PRIMARY_SESSION_CONTEXT)hSession;
    316 
    317       hSession = pSession->hCryptoSession;
    318 
    319       memset(&sOperation, 0, sizeof(TEEC_Operation));
    320       sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
    321       nTeeError = TEEC_InvokeCommand(&pSession->sSession,
    322                                   (pSession->hCryptoSession << 16 ) |
    323                                     (SERVICE_SYSTEM_PKCS11_C_CLOSE_SESSION_COMMAND_ID & 0x00007FFF),
    324                                   &sOperation,                 /* IN OUT operation */
    325                                   &nErrorOrigin                /* OUT returnOrigin, optional */
    326                                  );
    327       if (nTeeError != TEEC_SUCCESS)
    328       {
    329          goto end;
    330       }
    331 
    332       TEEC_CloseSession(&pSession->sSession);
    333       memset(&pSession->sSession, 0, sizeof(TEEC_Session));
    334 
    335       /* Free all secondary session contexts */
    336       libMutexLock(&pSession->sSecondarySessionTableMutex);
    337       pObject = libObjectHandle16RemoveOne(&pSession->sSecondarySessionTable);
    338       while (pObject != NULL)
    339       {
    340          /* find all secondary session contexts,
    341             and release associated resources */
    342 
    343          pSecSession = LIB_OBJECT_CONTAINER_OF(pObject, //ptr
    344                                                PKCS11_SECONDARY_SESSION_CONTEXT,//type
    345                                                sSecondarySessionNode);//member
    346 
    347          /* free secondary session context */
    348          free(pSecSession);
    349 
    350          pObject = libObjectHandle16RemoveOne(&pSession->sSecondarySessionTable);
    351       }
    352       libMutexUnlock(&pSession->sSecondarySessionTableMutex);
    353 
    354       libMutexDestroy(&pSession->sSecondarySessionTableMutex);
    355 
    356       /* free primary session context */
    357       free(pSession);
    358    }
    359    else
    360    {
    361       PPKCS11_SECONDARY_SESSION_CONTEXT pSecSession = (PPKCS11_SECONDARY_SESSION_CONTEXT)hSession;
    362       PPKCS11_PRIMARY_SESSION_CONTEXT   pSession;
    363 
    364       uint32_t nCommandID = ( (pSecSession->hSecondaryCryptoSession & 0xFFFF) << 16 ) |
    365                               (1 << 15) |
    366                               (SERVICE_SYSTEM_PKCS11_C_CLOSE_SESSION_COMMAND_ID & 0x00007FFF);
    367 
    368       /* every pre-check are fine, then, update the local handles */
    369       hSession = pSecSession->pPrimarySession->hCryptoSession;
    370       pSession = (PPKCS11_PRIMARY_SESSION_CONTEXT)(pSecSession->pPrimarySession);
    371 
    372       memset(&sOperation, 0, sizeof(TEEC_Operation));
    373       sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
    374       nTeeError = TEEC_InvokeCommand(&pSession->sSession,
    375                                   nCommandID,
    376                                   &sOperation,                 /* IN OUT operation */
    377                                   &nErrorOrigin                /* OUT returnOrigin, optional */
    378                                  );
    379       if (nTeeError != TEEC_SUCCESS)
    380       {
    381          goto end;
    382       }
    383 
    384       /* remove the object from the table */
    385       libMutexLock(&pSession->sSecondarySessionTableMutex);
    386       libObjectHandle16Remove(&pSecSession->pPrimarySession->sSecondarySessionTable, &pSecSession->sSecondarySessionNode);
    387       libMutexUnlock(&pSession->sSecondarySessionTableMutex);
    388 
    389       /* free secondary session context */
    390       free(pSecSession);
    391    }
    392 
    393 end:
    394    nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
    395                   nTeeError :
    396                   ckInternalTeeErrorToCKError(nTeeError));
    397    return nErrorCode;
    398 }
    399 
    400 
    401 CK_RV PKCS11_EXPORT C_Login(CK_SESSION_HANDLE hSession,  /* the session's handle */
    402                               CK_USER_TYPE      userType,  /* the user type */
    403                               const CK_UTF8CHAR*   pPin,      /* the user's PIN */
    404                               CK_ULONG          ulPinLen)  /* the length of the PIN */
    405 {
    406    /* Prevent the compiler from complaining about unused variables */
    407    do{(void)hSession;}while(0);
    408    do{(void)userType;}while(0);
    409    do{(void)pPin;}while(0);
    410    do{(void)ulPinLen;}while(0);
    411 
    412    return CKR_OK;
    413 }
    414 
    415 CK_RV PKCS11_EXPORT C_Logout(CK_SESSION_HANDLE hSession) /* the session's handle */
    416 {
    417    do{(void)hSession;}while(0);
    418 
    419    return CKR_OK;
    420 }
    421