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