corePKCS11  v3.2.0
PKCS #11 Cryptoki Library
C_GenerateKeyPair

Generates a public-key/private-key pair.

CK_DECLARE_FUNCTION( CK_RV, C_GenerateKeyPair )( CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_ATTRIBUTE_PTR pPublicKeyTemplate,
CK_ULONG ulPublicKeyAttributeCount,
CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
CK_ULONG ulPrivateKeyAttributeCount,
CK_OBJECT_HANDLE_PTR phPublicKey,
CK_OBJECT_HANDLE_PTR phPrivateKey )
{
uint8_t * pucDerFile = mbedtls_calloc( 1, pkcs11KEY_GEN_MAX_DER_SIZE );
int32_t lMbedTLSResult = 0;
uint32_t ulIndex = 0;
mbedtls_pk_context xCtx = { 0 };
CK_ATTRIBUTE_PTR pxPrivateLabel = NULL;
CK_ATTRIBUTE_PTR pxPublicLabel = NULL;
CK_OBJECT_HANDLE xPalPublic = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE xPalPrivate = CK_INVALID_HANDLE;
uint32_t xPublicRequiredAttributeMap = ( LABEL_IN_TEMPLATE | EC_PARAMS_IN_TEMPLATE | VERIFY_IN_TEMPLATE );
uint32_t xPrivateRequiredAttributeMap = ( LABEL_IN_TEMPLATE | PRIVATE_IN_TEMPLATE | SIGN_IN_TEMPLATE );
uint32_t xAttributeMap = 0;
CK_RV xAddObjectListResult = CKR_OK;
const P11Session_t * pxSession = prvSessionPointerFromHandle( hSession );
CK_RV xResult = prvCheckValidSessionAndModule( pxSession );
#ifdef pkcs11configSUPPRESS_ECDSA_MECHANISM
if( xResult == CKR_OK )
{
LogDebug( ( "ECDSA Mechanism is suppressed on this port." ) );
xResult = CKR_MECHANISM_INVALID;
}
#endif
if( xResult == CKR_OK )
{
if( ( pPublicKeyTemplate == NULL ) ||
( pPrivateKeyTemplate == NULL ) ||
( phPublicKey == NULL ) ||
( phPrivateKey == NULL ) ||
( pMechanism == NULL ) )
{
LogError( ( "Failed generating a key pair. One of the arguments "
"was NULL." ) );
xResult = CKR_ARGUMENTS_BAD;
}
}
if( xResult == CKR_OK )
{
if( pucDerFile == NULL )
{
LogError( ( "Failed generating a key pair. Could not allocated a "
"buffer of size %u bytes.", ( unsigned int ) pkcs11KEY_GEN_MAX_DER_SIZE ) );
xResult = CKR_HOST_MEMORY;
}
}
if( xResult == CKR_OK )
{
if( CKM_EC_KEY_PAIR_GEN != pMechanism->mechanism )
{
LogError( ( "Failed generating a key pair. CKM_EC_KEY_PAIR_GEN is "
"the only valid key generation mechanism currently." ) );
xResult = CKR_MECHANISM_INVALID;
}
}
if( xResult == CKR_OK )
{
for( ulIndex = 0; ulIndex < ulPrivateKeyAttributeCount; ++ulIndex )
{
xResult = prvCheckGenerateKeyPairPrivateTemplate( &pxPrivateLabel,
&pPrivateKeyTemplate[ ulIndex ],
&xAttributeMap );
if( xResult != CKR_OK )
{
break;
}
}
if( ( xResult == CKR_OK ) && ( ( xAttributeMap & xPrivateRequiredAttributeMap ) != xPrivateRequiredAttributeMap ) )
{
LogError( ( "Failed generating a key pair. Attributes were missing "
"in the private key template." ) );
xResult = CKR_TEMPLATE_INCOMPLETE;
}
}
if( xResult == CKR_OK )
{
xAttributeMap = 0;
for( ulIndex = 0; ulIndex < ulPublicKeyAttributeCount; ++ulIndex )
{
xResult = prvCheckGenerateKeyPairPublicTemplate( &pxPublicLabel,
&pPublicKeyTemplate[ ulIndex ],
&xAttributeMap );
if( xResult != CKR_OK )
{
break;
}
}
if( ( xResult == CKR_OK ) && ( ( xAttributeMap & xPublicRequiredAttributeMap ) != xPublicRequiredAttributeMap ) )
{
LogError( ( "Failed generating a key pair. Attributes were missing "
"in the public key template." ) );
xResult = CKR_TEMPLATE_INCOMPLETE;
}
}
if( xResult == CKR_OK )
{
mbedtls_pk_init( &xCtx );
lMbedTLSResult = mbedtls_pk_setup( &xCtx, mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) );
if( lMbedTLSResult != 0 )
{
LogError( ( "Failed generating a key pair. mbedtls_pk_setup failed: "
"mbed TLS error = %s : %s.",
mbedtlsHighLevelCodeOrDefault( lMbedTLSResult ),
mbedtlsLowLevelCodeOrDefault( lMbedTLSResult ) ) );
xResult = CKR_FUNCTION_FAILED;
}
else
{
LogDebug( ( "mbedtls_pk_setup was successful." ) );
}
}
if( xResult == CKR_OK )
{
lMbedTLSResult = mbedtls_ecp_gen_key( MBEDTLS_ECP_DP_SECP256R1,
mbedtls_pk_ec( xCtx ),
mbedtls_ctr_drbg_random,
if( 0 != lMbedTLSResult )
{
LogError( ( "Failed generating a key pair. mbedtls_ecp_gen_key "
"failed: mbed TLS error = %s : %s.",
mbedtlsHighLevelCodeOrDefault( lMbedTLSResult ),
mbedtlsLowLevelCodeOrDefault( lMbedTLSResult ) ) );
xResult = CKR_FUNCTION_FAILED;
}
}
if( xResult == CKR_OK )
{
lMbedTLSResult = mbedtls_pk_write_pubkey_der( &xCtx, pucDerFile, pkcs11KEY_GEN_MAX_DER_SIZE );
if( ( lMbedTLSResult > 0 ) &&
( lMbedTLSResult <= pkcs11KEY_GEN_MAX_DER_SIZE ) )
{
xPalPublic = PKCS11_PAL_SaveObject( pxPublicLabel, pucDerFile + pkcs11KEY_GEN_MAX_DER_SIZE - lMbedTLSResult, ( uint32_t ) lMbedTLSResult );
LogDebug( ( "PKCS11_PAL_SaveObject returned a %lu PAL handle value "
"for the public key.", ( unsigned long int ) xPalPublic ) );
}
else
{
LogError( ( "Failed generating a key pair. "
"mbedtls_pk_write_pubkey_der failed: mbed TLS error = %s : %s.",
mbedtlsHighLevelCodeOrDefault( lMbedTLSResult ),
mbedtlsLowLevelCodeOrDefault( lMbedTLSResult ) ) );
xResult = CKR_GENERAL_ERROR;
}
}
if( xResult == CKR_OK )
{
lMbedTLSResult = mbedtls_pk_write_key_der( &xCtx, pucDerFile, pkcs11KEY_GEN_MAX_DER_SIZE );
if( ( lMbedTLSResult > 0 ) &&
( lMbedTLSResult <= pkcs11KEY_GEN_MAX_DER_SIZE ) )
{
xPalPrivate = PKCS11_PAL_SaveObject( pxPrivateLabel, pucDerFile + pkcs11KEY_GEN_MAX_DER_SIZE - lMbedTLSResult, ( uint32_t ) lMbedTLSResult );
LogDebug( ( "PKCS11_PAL_SaveObject returned a %lu PAL handle value "
"for the private key.", ( unsigned long int ) xPalPrivate ) );
}
else
{
LogError( ( "Failed generating a key pair. mbedtls_pk_write_key_der "
"failed: mbed TLS error = %s : %s.",
mbedtlsHighLevelCodeOrDefault( lMbedTLSResult ),
mbedtlsLowLevelCodeOrDefault( lMbedTLSResult ) ) );
xResult = CKR_GENERAL_ERROR;
}
}
if( ( xPalPublic != CK_INVALID_HANDLE ) && ( xPalPrivate != CK_INVALID_HANDLE ) )
{
xAddObjectListResult = prvAddObjectToList( xPalPrivate, phPrivateKey, pxPrivateLabel->pValue, pxPrivateLabel->ulValueLen );
if( xAddObjectListResult == CKR_OK )
{
xAddObjectListResult = prvAddObjectToList( xPalPublic, phPublicKey, pxPublicLabel->pValue, pxPublicLabel->ulValueLen );
}
if( xAddObjectListResult != CKR_OK )
{
LogError( ( "Could not add private key to object list failed with (0x%0lX). Cleaning up PAL objects.", xResult ) );
xResult = PKCS11_PAL_DestroyObject( xPalPrivate );
if( xResult != CKR_OK )
{
LogError( ( "Could not clean up private key. PKCS11_PAL_DestroyObject failed with (0x%0lX).", xResult ) );
}
xResult = prvDeleteObjectFromList( xPalPrivate );
if( xResult != CKR_OK )
{
LogError( ( "Could not remove private key object from internal list. Failed with (0x%0lX).", xResult ) );
}
xResult = PKCS11_PAL_DestroyObject( xPalPublic );
if( xResult != CKR_OK )
{
LogError( ( "Could not clean up public key. PKCS11_PAL_DestroyObject failed with (0x%0lX).", xResult ) );
}
xResult = prvDeleteObjectFromList( xPalPublic );
if( xResult != CKR_OK )
{
LogError( ( "Could not remove private key object from internal list. Failed with (0x%0lX).", xResult ) );
}
if( xResult == CKR_OK )
{
xResult = xAddObjectListResult;
}
}
}
/* Clean up. */
mbedtls_free( pucDerFile );
mbedtls_pk_free( &xCtx );
return xResult;
}

This port only supports generating elliptic curve P-256 key pairs.

Parameters
[in]hSessionHandle of a valid PKCS #11 session.
[in]pMechanismPointer to a mechanism. At this time, CKM_EC_KEY_PAIR_GEN is the only supported mechanism.
[in]pPublicKeyTemplatePointer to a list of attributes that the generated public key should possess. Public key template must have the following attributes:
  • CKA_LABEL
    • Label should be no longer than pkcs11configMAX_LABEL_LENGTH and must be supported by port's PKCS #11 PAL.
  • CKA_EC_PARAMS
    • Must equal pkcs11DER_ENCODED_OID_P256. Only P-256 keys are supported.
  • CKA_VERIFY
    • Must be set to true. Only public keys used for verification are supported. Public key templates may have the following attributes:
  • CKA_KEY_TYPE
    • Must be set to CKK_EC. Only elliptic curve key generation is supported.
  • CKA_TOKEN
    • Must be set to CK_TRUE.
[in]ulPublicKeyAttributeCountNumber of attributes in pPublicKeyTemplate.
[in]pPrivateKeyTemplatePointer to a list of attributes that the generated private key should possess. Private key template must have the following attributes:
  • CKA_LABEL
    • Label should be no longer than pkcs11configMAX_LABEL_LENGTH and must be supported by port's PKCS #11 PAL.
  • CKA_PRIVATE
    • Must be set to true.
  • CKA_SIGN
    • Must be set to true. Only private keys used for signing are supported. Private key template may have the following attributes:
  • CKA_KEY_TYPE
    • Must be set to CKK_EC. Only elliptic curve key generation is supported.
  • CKA_TOKEN
    • Must be set to CK_TRUE.
[in]ulPrivateKeyAttributeCountNumber of attributes in pPrivateKeyTemplate.
[out]phPublicKeyPointer to the handle of the public key to be created.
[out]phPrivateKeyPointer to the handle of the private key to be created.
Note
Not all attributes specified by the PKCS #11 standard are supported.
CKA_LOCAL attribute is not supported.
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
pkcs11KEY_GEN_MAX_DER_SIZE
#define pkcs11KEY_GEN_MAX_DER_SIZE
The size of the buffer malloc'ed for the exported public key in C_GenerateKeyPair.
Definition: core_pkcs11_mbedtls.c:194
prvDeleteObjectFromList
static CK_RV prvDeleteObjectFromList(CK_OBJECT_HANDLE xPalHandle)
Removes an object from the module object list (xP11Context.xObjectList)
Definition: core_pkcs11_mbedtls.c:1100
PRIVATE_IN_TEMPLATE
#define PRIVATE_IN_TEMPLATE
Definition: core_pkcs11_mbedtls.c:209
PKCS11_PAL_DestroyObject
CK_RV PKCS11_PAL_DestroyObject(CK_OBJECT_HANDLE xHandle)
Delete an object from NVM.
xP11Context
static P11Struct_t xP11Context
The global PKCS #11 module object. Entropy/randomness and object lists are shared across PKCS #11 ses...
Definition: core_pkcs11_mbedtls.c:313
LogDebug
#define LogDebug(message)
Macro that is called in the corePKCS11 library for logging "Debug" level messages.
Definition: core_pkcs11_config_defaults.h:375
VERIFY_IN_TEMPLATE
#define VERIFY_IN_TEMPLATE
Definition: core_pkcs11_mbedtls.c:212
P11Struct_t::xMbedDrbgCtx
mbedtls_ctr_drbg_context xMbedDrbgCtx
CTR-DRBG context for PKCS #11 module - used to generate pseudo-random numbers.
Definition: core_pkcs11_mbedtls.c:273
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
EC_PARAMS_IN_TEMPLATE
#define EC_PARAMS_IN_TEMPLATE
Definition: core_pkcs11_mbedtls.c:211
prvAddObjectToList
static CK_RV prvAddObjectToList(CK_OBJECT_HANDLE xPalHandle, CK_OBJECT_HANDLE_PTR pxAppHandle, const CK_BYTE *pcLabel, CK_ULONG xLabelLength)
Add an object that exists in NVM to the application object array.
Definition: core_pkcs11_mbedtls.c:1141
SIGN_IN_TEMPLATE
#define SIGN_IN_TEMPLATE
Definition: core_pkcs11_mbedtls.c:210
P11Session_t
Session structure.
Definition: core_pkcs11_mbedtls.c:286
C_GenerateKeyPair
CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey)
Generates a public-key/private-key pair.
Definition: core_pkcs11_mbedtls.c:5330
prvCheckGenerateKeyPairPublicTemplate
static CK_RV prvCheckGenerateKeyPairPublicTemplate(CK_ATTRIBUTE **ppxLabel, CK_ATTRIBUTE *pxAttribute, uint32_t *pulAttributeMap)
Checks that the public key template provided for C_GenerateKeyPair contains all necessary attributes,...
Definition: core_pkcs11_mbedtls.c:5178
PKCS11_PAL_SaveObject
CK_OBJECT_HANDLE PKCS11_PAL_SaveObject(CK_ATTRIBUTE_PTR pxLabel, CK_BYTE_PTR pucData, CK_ULONG ulDataSize)
Saves an object in non-volatile storage.
LogError
#define LogError(message)
Macro that is called in the corePKCS11 library for logging "Error" level messages.
Definition: core_pkcs11_config_defaults.h:315
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
LABEL_IN_TEMPLATE
#define LABEL_IN_TEMPLATE
Private defines for checking that attribute templates are complete.
Definition: core_pkcs11_mbedtls.c:208
prvCheckGenerateKeyPairPrivateTemplate
static CK_RV prvCheckGenerateKeyPairPrivateTemplate(CK_ATTRIBUTE **ppxLabel, CK_ATTRIBUTE *pxAttribute, uint32_t *pulAttributeMap)
Checks that the private key template provided for C_GenerateKeyPair contains all necessary attributes...
Definition: core_pkcs11_mbedtls.c:5064