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_x509_crt xMbedX509Context = { 0 };
mbedtls_pk_type_t xKeyType;
const mbedtls_ecp_keypair * pxKeyPair;
CK_KEY_TYPE xPkcsKeyType = ( CK_KEY_TYPE ) ~0UL;
CK_OBJECT_CLASS xClass = ~0UL;
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 ) ) )
{
LogError( (
"Failed to get attribute. The template was a NULL pointer "
"or the attribute count was 0." ) );
xResult = CKR_ARGUMENTS_BAD;
}
if( ( CKR_OK == xResult ) && ( CK_INVALID_HANDLE == hObject ) )
{
LogError( (
"Failed to get attribute. The object handle was invalid." ) );
xResult = CKR_OBJECT_HANDLE_INVALID;
}
if( xResult == CKR_OK )
{
if( xPalHandle != CK_INVALID_HANDLE )
{
}
else
{
LogError( (
"Failed to get attribute. Could not find a valid "
"PKCS #11 PAL handle." ) );
xResult = CKR_OBJECT_HANDLE_INVALID;
}
}
if( xResult == CKR_OK )
{
mbedtls_pk_init( &xKeyContext );
mbedtls_x509_crt_init( &xMbedX509Context );
if( 0 == mbedtls_pk_parse_key( &xKeyContext, pxObjectValue, ulLength, NULL, 0 ) )
{
if( xIsPrivate == ( CK_BBOOL ) CK_TRUE )
{
LogDebug( (
"Object was a private key." ) );
xClass = CKO_PRIVATE_KEY;
}
else
{
LogDebug( (
"Object was a public key." ) );
xClass = CKO_PUBLIC_KEY;
}
}
else if( 0 == mbedtls_pk_parse_public_key( &xKeyContext, pxObjectValue, ulLength ) )
{
LogDebug( (
"Object was a public key." ) );
xClass = CKO_PUBLIC_KEY;
}
else if( 0 == mbedtls_x509_crt_parse( &xMbedX509Context, pxObjectValue, ulLength ) )
{
LogDebug( (
"Object was a certificate." ) );
xClass = CKO_CERTIFICATE;
}
else
{
LogDebug( (
"Object handle was invalid." ) );
xResult = CKR_OBJECT_HANDLE_INVALID;
}
}
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
{
LogError( (
"Failed to parse attribute template. "
"Received a buffer smaller than CK_OBJECT_CLASS." ) );
xResult = CKR_BUFFER_TOO_SMALL;
}
}
break;
case CKA_PUBLIC_KEY_INFO:
case CKA_VALUE:
if( xIsPrivate == ( CK_BBOOL ) CK_TRUE )
{
pTemplate[ iAttrib ].ulValueLen = CK_UNAVAILABLE_INFORMATION;
LogError( (
"Failed to parse attribute. This data is "
"sensitive and the value will not be returned." ) );
xResult = CKR_ATTRIBUTE_SENSITIVE;
}
else
{
if( pTemplate[ iAttrib ].pValue == NULL )
{
pTemplate[ iAttrib ].ulValueLen = ulLength;
}
else if( pTemplate[ iAttrib ].ulValueLen < ulLength )
{
LogError( (
"Failed to parse attribute. Buffer was "
"too small to contain data. Expected %lu "
"but got %lu.",
( unsigned long int ) ulLength,
( unsigned long int ) pTemplate[ iAttrib ].ulValueLen ) );
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 ) )
{
LogError( (
"Failed to parse attribute. Expected buffer "
"of size 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:
LogError( (
"Failed to parse attribute. "
"Could not parse key type." ) );
xResult = CKR_ATTRIBUTE_VALUE_INVALID;
break;
}
( void ) memcpy( pTemplate[ iAttrib ].pValue, &xPkcsKeyType, sizeof( CK_KEY_TYPE ) );
}
break;
case CKA_PRIVATE_EXPONENT:
LogError( (
"Failed to parse attribute. "
"CKA_PRIVATE_EXPONENT is private data." ) );
xResult = CKR_ATTRIBUTE_SENSITIVE;
break;
case CKA_EC_PARAMS:
if( pTemplate[ iAttrib ].pValue == NULL )
{
pTemplate[ iAttrib ].ulValueLen = sizeof( ucP256Oid );
}
else
{
if( pTemplate[ iAttrib ].ulValueLen < sizeof( ucP256Oid ) )
{
LogError( (
"Failed to parse attribute. "
"CKA_EC_PARAMS buffer too small." ) );
xResult = CKR_BUFFER_TOO_SMALL;
}
else
{
( void ) memcpy( pTemplate[ iAttrib ].pValue, ucP256Oid, sizeof( ucP256Oid ) );
}
}
break;
case CKA_EC_POINT:
if( pTemplate[ iAttrib ].pValue == NULL )
{
}
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;
}
else
{
xResult = CKR_BUFFER_TOO_SMALL;
}
if( ( xResult == CKR_OK ) && ( lMbedTLSResult < 0 ) )
{
if( lMbedTLSResult == MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL )
{
LogError( (
"Failed to extract EC point. "
"CKA_EC_POINT buffer was too small." ) );
xResult = CKR_BUFFER_TOO_SMALL;
}
else
{
LogError( (
"Failed to extract EC point. "
"mbedtls_ecp_tls_write_point failed: "
"mbed TLS error = %s : %s.",
xResult = CKR_FUNCTION_FAILED;
}
}
else
{
pTemplate[ iAttrib ].ulValueLen = xSize + 1UL;
}
}
break;
default:
LogError( (
"Failed to parse attribute. Received unknown "
"attribute type." ) );
xResult = CKR_ATTRIBUTE_TYPE_INVALID;
break;
}
}
mbedtls_pk_free( &xKeyContext );
mbedtls_x509_crt_free( &xMbedX509Context );
}
return xResult;
}