/**
* 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;
}