| /** |
| * Copyright(c) 2011 Trusted Logic. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name Trusted Logic nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "pkcs11_internal.h" |
| |
| /* ------------------------------------------------------------------------ |
| Internal Functions |
| ------------------------------------------------------------------------- */ |
| /** |
| * Checks the following pre-conditions: |
| * - cryptoki is initialized, |
| * - hSession is valid (primary and/or secondary), |
| * - the user is logged in. |
| * |
| * And updates handle values: |
| * IN/OUT : phSession |
| * IN = Cryptoki external handle |
| * OUT = TFAPI handle = primary cryptoki session handle |
| * OUT : phSecSession16Msb |
| * OUT = 0 for a primary session or |
| * the secondary cryptoki session handle in the 16 MSB bits |
| */ |
| static CK_RV static_checkPreConditionsAndUpdateHandles( |
| CK_SESSION_HANDLE* phSession, |
| uint32_t* phCommandIDAndSession, |
| PPKCS11_PRIMARY_SESSION_CONTEXT* ppSession) |
| { |
| bool bIsPrimarySession; |
| |
| /* Check Cryptoki is initialized */ |
| if (!g_bCryptokiInitialized) |
| { |
| return CKR_CRYPTOKI_NOT_INITIALIZED; |
| } |
| |
| if (phSession == NULL) |
| { |
| return CKR_SESSION_HANDLE_INVALID; |
| } |
| |
| /* Check that the session is valid */ |
| if (!ckInternalSessionIsOpenedEx(*phSession, &bIsPrimarySession)) |
| { |
| return CKR_SESSION_HANDLE_INVALID; |
| } |
| /* previous check is fine, then update session handles */ |
| if (bIsPrimarySession) |
| { |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession = |
| (PPKCS11_PRIMARY_SESSION_CONTEXT)(*phSession); |
| |
| *phSession = pSession->hCryptoSession; |
| *phCommandIDAndSession = (pSession->hCryptoSession<<16)|(*phCommandIDAndSession&0x00007FFF); |
| *ppSession = pSession; |
| } |
| else |
| { |
| PPKCS11_SECONDARY_SESSION_CONTEXT pSecSession = |
| (PPKCS11_SECONDARY_SESSION_CONTEXT)(*phSession); |
| |
| *phSession = pSecSession->pPrimarySession->hCryptoSession; |
| *phCommandIDAndSession = (pSecSession->hSecondaryCryptoSession<<16)|(1<<15)|(*phCommandIDAndSession&0x00007FFF); |
| *ppSession = pSecSession->pPrimarySession; |
| } |
| |
| return CKR_OK; |
| } |
| |
| /******************************************/ |
| /* The buffer must be freed by the caller */ |
| /******************************************/ |
| static CK_RV static_encodeTwoTemplates( |
| uint8_t** ppBuffer, |
| uint32_t * pBufferSize, |
| const uint32_t nParamIndex, |
| CK_ATTRIBUTE* pTemplate1, |
| CK_ULONG ulCount1, |
| CK_ATTRIBUTE* pTemplate2, |
| CK_ULONG ulCount2) |
| { |
| INPUT_TEMPLATE_ITEM sItem; |
| |
| uint32_t i; |
| uint32_t nDataOffset = 0; |
| uint32_t nBufferIndex = 0; |
| uint32_t nBufferSize = 0; |
| uint8_t* pBuffer = NULL; |
| CK_RV nErrorCode = CKR_OK; |
| |
| if (ulCount1 == 0) |
| { |
| /* Nothing to do */ |
| return CKR_OK; |
| } |
| if (pTemplate1 == NULL) |
| { |
| /* Nothing to do */ |
| return CKR_OK; |
| } |
| |
| /* First compute the total required buffer size that |
| * will contain the full templates (for the template 1 AND 2) |
| */ |
| nBufferSize = 4 + /* Nb Attributes */ |
| sizeof(INPUT_TEMPLATE_ITEM)*ulCount1; /* The attributes items */ |
| if (pTemplate2 != NULL) |
| { |
| nBufferSize += 4 + /* Nb Attributes */ |
| sizeof(INPUT_TEMPLATE_ITEM)*ulCount2; /* The attributes items */ |
| } |
| |
| /* First data (attribute values) on either template 1 or 2 will just be after the last item */ |
| nDataOffset = nBufferSize; |
| |
| for (i = 0; i < ulCount1; i++) |
| { |
| /* Each value will be aligned on 4 bytes. |
| This computation includes the spare bytes. */ |
| nBufferSize += PKCS11_GET_SIZE_WITH_ALIGNMENT(pTemplate1[i].ulValueLen); |
| } |
| if (pTemplate2 != NULL) |
| { |
| for (i = 0; i < ulCount2; i++) |
| { |
| /* Each value will be aligned on 4 bytes. |
| This computation includes the spare bytes. */ |
| nBufferSize += PKCS11_GET_SIZE_WITH_ALIGNMENT(pTemplate2[i].ulValueLen); |
| } |
| } |
| |
| pBuffer = (uint8_t*)malloc(nBufferSize); |
| if (pBuffer == NULL) |
| { |
| /* Not enough memory */ |
| return CKR_DEVICE_MEMORY; |
| } |
| |
| memset(pBuffer, 0, nBufferSize); |
| |
| /* |
| * First template |
| */ |
| *(uint32_t*)(pBuffer + nBufferIndex) = ulCount1; |
| nBufferIndex += 4; |
| for (i = 0; i < ulCount1; i++) |
| { |
| sItem.attributeType = (uint32_t)pTemplate1[i].type; |
| /* dataOffset = 0 means NULL buffer */ |
| sItem.dataOffset = ((pTemplate1[i].pValue == NULL) ? 0 : nDataOffset); |
| sItem.dataParamIndex = nParamIndex; /* The parameter where we store the data (0 to 3) */ |
| sItem.dataValueLen = (uint32_t)pTemplate1[i].ulValueLen; |
| /* Copy the item */ |
| memcpy(pBuffer + nBufferIndex, &sItem, sizeof(INPUT_TEMPLATE_ITEM)); |
| nBufferIndex += sizeof(INPUT_TEMPLATE_ITEM); |
| if (pTemplate1[i].pValue != NULL) |
| { |
| /* Copy the data */ |
| memcpy(pBuffer + nDataOffset, (uint8_t*)pTemplate1[i].pValue, (uint32_t)pTemplate1[i].ulValueLen); |
| /* Next data will be stored just after the previous one but aligned on 4 bytes */ |
| nDataOffset += PKCS11_GET_SIZE_WITH_ALIGNMENT(pTemplate1[i].ulValueLen); |
| if ((nDataOffset & 0xC0000000) != 0) |
| { |
| /* We whould never go in this case, that means the dataOffset will not be able to store the offset correctly */ |
| nErrorCode = CKR_DEVICE_ERROR; |
| goto error; |
| } |
| } |
| } |
| |
| /* |
| * Second template |
| */ |
| if (pTemplate2 != NULL) |
| { |
| *(uint32_t*)(pBuffer + nBufferIndex) = ulCount2; |
| nBufferIndex += 4; |
| for (i = 0; i < ulCount2; i++) |
| { |
| sItem.attributeType = (uint32_t)pTemplate2[i].type; |
| /* dataOffset = 0 means NULL buffer */ |
| sItem.dataOffset = ((pTemplate2[i].pValue == NULL) ? 0 : nDataOffset); |
| sItem.dataParamIndex = nParamIndex; /* The parameter where we store the data (0..3) */ |
| sItem.dataValueLen = (uint32_t)pTemplate2[i].ulValueLen; |
| /* Copy the item */ |
| memcpy(pBuffer + nBufferIndex, &sItem, sizeof(INPUT_TEMPLATE_ITEM)); |
| nBufferIndex += sizeof(INPUT_TEMPLATE_ITEM); |
| if (pTemplate2[i].pValue != NULL) |
| { |
| /* Copy the data */ |
| memcpy(pBuffer + nDataOffset, (uint8_t*)pTemplate2[i].pValue, (uint32_t)pTemplate2[i].ulValueLen); |
| /* Next data will be stored just after the previous one but aligned on 4 bytes */ |
| nDataOffset += PKCS11_GET_SIZE_WITH_ALIGNMENT(pTemplate2[i].ulValueLen); |
| if ((nDataOffset & 0xC0000000) != 0) |
| { |
| /* We whould never go in this case, that means the dataOffset will not be able to store the offset correctly */ |
| nErrorCode = CKR_DEVICE_ERROR; |
| goto error; |
| } |
| } |
| } |
| } |
| |
| *ppBuffer = pBuffer; |
| *pBufferSize = nBufferSize; |
| |
| return CKR_OK; |
| |
| error: |
| free(pBuffer); |
| return nErrorCode; |
| } |
| |
| /******************************************/ |
| /* The buffer must be freed by the caller */ |
| /******************************************/ |
| static CK_RV static_encodeTemplate( |
| uint8_t** ppBuffer, |
| uint32_t* pBufferSize, |
| const uint32_t nParamIndex, |
| CK_ATTRIBUTE* pTemplate, |
| CK_ULONG ulCount) |
| { |
| return static_encodeTwoTemplates(ppBuffer, pBufferSize, nParamIndex, pTemplate, ulCount, NULL, 0); |
| } |
| /* ----------------------------------------------------------------------- */ |
| |
| static CK_RV static_C_CallInit( |
| uint32_t nCommandID, |
| CK_SESSION_HANDLE hSession, |
| const CK_MECHANISM* pMechanism, |
| CK_OBJECT_HANDLE hKey) |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| uint32_t nCommandIDAndSession = nCommandID; |
| uint32_t nParamType2 = TEEC_NONE; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| if (pMechanism == NULL) |
| { |
| return CKR_ARGUMENTS_BAD; |
| } |
| |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| sOperation.params[0].value.a = (uint32_t)pMechanism->mechanism; |
| if (nCommandID != SERVICE_SYSTEM_PKCS11_C_DIGESTINIT_COMMAND_ID) |
| { |
| sOperation.params[0].value.b = (uint32_t)hKey; |
| |
| } |
| sOperation.params[1].tmpref.buffer = (uint8_t*)pMechanism->pParameter; |
| sOperation.params[1].tmpref.size = (uint32_t)pMechanism->ulParameterLen; |
| |
| /* Specific case of RSA OAEP */ |
| if (((nCommandID == SERVICE_SYSTEM_PKCS11_C_ENCRYPTINIT_COMMAND_ID) |
| ||(nCommandID == SERVICE_SYSTEM_PKCS11_C_DECRYPTINIT_COMMAND_ID)) |
| && (pMechanism->mechanism == CKM_RSA_PKCS_OAEP) |
| && (pMechanism->pParameter != NULL)) |
| { |
| /* Add the source buffer of the RSA OAEP mechanism parameters */ |
| nParamType2 = TEEC_MEMREF_TEMP_INPUT; |
| sOperation.params[2].tmpref.buffer = (uint8_t*)((CK_RSA_PKCS_OAEP_PARAMS_PTR)(pMechanism->pParameter))->pSourceData; |
| sOperation.params[2].tmpref.size = (uint32_t) ((CK_RSA_PKCS_OAEP_PARAMS_PTR)(pMechanism->pParameter))->ulSourceDataLen; |
| } |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_INPUT, nParamType2, TEEC_NONE); |
| teeErr = TEEC_InvokeCommand( &pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| |
| return nErrorCode; |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| /** |
| * If bSend, the pData buffer is sent to the service. |
| * If bResult, a buffer is received, the convention described in |
| * PKCS11 Section 11.2 applies for pResult and pulResultLen. |
| * Specific function used for single operation |
| */ |
| static CK_RV static_C_CallForSingle( |
| uint32_t nCommandID, |
| CK_SESSION_HANDLE hSession, |
| const CK_BYTE* pData, |
| CK_ULONG ulDataLen, |
| CK_BYTE* pResult, |
| CK_ULONG* pulResultLen, |
| bool bSend, |
| bool bReceive) |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| uint32_t nCommandIDAndSession = nCommandID; |
| uint32_t nParamType0 = TEEC_NONE; |
| uint32_t nParamType1 = TEEC_NONE; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| |
| if (bSend) |
| { |
| nParamType0 = TEEC_MEMREF_TEMP_INPUT; |
| sOperation.params[0].tmpref.buffer = (uint8_t*)pData; |
| sOperation.params[0].tmpref.size = (uint32_t)ulDataLen; |
| } |
| |
| if (bReceive) |
| { |
| if (pulResultLen == NULL) |
| { |
| /* The P11 API Spec states that, in this case, the operation must be |
| aborted and the error code CKR_ARGUMENTS_BAD must be returned. We |
| achieve this result by sending an invalid parameter type */ |
| nParamType1 = TEEC_NONE; |
| } |
| else if (pResult == NULL) |
| { |
| /* If pResult is NULL, the caller only wants the buffer length. |
| Send a NULL output memref */ |
| nParamType1 = TEEC_MEMREF_TEMP_OUTPUT; |
| sOperation.params[1].tmpref.buffer = (uint8_t*)NULL; |
| } |
| else |
| { |
| /* send the result buffer information */ |
| nParamType1 = TEEC_MEMREF_TEMP_OUTPUT; |
| sOperation.params[1].tmpref.buffer = (uint8_t*)pResult; |
| sOperation.params[1].tmpref.size = (uint32_t)*pulResultLen; |
| } |
| } |
| |
| sOperation.paramTypes = TEEC_PARAM_TYPES(nParamType0, nParamType1, TEEC_NONE, TEEC_NONE); |
| teeErr = TEEC_InvokeCommand(&pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| if (teeErr != TEEC_SUCCESS) |
| { |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| goto end; |
| } |
| |
| /* Success */ |
| nErrorCode = CKR_OK; |
| |
| end: |
| if (bReceive) |
| { |
| if ((nErrorCode == CKR_OK) || (nErrorCode == CKR_BUFFER_TOO_SMALL)) |
| { |
| /* The service has returned the actual result */ |
| /* The data is already in pResult, we get the returned length */ |
| *pulResultLen = sOperation.params[1].tmpref.size; |
| } |
| } |
| |
| return nErrorCode; |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| /** |
| * If bSend, the pData buffer is sent to the service. |
| * If bResult, a buffer is received, the convention described in |
| * PKCS11 Section 11.2 applies for pResult and pulResultLen. |
| * Specific function only used for update operations |
| */ |
| static CK_RV static_C_CallUpdate( |
| uint32_t nCommandID, |
| CK_SESSION_HANDLE hSession, |
| const CK_BYTE* pData, |
| CK_ULONG ulDataLen, |
| CK_BYTE* pResult, |
| CK_ULONG* pulResultLen, |
| bool bSend, |
| bool bReceive) |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| uint32_t nResultLen = 0; |
| uint32_t nCommandIDAndSession = nCommandID; |
| uint32_t nParamType0 = TEEC_NONE; |
| uint32_t nParamType1 = TEEC_NONE; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| if (pulResultLen != NULL) |
| { |
| nResultLen = *pulResultLen; |
| } |
| |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| |
| if (bSend) |
| { |
| nParamType0 = TEEC_MEMREF_TEMP_INPUT; |
| sOperation.params[0].tmpref.buffer = (void*)pData; |
| sOperation.params[0].tmpref.size = ulDataLen; |
| } |
| |
| if (bReceive) |
| { |
| if (pulResultLen == NULL) |
| { |
| /* The P11 API Spec states that, in this case, the operation must be |
| aborted and the error code CKR_ARGUMENTS_BAD must be returned. We |
| achieve this result by setting an invalid parameter type */ |
| nParamType1 = TEEC_NONE; |
| } |
| else if (pResult == NULL) |
| { |
| /* If pResult is NULL, the caller only wants the output buffer length. |
| Pass a NULL output ref */ |
| nParamType1 = TEEC_MEMREF_TEMP_OUTPUT; |
| sOperation.params[1].tmpref.buffer = NULL; |
| } |
| else |
| { |
| /* send the result buffer information */ |
| nParamType1 = TEEC_MEMREF_TEMP_OUTPUT; |
| sOperation.params[1].tmpref.buffer = pResult; |
| sOperation.params[1].tmpref.size = (uint32_t)*pulResultLen; |
| } |
| } |
| |
| sOperation.paramTypes = TEEC_PARAM_TYPES(nParamType0, nParamType1, TEEC_NONE, TEEC_NONE); |
| teeErr = TEEC_InvokeCommand( &pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| if (teeErr != TEEC_SUCCESS) |
| { |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| goto end; |
| } |
| |
| /* Success */ |
| nErrorCode = CKR_OK; |
| |
| end: |
| if (bReceive) |
| { |
| if ((nErrorCode == CKR_OK) || (nErrorCode == CKR_BUFFER_TOO_SMALL)) |
| { |
| /* The service has returned the actual result */ |
| /* The data is already in pResult, we get the returned length */ |
| *pulResultLen = sOperation.params[1].tmpref.size; |
| } |
| } |
| |
| return nErrorCode; |
| } |
| |
| /* Splits the buffer pData in chunks of nChunkSize size |
| * and calls static_C_CallUpdate for each chunk |
| */ |
| static CK_RV static_C_CallSplitUpdate( |
| uint32_t nCommandID, |
| CK_SESSION_HANDLE hSession, |
| const CK_BYTE* pData, |
| CK_ULONG ulDataLen, |
| CK_BYTE* pResult, |
| CK_ULONG* pulResultLen, |
| bool bSend, |
| bool bReceive, |
| uint32_t nChunkSize) |
| { |
| CK_RV nErrorCode; |
| CK_ULONG nPartDataLen; |
| CK_ULONG nPartResultLen = 0; |
| CK_ULONG ulResultLen = 0; |
| bool bIsSymOperation = false; |
| |
| if (pulResultLen != NULL) |
| { |
| ulResultLen = *pulResultLen; |
| /* Check wether the operation is a symetrical or asymetrical */ |
| if (*pulResultLen == ulDataLen) |
| { |
| bIsSymOperation = true; |
| } |
| *pulResultLen = 0; |
| } |
| |
| while (ulDataLen > 0) |
| { |
| nPartDataLen = (ulDataLen <= nChunkSize ? |
| ulDataLen : nChunkSize); |
| if (bIsSymOperation) |
| { |
| /* update the result only if it is a symetric operation */ |
| nPartResultLen = (ulResultLen <= nChunkSize ? |
| ulResultLen : nChunkSize); |
| } |
| else |
| { |
| nPartResultLen = ulResultLen; |
| } |
| |
| nErrorCode = static_C_CallUpdate( |
| nCommandID, |
| hSession, |
| pData, |
| nPartDataLen, |
| pResult, |
| &nPartResultLen, |
| bSend, |
| bReceive); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| ulDataLen -= nPartDataLen; |
| pData += nPartDataLen; |
| |
| if (pResult != NULL) |
| { |
| ulResultLen -= nPartResultLen; |
| pResult += nPartResultLen; |
| } |
| |
| if ((pulResultLen != NULL) && (bIsSymOperation)) |
| { |
| *pulResultLen += nPartResultLen; |
| } |
| } |
| return CKR_OK; |
| } |
| |
| /* Decides whether to split or not the inout/output buffer into chunks |
| */ |
| static CK_RV static_C_Call_CallForUpdate( |
| uint32_t nCommandID, |
| CK_SESSION_HANDLE hSession, |
| const CK_BYTE* pData, |
| CK_ULONG ulDataLen, |
| CK_BYTE* pResult, |
| CK_ULONG* pulResultLen, |
| bool bSend, |
| bool bReceive) |
| { |
| CK_RV nErrorCode; |
| uint32_t nChunkSize; |
| |
| TEEC_ImplementationLimits limits; |
| |
| if (!g_bCryptokiInitialized) |
| { |
| return CKR_CRYPTOKI_NOT_INITIALIZED; |
| } |
| |
| TEEC_GetImplementationLimits(&limits); |
| |
| /* We can split the buffer in chunks of fixed size. |
| No matter of the start address of the buffer, |
| a safe size would be TotalNumberOfPages - 1 |
| */ |
| nChunkSize = limits.tmprefMaxSize - limits.pageSize; |
| |
| if (ulDataLen > nChunkSize) |
| { |
| /* inoutMaxSize = 0 means unlimited size */ |
| nErrorCode = static_C_CallSplitUpdate(nCommandID, |
| hSession, |
| pData, |
| ulDataLen, |
| pResult, |
| pulResultLen, |
| bSend, |
| bReceive, |
| nChunkSize); |
| } |
| else |
| { |
| nErrorCode = static_C_CallUpdate(nCommandID, |
| hSession, |
| pData, |
| ulDataLen, |
| pResult, |
| pulResultLen, |
| bSend, |
| bReceive); |
| } |
| return nErrorCode; |
| |
| } |
| |
| /* ------------------------------------------------------------------------ |
| Public Functions |
| ------------------------------------------------------------------------- */ |
| |
| CK_RV PKCS11_EXPORT C_CreateObject( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_ATTRIBUTE* pTemplate, /* the object's template */ |
| CK_ULONG ulCount, /* attributes in template */ |
| CK_OBJECT_HANDLE* phObject) /* receives new object's handle. */ |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_CREATEOBJECT_COMMAND_ID; |
| uint8_t* pBuffer = NULL; |
| uint32_t nBufferSize = 0; |
| |
| if ( pTemplate == NULL || phObject == NULL ) |
| { |
| return CKR_ARGUMENTS_BAD; |
| } |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| nErrorCode = static_encodeTemplate(&pBuffer, &nBufferSize, 0, (CK_ATTRIBUTE*)pTemplate, ulCount); /* Sets the template on the param 0 */ |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_VALUE_OUTPUT, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].tmpref.buffer = pBuffer; |
| sOperation.params[0].tmpref.size = nBufferSize; |
| teeErr = TEEC_InvokeCommand( &pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| free(pBuffer); |
| |
| if (teeErr != TEEC_SUCCESS) |
| { |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| goto end; |
| } |
| |
| *phObject = sOperation.params[1].value.a; |
| |
| /* Success */ |
| nErrorCode = CKR_OK; |
| |
| end: |
| return nErrorCode; |
| } |
| |
| CK_RV PKCS11_EXPORT C_DestroyObject( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| CK_OBJECT_HANDLE hObject) /* the object's handle */ |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_DESTROYOBJECT_COMMAND_ID; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].value.a = (uint32_t)hObject; |
| teeErr = TEEC_InvokeCommand( &pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| return nErrorCode; |
| } |
| |
| CK_RV PKCS11_EXPORT C_GetAttributeValue( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| CK_OBJECT_HANDLE hObject, /* the object's handle */ |
| CK_ATTRIBUTE* pTemplate, /* specifies attributes, gets values */ |
| CK_ULONG ulCount) /* attributes in template */ |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| CK_RV nFinalErrorCode = CKR_OK; |
| uint32_t i = 0; |
| uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_GETATTRIBUTEVALUE_COMMAND_ID; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| if (pTemplate == NULL) |
| { |
| return CKR_ARGUMENTS_BAD; |
| } |
| |
| if (ulCount == 0) |
| { |
| return CKR_OK; |
| } |
| |
| for (i = 0; i < ulCount; i++) |
| { |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].value.a = (uint32_t)hObject; |
| sOperation.params[0].value.b = (uint32_t)pTemplate[i].type; |
| sOperation.params[1].tmpref.buffer = pTemplate[i].pValue; |
| sOperation.params[1].tmpref.size = pTemplate[i].ulValueLen; |
| teeErr = TEEC_InvokeCommand( &pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| if (nErrorCode != CKR_OK) |
| { |
| if ( (nErrorCode == CKR_ATTRIBUTE_SENSITIVE) || |
| (nErrorCode == CKR_ATTRIBUTE_TYPE_INVALID) || |
| (nErrorCode == CKR_BUFFER_TOO_SMALL)) |
| { |
| nFinalErrorCode = nErrorCode; |
| } |
| else |
| { |
| /* Not some of the special error codes: this is fatal */ |
| return nErrorCode; |
| } |
| } |
| |
| pTemplate[i].ulValueLen = sOperation.params[1].tmpref.size; |
| } |
| |
| return nFinalErrorCode; |
| } |
| |
| CK_RV PKCS11_EXPORT C_FindObjectsInit( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_ATTRIBUTE* pTemplate, /* attribute values to match */ |
| CK_ULONG ulCount) /* attributes in search template */ |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_FINDOBJECTSINIT_COMMAND_ID; |
| uint8_t* pBuffer = NULL; |
| uint32_t nBufferSize = 0; |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| nErrorCode = static_encodeTemplate(&pBuffer, &nBufferSize, 0, (CK_ATTRIBUTE*)pTemplate, ulCount); /* Sets the template on the param 0 */ |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].tmpref.buffer = pBuffer; |
| sOperation.params[0].tmpref.size = nBufferSize; |
| teeErr = TEEC_InvokeCommand( &pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| free(pBuffer); |
| |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| return nErrorCode; |
| } |
| |
| |
| CK_RV PKCS11_EXPORT C_FindObjects( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| CK_OBJECT_HANDLE* phObject, /* receives object handle array */ |
| CK_ULONG ulMaxObjectCount, /* max handles to be returned */ |
| CK_ULONG* pulObjectCount) /* actual number returned */ |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_FINDOBJECTS_COMMAND_ID; |
| |
| if ( (phObject == NULL) || (pulObjectCount == NULL)) |
| { |
| return CKR_ARGUMENTS_BAD; |
| } |
| |
| *pulObjectCount = 0; |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].tmpref.buffer = (uint8_t*)phObject; |
| sOperation.params[0].tmpref.size = (uint32_t)ulMaxObjectCount * sizeof(uint32_t); |
| |
| teeErr = TEEC_InvokeCommand( &pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| |
| if (teeErr != TEEC_SUCCESS) |
| { |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| return nErrorCode; |
| } |
| |
| *pulObjectCount = sOperation.params[0].tmpref.size / sizeof(uint32_t); |
| |
| return CKR_OK; |
| } |
| |
| CK_RV PKCS11_EXPORT C_FindObjectsFinal(CK_SESSION_HANDLE hSession) /* the session's handle */ |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_FINDOBJECTSFINAL_COMMAND_ID; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| teeErr = TEEC_InvokeCommand( &pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| return nErrorCode; |
| } |
| |
| |
| CK_RV PKCS11_EXPORT C_DigestInit( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_MECHANISM* pMechanism) /* the digesting mechanism */ |
| { |
| return static_C_CallInit( |
| SERVICE_SYSTEM_PKCS11_C_DIGESTINIT_COMMAND_ID, |
| hSession, |
| pMechanism, |
| CK_INVALID_HANDLE); |
| } |
| |
| CK_RV PKCS11_EXPORT C_Digest( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_BYTE* pData, /* data to be digested */ |
| CK_ULONG ulDataLen, /* bytes of data to be digested */ |
| CK_BYTE* pDigest, /* receives the message digest */ |
| CK_ULONG* pulDigestLen) /* receives byte length of digest */ |
| { |
| return static_C_CallForSingle( |
| SERVICE_SYSTEM_PKCS11_C_DIGEST_COMMAND_ID, |
| hSession, |
| pData, |
| ulDataLen, |
| pDigest, |
| pulDigestLen, |
| TRUE, |
| TRUE); |
| } |
| |
| CK_RV PKCS11_EXPORT C_DigestUpdate( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_BYTE* pPart, /* data to be digested */ |
| CK_ULONG ulPartLen) /* bytes of data to be digested */ |
| { |
| return static_C_Call_CallForUpdate( |
| SERVICE_SYSTEM_PKCS11_C_DIGESTUPDATE_COMMAND_ID, |
| hSession, |
| pPart, |
| ulPartLen, |
| NULL, |
| NULL, |
| TRUE, |
| FALSE); |
| } |
| |
| CK_RV PKCS11_EXPORT C_DigestFinal( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| CK_BYTE* pDigest, /* receives the message digest */ |
| CK_ULONG* pulDigestLen) /* receives byte count of digest */ |
| { |
| return static_C_Call_CallForUpdate( |
| SERVICE_SYSTEM_PKCS11_C_DIGESTFINAL_COMMAND_ID, |
| hSession, |
| NULL, |
| 0, |
| pDigest, |
| pulDigestLen, |
| FALSE, |
| TRUE); |
| } |
| |
| |
| CK_RV PKCS11_EXPORT C_SignInit( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_MECHANISM* pMechanism, /* the signature mechanism */ |
| CK_OBJECT_HANDLE hKey) /* handle of the signature key */ |
| { |
| return static_C_CallInit( |
| SERVICE_SYSTEM_PKCS11_C_SIGNINIT_COMMAND_ID, |
| hSession, |
| pMechanism, |
| hKey); |
| } |
| |
| CK_RV PKCS11_EXPORT C_Sign( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_BYTE* pData, /* the data (digest) to be signed */ |
| CK_ULONG ulDataLen, /* count of bytes to be signed */ |
| CK_BYTE* pSignature, /* receives the signature */ |
| CK_ULONG* pulSignatureLen) /* receives byte count of signature */ |
| { |
| return static_C_CallForSingle( |
| SERVICE_SYSTEM_PKCS11_C_SIGN_COMMAND_ID, |
| hSession, |
| pData, |
| ulDataLen, |
| pSignature, |
| pulSignatureLen, |
| TRUE, |
| TRUE); |
| } |
| |
| CK_RV PKCS11_EXPORT C_SignUpdate( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_BYTE* pPart, /* the data (digest) to be signed */ |
| CK_ULONG ulPartLen) /* count of bytes to be signed */ |
| { |
| return static_C_Call_CallForUpdate( |
| SERVICE_SYSTEM_PKCS11_C_SIGNUPDATE_COMMAND_ID, |
| hSession, |
| pPart, |
| ulPartLen, |
| NULL, |
| NULL, |
| TRUE, |
| FALSE); |
| } |
| |
| CK_RV PKCS11_EXPORT C_SignFinal( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| CK_BYTE* pSignature, /* receives the signature */ |
| CK_ULONG* pulSignatureLen) /* receives byte count of signature */ |
| { |
| return static_C_Call_CallForUpdate( |
| SERVICE_SYSTEM_PKCS11_C_SIGNFINAL_COMMAND_ID, |
| hSession, |
| NULL, |
| 0, |
| pSignature, |
| pulSignatureLen, |
| FALSE, |
| TRUE); |
| } |
| |
| CK_RV PKCS11_EXPORT C_EncryptInit( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_MECHANISM* pMechanism, /* the encryption mechanism */ |
| CK_OBJECT_HANDLE hKey) /* handle of encryption key */ |
| { |
| return static_C_CallInit( |
| SERVICE_SYSTEM_PKCS11_C_ENCRYPTINIT_COMMAND_ID, |
| hSession, |
| pMechanism, |
| hKey); |
| } |
| |
| CK_RV PKCS11_EXPORT C_Encrypt( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_BYTE* pData, /* the plaintext data */ |
| CK_ULONG ulDataLen, /* bytes of plaintext data */ |
| CK_BYTE* pEncryptedData, /* receives encrypted data */ |
| CK_ULONG* pulEncryptedDataLen) /* receives encrypted byte count */ |
| { |
| |
| return static_C_CallForSingle( |
| SERVICE_SYSTEM_PKCS11_C_ENCRYPT_COMMAND_ID, |
| hSession, |
| pData, |
| ulDataLen, |
| pEncryptedData, |
| pulEncryptedDataLen, |
| TRUE, |
| TRUE); |
| } |
| |
| |
| |
| CK_RV PKCS11_EXPORT C_EncryptUpdate( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_BYTE* pPart, /* the plaintext data */ |
| CK_ULONG ulPartLen, /* bytes of plaintext data */ |
| CK_BYTE* pEncryptedPart, /* receives encrypted data */ |
| CK_ULONG* pulEncryptedPartLen)/* receives encrypted byte count */ |
| { |
| return static_C_Call_CallForUpdate( |
| SERVICE_SYSTEM_PKCS11_C_ENCRYPTUPDATE_COMMAND_ID, |
| hSession, |
| pPart, |
| ulPartLen, |
| pEncryptedPart, |
| pulEncryptedPartLen, |
| TRUE, |
| TRUE); |
| } |
| |
| CK_RV PKCS11_EXPORT C_EncryptFinal( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| CK_BYTE* pLastEncryptedPart, /* receives encrypted last part */ |
| CK_ULONG* pulLastEncryptedPartLen) /* receives byte count */ |
| { |
| return static_C_Call_CallForUpdate( |
| SERVICE_SYSTEM_PKCS11_C_ENCRYPTFINAL_COMMAND_ID, |
| hSession, |
| NULL, |
| 0, |
| pLastEncryptedPart, |
| pulLastEncryptedPartLen, |
| FALSE, |
| TRUE); |
| } |
| |
| CK_RV PKCS11_EXPORT C_DecryptInit( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_MECHANISM* pMechanism, /* the decryption mechanism */ |
| CK_OBJECT_HANDLE hKey) /* handle of the decryption key */ |
| { |
| return static_C_CallInit( |
| SERVICE_SYSTEM_PKCS11_C_DECRYPTINIT_COMMAND_ID, |
| hSession, |
| pMechanism, |
| hKey); |
| } |
| |
| CK_RV PKCS11_EXPORT C_Decrypt( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_BYTE* pEncryptedData, /* input encrypted data */ |
| CK_ULONG ulEncryptedDataLen, /* count of bytes of input */ |
| CK_BYTE* pData, /* receives decrypted output */ |
| CK_ULONG* pulDataLen) /* receives decrypted byte count */ |
| { |
| |
| return static_C_CallForSingle( |
| SERVICE_SYSTEM_PKCS11_C_DECRYPT_COMMAND_ID, |
| hSession, |
| pEncryptedData, |
| ulEncryptedDataLen, |
| pData, |
| pulDataLen, |
| TRUE, |
| TRUE); |
| } |
| |
| CK_RV PKCS11_EXPORT C_DecryptUpdate( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_BYTE* pEncryptedPart, /* input encrypted data */ |
| CK_ULONG ulEncryptedPartLen, /* count of bytes of input */ |
| CK_BYTE* pPart, /* receives decrypted output */ |
| CK_ULONG* pulPartLen) /* receives decrypted byte count */ |
| { |
| return static_C_Call_CallForUpdate( |
| SERVICE_SYSTEM_PKCS11_C_DECRYPTUPDATE_COMMAND_ID, |
| hSession, |
| pEncryptedPart, |
| ulEncryptedPartLen, |
| pPart, |
| pulPartLen, |
| TRUE, |
| TRUE); |
| } |
| |
| CK_RV PKCS11_EXPORT C_DecryptFinal( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| CK_BYTE* pLastPart, /* receives decrypted output */ |
| CK_ULONG* pulLastPartLen) /* receives decrypted byte count */ |
| { |
| return static_C_Call_CallForUpdate( |
| SERVICE_SYSTEM_PKCS11_C_DECRYPTFINAL_COMMAND_ID, |
| hSession, |
| NULL, |
| 0, |
| pLastPart, |
| pulLastPartLen, |
| FALSE, |
| TRUE); |
| } |
| |
| |
| CK_RV PKCS11_EXPORT C_GenerateKey( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_MECHANISM* pMechanism, /* the key generation mechanism */ |
| const CK_ATTRIBUTE* pTemplate, /* template for the new key */ |
| CK_ULONG ulCount, /* number of attributes in template */ |
| CK_OBJECT_HANDLE* phKey) /* receives handle of new key */ |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_GENERATEKEY_COMMAND_ID; |
| uint8_t* pBuffer = NULL; |
| uint32_t nBufferSize = 0; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| |
| if ((pMechanism == NULL) || (phKey == NULL) || (pTemplate == NULL)) |
| { |
| return CKR_ARGUMENTS_BAD; |
| } |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| nErrorCode = static_encodeTemplate(&pBuffer, &nBufferSize, 2, (CK_ATTRIBUTE*)pTemplate, ulCount); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| sOperation.params[0].value.a = (uint32_t)pMechanism->mechanism; |
| sOperation.params[0].value.b = 0; |
| sOperation.params[1].tmpref.buffer = pMechanism->pParameter; |
| sOperation.params[1].tmpref.size = (uint32_t)pMechanism->ulParameterLen; |
| sOperation.params[2].tmpref.buffer = pBuffer; |
| sOperation.params[2].tmpref.size = nBufferSize; |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE); |
| teeErr = TEEC_InvokeCommand( &pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| free(pBuffer); |
| |
| if (teeErr != TEEC_SUCCESS) |
| { |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| return nErrorCode; |
| } |
| |
| *phKey = sOperation.params[0].value.a; |
| |
| return CKR_OK; |
| } |
| |
| CK_RV PKCS11_EXPORT C_GenerateKeyPair( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_MECHANISM* pMechanism, /* the key gen. mech. */ |
| const CK_ATTRIBUTE* pPublicKeyTemplate, /* pub. attr. template */ |
| CK_ULONG ulPublicKeyAttributeCount, /* # of pub. attrs. */ |
| const CK_ATTRIBUTE* pPrivateKeyTemplate, /* priv. attr. template */ |
| CK_ULONG ulPrivateKeyAttributeCount, /* # of priv. attrs. */ |
| CK_OBJECT_HANDLE* phPublicKey, /* gets pub. key handle */ |
| CK_OBJECT_HANDLE* phPrivateKey) /* gets priv. key handle */ |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_GENERATEKEYPAIR_COMMAND_ID; |
| uint8_t* pBuffer = NULL; |
| uint32_t nBufferSize = 0; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| |
| if ( (pMechanism == NULL) || |
| (pPublicKeyTemplate == NULL) || (pPrivateKeyTemplate == NULL) || |
| (phPublicKey== NULL) || (phPrivateKey== NULL)) |
| { |
| return CKR_ARGUMENTS_BAD; |
| } |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| nErrorCode = static_encodeTwoTemplates(&pBuffer, &nBufferSize, 2, (CK_ATTRIBUTE*)pPublicKeyTemplate, ulPublicKeyAttributeCount, (CK_ATTRIBUTE*)pPrivateKeyTemplate, ulPrivateKeyAttributeCount); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| sOperation.params[0].value.a = (uint32_t)pMechanism->mechanism; |
| sOperation.params[0].value.b = 0; |
| sOperation.params[1].tmpref.buffer = (uint8_t*)pMechanism->pParameter; |
| sOperation.params[1].tmpref.size = (uint32_t)pMechanism->ulParameterLen; |
| sOperation.params[2].tmpref.buffer = pBuffer; |
| sOperation.params[2].tmpref.size = nBufferSize; |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE); |
| teeErr = TEEC_InvokeCommand( &pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| free(pBuffer); |
| |
| if (teeErr != TEEC_SUCCESS) |
| { |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| return nErrorCode; |
| } |
| |
| *phPublicKey = sOperation.params[0].value.a; |
| *phPrivateKey = sOperation.params[0].value.b; |
| |
| return CKR_OK; |
| } |
| |
| CK_RV PKCS11_EXPORT C_DeriveKey( |
| CK_SESSION_HANDLE hSession, /* session's handle */ |
| const CK_MECHANISM* pMechanism, /* key deriv. mech. */ |
| CK_OBJECT_HANDLE hBaseKey, /* base key */ |
| const CK_ATTRIBUTE* pTemplate, /* new key template */ |
| CK_ULONG ulAttributeCount, /* template length */ |
| CK_OBJECT_HANDLE* phKey) /* gets new handle */ |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_DERIVEKEY_COMMAND_ID; |
| uint8_t* pBuffer = NULL; |
| uint32_t nBufferSize = 0; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| |
| if ((pMechanism == NULL) || (pTemplate == NULL) || (phKey == NULL)) |
| { |
| return CKR_ARGUMENTS_BAD; |
| } |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| nErrorCode = static_encodeTemplate(&pBuffer, &nBufferSize, 2, (CK_ATTRIBUTE*)pTemplate, ulAttributeCount); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| sOperation.params[0].value.a = (uint32_t)pMechanism->mechanism; |
| sOperation.params[0].value.b = (uint32_t)hBaseKey; |
| sOperation.params[1].tmpref.buffer = (uint8_t*)pMechanism->pParameter; |
| sOperation.params[1].tmpref.size = (uint32_t)pMechanism->ulParameterLen; |
| sOperation.params[2].tmpref.buffer = pBuffer; |
| sOperation.params[2].tmpref.size = nBufferSize; |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE); |
| teeErr = TEEC_InvokeCommand( &pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| free(pBuffer); |
| |
| if (teeErr != TEEC_SUCCESS) |
| { |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| return nErrorCode; |
| } |
| |
| *phKey = sOperation.params[0].value.a; |
| |
| return CKR_OK; |
| } |
| |
| CK_RV PKCS11_EXPORT C_SeedRandom( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_BYTE* pSeed, /* the seed material */ |
| CK_ULONG ulSeedLen) /* count of bytes of seed material */ |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_SEEDRANDOM_COMMAND_ID; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].tmpref.buffer = (uint8_t*)pSeed; |
| sOperation.params[0].tmpref.size = (uint32_t)ulSeedLen; |
| teeErr = TEEC_InvokeCommand( &pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| return nErrorCode; |
| } |
| |
| CK_RV PKCS11_EXPORT C_GenerateRandom( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| CK_BYTE* pRandomData, /* receives the random data */ |
| CK_ULONG ulRandomLen) /* number of bytes to be generated */ |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_GENERATERANDOM_COMMAND_ID; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| do |
| { |
| CK_ULONG nArrayLength; |
| nArrayLength = 1024; |
| if (ulRandomLen < nArrayLength) |
| { |
| nArrayLength = ulRandomLen; |
| } |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].tmpref.buffer = (uint8_t*)pRandomData; |
| sOperation.params[0].tmpref.size = (uint32_t)nArrayLength; |
| teeErr = TEEC_InvokeCommand( &pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| if (teeErr != TEEC_SUCCESS) |
| { |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| return nErrorCode; |
| } |
| |
| ulRandomLen -= nArrayLength; |
| pRandomData += nArrayLength; |
| if (ulRandomLen == 0) |
| { |
| break; |
| } |
| } |
| while(1); |
| |
| return CKR_OK; |
| } |
| |
| CK_RV PKCS11_EXPORT C_VerifyInit( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_MECHANISM* pMechanism, /* the verification mechanism */ |
| CK_OBJECT_HANDLE hKey) /* handle of the verification key */ |
| { |
| return static_C_CallInit( |
| SERVICE_SYSTEM_PKCS11_C_VERIFYINIT_COMMAND_ID, |
| hSession, |
| pMechanism, |
| hKey); |
| } |
| |
| CK_RV PKCS11_EXPORT C_Verify( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_BYTE* pData, /* plaintext data (digest) to compare */ |
| CK_ULONG ulDataLen, /* length of data (digest) in bytes */ |
| CK_BYTE* pSignature, /* the signature to be verified */ |
| CK_ULONG ulSignatureLen) /* count of bytes of signature */ |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_VERIFY_COMMAND_ID; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| sOperation.params[0].tmpref.buffer = (uint8_t*)pData; |
| sOperation.params[0].tmpref.size = (uint32_t)ulDataLen; |
| sOperation.params[1].tmpref.buffer = (uint8_t*)pSignature; |
| sOperation.params[1].tmpref.size = (uint32_t)ulSignatureLen; |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE); |
| teeErr = TEEC_InvokeCommand( &pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| return nErrorCode; |
| } |
| |
| CK_RV PKCS11_EXPORT C_VerifyUpdate( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_BYTE* pPart, /* plaintext data (digest) to compare */ |
| CK_ULONG ulPartLen) /* length of data (digest) in bytes */ |
| { |
| return static_C_Call_CallForUpdate( |
| SERVICE_SYSTEM_PKCS11_C_VERIFYUPDATE_COMMAND_ID, |
| hSession, |
| pPart, |
| ulPartLen, |
| NULL, |
| NULL, |
| TRUE, |
| FALSE); |
| } |
| |
| CK_RV PKCS11_EXPORT C_VerifyFinal( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| const CK_BYTE* pSignature, /* the signature to be verified */ |
| CK_ULONG ulSignatureLen) /* count of bytes of signature */ |
| { |
| return static_C_Call_CallForUpdate( |
| SERVICE_SYSTEM_PKCS11_C_VERIFYFINAL_COMMAND_ID, |
| hSession, |
| pSignature, |
| ulSignatureLen, |
| NULL, |
| NULL, |
| TRUE, |
| FALSE); |
| } |
| |
| CK_RV PKCS11_EXPORT C_CloseObjectHandle( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| CK_OBJECT_HANDLE hObject) /* the object's handle */ |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_CLOSEOBJECTHANDLE_COMMAND_ID; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); |
| sOperation.params[0].value.a = (uint32_t)hObject; |
| sOperation.params[0].value.b = 0; |
| teeErr = TEEC_InvokeCommand( &pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| return nErrorCode; |
| } |
| |
| CK_RV PKCS11_EXPORT C_CopyObject( |
| CK_SESSION_HANDLE hSession, /* the session's handle */ |
| CK_OBJECT_HANDLE hObject, /* the source object's handle */ |
| const CK_ATTRIBUTE* pTemplate, /* the template of the copied object */ |
| CK_ULONG ulCount, /* the number of attributes of the template*/ |
| CK_OBJECT_HANDLE* phNewObject) /* the copied object's handle */ |
| { |
| TEEC_Result teeErr; |
| uint32_t nErrorOrigin; |
| TEEC_Operation sOperation; |
| CK_RV nErrorCode = CKR_OK; |
| uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_COPYOBJECT_COMMAND_ID; |
| uint8_t* pBuffer = NULL; |
| uint32_t nBufferSize = 0; |
| PPKCS11_PRIMARY_SESSION_CONTEXT pSession; |
| |
| if ((pTemplate == NULL) || (phNewObject == NULL)) |
| { |
| return CKR_ARGUMENTS_BAD; |
| } |
| |
| nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| nErrorCode = static_encodeTemplate(&pBuffer, &nBufferSize, 1, (CK_ATTRIBUTE*)pTemplate, ulCount); |
| if (nErrorCode != CKR_OK) |
| { |
| return nErrorCode; |
| } |
| |
| memset(&sOperation, 0, sizeof(TEEC_Operation)); |
| sOperation.params[0].value.a = (uint32_t)hObject; |
| sOperation.params[0].value.b = 0; |
| sOperation.params[1].tmpref.buffer = pBuffer; |
| sOperation.params[1].tmpref.size = nBufferSize; |
| sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE); |
| teeErr = TEEC_InvokeCommand( &pSession->sSession, |
| nCommandIDAndSession, /* commandID */ |
| &sOperation, /* IN OUT operation */ |
| &nErrorOrigin /* OUT returnOrigin, optional */ |
| ); |
| free(pBuffer); |
| |
| if (teeErr != TEEC_SUCCESS) |
| { |
| nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ? |
| teeErr : |
| ckInternalTeeErrorToCKError(teeErr)); |
| return nErrorCode; |
| } |
| |
| *phNewObject = sOperation.params[0].value.a; |
| |
| return CKR_OK; |
| } |