Obtains an attribute value of an object.
CK_OBJECT_HANDLE hObject,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount )
{
CK_BBOOL xIsPrivate = ( CK_BBOOL ) CK_TRUE;
CK_ULONG iAttrib;
mbedtls_pk_context xKeyContext = { 0 };
mbedtls_pk_type_t xKeyType;
const mbedtls_ecp_keypair * pxKeyPair;
CK_KEY_TYPE xPkcsKeyType = ( CK_KEY_TYPE ) ~0UL;
CK_OBJECT_CLASS xClass;
CK_BYTE_PTR pxObjectValue = NULL;
CK_ULONG ulLength = 0;
int32_t lMbedTLSResult = 0;
CK_OBJECT_HANDLE xPalHandle = CK_INVALID_HANDLE;
CK_ULONG xSize = 0;
size_t xMbedSize = 0;
CK_BYTE_PTR pcLabel = NULL;
if( ( CKR_OK == xResult ) && ( ( ( NULL == pTemplate ) ) || ( 0UL == ulCount ) ) )
{
xResult = CKR_ARGUMENTS_BAD;
}
if( ( CKR_OK == xResult ) && ( CK_INVALID_HANDLE == hObject ) )
{
xResult = CKR_OBJECT_HANDLE_INVALID;
}
if( xResult == CKR_OK )
{
if( xPalHandle != CK_INVALID_HANDLE )
{
}
else
{
xResult = CKR_OBJECT_HANDLE_INVALID;
}
}
if( xResult == CKR_OK )
{
mbedtls_pk_init( &xKeyContext );
if( 0 == mbedtls_pk_parse_key( &xKeyContext, pxObjectValue, ulLength, NULL, 0 ) )
{
if( xIsPrivate == ( CK_BBOOL ) CK_TRUE )
{
xClass = CKO_PRIVATE_KEY;
}
else
{
xClass = CKO_PUBLIC_KEY;
}
}
else if( 0 == mbedtls_pk_parse_public_key( &xKeyContext, pxObjectValue, ulLength ) )
{
xClass = CKO_PUBLIC_KEY;
}
else
{
xClass = CKO_CERTIFICATE;
}
}
if( xResult == CKR_OK )
{
for( iAttrib = 0; iAttrib < ulCount; iAttrib++ )
{
if( xResult != CKR_OK )
{
break;
}
switch( pTemplate[ iAttrib ].type )
{
case CKA_CLASS:
if( pTemplate[ iAttrib ].pValue == NULL )
{
pTemplate[ iAttrib ].ulValueLen = sizeof( CK_OBJECT_CLASS );
}
else
{
if( pTemplate[ iAttrib ].ulValueLen >= sizeof( CK_OBJECT_CLASS ) )
{
( void ) memcpy( pTemplate[ iAttrib ].pValue, &xClass, sizeof( CK_OBJECT_CLASS ) );
}
else
{
xResult = CKR_BUFFER_TOO_SMALL;
}
}
break;
case CKA_VALUE:
if( xIsPrivate == ( CK_BBOOL ) CK_TRUE )
{
pTemplate[ iAttrib ].ulValueLen = CK_UNAVAILABLE_INFORMATION;
xResult = CKR_ATTRIBUTE_SENSITIVE;
}
else
{
if( pTemplate[ iAttrib ].pValue == NULL )
{
pTemplate[ iAttrib ].ulValueLen = ulLength;
}
else if( pTemplate[ iAttrib ].ulValueLen < ulLength )
{
xResult = CKR_BUFFER_TOO_SMALL;
}
else
{
( void ) memcpy( pTemplate[ iAttrib ].pValue, pxObjectValue, ulLength );
}
}
break;
case CKA_KEY_TYPE:
if( pTemplate[ iAttrib ].pValue == NULL )
{
pTemplate[ iAttrib ].ulValueLen = sizeof( CK_KEY_TYPE );
}
else if( pTemplate[ iAttrib ].ulValueLen < sizeof( CK_KEY_TYPE ) )
{
xResult = CKR_BUFFER_TOO_SMALL;
}
else
{
xKeyType = mbedtls_pk_get_type( &xKeyContext );
switch( xKeyType )
{
case MBEDTLS_PK_RSA:
case MBEDTLS_PK_RSA_ALT:
case MBEDTLS_PK_RSASSA_PSS:
xPkcsKeyType = CKK_RSA;
break;
case MBEDTLS_PK_ECKEY:
case MBEDTLS_PK_ECKEY_DH:
xPkcsKeyType = CKK_EC;
break;
case MBEDTLS_PK_ECDSA:
xPkcsKeyType = CKK_ECDSA;
break;
default:
xResult = CKR_ATTRIBUTE_VALUE_INVALID;
break;
}
( void ) memcpy( pTemplate[ iAttrib ].pValue, &xPkcsKeyType, sizeof( CK_KEY_TYPE ) );
}
break;
case CKA_PRIVATE_EXPONENT:
xResult = CKR_ATTRIBUTE_SENSITIVE;
break;
case CKA_EC_PARAMS:
pTemplate[ iAttrib ].ulValueLen = sizeof( ucP256Oid );
if( pTemplate[ iAttrib ].pValue != NULL )
{
if( pTemplate[ iAttrib ].ulValueLen < sizeof( ucP256Oid ) )
{
xResult = CKR_BUFFER_TOO_SMALL;
}
else
{
( void ) memcpy( pTemplate[ iAttrib ].pValue, ucP256Oid, sizeof( ucP256Oid ) );
}
}
break;
case CKA_EC_POINT:
if( pTemplate[ iAttrib ].pValue == NULL )
{
pTemplate[ iAttrib ].ulValueLen = 67;
}
else
{
pxKeyPair = ( mbedtls_ecp_keypair * ) xKeyContext.pk_ctx;
*( ( uint8_t * ) pTemplate[ iAttrib ].pValue ) = 0x04;
xMbedSize = xSize;
lMbedTLSResult = mbedtls_ecp_tls_write_point( &pxKeyPair->grp,
&pxKeyPair->Q,
MBEDTLS_ECP_PF_UNCOMPRESSED,
&xMbedSize,
( uint8_t * ) pTemplate[ iAttrib ].pValue + 1,
pTemplate[ iAttrib ].ulValueLen - 1UL );
xSize = xMbedSize;
if( lMbedTLSResult < 0 )
{
if( lMbedTLSResult == MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL )
{
xResult = CKR_BUFFER_TOO_SMALL;
}
else
{
xResult = CKR_FUNCTION_FAILED;
}
}
else
{
pTemplate[ iAttrib ].ulValueLen = xSize + 1UL;
}
}
break;
default:
xResult = CKR_ATTRIBUTE_TYPE_INVALID;
break;
}
}
mbedtls_pk_free( &xKeyContext );
}
return xResult;
}