corePKCS11  v3.2.0
PKCS #11 Cryptoki Library
C_Verify

Verifies a signature on single-part data.

CK_DECLARE_FUNCTION( CK_RV, C_Verify )( CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pData,
CK_ULONG ulDataLen,
CK_BYTE_PTR pSignature,
CK_ULONG ulSignatureLen )
{
P11Session_t * pxSessionObj;
int32_t lMbedTLSResult;
CK_RV xResult = CKR_OK;
CK_BYTE pxHMACBuffer[ pkcs11SHA256_DIGEST_LENGTH ] = { 0 };
CK_BYTE pxCMACBuffer[ MBEDTLS_AES_BLOCK_SIZE ] = { 0 };
pxSessionObj = prvSessionPointerFromHandle( hSession );
xResult = prvCheckValidSessionAndModule( pxSessionObj );
/* Check parameters. */
if( ( NULL == pData ) ||
( NULL == pSignature ) )
{
LogError( ( "Failed verify operation. Received a NULL pointer." ) );
xResult = CKR_ARGUMENTS_BAD;
}
/* Check that the signature and data are the expected length.
* These PKCS #11 mechanism expect data to be pre-hashed/formatted. */
if( xResult == CKR_OK )
{
if( pxSessionObj->xOperationVerifyMechanism == CKM_RSA_X_509 )
{
{
LogError( ( "Failed verify operation. Data Length was too "
"short for pkcs11RSA_2048_SIGNATURE_LENGTH." ) );
xResult = CKR_DATA_LEN_RANGE;
}
if( ulSignatureLen != pkcs11RSA_2048_SIGNATURE_LENGTH )
{
LogError( ( "Failed verify operation. Signature Length was too "
"short for pkcs11RSA_2048_SIGNATURE_LENGTH." ) );
xResult = CKR_SIGNATURE_LEN_RANGE;
}
}
else if( pxSessionObj->xOperationVerifyMechanism == CKM_ECDSA )
{
if( ulDataLen != pkcs11SHA256_DIGEST_LENGTH )
{
LogError( ( "Failed verify operation. Data Length was too "
"short for pkcs11SHA256_DIGEST_LENGTH." ) );
xResult = CKR_DATA_LEN_RANGE;
}
if( ulSignatureLen != pkcs11ECDSA_P256_SIGNATURE_LENGTH )
{
LogError( ( "Failed verify operation. Data Length was too "
"short for pkcs11ECDSA_P256_SIGNATURE_LENGTH." ) );
xResult = CKR_SIGNATURE_LEN_RANGE;
}
}
else if( pxSessionObj->xOperationVerifyMechanism == CKM_SHA256_HMAC )
{
if( ulSignatureLen != pkcs11SHA256_DIGEST_LENGTH )
{
LogError( ( "Failed verify operation. Data Length was too "
"short for pkcs11SHA256_DIGEST_LENGTH." ) );
xResult = CKR_SIGNATURE_LEN_RANGE;
}
}
else if( pxSessionObj->xOperationVerifyMechanism == CKM_AES_CMAC )
{
if( ulSignatureLen != PKCS11_AES_CMAC_MIN_SIZE )
{
LogError( ( "Failed verify operation. Data Length was too "
"short for PKCS11_AES_CMAC_MIN_SIZE." ) );
xResult = CKR_SIGNATURE_LEN_RANGE;
}
}
else
{
LogError( ( "Failed verify operation. A C_Verify operation must be "
"initialized by a preceding call to C_VerifyInit. "
"This must happen before every call to C_Verify." ) );
xResult = CKR_OPERATION_NOT_INITIALIZED;
}
}
/* Verification step. */
if( xResult == CKR_OK )
{
if( 0 == mbedtls_mutex_lock( &pxSessionObj->xVerifyMutex ) )
{
/* Perform an RSA verification. */
if( pxSessionObj->xOperationVerifyMechanism == CKM_RSA_X_509 )
{
/* Verify the signature. If a public key is present, use it. */
if( NULL != pxSessionObj->xVerifyKey.pk_ctx )
{
lMbedTLSResult = mbedtls_pk_verify( &pxSessionObj->xVerifyKey,
MBEDTLS_MD_SHA256,
pData,
ulDataLen,
pSignature,
ulSignatureLen );
if( 0 != lMbedTLSResult )
{
LogError( ( "Failed verify operation. mbedtls_pk_verify "
"failed: mbed TLS error = %s : %s.",
mbedtlsHighLevelCodeOrDefault( lMbedTLSResult ),
mbedtlsLowLevelCodeOrDefault( lMbedTLSResult ) ) );
xResult = CKR_SIGNATURE_INVALID;
}
}
else
{
LogError( ( "Failed verify operation. Verify Key was not "
"present in session context." ) );
xResult = CKR_SIGNATURE_INVALID;
}
prvVerifyInitEC_RSACleanUp( pxSessionObj );
}
/* Perform an ECDSA verification. */
else if( pxSessionObj->xOperationVerifyMechanism == CKM_ECDSA )
{
/* An ECDSA signature is comprised of 2 components - R & S. C_Sign returns them one after another. */
mbedtls_ecdsa_context * pxEcdsaContext;
mbedtls_mpi xR;
mbedtls_mpi xS;
mbedtls_mpi_init( &xR );
mbedtls_mpi_init( &xS );
lMbedTLSResult = mbedtls_mpi_read_binary( &xR, &pSignature[ 0 ], 32 );
if( lMbedTLSResult != 0 )
{
xResult = CKR_SIGNATURE_INVALID;
LogError( ( "Failed verify operation. Failed to parse R in EC "
"signature: mbed TLS error = %s : %s.",
mbedtlsHighLevelCodeOrDefault( lMbedTLSResult ),
mbedtlsLowLevelCodeOrDefault( lMbedTLSResult ) ) );
}
else
{
lMbedTLSResult = mbedtls_mpi_read_binary( &xS, &pSignature[ 32 ], 32 );
if( lMbedTLSResult != 0 )
{
xResult = CKR_SIGNATURE_INVALID;
LogError( ( "Failed verify operation. Failed to parse S in "
"EC signature: mbed TLS error = %s : %s.",
mbedtlsHighLevelCodeOrDefault( lMbedTLSResult ),
mbedtlsLowLevelCodeOrDefault( lMbedTLSResult ) ) );
}
}
if( xResult == CKR_OK )
{
/* Verify the signature. If a public key is present, use it. */
if( NULL != pxSessionObj->xVerifyKey.pk_ctx )
{
pxEcdsaContext = pxSessionObj->xVerifyKey.pk_ctx;
lMbedTLSResult = mbedtls_ecdsa_verify( &pxEcdsaContext->grp, pData, ulDataLen, &pxEcdsaContext->Q, &xR, &xS );
}
if( lMbedTLSResult != 0 )
{
xResult = CKR_SIGNATURE_INVALID;
LogError( ( "Failed verify operation. "
"mbedtls_ecdsa_verify failed: mbed TLS error = %s : %s.",
mbedtlsHighLevelCodeOrDefault( lMbedTLSResult ),
mbedtlsLowLevelCodeOrDefault( lMbedTLSResult ) ) );
}
}
mbedtls_mpi_free( &xR );
mbedtls_mpi_free( &xS );
prvVerifyInitEC_RSACleanUp( pxSessionObj );
}
else if( pxSessionObj->xOperationVerifyMechanism == CKM_SHA256_HMAC )
{
lMbedTLSResult = mbedtls_md_hmac_update( &pxSessionObj->xHMACSecretContext, pData, ulDataLen );
if( lMbedTLSResult != 0 )
{
xResult = CKR_SIGNATURE_INVALID;
LogError( ( "Failed verify operation. "
"mbedtls_md_hmac_update failed: mbed TLS error = %s : %s.",
mbedtlsHighLevelCodeOrDefault( lMbedTLSResult ),
mbedtlsLowLevelCodeOrDefault( lMbedTLSResult ) ) );
}
else
{
lMbedTLSResult = mbedtls_md_hmac_finish( &pxSessionObj->xHMACSecretContext, pxHMACBuffer );
if( lMbedTLSResult != 0 )
{
xResult = CKR_SIGNATURE_INVALID;
LogError( ( "Failed verify operation. "
"mbedtls_md_hmac_finish failed: mbed TLS error = %s : %s.",
mbedtlsHighLevelCodeOrDefault( lMbedTLSResult ),
mbedtlsLowLevelCodeOrDefault( lMbedTLSResult ) ) );
}
else
{
if( 0 != memcmp( pxHMACBuffer, pSignature, pkcs11SHA256_DIGEST_LENGTH ) )
{
xResult = CKR_SIGNATURE_INVALID;
LogError( ( "Failed verify operation. Signature was invalid." ) );
}
}
}
prvHMACCleanUp( pxSessionObj );
}
else if( pxSessionObj->xOperationVerifyMechanism == CKM_AES_CMAC )
{
lMbedTLSResult = mbedtls_cipher_cmac_update( &pxSessionObj->xCMACSecretContext, pData, ulDataLen );
if( lMbedTLSResult != 0 )
{
xResult = CKR_SIGNATURE_INVALID;
LogError( ( "Failed verify operation. "
"mbedtls_md_hmac_update failed: mbed TLS error = %s : %s.",
mbedtlsHighLevelCodeOrDefault( lMbedTLSResult ),
mbedtlsLowLevelCodeOrDefault( lMbedTLSResult ) ) );
}
else
{
lMbedTLSResult = mbedtls_cipher_cmac_finish( &pxSessionObj->xCMACSecretContext, pxCMACBuffer );
if( lMbedTLSResult != 0 )
{
xResult = CKR_SIGNATURE_INVALID;
LogError( ( "Failed verify operation. "
"mbedtls_md_hmac_finish failed: mbed TLS error = %s : %s.",
mbedtlsHighLevelCodeOrDefault( lMbedTLSResult ),
mbedtlsLowLevelCodeOrDefault( lMbedTLSResult ) ) );
}
else
{
if( 0 != memcmp( pxCMACBuffer, pSignature, MBEDTLS_AES_BLOCK_SIZE ) )
{
xResult = CKR_SIGNATURE_INVALID;
LogError( ( "Failed verify operation. Signature was invalid." ) );
}
}
}
prvCMACCleanUp( pxSessionObj );
}
else
{
LogError( ( "Failed verify operation. Received an unexpected mechanism." ) );
}
( void ) mbedtls_mutex_unlock( &pxSessionObj->xVerifyMutex );
}
else
{
LogError( ( "Failed to initialize verify operation. Could not "
"take xVerifyMutex." ) );
xResult = CKR_CANT_LOCK;
}
}
if( xResult != CKR_SESSION_HANDLE_INVALID )
{
LogDebug( ( "Reset Verify mechanism to pkcs11NO_OPERATION." ) );
}
/* Return the signature verification result. */
return xResult;
}
Note
C_VerifyInit() must have been called previously.
C_Verify() parameters are shared by a session. Calling C_VerifyInit() & C_Verify() with the same session across different tasks may lead to unexpected results.
Parameters
[in]hSessionHandle of a valid PKCS #11 session.
[in]pDataData who's signature is to be verified. Note: In this implementation, this is generally expected to be the hash of the data.
[in]ulDataLenLength of pucData.
[in]pSignatureThe signature to be verified.
[in]ulSignatureLenLength of pucSignature in bytes.
Returns
CKR_OK if successful.
P11Session_t::xOperationVerifyMechanism
CK_MECHANISM_TYPE xOperationVerifyMechanism
The mechanism of verify operation in progress. Set during C_VerifyInit.
Definition: core_pkcs11_mbedtls.c:292
pkcs11RSA_2048_SIGNATURE_LENGTH
#define pkcs11RSA_2048_SIGNATURE_LENGTH
Length of PKCS #11 signature for RSA 2048 key, in bytes.
Definition: core_pkcs11.h:134
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
C_Verify
CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
Verifies a signature on single-part data.
Definition: core_pkcs11_mbedtls.c:4775
P11Session_t::xVerifyMutex
mbedtls_threading_mutex_t xVerifyMutex
Protects the verification key from being modified while in use.
Definition: core_pkcs11_mbedtls.c:293
pkcs11SHA256_DIGEST_LENGTH
#define pkcs11SHA256_DIGEST_LENGTH
Length of a SHA256 digest, in bytes.
Definition: core_pkcs11.h:95
LogDebug
#define LogDebug(message)
Macro that is called in the corePKCS11 library for logging "Debug" level messages.
Definition: core_pkcs11_config_defaults.h:375
pkcs11ECDSA_P256_SIGNATURE_LENGTH
#define pkcs11ECDSA_P256_SIGNATURE_LENGTH
Length of a curve P-256 ECDSA signature, in bytes. PKCS #11 EC signatures are represented as a 32-bit...
Definition: core_pkcs11.h:109
P11Session_t::xVerifyKey
mbedtls_pk_context xVerifyKey
Verification key. Set during C_VerifyInit.
Definition: core_pkcs11_mbedtls.c:295
prvHMACCleanUp
static void prvHMACCleanUp(P11Session_t *pxSession)
Helper function for cleaning up a HMAC operation.
Definition: core_pkcs11_mbedtls.c:3785
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
P11Session_t::xCMACSecretContext
mbedtls_cipher_context_t xCMACSecretContext
Context for in progress CMAC operation. Set during C_SignInit or C_VerifyInit.
Definition: core_pkcs11_mbedtls.c:304
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
prvCMACCleanUp
static void prvCMACCleanUp(P11Session_t *pxSession)
Helper function for cleaning up an CMAC operation.
Definition: core_pkcs11_mbedtls.c:3887
prvVerifyInitEC_RSACleanUp
static void prvVerifyInitEC_RSACleanUp(P11Session_t *pxSession)
Helper function for cleaning up a verify operation for an EC or RSA key.
Definition: core_pkcs11_mbedtls.c:4508
P11Session_t
Session structure.
Definition: core_pkcs11_mbedtls.c:286
pkcs11NO_OPERATION
#define pkcs11NO_OPERATION
Indicates that no PKCS #11 operation is underway for given session.
Definition: core_pkcs11_mbedtls.c:106
LogError
#define LogError(message)
Macro that is called in the corePKCS11 library for logging "Error" level messages.
Definition: core_pkcs11_config_defaults.h:315
PKCS11_AES_CMAC_MIN_SIZE
#define PKCS11_AES_CMAC_MIN_SIZE
Private define for minimum AES-CMAC key size, in bytes.
Definition: core_pkcs11_mbedtls.c:230
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
P11Session_t::xHMACSecretContext
mbedtls_md_context_t xHMACSecretContext
Context for in progress HMAC operation. Set during C_SignInit or C_VerifyInit.
Definition: core_pkcs11_mbedtls.c:302