corePKCS11  V3.0.0
PKCS #11 Cryptoki Library
C_GetAttributeValue
CK_DECLARE_FUNCTION( CK_RV, C_GetAttributeValue )( CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount )
{
/* See explanation in prvCheckValidSessionAndModule for this exception. */
/* coverity[misra_c_2012_rule_10_5_violation] */
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;
const CK_BYTE ucP256Oid[] = pkcs11DER_ENCODED_OID_P256;
int32_t lMbedTLSResult = 0;
CK_OBJECT_HANDLE xPalHandle = CK_INVALID_HANDLE;
CK_ULONG xSize = 0;
size_t xMbedSize = 0;
CK_BYTE_PTR pcLabel = NULL;
const P11Session_t * pxSession = prvSessionPointerFromHandle( hSession );
CK_RV xResult = prvCheckValidSessionAndModule( pxSession );
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 )
{
/*
* Copy the object into a buffer.
*/
prvFindObjectInListByHandle( hObject, &xPalHandle, &pcLabel, &xSize ); /*pcLabel and xSize are ignored. */
if( xPalHandle != CK_INVALID_HANDLE )
{
xResult = PKCS11_PAL_GetObjectValue( xPalHandle, &pxObjectValue, &ulLength, &xIsPrivate );
}
else
{
LogError( ( "Failed to get attribute. Could not find a valid "
"PKCS #11 PAL handle." ) );
xResult = CKR_OBJECT_HANDLE_INVALID;
}
}
/* Determine what kind of object we are dealing with. */
if( xResult == CKR_OK )
{
/* Initialize mbed TLS key context. */
mbedtls_pk_init( &xKeyContext );
/* Initialize mbed TLS x509 context. */
mbedtls_x509_crt_init( &xMbedX509Context );
if( 0 == mbedtls_pk_parse_key( &xKeyContext, pxObjectValue, ulLength, NULL, 0 ) )
{
/* See explanation in prvCheckValidSessionAndModule for this exception. */
/* coverity[misra_c_2012_rule_10_5_violation] */
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:
/* See explanation in prvCheckValidSessionAndModule for this exception. */
/* coverity[misra_c_2012_rule_10_5_violation] */
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 )
{
pTemplate[ iAttrib ].ulValueLen = pkcs11EC_POINT_LENGTH;
}
else
{
if( pTemplate[ iAttrib ].ulValueLen == pkcs11EC_POINT_LENGTH )
{
pxKeyPair = ( mbedtls_ecp_keypair * ) xKeyContext.pk_ctx;
*( ( uint8_t * ) pTemplate[ iAttrib ].pValue ) = 0x04; /* Mark the point as uncompressed. */
/* Copy xSize value to avoid casting a CK_ULONG size pointer
* to a size_t sized pointer. */
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.",
mbedtlsHighLevelCodeOrDefault( lMbedTLSResult ),
mbedtlsLowLevelCodeOrDefault( lMbedTLSResult ) ) );
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;
}
}
/* Free the buffer where object was stored. */
PKCS11_PAL_GetObjectValueCleanup( pxObjectValue, ulLength );
/* Free the mbedTLS structure used to parse the key. */
mbedtls_pk_free( &xKeyContext );
/* Free the mbedTLS structure used to parse the certificate. */
mbedtls_x509_crt_free( &xMbedX509Context );
}
return xResult;
}
PKCS11_PAL_GetObjectValueCleanup
void PKCS11_PAL_GetObjectValueCleanup(CK_BYTE_PTR pucData, CK_ULONG ulDataSize)
Cleanup after PKCS11_GetObjectValue().
PKCS11_PAL_GetObjectValue
CK_RV PKCS11_PAL_GetObjectValue(CK_OBJECT_HANDLE xHandle, CK_BYTE_PTR *ppucData, CK_ULONG_PTR pulDataSize, CK_BBOOL *pIsPrivate)
Gets the value of an object in storage, by handle.
pkcs11DER_ENCODED_OID_P256
#define pkcs11DER_ENCODED_OID_P256
OID for curve P-256.
Definition: core_pkcs11.h:153
CK_DECLARE_FUNCTION
#define CK_DECLARE_FUNCTION(returnType, name)
Macro for defining a PKCS #11 functions.
Definition: core_pkcs11.h:72