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 #include "pkcs11_internal.h"
     32 
     33 /* ------------------------------------------------------------------------
     34 Internal Functions
     35 ------------------------------------------------------------------------- */
     36 /**
     37 * Checks the following pre-conditions:
     38 * - cryptoki is initialized,
     39 * - hSession is valid (primary and/or secondary),
     40 * - the user is logged in.
     41 *
     42 * And updates handle values:
     43 *  IN/OUT : phSession
     44 *           IN  = Cryptoki external handle
     45 *           OUT = TFAPI handle = primary cryptoki session handle
     46 *  OUT    : phSecSession16Msb
     47 *           OUT = 0 for a primary session or
     48 *                 the secondary cryptoki session handle in the 16 MSB bits
     49 */
     50 static CK_RV static_checkPreConditionsAndUpdateHandles(
     51          CK_SESSION_HANDLE*   phSession,
     52          uint32_t*            phCommandIDAndSession,
     53          PPKCS11_PRIMARY_SESSION_CONTEXT* ppSession)
     54 {
     55    bool  bIsPrimarySession;
     56 
     57    /* Check Cryptoki is initialized */
     58    if (!g_bCryptokiInitialized)
     59    {
     60       return CKR_CRYPTOKI_NOT_INITIALIZED;
     61    }
     62 
     63    if (phSession == NULL)
     64    {
     65       return CKR_SESSION_HANDLE_INVALID;
     66    }
     67 
     68    /* Check that the session is valid */
     69    if (!ckInternalSessionIsOpenedEx(*phSession, &bIsPrimarySession))
     70    {
     71       return CKR_SESSION_HANDLE_INVALID;
     72    }
     73    /* previous check is fine, then update session handles */
     74    if (bIsPrimarySession)
     75    {
     76       PPKCS11_PRIMARY_SESSION_CONTEXT pSession =
     77          (PPKCS11_PRIMARY_SESSION_CONTEXT)(*phSession);
     78 
     79       *phSession = pSession->hCryptoSession;
     80       *phCommandIDAndSession = (pSession->hCryptoSession<<16)|(*phCommandIDAndSession&0x00007FFF);
     81       *ppSession = pSession;
     82    }
     83    else
     84    {
     85       PPKCS11_SECONDARY_SESSION_CONTEXT pSecSession =
     86          (PPKCS11_SECONDARY_SESSION_CONTEXT)(*phSession);
     87 
     88       *phSession = pSecSession->pPrimarySession->hCryptoSession;
     89       *phCommandIDAndSession = (pSecSession->hSecondaryCryptoSession<<16)|(1<<15)|(*phCommandIDAndSession&0x00007FFF);
     90       *ppSession = pSecSession->pPrimarySession;
     91    }
     92 
     93    return CKR_OK;
     94 }
     95 
     96 /******************************************/
     97 /* The buffer must be freed by the caller */
     98 /******************************************/
     99 static CK_RV static_encodeTwoTemplates(
    100    uint8_t**         ppBuffer,
    101    uint32_t *        pBufferSize,
    102    const uint32_t    nParamIndex,
    103    CK_ATTRIBUTE*     pTemplate1,
    104    CK_ULONG          ulCount1,
    105    CK_ATTRIBUTE*     pTemplate2,
    106    CK_ULONG          ulCount2)
    107 {
    108    INPUT_TEMPLATE_ITEM  sItem;
    109 
    110    uint32_t i;
    111    uint32_t nDataOffset    = 0;
    112    uint32_t nBufferIndex   = 0;
    113    uint32_t nBufferSize    = 0;
    114    uint8_t* pBuffer = NULL;
    115    CK_RV    nErrorCode = CKR_OK;
    116 
    117    if (ulCount1 == 0)
    118    {
    119       /* Nothing to do */
    120       return CKR_OK;
    121    }
    122    if (pTemplate1 == NULL)
    123    {
    124       /* Nothing to do */
    125       return CKR_OK;
    126    }
    127 
    128    /* First compute the total required buffer size that
    129     * will contain the full templates (for the template 1 AND 2)
    130     */
    131    nBufferSize =  4 +                                    /* Nb Attributes */
    132                   sizeof(INPUT_TEMPLATE_ITEM)*ulCount1;  /* The attributes items */
    133    if (pTemplate2 != NULL)
    134    {
    135       nBufferSize += 4 +                                    /* Nb Attributes */
    136                      sizeof(INPUT_TEMPLATE_ITEM)*ulCount2;  /* The attributes items */
    137    }
    138 
    139    /* First data (attribute values) on either template 1 or 2 will just be after the last item */
    140    nDataOffset = nBufferSize;
    141 
    142    for (i = 0; i < ulCount1; i++)
    143    {
    144       /* Each value will be aligned on 4 bytes.
    145          This computation includes the spare bytes. */
    146       nBufferSize += PKCS11_GET_SIZE_WITH_ALIGNMENT(pTemplate1[i].ulValueLen);
    147    }
    148    if (pTemplate2 != NULL)
    149    {
    150       for (i = 0; i < ulCount2; i++)
    151       {
    152          /* Each value will be aligned on 4 bytes.
    153             This computation includes the spare bytes. */
    154          nBufferSize += PKCS11_GET_SIZE_WITH_ALIGNMENT(pTemplate2[i].ulValueLen);
    155       }
    156    }
    157 
    158    pBuffer = (uint8_t*)malloc(nBufferSize);
    159    if (pBuffer == NULL)
    160    {
    161       /* Not enough memory */
    162       return CKR_DEVICE_MEMORY;
    163    }
    164 
    165    memset(pBuffer, 0, nBufferSize);
    166 
    167    /*
    168     * First template
    169     */
    170    *(uint32_t*)(pBuffer + nBufferIndex) = ulCount1;
    171    nBufferIndex += 4;
    172    for (i = 0; i < ulCount1; i++)
    173    {
    174       sItem.attributeType     = (uint32_t)pTemplate1[i].type;
    175       /* dataOffset = 0 means NULL buffer */
    176       sItem.dataOffset        = ((pTemplate1[i].pValue == NULL) ? 0 : nDataOffset);
    177       sItem.dataParamIndex    = nParamIndex; /* The parameter where we store the data (0 to 3) */
    178       sItem.dataValueLen      = (uint32_t)pTemplate1[i].ulValueLen;
    179       /* Copy the item */
    180       memcpy(pBuffer + nBufferIndex, &sItem, sizeof(INPUT_TEMPLATE_ITEM));
    181       nBufferIndex += sizeof(INPUT_TEMPLATE_ITEM);
    182       if (pTemplate1[i].pValue != NULL)
    183       {
    184          /* Copy the data */
    185          memcpy(pBuffer + nDataOffset, (uint8_t*)pTemplate1[i].pValue, (uint32_t)pTemplate1[i].ulValueLen);
    186          /* Next data will be stored just after the previous one but aligned on 4 bytes */
    187          nDataOffset += PKCS11_GET_SIZE_WITH_ALIGNMENT(pTemplate1[i].ulValueLen);
    188          if ((nDataOffset & 0xC0000000) != 0)
    189          {
    190             /* We whould never go in this case, that means the dataOffset will not be able to store the offset correctly */
    191             nErrorCode = CKR_DEVICE_ERROR;
    192             goto error;
    193          }
    194       }
    195    }
    196 
    197    /*
    198     * Second template
    199     */
    200    if (pTemplate2 != NULL)
    201    {
    202       *(uint32_t*)(pBuffer + nBufferIndex) = ulCount2;
    203       nBufferIndex += 4;
    204       for (i = 0; i < ulCount2; i++)
    205       {
    206          sItem.attributeType     = (uint32_t)pTemplate2[i].type;
    207          /* dataOffset = 0 means NULL buffer */
    208          sItem.dataOffset        = ((pTemplate2[i].pValue == NULL) ? 0 : nDataOffset);
    209          sItem.dataParamIndex    = nParamIndex; /* The parameter where we store the data (0..3) */
    210          sItem.dataValueLen      = (uint32_t)pTemplate2[i].ulValueLen;
    211          /* Copy the item */
    212          memcpy(pBuffer + nBufferIndex, &sItem, sizeof(INPUT_TEMPLATE_ITEM));
    213          nBufferIndex += sizeof(INPUT_TEMPLATE_ITEM);
    214          if (pTemplate2[i].pValue != NULL)
    215          {
    216             /* Copy the data */
    217             memcpy(pBuffer + nDataOffset, (uint8_t*)pTemplate2[i].pValue, (uint32_t)pTemplate2[i].ulValueLen);
    218             /* Next data will be stored just after the previous one but aligned on 4 bytes */
    219             nDataOffset += PKCS11_GET_SIZE_WITH_ALIGNMENT(pTemplate2[i].ulValueLen);
    220             if ((nDataOffset & 0xC0000000) != 0)
    221             {
    222                /* We whould never go in this case, that means the dataOffset will not be able to store the offset correctly */
    223                nErrorCode = CKR_DEVICE_ERROR;
    224                goto error;
    225             }
    226          }
    227       }
    228    }
    229 
    230    *ppBuffer      = pBuffer;
    231    *pBufferSize   = nBufferSize;
    232 
    233    return CKR_OK;
    234 
    235 error:
    236    free(pBuffer);
    237    return nErrorCode;
    238 }
    239 
    240 /******************************************/
    241 /* The buffer must be freed by the caller */
    242 /******************************************/
    243 static CK_RV static_encodeTemplate(
    244    uint8_t**         ppBuffer,
    245    uint32_t*         pBufferSize,
    246    const uint32_t    nParamIndex,
    247    CK_ATTRIBUTE*     pTemplate,
    248    CK_ULONG          ulCount)
    249 {
    250    return static_encodeTwoTemplates(ppBuffer, pBufferSize, nParamIndex, pTemplate, ulCount, NULL, 0);
    251 }
    252 /* ----------------------------------------------------------------------- */
    253 
    254 static CK_RV static_C_CallInit(
    255    uint32_t            nCommandID,
    256    CK_SESSION_HANDLE   hSession,
    257    const CK_MECHANISM* pMechanism,
    258    CK_OBJECT_HANDLE    hKey)
    259 {
    260    TEEC_Result    teeErr;
    261    uint32_t       nErrorOrigin;
    262    TEEC_Operation sOperation;
    263    CK_RV          nErrorCode = CKR_OK;
    264    uint32_t       nCommandIDAndSession = nCommandID;
    265    uint32_t       nParamType2 = TEEC_NONE;
    266    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
    267 
    268    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
    269    if (nErrorCode != CKR_OK)
    270    {
    271       return nErrorCode;
    272    }
    273    if (pMechanism == NULL)
    274    {
    275       return CKR_ARGUMENTS_BAD;
    276    }
    277 
    278    memset(&sOperation, 0, sizeof(TEEC_Operation));
    279    sOperation.params[0].value.a = (uint32_t)pMechanism->mechanism;
    280    if (nCommandID != SERVICE_SYSTEM_PKCS11_C_DIGESTINIT_COMMAND_ID)
    281    {
    282       sOperation.params[0].value.b = (uint32_t)hKey;
    283 
    284    }
    285    sOperation.params[1].tmpref.buffer = (uint8_t*)pMechanism->pParameter;
    286    sOperation.params[1].tmpref.size   = (uint32_t)pMechanism->ulParameterLen;
    287 
    288    /* Specific case of RSA OAEP */
    289    if (((nCommandID == SERVICE_SYSTEM_PKCS11_C_ENCRYPTINIT_COMMAND_ID)
    290       ||(nCommandID == SERVICE_SYSTEM_PKCS11_C_DECRYPTINIT_COMMAND_ID))
    291       && (pMechanism->mechanism == CKM_RSA_PKCS_OAEP)
    292       && (pMechanism->pParameter != NULL))
    293    {
    294       /* Add the source buffer of the RSA OAEP mechanism parameters */
    295       nParamType2 = TEEC_MEMREF_TEMP_INPUT;
    296       sOperation.params[2].tmpref.buffer = (uint8_t*)((CK_RSA_PKCS_OAEP_PARAMS_PTR)(pMechanism->pParameter))->pSourceData;
    297       sOperation.params[2].tmpref.size   = (uint32_t) ((CK_RSA_PKCS_OAEP_PARAMS_PTR)(pMechanism->pParameter))->ulSourceDataLen;
    298    }
    299    sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_INPUT, nParamType2, TEEC_NONE);
    300    teeErr = TEEC_InvokeCommand(   &pSession->sSession,
    301                                   nCommandIDAndSession,        /* commandID */
    302                                   &sOperation,                 /* IN OUT operation */
    303                                   &nErrorOrigin                /* OUT returnOrigin, optional */
    304                                  );
    305    nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
    306                   teeErr :
    307                   ckInternalTeeErrorToCKError(teeErr));
    308 
    309    return nErrorCode;
    310 }
    311 
    312 /* ----------------------------------------------------------------------- */
    313 /**
    314 * If bSend, the pData buffer is sent to the service.
    315 * If bResult, a buffer is received, the convention described in
    316 * PKCS11 Section 11.2 applies for pResult and pulResultLen.
    317 * Specific function used for single operation
    318 */
    319 static CK_RV static_C_CallForSingle(
    320    uint32_t             nCommandID,
    321    CK_SESSION_HANDLE    hSession,
    322    const CK_BYTE*       pData,
    323    CK_ULONG             ulDataLen,
    324    CK_BYTE*             pResult,
    325    CK_ULONG*            pulResultLen,
    326    bool                 bSend,
    327    bool                 bReceive)
    328 {
    329    TEEC_Result       teeErr;
    330    uint32_t          nErrorOrigin;
    331    TEEC_Operation    sOperation;
    332    CK_RV             nErrorCode = CKR_OK;
    333    uint32_t          nCommandIDAndSession = nCommandID;
    334    uint32_t          nParamType0 = TEEC_NONE;
    335    uint32_t          nParamType1 = TEEC_NONE;
    336    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
    337 
    338    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
    339    if (nErrorCode != CKR_OK)
    340    {
    341       return nErrorCode;
    342    }
    343 
    344    memset(&sOperation, 0, sizeof(TEEC_Operation));
    345 
    346    if (bSend)
    347    {
    348       nParamType0 = TEEC_MEMREF_TEMP_INPUT;
    349       sOperation.params[0].tmpref.buffer = (uint8_t*)pData;
    350       sOperation.params[0].tmpref.size   = (uint32_t)ulDataLen;
    351    }
    352 
    353    if (bReceive)
    354    {
    355       if (pulResultLen == NULL)
    356       {
    357          /* The P11 API Spec states that, in this case, the operation must be
    358             aborted and the error code CKR_ARGUMENTS_BAD must be returned. We
    359             achieve this result by sending an invalid parameter type */
    360          nParamType1 = TEEC_NONE;
    361       }
    362       else if (pResult == NULL)
    363       {
    364          /* If pResult is NULL, the caller only wants the buffer length.
    365             Send a NULL output memref */
    366          nParamType1 = TEEC_MEMREF_TEMP_OUTPUT;
    367          sOperation.params[1].tmpref.buffer = (uint8_t*)NULL;
    368       }
    369       else
    370       {
    371          /* send the result buffer information */
    372          nParamType1 = TEEC_MEMREF_TEMP_OUTPUT;
    373          sOperation.params[1].tmpref.buffer = (uint8_t*)pResult;
    374          sOperation.params[1].tmpref.size   = (uint32_t)*pulResultLen;
    375       }
    376    }
    377 
    378    sOperation.paramTypes = TEEC_PARAM_TYPES(nParamType0, nParamType1, TEEC_NONE, TEEC_NONE);
    379    teeErr = TEEC_InvokeCommand(&pSession->sSession,
    380                                nCommandIDAndSession,     /* commandID */
    381                                &sOperation,              /* IN OUT operation */
    382                                &nErrorOrigin             /* OUT returnOrigin, optional */
    383                               );
    384    if (teeErr != TEEC_SUCCESS)
    385    {
    386       nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
    387                      teeErr :
    388                      ckInternalTeeErrorToCKError(teeErr));
    389       goto end;
    390    }
    391 
    392    /* Success */
    393    nErrorCode = CKR_OK;
    394 
    395  end:
    396    if (bReceive)
    397    {
    398       if ((nErrorCode == CKR_OK) || (nErrorCode == CKR_BUFFER_TOO_SMALL))
    399       {
    400          /* The service has returned the actual result */
    401          /* The data is already in pResult, we get the returned length */
    402          *pulResultLen = sOperation.params[1].tmpref.size;
    403       }
    404    }
    405 
    406    return nErrorCode;
    407 }
    408 
    409 /* ----------------------------------------------------------------------- */
    410 /**
    411 * If bSend, the pData buffer is sent to the service.
    412 * If bResult, a buffer is received, the convention described in
    413 * PKCS11 Section 11.2 applies for pResult and pulResultLen.
    414 * Specific function only used for update operations
    415 */
    416 static CK_RV static_C_CallUpdate(
    417    uint32_t             nCommandID,
    418    CK_SESSION_HANDLE    hSession,
    419    const CK_BYTE*       pData,
    420    CK_ULONG             ulDataLen,
    421    CK_BYTE*             pResult,
    422    CK_ULONG*            pulResultLen,
    423    bool                 bSend,
    424    bool                 bReceive)
    425 {
    426    TEEC_Result       teeErr;
    427    uint32_t          nErrorOrigin;
    428    TEEC_Operation    sOperation;
    429    CK_RV             nErrorCode = CKR_OK;
    430    uint32_t          nResultLen = 0;
    431    uint32_t          nCommandIDAndSession = nCommandID;
    432    uint32_t          nParamType0 = TEEC_NONE;
    433    uint32_t          nParamType1 = TEEC_NONE;
    434    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
    435 
    436    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
    437    if (nErrorCode != CKR_OK)
    438    {
    439       return nErrorCode;
    440    }
    441 
    442    if (pulResultLen != NULL)
    443    {
    444       nResultLen = *pulResultLen;
    445    }
    446 
    447    memset(&sOperation, 0, sizeof(TEEC_Operation));
    448 
    449    if (bSend)
    450    {
    451       nParamType0 = TEEC_MEMREF_TEMP_INPUT;
    452       sOperation.params[0].tmpref.buffer = (void*)pData;
    453       sOperation.params[0].tmpref.size   = ulDataLen;
    454    }
    455 
    456    if (bReceive)
    457    {
    458       if (pulResultLen == NULL)
    459       {
    460          /* The P11 API Spec states that, in this case, the operation must be
    461             aborted and the error code CKR_ARGUMENTS_BAD must be returned. We
    462             achieve this result by setting an invalid parameter type */
    463          nParamType1 = TEEC_NONE;
    464       }
    465       else if (pResult == NULL)
    466       {
    467          /* If pResult is NULL, the caller only wants the output buffer length.
    468             Pass a NULL output ref */
    469          nParamType1 = TEEC_MEMREF_TEMP_OUTPUT;
    470          sOperation.params[1].tmpref.buffer = NULL;
    471       }
    472       else
    473       {
    474          /* send the result buffer information */
    475          nParamType1 = TEEC_MEMREF_TEMP_OUTPUT;
    476          sOperation.params[1].tmpref.buffer = pResult;
    477          sOperation.params[1].tmpref.size   = (uint32_t)*pulResultLen;
    478       }
    479    }
    480 
    481    sOperation.paramTypes = TEEC_PARAM_TYPES(nParamType0, nParamType1, TEEC_NONE, TEEC_NONE);
    482    teeErr = TEEC_InvokeCommand(   &pSession->sSession,
    483                                   nCommandIDAndSession,        /* commandID */
    484                                   &sOperation,                 /* IN OUT operation */
    485                                   &nErrorOrigin                /* OUT returnOrigin, optional */
    486                                  );
    487    if (teeErr != TEEC_SUCCESS)
    488    {
    489       nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
    490                      teeErr :
    491                      ckInternalTeeErrorToCKError(teeErr));
    492       goto end;
    493    }
    494 
    495    /* Success */
    496    nErrorCode = CKR_OK;
    497 
    498  end:
    499    if (bReceive)
    500    {
    501       if ((nErrorCode == CKR_OK) || (nErrorCode == CKR_BUFFER_TOO_SMALL))
    502       {
    503          /* The service has returned the actual result */
    504          /* The data is already in pResult, we get the returned length */
    505          *pulResultLen = sOperation.params[1].tmpref.size;
    506       }
    507    }
    508 
    509    return nErrorCode;
    510 }
    511 
    512 /* Splits the buffer pData in chunks of nChunkSize size
    513  * and calls static_C_CallUpdate for each chunk
    514  */
    515 static CK_RV static_C_CallSplitUpdate(
    516                            uint32_t           nCommandID,
    517                            CK_SESSION_HANDLE  hSession,
    518                            const CK_BYTE*     pData,
    519                            CK_ULONG           ulDataLen,
    520                            CK_BYTE*           pResult,
    521                            CK_ULONG*          pulResultLen,
    522                            bool               bSend,
    523                            bool               bReceive,
    524                            uint32_t           nChunkSize)
    525 {
    526    CK_RV nErrorCode;
    527    CK_ULONG nPartDataLen;
    528    CK_ULONG nPartResultLen = 0;
    529    CK_ULONG ulResultLen = 0;
    530    bool bIsSymOperation = false;
    531 
    532    if (pulResultLen != NULL)
    533    {
    534       ulResultLen = *pulResultLen;
    535       /* Check wether the operation is a symetrical or asymetrical */
    536       if (*pulResultLen == ulDataLen)
    537       {
    538          bIsSymOperation = true;
    539       }
    540       *pulResultLen = 0;
    541    }
    542 
    543    while (ulDataLen > 0)
    544    {
    545       nPartDataLen = (ulDataLen <= nChunkSize ?
    546                         ulDataLen : nChunkSize);
    547       if (bIsSymOperation)
    548       {
    549          /* update the result only if it is a symetric operation */
    550          nPartResultLen = (ulResultLen <= nChunkSize ?
    551                                ulResultLen : nChunkSize);
    552       }
    553       else
    554       {
    555          nPartResultLen = ulResultLen;
    556       }
    557 
    558       nErrorCode =  static_C_CallUpdate(
    559                                  nCommandID,
    560                                  hSession,
    561                                  pData,
    562                                  nPartDataLen,
    563                                  pResult,
    564                                  &nPartResultLen,
    565                                  bSend,
    566                                  bReceive);
    567       if (nErrorCode != CKR_OK)
    568       {
    569          return nErrorCode;
    570       }
    571 
    572       ulDataLen -= nPartDataLen;
    573       pData += nPartDataLen;
    574 
    575       if (pResult != NULL)
    576       {
    577          ulResultLen -= nPartResultLen;
    578          pResult += nPartResultLen;
    579       }
    580 
    581       if ((pulResultLen != NULL) && (bIsSymOperation))
    582       {
    583          *pulResultLen += nPartResultLen;
    584       }
    585    }
    586    return CKR_OK;
    587 }
    588 
    589 /* Decides whether to split or not the inout/output buffer into chunks
    590 */
    591 static CK_RV static_C_Call_CallForUpdate(
    592                            uint32_t           nCommandID,
    593                            CK_SESSION_HANDLE  hSession,
    594                            const CK_BYTE*     pData,
    595                            CK_ULONG           ulDataLen,
    596                            CK_BYTE*           pResult,
    597                            CK_ULONG*          pulResultLen,
    598                            bool               bSend,
    599                            bool               bReceive)
    600 {
    601    CK_RV                   nErrorCode;
    602    uint32_t                nChunkSize;
    603 
    604    TEEC_ImplementationLimits  limits;
    605 
    606    if (!g_bCryptokiInitialized)
    607    {
    608       return CKR_CRYPTOKI_NOT_INITIALIZED;
    609    }
    610 
    611    TEEC_GetImplementationLimits(&limits);
    612 
    613    /* We can split the buffer in chunks of fixed size.
    614       No matter of the start address of the buffer,
    615       a safe size would be TotalNumberOfPages - 1
    616    */
    617    nChunkSize = limits.tmprefMaxSize - limits.pageSize;
    618 
    619    if (ulDataLen > nChunkSize)
    620    {
    621       /* inoutMaxSize = 0  means unlimited size */
    622        nErrorCode = static_C_CallSplitUpdate(nCommandID,
    623                                  hSession,
    624                                  pData,
    625                                  ulDataLen,
    626                                  pResult,
    627                                  pulResultLen,
    628                                  bSend,
    629                                  bReceive,
    630                                  nChunkSize);
    631    }
    632    else
    633    {
    634       nErrorCode = static_C_CallUpdate(nCommandID,
    635                                  hSession,
    636                                  pData,
    637                                  ulDataLen,
    638                                  pResult,
    639                                  pulResultLen,
    640                                  bSend,
    641                                  bReceive);
    642    }
    643    return nErrorCode;
    644 
    645 }
    646 
    647 /* ------------------------------------------------------------------------
    648 Public Functions
    649 ------------------------------------------------------------------------- */
    650 
    651 CK_RV PKCS11_EXPORT C_CreateObject(
    652    CK_SESSION_HANDLE    hSession,    /* the session's handle */
    653    const CK_ATTRIBUTE*  pTemplate,   /* the object's template */
    654    CK_ULONG             ulCount,     /* attributes in template */
    655    CK_OBJECT_HANDLE*    phObject)    /* receives new object's handle. */
    656 {
    657    TEEC_Result          teeErr;
    658    uint32_t             nErrorOrigin;
    659    TEEC_Operation       sOperation;
    660    CK_RV                nErrorCode = CKR_OK;
    661    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
    662    uint32_t             nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_CREATEOBJECT_COMMAND_ID;
    663    uint8_t*             pBuffer = NULL;
    664    uint32_t             nBufferSize = 0;
    665 
    666    if ( pTemplate == NULL || phObject == NULL )
    667    {
    668       return CKR_ARGUMENTS_BAD;
    669    }
    670 
    671    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
    672    if (nErrorCode != CKR_OK)
    673    {
    674       return nErrorCode;
    675    }
    676 
    677    nErrorCode = static_encodeTemplate(&pBuffer, &nBufferSize, 0, (CK_ATTRIBUTE*)pTemplate, ulCount); /* Sets the template on the param 0 */
    678    if (nErrorCode != CKR_OK)
    679    {
    680       return nErrorCode;
    681    }
    682 
    683    memset(&sOperation, 0, sizeof(TEEC_Operation));
    684    sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_VALUE_OUTPUT, TEEC_NONE, TEEC_NONE);
    685    sOperation.params[0].tmpref.buffer = pBuffer;
    686    sOperation.params[0].tmpref.size   = nBufferSize;
    687    teeErr = TEEC_InvokeCommand(   &pSession->sSession,
    688                                   nCommandIDAndSession,        /* commandID */
    689                                   &sOperation,                 /* IN OUT operation */
    690                                   &nErrorOrigin                /* OUT returnOrigin, optional */
    691                                  );
    692    free(pBuffer);
    693 
    694    if (teeErr != TEEC_SUCCESS)
    695    {
    696       nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
    697                      teeErr :
    698                      ckInternalTeeErrorToCKError(teeErr));
    699       goto end;
    700    }
    701 
    702    *phObject = sOperation.params[1].value.a;
    703 
    704    /* Success */
    705    nErrorCode = CKR_OK;
    706 
    707 end:
    708    return nErrorCode;
    709 }
    710 
    711 CK_RV PKCS11_EXPORT C_DestroyObject(
    712    CK_SESSION_HANDLE hSession,  /* the session's handle */
    713    CK_OBJECT_HANDLE  hObject)   /* the object's handle */
    714 {
    715    TEEC_Result    teeErr;
    716    uint32_t       nErrorOrigin;
    717    TEEC_Operation sOperation;
    718    CK_RV       nErrorCode = CKR_OK;
    719    uint32_t    nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_DESTROYOBJECT_COMMAND_ID;
    720    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
    721 
    722    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
    723    if (nErrorCode != CKR_OK)
    724    {
    725       return nErrorCode;
    726    }
    727 
    728    memset(&sOperation, 0, sizeof(TEEC_Operation));
    729    sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
    730    sOperation.params[0].value.a = (uint32_t)hObject;
    731    teeErr = TEEC_InvokeCommand(   &pSession->sSession,
    732                                   nCommandIDAndSession,        /* commandID */
    733                                   &sOperation,                 /* IN OUT operation */
    734                                   &nErrorOrigin                /* OUT returnOrigin, optional */
    735                                  );
    736    nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
    737                   teeErr :
    738                   ckInternalTeeErrorToCKError(teeErr));
    739    return nErrorCode;
    740 }
    741 
    742 CK_RV PKCS11_EXPORT C_GetAttributeValue(
    743    CK_SESSION_HANDLE hSession,   /* the session's handle */
    744    CK_OBJECT_HANDLE  hObject,    /* the object's handle */
    745    CK_ATTRIBUTE*     pTemplate,  /* specifies attributes, gets values */
    746    CK_ULONG          ulCount)    /* attributes in template */
    747 {
    748    TEEC_Result       teeErr;
    749    uint32_t          nErrorOrigin;
    750    TEEC_Operation    sOperation;
    751    CK_RV             nErrorCode = CKR_OK;
    752    CK_RV             nFinalErrorCode = CKR_OK;
    753    uint32_t          i = 0;
    754    uint32_t          nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_GETATTRIBUTEVALUE_COMMAND_ID;
    755    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
    756 
    757    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
    758    if (nErrorCode != CKR_OK)
    759    {
    760       return nErrorCode;
    761    }
    762 
    763    if (pTemplate == NULL)
    764    {
    765       return CKR_ARGUMENTS_BAD;
    766    }
    767 
    768    if (ulCount == 0)
    769    {
    770       return CKR_OK;
    771    }
    772 
    773    for (i = 0; i < ulCount; i++)
    774    {
    775       memset(&sOperation, 0, sizeof(TEEC_Operation));
    776       sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, TEEC_NONE);
    777       sOperation.params[0].value.a = (uint32_t)hObject;
    778       sOperation.params[0].value.b = (uint32_t)pTemplate[i].type;
    779       sOperation.params[1].tmpref.buffer = pTemplate[i].pValue;
    780       sOperation.params[1].tmpref.size   = pTemplate[i].ulValueLen;
    781       teeErr = TEEC_InvokeCommand(   &pSession->sSession,
    782                                      nCommandIDAndSession,        /* commandID */
    783                                      &sOperation,                 /* IN OUT operation */
    784                                      &nErrorOrigin                /* OUT returnOrigin, optional */
    785                                     );
    786       nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
    787                      teeErr :
    788                      ckInternalTeeErrorToCKError(teeErr));
    789       if (nErrorCode != CKR_OK)
    790       {
    791          if (  (nErrorCode == CKR_ATTRIBUTE_SENSITIVE) ||
    792                (nErrorCode == CKR_ATTRIBUTE_TYPE_INVALID) ||
    793                (nErrorCode == CKR_BUFFER_TOO_SMALL))
    794          {
    795             nFinalErrorCode = nErrorCode;
    796          }
    797          else
    798          {
    799             /* Not some of the special error codes: this is fatal */
    800             return nErrorCode;
    801          }
    802       }
    803 
    804       pTemplate[i].ulValueLen = sOperation.params[1].tmpref.size;
    805    }
    806 
    807    return nFinalErrorCode;
    808 }
    809 
    810 CK_RV PKCS11_EXPORT C_FindObjectsInit(
    811    CK_SESSION_HANDLE    hSession,   /* the session's handle */
    812    const CK_ATTRIBUTE*  pTemplate,  /* attribute values to match */
    813    CK_ULONG             ulCount)    /* attributes in search template */
    814 {
    815    TEEC_Result    teeErr;
    816    uint32_t       nErrorOrigin;
    817    TEEC_Operation sOperation;
    818    CK_RV       nErrorCode = CKR_OK;
    819    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
    820    uint32_t    nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_FINDOBJECTSINIT_COMMAND_ID;
    821    uint8_t*    pBuffer     = NULL;
    822    uint32_t    nBufferSize = 0;
    823 
    824    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
    825    if (nErrorCode != CKR_OK)
    826    {
    827       return nErrorCode;
    828    }
    829 
    830    nErrorCode = static_encodeTemplate(&pBuffer, &nBufferSize, 0, (CK_ATTRIBUTE*)pTemplate, ulCount); /* Sets the template on the param 0 */
    831    if (nErrorCode != CKR_OK)
    832    {
    833       return nErrorCode;
    834    }
    835 
    836    memset(&sOperation, 0, sizeof(TEEC_Operation));
    837    sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
    838    sOperation.params[0].tmpref.buffer = pBuffer;
    839    sOperation.params[0].tmpref.size   = nBufferSize;
    840    teeErr = TEEC_InvokeCommand(   &pSession->sSession,
    841                                   nCommandIDAndSession,        /* commandID */
    842                                   &sOperation,                 /* IN OUT operation */
    843                                   &nErrorOrigin                /* OUT returnOrigin, optional */
    844                                  );
    845    free(pBuffer);
    846 
    847    nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
    848                   teeErr :
    849                   ckInternalTeeErrorToCKError(teeErr));
    850    return nErrorCode;
    851 }
    852 
    853 
    854 CK_RV PKCS11_EXPORT C_FindObjects(
    855    CK_SESSION_HANDLE hSession,          /* the session's handle */
    856    CK_OBJECT_HANDLE* phObject,          /* receives object handle array */
    857    CK_ULONG          ulMaxObjectCount,  /* max handles to be returned */
    858    CK_ULONG*         pulObjectCount)    /* actual number returned */
    859 {
    860    TEEC_Result       teeErr;
    861    uint32_t          nErrorOrigin;
    862    TEEC_Operation    sOperation;
    863    CK_RV             nErrorCode = CKR_OK;
    864    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
    865    uint32_t          nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_FINDOBJECTS_COMMAND_ID;
    866 
    867    if ( (phObject == NULL) || (pulObjectCount == NULL))
    868    {
    869       return CKR_ARGUMENTS_BAD;
    870    }
    871 
    872    *pulObjectCount = 0;
    873 
    874    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
    875    if (nErrorCode != CKR_OK)
    876    {
    877       return nErrorCode;
    878    }
    879 
    880    memset(&sOperation, 0, sizeof(TEEC_Operation));
    881    sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
    882    sOperation.params[0].tmpref.buffer = (uint8_t*)phObject;
    883    sOperation.params[0].tmpref.size   = (uint32_t)ulMaxObjectCount * sizeof(uint32_t);
    884 
    885    teeErr = TEEC_InvokeCommand(   &pSession->sSession,
    886                                   nCommandIDAndSession,        /* commandID */
    887                                   &sOperation,                 /* IN OUT operation */
    888                                   &nErrorOrigin                /* OUT returnOrigin, optional */
    889                                  );
    890 
    891    if (teeErr != TEEC_SUCCESS)
    892    {
    893       nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
    894                      teeErr :
    895                      ckInternalTeeErrorToCKError(teeErr));
    896       return nErrorCode;
    897    }
    898 
    899    *pulObjectCount = sOperation.params[0].tmpref.size / sizeof(uint32_t);
    900 
    901    return CKR_OK;
    902 }
    903 
    904 CK_RV PKCS11_EXPORT C_FindObjectsFinal(CK_SESSION_HANDLE hSession) /* the session's handle */
    905 {
    906    TEEC_Result    teeErr;
    907    uint32_t       nErrorOrigin;
    908    TEEC_Operation sOperation;
    909    CK_RV          nErrorCode = CKR_OK;
    910    uint32_t       nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_FINDOBJECTSFINAL_COMMAND_ID;
    911    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
    912 
    913    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
    914    if (nErrorCode != CKR_OK)
    915    {
    916       return nErrorCode;
    917    }
    918 
    919    memset(&sOperation, 0, sizeof(TEEC_Operation));
    920    teeErr = TEEC_InvokeCommand(   &pSession->sSession,
    921                                   nCommandIDAndSession,        /* commandID */
    922                                   &sOperation,                 /* IN OUT operation */
    923                                   &nErrorOrigin                /* OUT returnOrigin, optional */
    924                                  );
    925 
    926    nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
    927                   teeErr :
    928                   ckInternalTeeErrorToCKError(teeErr));
    929    return nErrorCode;
    930 }
    931 
    932 
    933 CK_RV PKCS11_EXPORT C_DigestInit(
    934    CK_SESSION_HANDLE   hSession,   /* the session's handle */
    935    const CK_MECHANISM* pMechanism) /* the digesting mechanism */
    936 {
    937    return static_C_CallInit(
    938       SERVICE_SYSTEM_PKCS11_C_DIGESTINIT_COMMAND_ID,
    939       hSession,
    940       pMechanism,
    941       CK_INVALID_HANDLE);
    942 }
    943 
    944 CK_RV PKCS11_EXPORT C_Digest(
    945    CK_SESSION_HANDLE hSession,     /* the session's handle */
    946    const CK_BYTE*    pData,        /* data to be digested */
    947    CK_ULONG          ulDataLen,    /* bytes of data to be digested */
    948    CK_BYTE*          pDigest,      /* receives the message digest */
    949    CK_ULONG*         pulDigestLen) /* receives byte length of digest */
    950 {
    951    return static_C_CallForSingle(
    952       SERVICE_SYSTEM_PKCS11_C_DIGEST_COMMAND_ID,
    953       hSession,
    954       pData,
    955       ulDataLen,
    956       pDigest,
    957       pulDigestLen,
    958       TRUE,
    959       TRUE);
    960 }
    961 
    962 CK_RV PKCS11_EXPORT C_DigestUpdate(
    963    CK_SESSION_HANDLE hSession,  /* the session's handle */
    964    const CK_BYTE*    pPart,     /* data to be digested */
    965    CK_ULONG          ulPartLen) /* bytes of data to be digested */
    966 {
    967    return static_C_Call_CallForUpdate(
    968       SERVICE_SYSTEM_PKCS11_C_DIGESTUPDATE_COMMAND_ID,
    969       hSession,
    970       pPart,
    971       ulPartLen,
    972       NULL,
    973       NULL,
    974       TRUE,
    975       FALSE);
    976 }
    977 
    978 CK_RV PKCS11_EXPORT C_DigestFinal(
    979    CK_SESSION_HANDLE hSession,  /* the session's handle */
    980    CK_BYTE*       pDigest,      /* receives the message digest */
    981    CK_ULONG*      pulDigestLen) /* receives byte count of digest */
    982 {
    983    return static_C_Call_CallForUpdate(
    984       SERVICE_SYSTEM_PKCS11_C_DIGESTFINAL_COMMAND_ID,
    985       hSession,
    986       NULL,
    987       0,
    988       pDigest,
    989       pulDigestLen,
    990       FALSE,
    991       TRUE);
    992 }
    993 
    994 
    995 CK_RV PKCS11_EXPORT C_SignInit(
    996    CK_SESSION_HANDLE    hSession,    /* the session's handle */
    997    const CK_MECHANISM*  pMechanism,  /* the signature mechanism */
    998    CK_OBJECT_HANDLE     hKey)        /* handle of the signature key */
    999 {
   1000    return static_C_CallInit(
   1001       SERVICE_SYSTEM_PKCS11_C_SIGNINIT_COMMAND_ID,
   1002       hSession,
   1003       pMechanism,
   1004       hKey);
   1005 }
   1006 
   1007 CK_RV PKCS11_EXPORT C_Sign(
   1008    CK_SESSION_HANDLE hSession,        /* the session's handle */
   1009    const CK_BYTE*    pData,           /* the data (digest) to be signed */
   1010    CK_ULONG          ulDataLen,       /* count of bytes to be signed */
   1011    CK_BYTE*          pSignature,      /* receives the signature */
   1012    CK_ULONG*         pulSignatureLen) /* receives byte count of signature */
   1013 {
   1014    return static_C_CallForSingle(
   1015       SERVICE_SYSTEM_PKCS11_C_SIGN_COMMAND_ID,
   1016       hSession,
   1017       pData,
   1018       ulDataLen,
   1019       pSignature,
   1020       pulSignatureLen,
   1021       TRUE,
   1022       TRUE);
   1023 }
   1024 
   1025 CK_RV PKCS11_EXPORT C_SignUpdate(
   1026    CK_SESSION_HANDLE hSession,  /* the session's handle */
   1027    const CK_BYTE*    pPart,     /* the data (digest) to be signed */
   1028    CK_ULONG          ulPartLen) /* count of bytes to be signed */
   1029 {
   1030    return static_C_Call_CallForUpdate(
   1031       SERVICE_SYSTEM_PKCS11_C_SIGNUPDATE_COMMAND_ID,
   1032       hSession,
   1033       pPart,
   1034       ulPartLen,
   1035       NULL,
   1036       NULL,
   1037       TRUE,
   1038       FALSE);
   1039 }
   1040 
   1041 CK_RV PKCS11_EXPORT C_SignFinal(
   1042    CK_SESSION_HANDLE hSession,     /* the session's handle */
   1043    CK_BYTE*       pSignature,      /* receives the signature */
   1044    CK_ULONG*      pulSignatureLen) /* receives byte count of signature */
   1045 {
   1046    return static_C_Call_CallForUpdate(
   1047       SERVICE_SYSTEM_PKCS11_C_SIGNFINAL_COMMAND_ID,
   1048       hSession,
   1049       NULL,
   1050       0,
   1051       pSignature,
   1052       pulSignatureLen,
   1053       FALSE,
   1054       TRUE);
   1055 }
   1056 
   1057 CK_RV PKCS11_EXPORT C_EncryptInit(
   1058    CK_SESSION_HANDLE   hSession,    /* the session's handle */
   1059    const CK_MECHANISM* pMechanism,  /* the encryption mechanism */
   1060    CK_OBJECT_HANDLE    hKey)        /* handle of encryption key */
   1061 {
   1062    return static_C_CallInit(
   1063       SERVICE_SYSTEM_PKCS11_C_ENCRYPTINIT_COMMAND_ID,
   1064       hSession,
   1065       pMechanism,
   1066       hKey);
   1067 }
   1068 
   1069 CK_RV PKCS11_EXPORT C_Encrypt(
   1070    CK_SESSION_HANDLE hSession,            /* the session's handle */
   1071    const CK_BYTE*    pData,               /* the plaintext data */
   1072    CK_ULONG          ulDataLen,           /* bytes of plaintext data */
   1073    CK_BYTE*          pEncryptedData,      /* receives encrypted data */
   1074    CK_ULONG*         pulEncryptedDataLen) /* receives encrypted byte count */
   1075 {
   1076 
   1077    return static_C_CallForSingle(
   1078       SERVICE_SYSTEM_PKCS11_C_ENCRYPT_COMMAND_ID,
   1079       hSession,
   1080       pData,
   1081       ulDataLen,
   1082       pEncryptedData,
   1083       pulEncryptedDataLen,
   1084       TRUE,
   1085       TRUE);
   1086 }
   1087 
   1088 
   1089 
   1090 CK_RV PKCS11_EXPORT C_EncryptUpdate(
   1091    CK_SESSION_HANDLE hSession,           /* the session's handle */
   1092    const CK_BYTE*    pPart,              /* the plaintext data */
   1093    CK_ULONG          ulPartLen,          /* bytes of plaintext data */
   1094    CK_BYTE*          pEncryptedPart,     /* receives encrypted data */
   1095    CK_ULONG*         pulEncryptedPartLen)/* receives encrypted byte count */
   1096 {
   1097    return static_C_Call_CallForUpdate(
   1098       SERVICE_SYSTEM_PKCS11_C_ENCRYPTUPDATE_COMMAND_ID,
   1099       hSession,
   1100       pPart,
   1101       ulPartLen,
   1102       pEncryptedPart,
   1103       pulEncryptedPartLen,
   1104       TRUE,
   1105       TRUE);
   1106 }
   1107 
   1108 CK_RV PKCS11_EXPORT C_EncryptFinal(
   1109    CK_SESSION_HANDLE hSession,             /* the session's handle */
   1110    CK_BYTE*       pLastEncryptedPart,      /* receives encrypted last part */
   1111    CK_ULONG*      pulLastEncryptedPartLen) /* receives byte count */
   1112 {
   1113    return static_C_Call_CallForUpdate(
   1114       SERVICE_SYSTEM_PKCS11_C_ENCRYPTFINAL_COMMAND_ID,
   1115       hSession,
   1116       NULL,
   1117       0,
   1118       pLastEncryptedPart,
   1119       pulLastEncryptedPartLen,
   1120       FALSE,
   1121       TRUE);
   1122 }
   1123 
   1124 CK_RV PKCS11_EXPORT C_DecryptInit(
   1125    CK_SESSION_HANDLE   hSession,    /* the session's handle */
   1126    const CK_MECHANISM* pMechanism,  /* the decryption mechanism */
   1127    CK_OBJECT_HANDLE    hKey)        /* handle of the decryption key */
   1128 {
   1129    return static_C_CallInit(
   1130       SERVICE_SYSTEM_PKCS11_C_DECRYPTINIT_COMMAND_ID,
   1131       hSession,
   1132       pMechanism,
   1133       hKey);
   1134 }
   1135 
   1136 CK_RV PKCS11_EXPORT C_Decrypt(
   1137    CK_SESSION_HANDLE hSession,           /* the session's handle */
   1138    const CK_BYTE*    pEncryptedData,     /* input encrypted data */
   1139    CK_ULONG          ulEncryptedDataLen, /* count of bytes of input */
   1140    CK_BYTE*          pData,              /* receives decrypted output */
   1141    CK_ULONG*         pulDataLen)         /* receives decrypted byte count */
   1142 {
   1143 
   1144    return static_C_CallForSingle(
   1145       SERVICE_SYSTEM_PKCS11_C_DECRYPT_COMMAND_ID,
   1146       hSession,
   1147       pEncryptedData,
   1148       ulEncryptedDataLen,
   1149       pData,
   1150       pulDataLen,
   1151       TRUE,
   1152       TRUE);
   1153 }
   1154 
   1155 CK_RV PKCS11_EXPORT C_DecryptUpdate(
   1156    CK_SESSION_HANDLE hSession,            /* the session's handle */
   1157    const CK_BYTE*    pEncryptedPart,      /* input encrypted data */
   1158    CK_ULONG          ulEncryptedPartLen,  /* count of bytes of input */
   1159    CK_BYTE*          pPart,               /* receives decrypted output */
   1160    CK_ULONG*         pulPartLen)          /* receives decrypted byte count */
   1161 {
   1162    return static_C_Call_CallForUpdate(
   1163       SERVICE_SYSTEM_PKCS11_C_DECRYPTUPDATE_COMMAND_ID,
   1164       hSession,
   1165       pEncryptedPart,
   1166       ulEncryptedPartLen,
   1167       pPart,
   1168       pulPartLen,
   1169       TRUE,
   1170       TRUE);
   1171 }
   1172 
   1173 CK_RV PKCS11_EXPORT C_DecryptFinal(
   1174    CK_SESSION_HANDLE hSession,    /* the session's handle */
   1175    CK_BYTE*       pLastPart,      /* receives decrypted output */
   1176    CK_ULONG*      pulLastPartLen) /* receives decrypted byte count */
   1177 {
   1178    return static_C_Call_CallForUpdate(
   1179       SERVICE_SYSTEM_PKCS11_C_DECRYPTFINAL_COMMAND_ID,
   1180       hSession,
   1181       NULL,
   1182       0,
   1183       pLastPart,
   1184       pulLastPartLen,
   1185       FALSE,
   1186       TRUE);
   1187 }
   1188 
   1189 
   1190 CK_RV PKCS11_EXPORT C_GenerateKey(
   1191    CK_SESSION_HANDLE    hSession,    /* the session's handle */
   1192    const CK_MECHANISM*  pMechanism,  /* the key generation mechanism */
   1193    const CK_ATTRIBUTE*  pTemplate,   /* template for the new key */
   1194    CK_ULONG             ulCount,     /* number of attributes in template */
   1195    CK_OBJECT_HANDLE*    phKey)       /* receives handle of new key */
   1196 {
   1197    TEEC_Result    teeErr;
   1198    uint32_t       nErrorOrigin;
   1199    TEEC_Operation sOperation;
   1200    CK_RV       nErrorCode = CKR_OK;
   1201    uint32_t    nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_GENERATEKEY_COMMAND_ID;
   1202    uint8_t*    pBuffer     = NULL;
   1203    uint32_t    nBufferSize = 0;
   1204    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
   1205 
   1206    if ((pMechanism == NULL) || (phKey == NULL) || (pTemplate == NULL))
   1207    {
   1208       return CKR_ARGUMENTS_BAD;
   1209    }
   1210 
   1211    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
   1212    if (nErrorCode != CKR_OK)
   1213    {
   1214       return nErrorCode;
   1215    }
   1216 
   1217    nErrorCode = static_encodeTemplate(&pBuffer, &nBufferSize, 2, (CK_ATTRIBUTE*)pTemplate, ulCount);
   1218    if (nErrorCode != CKR_OK)
   1219    {
   1220       return nErrorCode;
   1221    }
   1222 
   1223    memset(&sOperation, 0, sizeof(TEEC_Operation));
   1224    sOperation.params[0].value.a = (uint32_t)pMechanism->mechanism;
   1225    sOperation.params[0].value.b = 0;
   1226    sOperation.params[1].tmpref.buffer = pMechanism->pParameter;
   1227    sOperation.params[1].tmpref.size = (uint32_t)pMechanism->ulParameterLen;
   1228    sOperation.params[2].tmpref.buffer = pBuffer;
   1229    sOperation.params[2].tmpref.size = nBufferSize;
   1230    sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE);
   1231    teeErr = TEEC_InvokeCommand(   &pSession->sSession,
   1232                                   nCommandIDAndSession,        /* commandID */
   1233                                   &sOperation,                 /* IN OUT operation */
   1234                                   &nErrorOrigin                /* OUT returnOrigin, optional */
   1235                                  );
   1236    free(pBuffer);
   1237 
   1238    if (teeErr != TEEC_SUCCESS)
   1239    {
   1240       nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
   1241                      teeErr :
   1242                      ckInternalTeeErrorToCKError(teeErr));
   1243       return nErrorCode;
   1244    }
   1245 
   1246    *phKey = sOperation.params[0].value.a;
   1247 
   1248    return CKR_OK;
   1249 }
   1250 
   1251 CK_RV PKCS11_EXPORT C_GenerateKeyPair(
   1252    CK_SESSION_HANDLE    hSession,                    /* the session's handle */
   1253    const CK_MECHANISM*  pMechanism,                  /* the key gen. mech. */
   1254    const CK_ATTRIBUTE*  pPublicKeyTemplate,          /* pub. attr. template */
   1255    CK_ULONG             ulPublicKeyAttributeCount,   /* # of pub. attrs. */
   1256    const CK_ATTRIBUTE*  pPrivateKeyTemplate,         /* priv. attr. template */
   1257    CK_ULONG             ulPrivateKeyAttributeCount,  /* # of priv. attrs. */
   1258    CK_OBJECT_HANDLE*    phPublicKey,                 /* gets pub. key handle */
   1259    CK_OBJECT_HANDLE*    phPrivateKey)                /* gets priv. key handle */
   1260 {
   1261    TEEC_Result    teeErr;
   1262    uint32_t       nErrorOrigin;
   1263    TEEC_Operation sOperation;
   1264    CK_RV       nErrorCode = CKR_OK;
   1265    uint32_t    nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_GENERATEKEYPAIR_COMMAND_ID;
   1266    uint8_t*    pBuffer     = NULL;
   1267    uint32_t    nBufferSize = 0;
   1268    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
   1269 
   1270    if (  (pMechanism == NULL) ||
   1271          (pPublicKeyTemplate == NULL) || (pPrivateKeyTemplate == NULL) ||
   1272          (phPublicKey== NULL) || (phPrivateKey== NULL))
   1273    {
   1274       return CKR_ARGUMENTS_BAD;
   1275    }
   1276 
   1277    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
   1278    if (nErrorCode != CKR_OK)
   1279    {
   1280       return nErrorCode;
   1281    }
   1282 
   1283    nErrorCode = static_encodeTwoTemplates(&pBuffer, &nBufferSize, 2, (CK_ATTRIBUTE*)pPublicKeyTemplate, ulPublicKeyAttributeCount, (CK_ATTRIBUTE*)pPrivateKeyTemplate, ulPrivateKeyAttributeCount);
   1284    if (nErrorCode != CKR_OK)
   1285    {
   1286       return nErrorCode;
   1287    }
   1288 
   1289    memset(&sOperation, 0, sizeof(TEEC_Operation));
   1290    sOperation.params[0].value.a = (uint32_t)pMechanism->mechanism;
   1291    sOperation.params[0].value.b = 0;
   1292    sOperation.params[1].tmpref.buffer = (uint8_t*)pMechanism->pParameter;
   1293    sOperation.params[1].tmpref.size = (uint32_t)pMechanism->ulParameterLen;
   1294    sOperation.params[2].tmpref.buffer = pBuffer;
   1295    sOperation.params[2].tmpref.size = nBufferSize;
   1296    sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE);
   1297    teeErr = TEEC_InvokeCommand(   &pSession->sSession,
   1298                                   nCommandIDAndSession,        /* commandID */
   1299                                   &sOperation,                 /* IN OUT operation */
   1300                                   &nErrorOrigin                /* OUT returnOrigin, optional */
   1301                                  );
   1302    free(pBuffer);
   1303 
   1304    if (teeErr != TEEC_SUCCESS)
   1305    {
   1306       nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
   1307                      teeErr :
   1308                      ckInternalTeeErrorToCKError(teeErr));
   1309       return nErrorCode;
   1310    }
   1311 
   1312    *phPublicKey  = sOperation.params[0].value.a;
   1313    *phPrivateKey = sOperation.params[0].value.b;
   1314 
   1315    return CKR_OK;
   1316 }
   1317 
   1318 CK_RV PKCS11_EXPORT C_DeriveKey(
   1319    CK_SESSION_HANDLE    hSession,          /* session's handle */
   1320    const CK_MECHANISM*  pMechanism,        /* key deriv. mech. */
   1321    CK_OBJECT_HANDLE     hBaseKey,          /* base key */
   1322    const CK_ATTRIBUTE*  pTemplate,         /* new key template */
   1323    CK_ULONG             ulAttributeCount,  /* template length */
   1324    CK_OBJECT_HANDLE*    phKey)             /* gets new handle */
   1325 {
   1326    TEEC_Result    teeErr;
   1327    uint32_t       nErrorOrigin;
   1328    TEEC_Operation sOperation;
   1329    CK_RV       nErrorCode = CKR_OK;
   1330    uint32_t    nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_DERIVEKEY_COMMAND_ID;
   1331    uint8_t*    pBuffer     = NULL;
   1332    uint32_t    nBufferSize = 0;
   1333    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
   1334 
   1335    if ((pMechanism == NULL) || (pTemplate == NULL) || (phKey == NULL))
   1336    {
   1337       return CKR_ARGUMENTS_BAD;
   1338    }
   1339 
   1340    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
   1341    if (nErrorCode != CKR_OK)
   1342    {
   1343       return nErrorCode;
   1344    }
   1345 
   1346    nErrorCode = static_encodeTemplate(&pBuffer, &nBufferSize, 2, (CK_ATTRIBUTE*)pTemplate, ulAttributeCount);
   1347    if (nErrorCode != CKR_OK)
   1348    {
   1349       return nErrorCode;
   1350    }
   1351 
   1352    memset(&sOperation, 0, sizeof(TEEC_Operation));
   1353    sOperation.params[0].value.a = (uint32_t)pMechanism->mechanism;
   1354    sOperation.params[0].value.b = (uint32_t)hBaseKey;
   1355    sOperation.params[1].tmpref.buffer = (uint8_t*)pMechanism->pParameter;
   1356    sOperation.params[1].tmpref.size = (uint32_t)pMechanism->ulParameterLen;
   1357    sOperation.params[2].tmpref.buffer = pBuffer;
   1358    sOperation.params[2].tmpref.size = nBufferSize;
   1359    sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE);
   1360    teeErr = TEEC_InvokeCommand(   &pSession->sSession,
   1361                                   nCommandIDAndSession,        /* commandID */
   1362                                   &sOperation,                 /* IN OUT operation */
   1363                                   &nErrorOrigin                /* OUT returnOrigin, optional */
   1364                                  );
   1365    free(pBuffer);
   1366 
   1367    if (teeErr != TEEC_SUCCESS)
   1368    {
   1369       nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
   1370                      teeErr :
   1371                      ckInternalTeeErrorToCKError(teeErr));
   1372       return nErrorCode;
   1373    }
   1374 
   1375    *phKey = sOperation.params[0].value.a;
   1376 
   1377    return CKR_OK;
   1378 }
   1379 
   1380 CK_RV PKCS11_EXPORT C_SeedRandom(
   1381    CK_SESSION_HANDLE hSession,  /* the session's handle */
   1382    const CK_BYTE*    pSeed,     /* the seed material */
   1383    CK_ULONG          ulSeedLen) /* count of bytes of seed material */
   1384 {
   1385    TEEC_Result    teeErr;
   1386    uint32_t       nErrorOrigin;
   1387    TEEC_Operation sOperation;
   1388    CK_RV       nErrorCode = CKR_OK;
   1389    uint32_t    nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_SEEDRANDOM_COMMAND_ID;
   1390    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
   1391 
   1392    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
   1393    if (nErrorCode != CKR_OK)
   1394    {
   1395       return nErrorCode;
   1396    }
   1397    memset(&sOperation, 0, sizeof(TEEC_Operation));
   1398    sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
   1399    sOperation.params[0].tmpref.buffer = (uint8_t*)pSeed;
   1400    sOperation.params[0].tmpref.size   = (uint32_t)ulSeedLen;
   1401    teeErr = TEEC_InvokeCommand(   &pSession->sSession,
   1402                                   nCommandIDAndSession,        /* commandID */
   1403                                   &sOperation,                 /* IN OUT operation */
   1404                                   &nErrorOrigin                /* OUT returnOrigin, optional */
   1405                                  );
   1406 
   1407    nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
   1408                   teeErr :
   1409                   ckInternalTeeErrorToCKError(teeErr));
   1410    return nErrorCode;
   1411 }
   1412 
   1413 CK_RV PKCS11_EXPORT C_GenerateRandom(
   1414    CK_SESSION_HANDLE hSession,    /* the session's handle */
   1415    CK_BYTE*          pRandomData,  /* receives the random data */
   1416    CK_ULONG          ulRandomLen) /* number of bytes to be generated */
   1417 {
   1418    TEEC_Result    teeErr;
   1419    uint32_t       nErrorOrigin;
   1420    TEEC_Operation sOperation;
   1421    CK_RV       nErrorCode = CKR_OK;
   1422    uint32_t    nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_GENERATERANDOM_COMMAND_ID;
   1423    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
   1424 
   1425    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
   1426    if (nErrorCode != CKR_OK)
   1427    {
   1428       return nErrorCode;
   1429    }
   1430 
   1431    do
   1432    {
   1433       CK_ULONG nArrayLength;
   1434       nArrayLength = 1024;
   1435       if (ulRandomLen < nArrayLength)
   1436       {
   1437          nArrayLength = ulRandomLen;
   1438       }
   1439       memset(&sOperation, 0, sizeof(TEEC_Operation));
   1440       sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
   1441       sOperation.params[0].tmpref.buffer = (uint8_t*)pRandomData;
   1442       sOperation.params[0].tmpref.size   = (uint32_t)nArrayLength;
   1443       teeErr = TEEC_InvokeCommand(   &pSession->sSession,
   1444                                      nCommandIDAndSession,        /* commandID */
   1445                                      &sOperation,                 /* IN OUT operation */
   1446                                      &nErrorOrigin                /* OUT returnOrigin, optional */
   1447                                     );
   1448       if (teeErr != TEEC_SUCCESS)
   1449       {
   1450          nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
   1451                         teeErr :
   1452                         ckInternalTeeErrorToCKError(teeErr));
   1453          return nErrorCode;
   1454       }
   1455 
   1456       ulRandomLen -= nArrayLength;
   1457       pRandomData += nArrayLength;
   1458       if (ulRandomLen == 0)
   1459       {
   1460          break;
   1461       }
   1462    }
   1463    while(1);
   1464 
   1465    return CKR_OK;
   1466 }
   1467 
   1468 CK_RV PKCS11_EXPORT C_VerifyInit(
   1469    CK_SESSION_HANDLE   hSession,    /* the session's handle */
   1470    const CK_MECHANISM* pMechanism,  /* the verification mechanism */
   1471    CK_OBJECT_HANDLE    hKey)        /* handle of the verification key */
   1472 {
   1473    return static_C_CallInit(
   1474       SERVICE_SYSTEM_PKCS11_C_VERIFYINIT_COMMAND_ID,
   1475       hSession,
   1476       pMechanism,
   1477       hKey);
   1478 }
   1479 
   1480 CK_RV PKCS11_EXPORT C_Verify(
   1481    CK_SESSION_HANDLE hSession,       /* the session's handle */
   1482    const CK_BYTE*    pData,          /* plaintext data (digest) to compare */
   1483    CK_ULONG          ulDataLen,      /* length of data (digest) in bytes */
   1484    CK_BYTE*          pSignature,     /* the signature to be verified */
   1485    CK_ULONG          ulSignatureLen) /* count of bytes of signature */
   1486 {
   1487    TEEC_Result    teeErr;
   1488    uint32_t       nErrorOrigin;
   1489    TEEC_Operation sOperation;
   1490    CK_RV       nErrorCode = CKR_OK;
   1491    uint32_t    nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_VERIFY_COMMAND_ID;
   1492    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
   1493 
   1494    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
   1495    if (nErrorCode != CKR_OK)
   1496    {
   1497       return nErrorCode;
   1498    }
   1499 
   1500    memset(&sOperation, 0, sizeof(TEEC_Operation));
   1501    sOperation.params[0].tmpref.buffer = (uint8_t*)pData;
   1502    sOperation.params[0].tmpref.size   = (uint32_t)ulDataLen;
   1503    sOperation.params[1].tmpref.buffer = (uint8_t*)pSignature;
   1504    sOperation.params[1].tmpref.size   = (uint32_t)ulSignatureLen;
   1505    sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE);
   1506    teeErr = TEEC_InvokeCommand(   &pSession->sSession,
   1507                                   nCommandIDAndSession,        /* commandID */
   1508                                   &sOperation,                 /* IN OUT operation */
   1509                                   &nErrorOrigin                /* OUT returnOrigin, optional */
   1510                                  );
   1511    nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
   1512                   teeErr :
   1513                   ckInternalTeeErrorToCKError(teeErr));
   1514    return nErrorCode;
   1515 }
   1516 
   1517 CK_RV PKCS11_EXPORT C_VerifyUpdate(
   1518    CK_SESSION_HANDLE hSession,  /* the session's handle */
   1519    const CK_BYTE*    pPart,     /* plaintext data (digest) to compare */
   1520    CK_ULONG          ulPartLen) /* length of data (digest) in bytes */
   1521 {
   1522    return static_C_Call_CallForUpdate(
   1523       SERVICE_SYSTEM_PKCS11_C_VERIFYUPDATE_COMMAND_ID,
   1524       hSession,
   1525       pPart,
   1526       ulPartLen,
   1527       NULL,
   1528       NULL,
   1529       TRUE,
   1530       FALSE);
   1531 }
   1532 
   1533 CK_RV PKCS11_EXPORT C_VerifyFinal(
   1534    CK_SESSION_HANDLE hSession,       /* the session's handle */
   1535    const CK_BYTE*    pSignature,     /* the signature to be verified */
   1536    CK_ULONG          ulSignatureLen) /* count of bytes of signature */
   1537 {
   1538    return static_C_Call_CallForUpdate(
   1539       SERVICE_SYSTEM_PKCS11_C_VERIFYFINAL_COMMAND_ID,
   1540       hSession,
   1541       pSignature,
   1542       ulSignatureLen,
   1543       NULL,
   1544       NULL,
   1545       TRUE,
   1546       FALSE);
   1547 }
   1548 
   1549 CK_RV PKCS11_EXPORT C_CloseObjectHandle(
   1550    CK_SESSION_HANDLE hSession,  /* the session's handle */
   1551    CK_OBJECT_HANDLE  hObject)   /* the object's handle */
   1552 {
   1553    TEEC_Result    teeErr;
   1554    uint32_t       nErrorOrigin;
   1555    TEEC_Operation sOperation;
   1556    CK_RV       nErrorCode = CKR_OK;
   1557    uint32_t    nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_CLOSEOBJECTHANDLE_COMMAND_ID;
   1558    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
   1559 
   1560    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
   1561    if (nErrorCode != CKR_OK)
   1562    {
   1563       return nErrorCode;
   1564    }
   1565    memset(&sOperation, 0, sizeof(TEEC_Operation));
   1566    sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
   1567    sOperation.params[0].value.a = (uint32_t)hObject;
   1568    sOperation.params[0].value.b = 0;
   1569    teeErr = TEEC_InvokeCommand(   &pSession->sSession,
   1570                                   nCommandIDAndSession,        /* commandID */
   1571                                   &sOperation,                 /* IN OUT operation */
   1572                                   &nErrorOrigin                /* OUT returnOrigin, optional */
   1573                                  );
   1574    nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
   1575                   teeErr :
   1576                   ckInternalTeeErrorToCKError(teeErr));
   1577    return nErrorCode;
   1578 }
   1579 
   1580 CK_RV PKCS11_EXPORT C_CopyObject(
   1581          CK_SESSION_HANDLE    hSession,    /* the session's handle */
   1582          CK_OBJECT_HANDLE     hObject,     /* the source object's handle */
   1583    const CK_ATTRIBUTE*        pTemplate,   /* the template of the copied object */
   1584          CK_ULONG             ulCount,     /* the number of attributes of the template*/
   1585          CK_OBJECT_HANDLE*    phNewObject) /* the copied object's handle */
   1586 {
   1587    TEEC_Result    teeErr;
   1588    uint32_t       nErrorOrigin;
   1589    TEEC_Operation sOperation;
   1590    CK_RV       nErrorCode = CKR_OK;
   1591    uint32_t    nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_COPYOBJECT_COMMAND_ID;
   1592    uint8_t*    pBuffer     = NULL;
   1593    uint32_t    nBufferSize = 0;
   1594    PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
   1595 
   1596    if ((pTemplate == NULL) || (phNewObject == NULL))
   1597    {
   1598       return CKR_ARGUMENTS_BAD;
   1599    }
   1600 
   1601    nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
   1602    if (nErrorCode != CKR_OK)
   1603    {
   1604       return nErrorCode;
   1605    }
   1606 
   1607    nErrorCode = static_encodeTemplate(&pBuffer, &nBufferSize, 1, (CK_ATTRIBUTE*)pTemplate, ulCount);
   1608    if (nErrorCode != CKR_OK)
   1609    {
   1610       return nErrorCode;
   1611    }
   1612 
   1613    memset(&sOperation, 0, sizeof(TEEC_Operation));
   1614    sOperation.params[0].value.a = (uint32_t)hObject;
   1615    sOperation.params[0].value.b = 0;
   1616    sOperation.params[1].tmpref.buffer = pBuffer;
   1617    sOperation.params[1].tmpref.size   = nBufferSize;
   1618    sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE);
   1619    teeErr = TEEC_InvokeCommand(   &pSession->sSession,
   1620                                   nCommandIDAndSession,        /* commandID */
   1621                                   &sOperation,                 /* IN OUT operation */
   1622                                   &nErrorOrigin                /* OUT returnOrigin, optional */
   1623                                  );
   1624    free(pBuffer);
   1625 
   1626    if (teeErr != TEEC_SUCCESS)
   1627    {
   1628       nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
   1629                      teeErr :
   1630                      ckInternalTeeErrorToCKError(teeErr));
   1631       return nErrorCode;
   1632    }
   1633 
   1634    *phNewObject = sOperation.params[0].value.a;
   1635 
   1636    return CKR_OK;
   1637 }
   1638