| /* |
| * Generic wrapper for Cryptoki (PKCS#11) support |
| * |
| * Copyright (C) 2017, ARM Limited, All Rights Reserved |
| * SPDX-License-Identifier: Apache-2.0 |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may |
| * not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| * This file is part of mbed TLS (https://tls.mbed.org) |
| */ |
| |
| #if !defined(MBEDTLS_CONFIG_FILE) |
| #include "mbedtls/config.h" |
| #else |
| #include MBEDTLS_CONFIG_FILE |
| #endif |
| |
| #if defined(MBEDTLS_PKCS11_CLIENT_C) |
| |
| #include <stdint.h> |
| #include <string.h> |
| #include <pkcs11.h> |
| |
| #include "mbedtls/pkcs11_client.h" |
| |
| #if defined(MBEDTLS_PLATFORM_C) |
| #include "mbedtls/platform.h" |
| #else |
| #include <stdlib.h> |
| #define mbedtls_calloc calloc |
| #define mbedtls_free free |
| #endif |
| |
| |
| |
| #if defined(MBEDTLS_PK_C) |
| #include "mbedtls/pk.h" |
| #include "mbedtls/pk_info.h" |
| |
| #if defined(MBEDTLS_RSA_C) |
| #include "mbedtls/bignum.h" |
| #include "mbedtls/rsa.h" |
| #endif |
| |
| #if defined(MBEDTLS_ECDSA_C) |
| #include "mbedtls/asn1.h" |
| #include "mbedtls/asn1write.h" |
| #include "mbedtls/bignum.h" |
| #include "mbedtls/ecdsa.h" |
| #include "mbedtls/ecp.h" |
| #include "mbedtls/oid.h" |
| #endif |
| |
| #define ARRAY_LENGTH( a ) ( sizeof( a ) / sizeof( *( a ) ) ) |
| |
| typedef struct { |
| mbedtls_pk_type_t key_type; /**< key type */ |
| CK_SESSION_HANDLE hSession; /**< session handle */ |
| CK_OBJECT_HANDLE hPublicKey; /**< public key handle (must not be null) */ |
| CK_OBJECT_HANDLE hPrivateKey; /**< private key handle (may be null) */ |
| uint16_t bit_length; /**< key length in bits */ |
| } mbedtls_pk_pkcs11_context_t; |
| |
| static int pkcs11_err_to_mbedtls_pk_err( CK_RV rv ) |
| { |
| switch( rv ) |
| { |
| case CKR_OK: |
| return( 0 ); |
| case CKR_HOST_MEMORY: |
| return( MBEDTLS_ERR_PK_ALLOC_FAILED ); |
| case CKR_ARGUMENTS_BAD: |
| return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
| case CKR_KEY_FUNCTION_NOT_PERMITTED: |
| return( MBEDTLS_ERR_PK_NOT_PERMITTED ); |
| case CKR_MECHANISM_INVALID: |
| return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); |
| case CKR_MECHANISM_PARAM_INVALID: |
| return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
| case CKR_OBJECT_HANDLE_INVALID: |
| return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
| case CKR_SIGNATURE_INVALID: |
| return( MBEDTLS_ERR_PK_INVALID_SIGNATURE ); |
| case CKR_SIGNATURE_LEN_RANGE: |
| return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); |
| case CKR_TEMPLATE_INCOMPLETE: |
| return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
| case CKR_BUFFER_TOO_SMALL: |
| return( MBEDTLS_ERR_PK_BUFFER_TOO_SMALL ); |
| default: |
| return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); |
| } |
| } |
| |
| static size_t pkcs11_pk_get_bitlen( const void *ctx_arg ) |
| { |
| const mbedtls_pk_pkcs11_context_t *ctx = ctx_arg; |
| return( ctx->bit_length ); |
| } |
| |
| static int pkcs11_pk_can_do( const void *ctx_arg, mbedtls_pk_type_t type ) |
| { |
| const mbedtls_pk_pkcs11_context_t *ctx = ctx_arg; |
| return( ctx->key_type == mbedtls_pk_representation_type( type ) ); |
| } |
| |
| static void *pkcs11_pk_alloc( ) |
| { |
| return( mbedtls_calloc( 1, sizeof( mbedtls_pk_pkcs11_context_t ) ) ); |
| } |
| |
| static void pkcs11_pk_free( void *ctx ) |
| { |
| mbedtls_free( ctx ); |
| } |
| |
| static size_t pkcs11_pk_signature_size( const void *ctx_arg ) |
| { |
| const mbedtls_pk_pkcs11_context_t *ctx = ctx_arg; |
| switch( ctx->key_type ) |
| { |
| case MBEDTLS_PK_RSA: |
| return( ( ctx->bit_length + 7 ) / 8 ); |
| case MBEDTLS_PK_ECKEY: |
| return( MBEDTLS_ECDSA_MAX_SIG_LEN( ctx->bit_length ) ); |
| default: |
| return( 0 ); |
| } |
| } |
| |
| #if defined(MBEDTLS_RSA_C) |
| static int pkcs11_sign_core( mbedtls_pk_pkcs11_context_t *ctx, |
| CK_MECHANISM_TYPE mechanism_type, |
| const unsigned char *payload, size_t payload_len, |
| unsigned char *sig, size_t *sig_len, |
| size_t sig_size ) |
| { |
| CK_ULONG ck_sig_len = sig_size; |
| CK_MECHANISM mechanism = { mechanism_type, NULL_PTR, 0 }; |
| CK_RV rv; |
| rv = C_SignInit( ctx->hSession, &mechanism, ctx->hPrivateKey ); |
| if( rv != CKR_OK ) |
| goto exit; |
| rv = C_Sign( ctx->hSession, (CK_BYTE_PTR) payload, payload_len, |
| sig, &ck_sig_len ); |
| if( rv != CKR_OK ) |
| goto exit; |
| *sig_len = ck_sig_len; |
| exit: |
| if( rv != CKR_OK ) |
| memset( sig, 0, ck_sig_len ); |
| return( pkcs11_err_to_mbedtls_pk_err( rv ) ); |
| } |
| #endif /* MBEDTLS_RSA_C */ |
| |
| #if defined(MBEDTLS_RSA_C) |
| static int pkcs11_sign_rsa( mbedtls_pk_pkcs11_context_t *ctx, |
| const unsigned char *digest_info, |
| size_t digest_info_len, |
| unsigned char *sig, size_t *sig_len ) |
| { |
| return( pkcs11_sign_core( ctx, CKM_RSA_PKCS, |
| digest_info, digest_info_len, |
| sig, sig_len, ( ctx->bit_length + 7 ) / 8 ) ); |
| } |
| #endif /* MBEDTLS_RSA_C */ |
| |
| static int pkcs11_sign( void *ctx_arg, |
| mbedtls_md_type_t md_alg, |
| const unsigned char *hash, size_t hash_len, |
| unsigned char *sig, size_t *sig_len, |
| int (*f_rng)(void *, unsigned char *, size_t), |
| void *p_rng ) |
| { |
| mbedtls_pk_pkcs11_context_t *ctx = ctx_arg; |
| int ret; |
| |
| *sig_len = 0; |
| |
| /* This function takes size_t arguments but the underlying layer |
| takes unsigned long. Either type may be smaller than the other. |
| Legitimate values won't overflow either type but we still need |
| to check for overflow for robustness. */ |
| if( hash_len > (CK_ULONG)( -1 ) ) |
| return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
| (void) f_rng; |
| (void) p_rng; |
| |
| switch( ctx->key_type ) |
| { |
| #if defined(MBEDTLS_RSA_C) |
| case MBEDTLS_PK_RSA: |
| /* There is no mechanism in PKCS#11 that computes a PKCS#1 v1.5 |
| * signature from a hash value and a hash type, only mechanisms |
| * that include the hash calculation and a mechanism that expects |
| * a DigestInfo (encoded hash that isn't padded). So we use the |
| * mechanism that expects a DigestInfo, and calculate the DigestInfo |
| * ourselves if needed. */ |
| if( md_alg == MBEDTLS_MD_NONE ) |
| { |
| ret = pkcs11_sign_rsa( ctx, hash, hash_len, sig, sig_len ); |
| } |
| else |
| { |
| unsigned char digest_info[MBEDTLS_RSA_PKCS1_DIGESTINFO_MAX_SIZE]; |
| unsigned char *p = digest_info + sizeof( digest_info ); |
| size_t digest_info_len; |
| if( mbedtls_rsa_emsa_pkcs1_v15_encode_digestinfo( |
| &p, digest_info, |
| md_alg, hash, hash_len ) != 0 ) |
| return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
| digest_info_len = digest_info + sizeof( digest_info ) - p; |
| ret = pkcs11_sign_rsa( ctx, p, digest_info_len, sig, sig_len ); |
| } |
| break; |
| #endif /* MBEDTLS_RSA_C */ |
| default: |
| return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); |
| } |
| |
| return( ret ); |
| } |
| |
| static int pkcs11_verify_core( mbedtls_pk_pkcs11_context_t *ctx, |
| CK_MECHANISM_TYPE mechanism_type, |
| const unsigned char *payload, size_t payload_len, |
| const unsigned char *sig, size_t sig_len ) |
| { |
| CK_MECHANISM mechanism = { mechanism_type, NULL_PTR, 0 }; |
| CK_RV rv; |
| |
| rv = C_VerifyInit( ctx->hSession, &mechanism, ctx->hPublicKey ); |
| if( rv != CKR_OK ) |
| goto exit; |
| rv = C_Verify( ctx->hSession, (CK_BYTE_PTR) payload, payload_len, |
| (CK_BYTE_PTR) sig, sig_len ); |
| if( rv != CKR_OK ) |
| goto exit; |
| |
| exit: |
| return( pkcs11_err_to_mbedtls_pk_err( rv ) ); |
| } |
| |
| static int pkcs11_verify( void *ctx_arg, |
| mbedtls_md_type_t md_alg, |
| const unsigned char *hash, size_t hash_len, |
| const unsigned char *sig, size_t sig_len) |
| { |
| mbedtls_pk_pkcs11_context_t *ctx = ctx_arg; |
| |
| /* This function takes size_t arguments but the underlying layer |
| takes unsigned long. Either type may be smaller than the other. |
| Legitimate values won't overflow either type but we still need |
| to check for overflow for robustness. */ |
| if( hash_len > (CK_ULONG)( -1 ) ) |
| return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
| |
| switch( ctx->key_type ) |
| { |
| #if defined(MBEDTLS_RSA_C) |
| case MBEDTLS_PK_RSA: |
| /* There is no mechanism in PKCS#11 that computes a PKCS#1 v1.5 |
| * signature from a hash value and a hash type, only mechanisms |
| * that include the hash calculation and a mechanism that expects |
| * a DigestInfo (encoded hash that isn't padded). So we use the |
| * mechanism that expects a DigestInfo, and calculate the DigestInfo |
| * ourselves if needed. */ |
| if( md_alg == MBEDTLS_MD_NONE ) |
| { |
| return( pkcs11_verify_core( ctx, CKM_RSA_PKCS, |
| hash, hash_len, |
| sig, sig_len ) ); |
| } |
| else |
| { |
| unsigned char digest_info[MBEDTLS_RSA_PKCS1_DIGESTINFO_MAX_SIZE]; |
| unsigned char *p = digest_info + sizeof( digest_info ); |
| size_t digest_info_len; |
| if( mbedtls_rsa_emsa_pkcs1_v15_encode_digestinfo( |
| &p, digest_info, |
| md_alg, hash, hash_len ) != 0 ) |
| return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
| digest_info_len = digest_info + sizeof( digest_info ) - p; |
| return( pkcs11_verify_core( ctx, CKM_RSA_PKCS, |
| p, digest_info_len, |
| sig, sig_len ) ); |
| } |
| break; |
| #endif /* MBEDTLS_RSA_C */ |
| default: |
| return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); |
| } |
| } |
| |
| static const mbedtls_pk_info_t mbedtls_pk_pkcs11_info = |
| MBEDTLS_PK_OPAQUE_INFO_1( "pkcs11" |
| , pkcs11_pk_get_bitlen |
| , pkcs11_pk_can_do //can_do |
| , pkcs11_pk_signature_size |
| , pkcs11_verify |
| , pkcs11_sign |
| , NULL //pkcs11_decrypt |
| , NULL //pkcs11_encrypt |
| , NULL //check_pair_func |
| , pkcs11_pk_alloc |
| , pkcs11_pk_free |
| , NULL //debug_func |
| ); |
| |
| int mbedtls_pk_setup_pkcs11( mbedtls_pk_context *ctx, |
| CK_SESSION_HANDLE hSession, |
| CK_OBJECT_HANDLE hPublicKey, |
| CK_OBJECT_HANDLE hPrivateKey ) |
| { |
| CK_OBJECT_CLASS public_key_class = -1, private_key_class = -1; |
| CK_KEY_TYPE public_key_type = -1, private_key_type = -1; |
| mbedtls_pk_type_t can_do; |
| CK_ATTRIBUTE attributes[] = { |
| {CKA_CLASS, &public_key_class, sizeof( public_key_class )}, |
| {CKA_KEY_TYPE, &public_key_type, sizeof( public_key_type )}, |
| }; |
| CK_RV rv; |
| uint16_t key_size = 0; |
| |
| rv = C_GetAttributeValue( hSession, hPublicKey, |
| attributes, ARRAY_LENGTH( attributes ) ); |
| if( rv != CKR_OK ) |
| return( pkcs11_err_to_mbedtls_pk_err( rv ) ); |
| if( public_key_class != CKO_PUBLIC_KEY ) |
| return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
| |
| if( hPrivateKey != CK_INVALID_HANDLE ) |
| { |
| attributes[0].pValue = &private_key_class; |
| attributes[1].pValue = &private_key_type; |
| rv = C_GetAttributeValue( hSession, hPrivateKey, |
| attributes, ARRAY_LENGTH( attributes ) ); |
| if( rv != CKR_OK ) |
| return( pkcs11_err_to_mbedtls_pk_err( rv ) ); |
| if( private_key_class != CKO_PRIVATE_KEY ) |
| return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
| if( public_key_type != private_key_type ) |
| return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
| } |
| |
| switch( public_key_type ) { |
| #if defined(MBEDTLS_RSA_C) |
| case CKK_RSA: |
| can_do = MBEDTLS_PK_RSA; |
| { |
| CK_ULONG modulus_bits; |
| attributes[0].type = CKA_MODULUS_BITS; |
| attributes[0].pValue = &modulus_bits; |
| attributes[0].ulValueLen = sizeof( modulus_bits ); |
| rv = C_GetAttributeValue( hSession, hPublicKey, attributes, 1 ); |
| if( rv != CKR_OK ) |
| return( pkcs11_err_to_mbedtls_pk_err( rv ) ); |
| if( modulus_bits > (uint16_t)( -1 ) ) |
| return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); |
| key_size = modulus_bits; |
| } |
| break; |
| #endif /* MBEDTLS_RSA_C */ |
| default: |
| can_do = MBEDTLS_PK_OPAQUE; |
| break; |
| } |
| |
| { |
| int ret = mbedtls_pk_setup( ctx, &mbedtls_pk_pkcs11_info ); |
| if( ret != 0 ) |
| return( MBEDTLS_ERR_PK_ALLOC_FAILED ); |
| } |
| { |
| mbedtls_pk_pkcs11_context_t *pkcs11_ctx = ctx->pk_ctx; |
| pkcs11_ctx->key_type = can_do; |
| pkcs11_ctx->bit_length = key_size; |
| pkcs11_ctx->hSession = hSession; |
| pkcs11_ctx->hPublicKey = hPublicKey; |
| pkcs11_ctx->hPrivateKey = hPrivateKey; |
| } |
| return( 0 ); |
| } |
| |
| #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) |
| static int mpi_to_ck( const mbedtls_mpi *mpi, |
| CK_ATTRIBUTE *attr, CK_ATTRIBUTE_TYPE at, |
| unsigned char **p, size_t len ) |
| { |
| if( mbedtls_mpi_write_binary( mpi, *p, len ) != 0 ) |
| return( 0 ); |
| attr->type = at; |
| attr->pValue = *p; |
| attr->ulValueLen = len; |
| *p += len; |
| return( 1 ); |
| } |
| #define MPI_TO_CK( mpi, attr, at, p, len ) \ |
| do \ |
| { \ |
| if( !mpi_to_ck( ( mpi ), ( attr ), ( at ), ( p ), ( len ) ) ) \ |
| { \ |
| rv = CKR_ARGUMENTS_BAD; \ |
| goto exit; \ |
| } \ |
| } \ |
| while( 0 ) |
| #endif /* defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) */ |
| |
| #define CK_BOOL( x ) ( ( x ) ? CK_TRUE : CK_FALSE ) |
| |
| int mbedtls_pk_import_to_pkcs11( const mbedtls_pk_context *ctx, |
| uint32_t flags, |
| CK_SESSION_HANDLE hSession, |
| CK_OBJECT_HANDLE *hPublicKey, |
| CK_OBJECT_HANDLE *hPrivateKey ) |
| { |
| CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY; |
| CK_OBJECT_CLASS cko_public_key = CKO_PUBLIC_KEY; |
| CK_KEY_TYPE ck_key_type; |
| CK_BBOOL ck_sensitive = CK_BOOL( flags & MBEDTLS_PK_FLAG_SENSITIVE ); |
| CK_BBOOL ck_extractable = CK_BOOL( flags & MBEDTLS_PK_FLAG_EXTRACTABLE ); |
| CK_BBOOL ck_sign = CK_BOOL( flags & MBEDTLS_PK_FLAG_SIGN ); |
| CK_BBOOL ck_verify = CK_BOOL( flags & MBEDTLS_PK_FLAG_VERIFY ); |
| CK_BBOOL ck_decrypt = CK_BOOL( flags & MBEDTLS_PK_FLAG_DECRYPT ); |
| CK_BBOOL ck_encrypt = CK_BOOL( flags & MBEDTLS_PK_FLAG_ENCRYPT ); |
| CK_BBOOL ck_token = CK_BOOL( flags & MBEDTLS_PKCS11_FLAG_TOKEN ); |
| CK_ATTRIBUTE public_attributes[] = { |
| {CKA_CLASS, &cko_public_key, sizeof( cko_public_key )}, |
| {CKA_KEY_TYPE, &ck_key_type, sizeof( ck_key_type )}, |
| {CKA_TOKEN, &ck_token, sizeof( ck_token )}, |
| {CKA_ENCRYPT, &ck_encrypt, sizeof( ck_encrypt )}, |
| {CKA_VERIFY, &ck_verify, sizeof( ck_verify )}, |
| #define COMMON_PUBLIC_ATTRIBUTES 5 // number of attributes above |
| {-1, NULL, 0}, |
| {-1, NULL, 0}, |
| }; |
| CK_ATTRIBUTE private_attributes[] = { |
| {CKA_CLASS, &cko_private_key, sizeof( cko_private_key )}, |
| {CKA_KEY_TYPE, &ck_key_type, sizeof( ck_key_type )}, |
| {CKA_TOKEN, &ck_token, sizeof( ck_token )}, |
| {CKA_DECRYPT, &ck_decrypt, sizeof( ck_decrypt )}, |
| {CKA_SIGN, &ck_sign, sizeof( ck_sign )}, |
| {CKA_SENSITIVE, &ck_sensitive, sizeof( ck_sensitive )}, |
| {CKA_EXTRACTABLE, &ck_extractable, sizeof( ck_extractable )}, |
| #define COMMON_PRIVATE_ATTRIBUTES 7 // number of attributes above |
| {-1, NULL, 0}, |
| {-1, NULL, 0}, |
| {-1, NULL, 0}, |
| {-1, NULL, 0}, |
| {-1, NULL, 0}, |
| {-1, NULL, 0}, |
| {-1, NULL, 0}, |
| {-1, NULL, 0}, |
| }; |
| CK_ATTRIBUTE *public_end = public_attributes + COMMON_PUBLIC_ATTRIBUTES; |
| CK_ATTRIBUTE *private_end = private_attributes + COMMON_PRIVATE_ATTRIBUTES; |
| #undef COMMON_PUBLIC_ATTRIBUTES |
| #undef COMMON_PRIVATE_ATTRIBUTES |
| unsigned char *data = NULL; |
| CK_RV rv; |
| |
| if( hPublicKey != NULL ) |
| *hPublicKey = CK_INVALID_HANDLE; |
| if( hPrivateKey != NULL ) |
| *hPrivateKey = CK_INVALID_HANDLE; |
| |
| /* Prepare the data-dependent key attributes */ |
| switch( mbedtls_pk_representation_type( mbedtls_pk_get_type( ctx ) ) ) |
| { |
| #if defined(MBEDTLS_RSA_C) |
| case MBEDTLS_PK_RSA: |
| { |
| const mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *ctx ); |
| unsigned char *p; |
| size_t half_len = ( rsa->len + 1 ) / 2; |
| data = mbedtls_calloc( 1, 3 * rsa->len + 5 * half_len ); |
| if( data == NULL ) |
| { |
| rv = CKR_HOST_MEMORY; |
| goto exit; |
| } |
| p = data; |
| ck_key_type = CKK_RSA; |
| MPI_TO_CK( &rsa->N, public_end, CKA_MODULUS, &p, rsa->len ); |
| *private_end++ = *public_end++; |
| MPI_TO_CK( &rsa->E, public_end, CKA_PUBLIC_EXPONENT, &p, rsa->len ); |
| *private_end++ = *public_end++; |
| if( hPrivateKey != NULL ) |
| { |
| MPI_TO_CK( &rsa->D, private_end++, |
| CKA_PRIVATE_EXPONENT, &p, rsa->len ); |
| MPI_TO_CK( &rsa->P, private_end++, |
| CKA_PRIME_1, &p, half_len ); |
| MPI_TO_CK( &rsa->Q, private_end++, |
| CKA_PRIME_2, &p, half_len ); |
| MPI_TO_CK( &rsa->DP, private_end++, |
| CKA_EXPONENT_1, &p, half_len ); |
| MPI_TO_CK( &rsa->DQ, private_end++, |
| CKA_EXPONENT_2, &p, half_len ); |
| MPI_TO_CK( &rsa->QP, private_end++, |
| CKA_COEFFICIENT, &p, half_len ); |
| } |
| } |
| break; |
| #endif /* MBEDTLS_RSA_C */ |
| default: |
| return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); |
| } |
| |
| if( hPublicKey != NULL ) |
| { |
| *hPublicKey = CK_INVALID_HANDLE; |
| rv = C_CreateObject( hSession, |
| public_attributes, |
| public_end - public_attributes, |
| hPublicKey ); |
| if( rv != CKR_OK ) |
| goto exit; |
| } |
| |
| if( hPrivateKey != NULL ) |
| { |
| rv = C_CreateObject( hSession, |
| private_attributes, |
| private_end - private_attributes, |
| hPrivateKey ); |
| if( rv != CKR_OK ) |
| goto exit; |
| } |
| |
| exit: |
| if( rv != CKR_OK ) |
| { |
| /* In case an error happened, destroy any object that we |
| created. In case C_DestroyObject failed, we report the original |
| error, but *hPublicKey may contain a valid handle if |
| creating the private key failed and then destroying the public key |
| also failed (e.g. because the token disconnected). */ |
| if( hPublicKey != NULL && *hPublicKey != CK_INVALID_HANDLE ) |
| { |
| if( C_DestroyObject( hSession, *hPublicKey ) == CKR_OK ) |
| *hPublicKey = CK_INVALID_HANDLE; |
| } |
| if( hPrivateKey != NULL && *hPrivateKey != CK_INVALID_HANDLE ) |
| { |
| if( C_DestroyObject( hSession, *hPrivateKey ) == CKR_OK ) |
| *hPrivateKey = CK_INVALID_HANDLE; |
| } |
| } |
| mbedtls_free( data ); |
| return( pkcs11_err_to_mbedtls_pk_err( rv ) ); |
| } |
| |
| #endif /* MBEDTLS_PK_C */ |
| |
| |
| |
| #endif /* MBEDTLS_PKCS11_CLIENT_C */ |