blob: 439c50cffafc5fde618c7c9601be2831ac35c9e2 [file] [log] [blame]
Andrzej Kurekc53dee32018-01-23 05:44:20 -05001/*
2 * Generic wrapper for Cryptoki (PKCS#11) support
3 *
Andrzej Kurekdfedd822018-02-27 09:23:22 -05004 * Copyright (C) 2017-2018, ARM Limited, All Rights Reserved
Andrzej Kurekc53dee32018-01-23 05:44:20 -05005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
22#if !defined(MBEDTLS_CONFIG_FILE)
23#include "mbedtls/config.h"
24#else
25#include MBEDTLS_CONFIG_FILE
26#endif
27
28#if defined(MBEDTLS_PKCS11_CLIENT_C)
29
30#include <stdint.h>
31#include <string.h>
Andrzej Kurekc53dee32018-01-23 05:44:20 -050032
33#include "mbedtls/pkcs11_client.h"
34
35#if defined(MBEDTLS_PLATFORM_C)
36#include "mbedtls/platform.h"
37#else
38#include <stdlib.h>
39#define mbedtls_calloc calloc
40#define mbedtls_free free
41#endif
42
43
44
45#if defined(MBEDTLS_PK_C)
46#include "mbedtls/pk.h"
47#include "mbedtls/pk_info.h"
48
49#if defined(MBEDTLS_ECDSA_C)
50#include "mbedtls/asn1.h"
51#include "mbedtls/asn1write.h"
52#include "mbedtls/bignum.h"
53#include "mbedtls/ecdsa.h"
54#include "mbedtls/ecp.h"
55#include "mbedtls/oid.h"
56#endif
57
58#define ARRAY_LENGTH( a ) ( sizeof( a ) / sizeof( *( a ) ) )
59
60typedef struct {
61 mbedtls_pk_type_t key_type; /**< key type */
62 CK_SESSION_HANDLE hSession; /**< session handle */
63 CK_OBJECT_HANDLE hPublicKey; /**< public key handle (must not be null) */
64 CK_OBJECT_HANDLE hPrivateKey; /**< private key handle (may be null) */
65 uint16_t bit_length; /**< key length in bits */
66} mbedtls_pk_pkcs11_context_t;
67
68static int pkcs11_err_to_mbedtls_pk_err( CK_RV rv )
69{
70 switch( rv )
71 {
72 case CKR_OK:
73 return( 0 );
74 case CKR_HOST_MEMORY:
75 return( MBEDTLS_ERR_PK_ALLOC_FAILED );
76 case CKR_ARGUMENTS_BAD:
77 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
78 case CKR_KEY_FUNCTION_NOT_PERMITTED:
79 return( MBEDTLS_ERR_PK_NOT_PERMITTED );
80 case CKR_MECHANISM_INVALID:
81 return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
82 case CKR_MECHANISM_PARAM_INVALID:
83 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
84 case CKR_OBJECT_HANDLE_INVALID:
85 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
86 case CKR_SIGNATURE_INVALID:
87 return( MBEDTLS_ERR_PK_INVALID_SIGNATURE );
88 case CKR_SIGNATURE_LEN_RANGE:
89 return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
90 case CKR_TEMPLATE_INCOMPLETE:
91 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
92 case CKR_BUFFER_TOO_SMALL:
93 return( MBEDTLS_ERR_PK_BUFFER_TOO_SMALL );
94 default:
95 return( MBEDTLS_ERR_PK_FILE_IO_ERROR );
96 }
97}
98
99static size_t pkcs11_pk_get_bitlen( const void *ctx_arg )
100{
101 const mbedtls_pk_pkcs11_context_t *ctx = ctx_arg;
102 return( ctx->bit_length );
103}
104
105static int pkcs11_pk_can_do( const void *ctx_arg, mbedtls_pk_type_t type )
106{
107 const mbedtls_pk_pkcs11_context_t *ctx = ctx_arg;
108 return ctx->key_type == mbedtls_pk_representation_type( type );
109}
110
111static void *pkcs11_pk_alloc( )
112{
113 return( mbedtls_calloc( 1, sizeof( mbedtls_pk_pkcs11_context_t ) ) );
114}
115
116static void pkcs11_pk_free( void *ctx )
117{
118 mbedtls_free( ctx );
119}
120
121static size_t pkcs11_pk_signature_size( const void *ctx_arg )
122{
123 const mbedtls_pk_pkcs11_context_t *ctx = ctx_arg;
124 switch( ctx->key_type )
125 {
126 case MBEDTLS_PK_RSA:
127 return( ( ctx->bit_length + 7 ) / 8 );
128 case MBEDTLS_PK_ECKEY:
129 return( MBEDTLS_ECDSA_MAX_SIG_LEN( ctx->bit_length ) );
130 default:
131 return( 0 );
132 }
133}
134
135static int pkcs11_sign( void *ctx_arg,
136 mbedtls_md_type_t md_alg,
137 const unsigned char *hash, size_t hash_len,
138 unsigned char *sig, size_t *sig_len,
139 int (*f_rng)(void *, unsigned char *, size_t),
140 void *p_rng )
141{
142 mbedtls_pk_pkcs11_context_t *ctx = ctx_arg;
143 CK_RV rv;
144 CK_MECHANISM mechanism = {0, NULL_PTR, 0};
145 CK_ULONG ck_sig_len;
Andrzej Kureke1f26b82018-02-19 03:57:07 -0500146 (void)(md_alg);
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500147 /* This function takes size_t arguments but the underlying layer
148 takes unsigned long. Either type may be smaller than the other.
149 Legitimate values won't overflow either type but we still need
150 to check for overflow for robustness. */
151 if( hash_len > (CK_ULONG)( -1 ) )
152 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
153 (void) f_rng;
154 (void) p_rng;
155
156 switch( ctx->key_type )
157 {
158#if defined(MBEDTLS_ECDSA_C)
159 case MBEDTLS_PK_ECKEY:
160 ck_sig_len = MBEDTLS_ECDSA_MAX_SIG_LEN( ctx->bit_length );
161 mechanism.mechanism = CKM_ECDSA;
162 break;
163#endif /* MBEDTLS_ECDSA_C */
164 default:
165 return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
166 }
167
168 rv = C_SignInit( ctx->hSession, &mechanism, ctx->hPrivateKey );
169 if( rv != CKR_OK )
170 goto exit;
171 rv = C_Sign( ctx->hSession, (CK_BYTE_PTR) hash, hash_len,
172 sig, &ck_sig_len );
173 if( rv != CKR_OK )
174 goto exit;
175
176 if( mechanism.mechanism == CKM_ECDSA )
177 {
178 /* The signature from the token contains r and s concatenated,
179 * each in the form of a big-endian byte sequence, with r and s
180 * having the same length as the base point.
181 *
Andrzej Kureke1f26b82018-02-19 03:57:07 -0500182 * This library encodes ECDSA signatures in ASN.1 as documented
183 * for mbedtls_ecdsa_write_signature:
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500184 * SEQUENCE {
185 * r INTEGER,
186 * s INTEGER
187 * }
188 *
189 * Perform the conversion using existing utility functions,
190 * with temporary bignums.
191 */
192 uint16_t byte_len = ( ( ctx->bit_length + 7 ) / 8 );
193 size_t sig_size = MBEDTLS_ECDSA_MAX_SIG_LEN( ctx->bit_length );
Andrzej Kurekb91a3932018-03-01 09:09:55 -0500194
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500195 rv = CKR_OK;
196 if( ck_sig_len != 2 * byte_len )
197 {
198 /* Bad data from the token */
199 rv = CKR_GENERAL_ERROR;
200 goto ecdsa_exit;
201 }
Andrzej Kurekb91a3932018-03-01 09:09:55 -0500202
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500203 /* The signature buffer is guaranteed to have enough room for
204 the encoded signature by the pk_sign interface. */
Andrzej Kurekb91a3932018-03-01 09:09:55 -0500205 if( mbedtls_raw_ecdsa_signature_to_asn1( sig, sig + byte_len, byte_len, sig, sig_len, sig_size ) != 0 )
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500206 {
207 rv = CKR_GENERAL_ERROR;
208 goto ecdsa_exit;
209 }
210 ecdsa_exit:
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500211 if( rv != CKR_OK )
212 goto exit;
213 }
214 else
215 {
216 *sig_len = ck_sig_len;
217 }
218
219exit:
220 if( rv != CKR_OK )
221 memset( sig, 0, ck_sig_len );
222 return( pkcs11_err_to_mbedtls_pk_err( rv ) );
223}
224
Andrzej Kurekc289bf12018-01-23 06:10:53 -0500225static int pkcs11_verify( void *ctx_arg,
226 mbedtls_md_type_t md_alg,
227 const unsigned char *hash, size_t hash_len,
228 const unsigned char *sig, size_t sig_len)
229{
230 mbedtls_pk_pkcs11_context_t *ctx = ctx_arg;
231 CK_RV rv;
232 CK_MECHANISM mechanism = {0, NULL_PTR, 0};
Andrzej Kurekb03bc432018-01-23 06:25:32 -0500233 unsigned char *decoded_sig = NULL;
Andrzej Kurekc289bf12018-01-23 06:10:53 -0500234 size_t decoded_sig_len;
235
236 /* This function takes size_t arguments but the underlying layer
237 takes unsigned long. Either type may be smaller than the other.
238 Legitimate values won't overflow either type but we still need
239 to check for overflow for robustness. */
240 if( hash_len > (CK_ULONG)( -1 ) )
241 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
242
243 switch( ctx->key_type )
244 {
245#if defined(MBEDTLS_RSA_C)
246 case MBEDTLS_PK_RSA:
247 switch( md_alg )
248 {
249 case MBEDTLS_MD_MD5:
250 mechanism.mechanism = CKM_MD5_RSA_PKCS;
251 break;
252 case MBEDTLS_MD_SHA1:
253 mechanism.mechanism = CKM_SHA1_RSA_PKCS;
254 break;
255 case MBEDTLS_MD_SHA256:
256 mechanism.mechanism = CKM_SHA256_RSA_PKCS;
257 break;
258 case MBEDTLS_MD_SHA384:
259 mechanism.mechanism = CKM_SHA384_RSA_PKCS;
260 break;
261 case MBEDTLS_MD_SHA512:
262 mechanism.mechanism = CKM_SHA512_RSA_PKCS;
263 break;
264 default:
265 return( MBEDTLS_ERR_PK_INVALID_ALG );
266 }
267 break;
268#endif /* MBEDTLS_RSA_C */
269#if defined(MBEDTLS_ECDSA_C)
270 case MBEDTLS_PK_ECKEY:
271 mechanism.mechanism = CKM_ECDSA;
272 break;
273#endif /* MBEDTLS_ECDSA_C */
274 default:
275 return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
276 }
277 if( mechanism.mechanism == CKM_ECDSA )
278 {
279 uint16_t byte_len = ( ( ctx->bit_length + 7 ) / 8 );
Andrzej Kurekb03bc432018-01-23 06:25:32 -0500280 decoded_sig = mbedtls_calloc( 1, 2 * byte_len );
281 if( decoded_sig == NULL )
282 {
283 return( MBEDTLS_ERR_PK_ALLOC_FAILED );
284 }
Andrzej Kurekc289bf12018-01-23 06:10:53 -0500285 if( mbedtls_ecdsa_signature_to_raw( sig, sig_len, byte_len,
Andrzej Kurekdfedd822018-02-27 09:23:22 -0500286 decoded_sig, &decoded_sig_len,
287 2 * byte_len ) != 0 )
Andrzej Kurekc289bf12018-01-23 06:10:53 -0500288 {
289 rv = CKR_GENERAL_ERROR;
290 goto exit;
291 }
292 }
293 rv = C_VerifyInit( ctx->hSession, &mechanism, ctx->hPublicKey );
294 if( rv != CKR_OK )
295 goto exit;
296 rv = C_Verify( ctx->hSession, (CK_BYTE_PTR) hash, hash_len,
297 decoded_sig, decoded_sig_len );
298 if( rv != CKR_OK )
299 goto exit;
300
301exit:
Andrzej Kurekb03bc432018-01-23 06:25:32 -0500302 mbedtls_free(decoded_sig);
Andrzej Kurekc289bf12018-01-23 06:10:53 -0500303 return( pkcs11_err_to_mbedtls_pk_err( rv ) );
304}
305
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500306static const mbedtls_pk_info_t mbedtls_pk_pkcs11_info =
307 MBEDTLS_PK_OPAQUE_INFO_1( "pkcs11"
308 , pkcs11_pk_get_bitlen
Andrzej Kureke1f26b82018-02-19 03:57:07 -0500309 , pkcs11_pk_can_do
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500310 , pkcs11_pk_signature_size
Andrzej Kurekc289bf12018-01-23 06:10:53 -0500311 , pkcs11_verify
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500312 , pkcs11_sign
313 , NULL //pkcs11_decrypt
314 , NULL //pkcs11_encrypt
315 , NULL //check_pair_func
316 , pkcs11_pk_alloc
317 , pkcs11_pk_free
318 , NULL //debug_func
319 );
320
Andrzej Kurek12603542018-02-19 04:06:05 -0500321int mbedtls_pkcs11_setup_pk( mbedtls_pk_context *ctx,
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500322 CK_SESSION_HANDLE hSession,
323 CK_OBJECT_HANDLE hPublicKey,
324 CK_OBJECT_HANDLE hPrivateKey )
325{
326 CK_OBJECT_CLASS public_key_class = -1, private_key_class = -1;
327 CK_KEY_TYPE public_key_type = -1, private_key_type = -1;
328 mbedtls_pk_type_t can_do;
329 CK_ATTRIBUTE attributes[] = {
330 {CKA_CLASS, &public_key_class, sizeof( public_key_class )},
331 {CKA_KEY_TYPE, &public_key_type, sizeof( public_key_type )},
332 };
333 CK_RV rv;
334 uint16_t key_size = 0;
335
336 rv = C_GetAttributeValue( hSession, hPublicKey,
337 attributes, ARRAY_LENGTH( attributes ) );
338 if( rv != CKR_OK )
339 return( pkcs11_err_to_mbedtls_pk_err( rv ) );
340 if( public_key_class != CKO_PUBLIC_KEY )
341 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
342
343 if( hPrivateKey != CK_INVALID_HANDLE )
344 {
345 attributes[0].pValue = &private_key_class;
346 attributes[1].pValue = &private_key_type;
347 rv = C_GetAttributeValue( hSession, hPrivateKey,
348 attributes, ARRAY_LENGTH( attributes ) );
349 if( rv != CKR_OK )
350 return( pkcs11_err_to_mbedtls_pk_err( rv ) );
351 if( private_key_class != CKO_PRIVATE_KEY )
352 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
353 if( public_key_type != private_key_type )
354 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
355 }
356
357 switch( public_key_type ) {
358#if defined(MBEDTLS_ECDSA_C)
359 case CKK_ECDSA:
360 can_do = MBEDTLS_PK_ECKEY;
361 {
Andrzej Kurek33f56652018-02-19 04:03:11 -0500362 unsigned char ecParams[MBEDTLS_OID_EC_GRP_MAX_SIZE];
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500363 mbedtls_asn1_buf params_asn1;
364 mbedtls_ecp_group_id grp_id;
365 const mbedtls_ecp_curve_info *curve_info;
366 attributes[0].type = CKA_EC_PARAMS;
367 attributes[0].pValue = ecParams;
368 attributes[0].ulValueLen = sizeof( ecParams );
Andrzej Kurek18f53892018-01-23 06:30:09 -0500369 rv = C_GetAttributeValue( hSession, hPublicKey, attributes, 1 );
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500370 if( rv != CKR_OK )
371 return( pkcs11_err_to_mbedtls_pk_err( rv ) );
372 params_asn1.tag = ecParams[0];
373 params_asn1.len = ecParams[1];
374 params_asn1.p = ecParams + 2;
375 if( mbedtls_oid_get_ec_grp( &params_asn1, &grp_id ) != 0 )
376 return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE );
377 curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id );
378 if( curve_info == NULL )
379 return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE );
380 key_size = curve_info->bit_size;
381 }
382 break;
383#endif /* MBEDTLS_ECDSA_C */
384 default:
385 can_do = MBEDTLS_PK_OPAQUE;
386 break;
387 }
388
389 {
390 int ret = mbedtls_pk_setup( ctx, &mbedtls_pk_pkcs11_info );
391 if( ret != 0 )
392 return( MBEDTLS_ERR_PK_ALLOC_FAILED );
393 }
394 {
395 mbedtls_pk_pkcs11_context_t *pkcs11_ctx = ctx->pk_ctx;
396 pkcs11_ctx->key_type = can_do;
397 pkcs11_ctx->bit_length = key_size;
398 pkcs11_ctx->hSession = hSession;
399 pkcs11_ctx->hPublicKey = hPublicKey;
400 pkcs11_ctx->hPrivateKey = hPrivateKey;
401 }
402 return( 0 );
403}
404
405#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C)
406static int mpi_to_ck( const mbedtls_mpi *mpi,
407 CK_ATTRIBUTE *attr, CK_ATTRIBUTE_TYPE at,
408 unsigned char **p, size_t len )
409{
Andrzej Kurek9982e072018-02-19 04:07:31 -0500410 int ret = mbedtls_mpi_write_binary( mpi, *p, len );
411 if( ret != 0 )
412 return( ret );
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500413 attr->type = at;
414 attr->pValue = *p;
415 attr->ulValueLen = len;
416 *p += len;
Andrzej Kurek9982e072018-02-19 04:07:31 -0500417 return( 0 );
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500418}
Andrzej Kurek9982e072018-02-19 04:07:31 -0500419#define MPI_TO_CK( mpi, attr, at, p, len ) \
420 do \
421 { \
422 if( mpi_to_ck( ( mpi ), ( attr ), ( at ), ( p ), ( len ) ) != 0) \
423 { \
424 rv = CKR_ARGUMENTS_BAD; \
425 goto exit; \
426 } \
427 } \
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500428 while( 0 )
429#endif /* defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) */
430
Andrzej Kurek7e19f772018-02-19 04:00:27 -0500431#define MBEDTLS_PKCS11_BOOL( x ) ( ( x ) ? CK_TRUE : CK_FALSE )
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500432
Andrzej Kurek12603542018-02-19 04:06:05 -0500433int mbedtls_pkcs11_import_pk( const mbedtls_pk_context *ctx,
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500434 uint32_t flags,
435 CK_SESSION_HANDLE hSession,
436 CK_OBJECT_HANDLE *hPublicKey,
437 CK_OBJECT_HANDLE *hPrivateKey )
438{
439 CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY;
440 CK_OBJECT_CLASS cko_public_key = CKO_PUBLIC_KEY;
441 CK_KEY_TYPE ck_key_type;
Andrzej Kurek7e19f772018-02-19 04:00:27 -0500442 CK_BBOOL ck_sensitive = MBEDTLS_PKCS11_BOOL( flags & MBEDTLS_PKCS11_FLAG_SENSITIVE );
443 CK_BBOOL ck_extractable = MBEDTLS_PKCS11_BOOL( flags & MBEDTLS_PKCS11_FLAG_EXTRACTABLE );
444 CK_BBOOL ck_sign = MBEDTLS_PKCS11_BOOL( flags & MBEDTLS_PKCS11_FLAG_SIGN );
445 CK_BBOOL ck_verify = MBEDTLS_PKCS11_BOOL( flags & MBEDTLS_PKCS11_FLAG_VERIFY );
446 CK_BBOOL ck_decrypt = MBEDTLS_PKCS11_BOOL( flags & MBEDTLS_PKCS11_FLAG_DECRYPT );
447 CK_BBOOL ck_encrypt = MBEDTLS_PKCS11_BOOL( flags & MBEDTLS_PKCS11_FLAG_ENCRYPT );
448 CK_BBOOL ck_token = MBEDTLS_PKCS11_BOOL( flags & MBEDTLS_PKCS11_FLAG_TOKEN );
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500449 CK_ATTRIBUTE public_attributes[] = {
450 {CKA_CLASS, &cko_public_key, sizeof( cko_public_key )},
451 {CKA_KEY_TYPE, &ck_key_type, sizeof( ck_key_type )},
452 {CKA_TOKEN, &ck_token, sizeof( ck_token )},
453 {CKA_ENCRYPT, &ck_encrypt, sizeof( ck_encrypt )},
454 {CKA_VERIFY, &ck_verify, sizeof( ck_verify )},
455#define COMMON_PUBLIC_ATTRIBUTES 5 // number of attributes above
456 {-1, NULL, 0},
457 {-1, NULL, 0},
458 };
459 CK_ATTRIBUTE private_attributes[] = {
460 {CKA_CLASS, &cko_private_key, sizeof( cko_private_key )},
461 {CKA_KEY_TYPE, &ck_key_type, sizeof( ck_key_type )},
462 {CKA_TOKEN, &ck_token, sizeof( ck_token )},
463 {CKA_DECRYPT, &ck_decrypt, sizeof( ck_decrypt )},
464 {CKA_SIGN, &ck_sign, sizeof( ck_sign )},
465 {CKA_SENSITIVE, &ck_sensitive, sizeof( ck_sensitive )},
466 {CKA_EXTRACTABLE, &ck_extractable, sizeof( ck_extractable )},
467#define COMMON_PRIVATE_ATTRIBUTES 7 // number of attributes above
468 {-1, NULL, 0},
469 {-1, NULL, 0},
470 {-1, NULL, 0},
471 {-1, NULL, 0},
472 {-1, NULL, 0},
473 {-1, NULL, 0},
474 {-1, NULL, 0},
475 {-1, NULL, 0},
476 };
477 CK_ATTRIBUTE *public_end = public_attributes + COMMON_PUBLIC_ATTRIBUTES;
478 CK_ATTRIBUTE *private_end = private_attributes + COMMON_PRIVATE_ATTRIBUTES;
479#undef COMMON_PUBLIC_ATTRIBUTES
480#undef COMMON_PRIVATE_ATTRIBUTES
481 unsigned char *data = NULL;
482 CK_RV rv;
483
484 if( hPublicKey != NULL )
485 *hPublicKey = CK_INVALID_HANDLE;
486 if( hPrivateKey != NULL )
487 *hPrivateKey = CK_INVALID_HANDLE;
488
489 /* Prepare the data-dependent key attributes */
490 switch( mbedtls_pk_representation_type( mbedtls_pk_get_type( ctx ) ) )
491 {
492#if defined(MBEDTLS_ECDSA_C)
493 case MBEDTLS_PK_ECKEY:
494 {
495 const mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *ctx );
496 unsigned char *p;
497 size_t curve_bytes = ( ec->grp.pbits + 7 ) / 8;
498 size_t point_bytes = 4 + 2 * curve_bytes; // overapproximation
499 int format = MBEDTLS_ECP_PF_UNCOMPRESSED;
500 int ret;
501 data = mbedtls_calloc( 1,
502 MBEDTLS_OID_EC_GRP_MAX_SIZE +
503 ( hPublicKey == NULL ? 0 : point_bytes ) +
504 ( hPrivateKey == NULL ? 0 : curve_bytes ) );
505 if( data == NULL )
506 {
507 rv = CKR_HOST_MEMORY;
508 goto exit;
509 }
510 p = data;
511 ck_key_type = CKK_ECDSA;
512 /* Convert the group identifier */
513 ret = mbedtls_ecp_ansi_write_group( &ec->grp, p,
514 MBEDTLS_OID_EC_GRP_MAX_SIZE );
515 if( ret < 0 )
516 {
517 rv = CKR_GENERAL_ERROR;
518 goto exit;
519 }
520 public_end->type = CKA_EC_PARAMS;
521 public_end->pValue = p;
522 public_end->ulValueLen = ret;
523 p += ret;
524 *private_end++ = *public_end++;
525 if( hPublicKey != NULL )
526 {
527 /* Convert the public point */
528 ret = mbedtls_ecp_ansi_write_point( ec, format, p, point_bytes );
529 if( ret < 0 )
530 {
531 rv = CKR_GENERAL_ERROR;
532 goto exit;
533 }
534 public_end->type = CKA_EC_POINT;
535 public_end->pValue = p;
536 public_end->ulValueLen = ret;
537 p += ret;
538 public_end++;
539 }
540 if( hPrivateKey != NULL )
541 {
542 /* Convert the private value */
543 MPI_TO_CK( &ec->d, private_end++, CKA_VALUE, &p, curve_bytes );
544 }
545 }
546 break;
547#endif /* MBEDTLS_ECDSA_C */
548 default:
549 return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
550 }
551
552 if( hPublicKey != NULL )
553 {
554 *hPublicKey = CK_INVALID_HANDLE;
555 rv = C_CreateObject( hSession,
556 public_attributes,
557 public_end - public_attributes,
558 hPublicKey );
559 if( rv != CKR_OK )
560 goto exit;
561 }
562
563 if( hPrivateKey != NULL )
564 {
565 rv = C_CreateObject( hSession,
566 private_attributes,
567 private_end - private_attributes,
568 hPrivateKey );
569 if( rv != CKR_OK )
570 goto exit;
571 }
572
573exit:
574 if( rv != CKR_OK )
575 {
576 /* In case an error happened, destroy any object that we
577 created. In case C_DestroyObject failed, we report the original
578 error, but *hPublicKey may contain a valid handle if
579 creating the private key failed and then destroying the public key
580 also failed (e.g. because the token disconnected). */
581 if( hPublicKey != NULL && *hPublicKey != CK_INVALID_HANDLE )
582 {
583 if( C_DestroyObject( hSession, *hPublicKey ) == CKR_OK )
584 *hPublicKey = CK_INVALID_HANDLE;
585 }
586 if( hPrivateKey != NULL && *hPrivateKey != CK_INVALID_HANDLE )
587 {
588 if( C_DestroyObject( hSession, *hPrivateKey ) == CKR_OK )
589 *hPrivateKey = CK_INVALID_HANDLE;
590 }
591 }
592 mbedtls_free( data );
593 return( pkcs11_err_to_mbedtls_pk_err( rv ) );
594}
595
596#endif /* MBEDTLS_PK_C */
597
598
599
600#endif /* MBEDTLS_PKCS11_CLIENT_C */