corePKCS11  v3.2.0
PKCS #11 Cryptoki Library
C_GetAttributeValue

Obtains an attribute value of an object.

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;
}
Parameters
[in]hSessionHandle of a valid PKCS #11 session.
[in]hObjectPKCS #11 object handle to be queried.
[in,out]pTemplateAttribute template. pxTemplate.pValue should be set to the attribute to be queried. pxTemplate.ulValueLen should be set to the length of the buffer allocated at pxTemplate.pValue, and will be updated to contain the actual length of the data copied. pxTemplate.pValue should be set to point to a buffer to receive the attribute value data. If parameter length is unknown, pxTemplate.pValue may be set to NULL, and this function will set the required buffer length in pxTemplate.ulValueLen.
[in]ulCountThe number of attributes in the template.
Object Type Queryable Attributes
CertificateCKA_CLASS
CKA_VALUE
EC Private KeyCKA_CLASS
CKA_KEY_TYPE
CKA_EC_PARAMS
EC Public KeyCKA_CLASS
CKA_KEY_TYPE
CKA_EC_PARAMS
CKA_EC_POINT
RSA Private KeyCKA_CLASS
CKA_KEY_TYPE
RSA Public KeyCKA_CLASS
CKA_KEY_TYPE
Returns
CKR_OK if successful.
mbedtlsLowLevelCodeOrDefault
#define mbedtlsLowLevelCodeOrDefault(mbedTlsCode)
Utility for converting the level-level code in an mbedTLS error to string, if the code-contains a lev...
Definition: core_pkcs11_mbedtls.c:90
pkcs11EC_POINT_LENGTH
#define pkcs11EC_POINT_LENGTH
Length of bytes to contain an EC point.
Definition: core_pkcs11_mbedtls.c:165
prvFindObjectInListByHandle
static void prvFindObjectInListByHandle(CK_OBJECT_HANDLE xAppHandle, CK_OBJECT_HANDLE_PTR pxPalHandle, CK_BYTE_PTR *ppcLabel, CK_ULONG_PTR pxLabelLength)
Looks up a PKCS #11 object's label and PAL handle given an application handle.
Definition: core_pkcs11_mbedtls.c:1070
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.
LogDebug
#define LogDebug(message)
Macro that is called in the corePKCS11 library for logging "Debug" level messages.
Definition: core_pkcs11_config_defaults.h:375
pkcs11DER_ENCODED_OID_P256
#define pkcs11DER_ENCODED_OID_P256
OID for curve P-256.
Definition: core_pkcs11.h:162
prvCheckValidSessionAndModule
static CK_RV prvCheckValidSessionAndModule(const P11Session_t *pxSession)
Helper to check if the current session is initialized and valid.
Definition: core_pkcs11_mbedtls.c:323
CK_DECLARE_FUNCTION
#define CK_DECLARE_FUNCTION(returnType, name)
Macro for defining a PKCS #11 functions.
Definition: core_pkcs11.h:75
prvSessionPointerFromHandle
static P11Session_t * prvSessionPointerFromHandle(CK_SESSION_HANDLE xSession)
Maps an opaque caller session handle into its internal state structure.
Definition: core_pkcs11_mbedtls.c:365
P11Session_t
Session structure.
Definition: core_pkcs11_mbedtls.c:286
LogError
#define LogError(message)
Macro that is called in the corePKCS11 library for logging "Error" level messages.
Definition: core_pkcs11_config_defaults.h:315
C_GetAttributeValue
CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
Obtains an attribute value of an object.
Definition: core_pkcs11_mbedtls.c:2944
mbedtlsHighLevelCodeOrDefault
#define mbedtlsHighLevelCodeOrDefault(mbedTlsCode)
Utility for converting the high-level code in an mbedTLS error to string, if the code-contains a high...
Definition: core_pkcs11_mbedtls.c:82